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: ");
+ }
}