diff --git a/docs/src/main/sphinx/functions/geospatial.md b/docs/src/main/sphinx/functions/geospatial.md index 8b02504951ab..af82708e4999 100644 --- a/docs/src/main/sphinx/functions/geospatial.md +++ b/docs/src/main/sphinx/functions/geospatial.md @@ -64,6 +64,10 @@ Returns a geometry type object from WKT representation. Returns a geometry type object from WKB or EWKB representation. ::: +:::{function} ST_GeomFromKML(varchar) -> Geometry +Returns a geometry type object from KML representation. +::: + :::{function} geometry_from_hadoop_shape(varbinary) -> Geometry Returns a geometry type object from Spatial Framework for Hadoop representation. ::: diff --git a/plugin/trino-geospatial/src/main/java/io/trino/plugin/geospatial/GeoFunctions.java b/plugin/trino-geospatial/src/main/java/io/trino/plugin/geospatial/GeoFunctions.java index cd46c73d9373..5ff4d12f7327 100644 --- a/plugin/trino-geospatial/src/main/java/io/trino/plugin/geospatial/GeoFunctions.java +++ b/plugin/trino-geospatial/src/main/java/io/trino/plugin/geospatial/GeoFunctions.java @@ -64,6 +64,7 @@ import org.locationtech.jts.geom.GeometryFactory; import org.locationtech.jts.io.ParseException; import org.locationtech.jts.io.WKBReader; +import org.locationtech.jts.io.kml.KMLReader; import org.locationtech.jts.linearref.LengthIndexedLine; import org.locationtech.jts.operation.distance.DistanceOp; @@ -317,6 +318,14 @@ public static Slice stGeomFromBinary(@SqlType(VARBINARY) Slice input) return serialize(geomFromBinary(input)); } + @Description("Returns a Geometry type object from OGC KML representation") + @ScalarFunction("ST_GeomFromKML") + @SqlType(GEOMETRY_TYPE_NAME) + public static Slice stGeomFromKML(@SqlType(VARCHAR) Slice input) + { + return serialize(geomFromKML(input)); + } + @Description("Returns a Geometry type object from Spatial Framework for Hadoop representation") @ScalarFunction("geometry_from_hadoop_shape") @SqlType(GEOMETRY_TYPE_NAME) @@ -1551,6 +1560,16 @@ private static Geometry geomFromBinary(Slice input) } } + private static Geometry geomFromKML(Slice input) + { + try { + return new KMLReader().read(input.toStringUtf8()); + } + catch (ParseException e) { + throw new TrinoException(INVALID_FUNCTION_ARGUMENT, "Invalid KML: " + input.toStringUtf8(), e); + } + } + private static ByteBuffer getShapeByteBuffer(Slice input) { int offset = HADOOP_SHAPE_SIZE_WKID + HADOOP_SHAPE_SIZE_TYPE; diff --git a/plugin/trino-geospatial/src/test/java/io/trino/plugin/geospatial/TestGeoFunctions.java b/plugin/trino-geospatial/src/test/java/io/trino/plugin/geospatial/TestGeoFunctions.java index ff70ab54b965..f036a27eb1ee 100644 --- a/plugin/trino-geospatial/src/test/java/io/trino/plugin/geospatial/TestGeoFunctions.java +++ b/plugin/trino-geospatial/src/test/java/io/trino/plugin/geospatial/TestGeoFunctions.java @@ -2325,4 +2325,16 @@ private void assertInvalidGeometryJson(String json, String message) assertTrinoExceptionThrownBy(assertions.function("from_geojson_geometry", "'%s'".formatted(json))::evaluate) .hasMessage(message); } + + @Test + public void testSTGeomFromKML() + { + assertThat(assertions.expression("ST_AsText(ST_GeomFromKML(geometry))") + .binding("geometry", "'-2,2'")) + .hasType(VARCHAR) + .isEqualTo("POINT (-2 2)"); + + assertTrinoExceptionThrownBy(assertions.function("ST_GeomFromKML", "''")::evaluate) + .hasMessage("Invalid KML: "); + } }