This is an automated email from the ASF dual-hosted git repository.

jiayu pushed a commit to branch SEDONA-590
in repository https://gitbox.apache.org/repos/asf/sedona.git

commit fc7e6df86b8abb8a5148963c1d153e9afaab79eb
Author: Furqaan Khan <[email protected]>
AuthorDate: Fri Apr 26 16:18:00 2024 -0400

    [TASK-238] Add ST_GeomCollFromText (#171)
---
 .../org/apache/sedona/common/Constructors.java     |  8 +++
 .../org/apache/sedona/common/ConstructorsTest.java | 17 ++++++
 docs/api/flink/Constructor.md                      | 60 ++++++++++++++++++++++
 docs/api/snowflake/vector-data/Constructor.md      | 56 ++++++++++++++++++++
 docs/api/sql/Constructor.md                        | 60 ++++++++++++++++++++++
 .../main/java/org/apache/sedona/flink/Catalog.java |  1 +
 .../sedona/flink/expressions/Constructors.java     | 11 ++++
 .../org/apache/sedona/flink/ConstructorTest.java   | 20 ++++++++
 python/sedona/sql/st_constructors.py               | 15 ++++++
 python/tests/sql/test_constructor_test.py          | 13 +++++
 python/tests/sql/test_dataframe_api.py             |  8 ++-
 .../sedona/snowflake/snowsql/TestConstructors.java | 14 +++++
 .../org/apache/sedona/snowflake/snowsql/UDFs.java  | 14 +++++
 .../scala/org/apache/sedona/sql/UDF/Catalog.scala  |  1 +
 .../sql/sedona_sql/expressions/Constructors.scala  |  8 +++
 .../sedona_sql/expressions/st_constructors.scala   |  5 ++
 .../apache/sedona/sql/constructorTestScala.scala   | 13 +++++
 .../apache/sedona/sql/dataFrameAPITestScala.scala  | 13 +++++
 18 files changed, 336 insertions(+), 1 deletion(-)

diff --git a/common/src/main/java/org/apache/sedona/common/Constructors.java 
b/common/src/main/java/org/apache/sedona/common/Constructors.java
index 93dd8b00d..106bc1d13 100644
--- a/common/src/main/java/org/apache/sedona/common/Constructors.java
+++ b/common/src/main/java/org/apache/sedona/common/Constructors.java
@@ -108,6 +108,14 @@ public class Constructors {
         return new WKTReader(geometryFactory).read(wkt);
     }
 
+    public static Geometry geomCollFromText(String wkt, int srid) throws 
ParseException {
+        if (wkt == null || !wkt.startsWith("GEOMETRYCOLLECTION")) {
+            return null;
+        }
+        GeometryFactory geometryFactory = new GeometryFactory(new 
PrecisionModel(), srid);
+        return new WKTReader(geometryFactory).read(wkt);
+    }
+
 
     /**
      * Creates a point from the given coordinate.
diff --git 
a/common/src/test/java/org/apache/sedona/common/ConstructorsTest.java 
b/common/src/test/java/org/apache/sedona/common/ConstructorsTest.java
index 49336f9f4..0f5c4fec4 100644
--- a/common/src/test/java/org/apache/sedona/common/ConstructorsTest.java
+++ b/common/src/test/java/org/apache/sedona/common/ConstructorsTest.java
@@ -98,6 +98,23 @@ public class ConstructorsTest {
 
     }
 
+    @Test
+    public void geomCollFromText() throws ParseException {
+        assertNull(Constructors.geomCollFromText(null, 0));
+        assertNull(Constructors.geomCollFromText("MULTIPOLYGON (((0 0, 20 0, 
20 20, 0 20, 0 0), (5 5, 5 7, 7 7, 7 5, 5 5)))", 0));
+        Geometry geom = Constructors.geomCollFromText("GEOMETRYCOLLECTION 
(POINT (10 20),LINESTRING (30 40, 50 60, 70 80),POLYGON ((10 10, 20 20, 10 20, 
10 10)))", 0);
+        assertEquals(0,geom.getSRID());
+        assertEquals("GEOMETRYCOLLECTION (POINT (10 20), LINESTRING (30 40, 50 
60, 70 80), POLYGON ((10 10, 20 20, 10 20, 10 10)))",geom.toText());
+
+        geom = Constructors.geomCollFromText("GEOMETRYCOLLECTION (POINT (10 
20),LINESTRING (30 40, 50 60, 70 80),POLYGON ((10 10, 20 20, 10 20, 10 10)))", 
3306);
+        assertEquals(3306,geom.getSRID());
+        assertEquals("GEOMETRYCOLLECTION (POINT (10 20), LINESTRING (30 40, 50 
60, 70 80), POLYGON ((10 10, 20 20, 10 20, 10 10)))"
+                ,geom.toText());
+
+        ParseException parseException = assertThrows(ParseException.class, () 
-> Constructors.geomCollFromText("GEOMETRYCOLLECTION (POLYGON(not valid))", 0));
+        assertEquals("Expected EMPTY or ( but found 'not' (line 1)", 
parseException.getMessage());
+    }
+
     @Test
     public void point() {
         Geometry point = Constructors.point(1.0d, 2.0d);
diff --git a/docs/api/flink/Constructor.md b/docs/api/flink/Constructor.md
index ae3c32e9a..9061b14f8 100644
--- a/docs/api/flink/Constructor.md
+++ b/docs/api/flink/Constructor.md
@@ -1,3 +1,63 @@
+## ST_GeomCollFromText
+
+Introduction: Constructs a GeometryCollection from the WKT with the given 
SRID. If SRID is not provided then it defaults to 0. It returns `null` if the 
WKT is not a `GEOMETRYCOLLECTION`.
+
+Format:
+
+`ST_GeomCollFromText (Wkt: String)`
+
+`ST_GeomCollFromText (Wkt: String, srid: Integer)`
+
+Since: `vTBD`
+
+SQL Example:
+
+```sql
+SELECT ST_GeomCollFromText('GEOMETRYCOLLECTION (POINT (50 50), LINESTRING (20 
30, 40 60, 80 90), POLYGON ((30 10, 40 20, 30 20, 30 10), (35 15, 45 15, 40 25, 
35 15)))')
+```
+
+Output:
+
+```
+GEOMETRYCOLLECTION (POINT (50 50), LINESTRING (20 30, 40 60, 80 90), POLYGON 
((30 10, 40 20, 30 20, 30 10), (35 15, 45 15, 40 25, 35 15)))
+```
+
+## ST_GeomFromEWKB
+
+Introduction: Construct a Geometry from EWKB string or Binary. This function 
is an alias of [ST_GeomFromWKB](#st_geomfromwkb).
+
+Format:
+
+`ST_GeomFromEWKB (Wkb: String)`
+
+`ST_GeomFromEWKB (Wkb: Binary)`
+
+Since: `vTBD`
+
+SQL Example
+
+```sql
+SELECT ST_GeomFromEWKB([01 02 00 00 00 02 00 00 00 00 00 00 00 84 D6 00 C0 00 
00 00 00 80 B5 D6 BF 00 00 00 60 E1 EF F7 BF 00 00 00 80 07 5D E5 BF])
+```
+
+Output:
+
+```
+LINESTRING (-2.1047439575195312 -0.354827880859375, -1.49606454372406 
-0.6676061153411865)
+```
+
+SQL Example
+
+```sql
+SELECT 
ST_asEWKT(ST_GeomFromEWKB('01010000a0e6100000000000000000f03f000000000000f03f000000000000f03f'))
+```
+
+Output:
+
+```
+SRID=4326;POINT Z(1 1 1)
+```
+
 ## ST_GeomFromEWKT
 
 Introduction: Construct a Geometry from OGC Extended WKT
diff --git a/docs/api/snowflake/vector-data/Constructor.md 
b/docs/api/snowflake/vector-data/Constructor.md
index f35972a30..44bac2825 100644
--- a/docs/api/snowflake/vector-data/Constructor.md
+++ b/docs/api/snowflake/vector-data/Constructor.md
@@ -1,6 +1,62 @@
 !!!note
     Please always keep the schema name `SEDONA` (e.g., 
`SEDONA.ST_GeomFromWKT`) when you use Sedona functions to avoid conflicting 
with Snowflake's built-in functions.
 
+## ST_GeomCollFromText
+
+Introduction: Constructs a GeometryCollection from the WKT with the given 
SRID. If SRID is not provided then it defaults to 0. It returns `null` if the 
WKT is not a `GEOMETRYCOLLECTION`.
+
+Format:
+
+`ST_GeomCollFromText (Wkt: String)`
+
+`ST_GeomCollFromText (Wkt: String, srid: Integer)`
+
+SQL Example:
+
+```sql
+SELECT ST_GeomCollFromText('GEOMETRYCOLLECTION (POINT (50 50), LINESTRING (20 
30, 40 60, 80 90), POLYGON ((30 10, 40 20, 30 20, 30 10), (35 15, 45 15, 40 25, 
35 15)))')
+```
+
+Output:
+
+```
+GEOMETRYCOLLECTION (POINT (50 50), LINESTRING (20 30, 40 60, 80 90), POLYGON 
((30 10, 40 20, 30 20, 30 10), (35 15, 45 15, 40 25, 35 15)))
+```
+
+## ST_GeomFromEWKB
+
+Introduction: Construct a Geometry from EWKB string or Binary. This function 
is an alias of [ST_GeomFromWKB](#st_geomfromwkb).
+
+Format:
+
+`ST_GeomFromEWKB (Wkb: String)`
+
+`ST_GeomFromEWKB (Wkb: Binary)`
+
+SQL Example
+
+```sql
+SELECT ST_GeomFromEWKB([01 02 00 00 00 02 00 00 00 00 00 00 00 84 D6 00 C0 00 
00 00 00 80 B5 D6 BF 00 00 00 60 E1 EF F7 BF 00 00 00 80 07 5D E5 BF])
+```
+
+Output:
+
+```
+LINESTRING (-2.1047439575195312 -0.354827880859375, -1.49606454372406 
-0.6676061153411865)
+```
+
+SQL Example
+
+```sql
+SELECT 
ST_asEWKT(ST_GeomFromEWKB('01010000a0e6100000000000000000f03f000000000000f03f000000000000f03f'))
+```
+
+Output:
+
+```
+SRID=4326;POINT Z(1 1 1)
+```
+
 ## ST_GeomFromEWKT
 
 Introduction: Construct a Geometry from OGC Extended WKT
diff --git a/docs/api/sql/Constructor.md b/docs/api/sql/Constructor.md
index e3ca74631..68888c2c7 100644
--- a/docs/api/sql/Constructor.md
+++ b/docs/api/sql/Constructor.md
@@ -44,6 +44,66 @@ spark.driver.extraJavaOptions  -Dsedona.global.charset=utf8
 spark.executor.extraJavaOptions  -Dsedona.global.charset=utf8
 ```
 
+## ST_GeomCollFromText
+
+Introduction: Constructs a GeometryCollection from the WKT with the given 
SRID. If SRID is not provided then it defaults to 0. It returns `null` if the 
WKT is not a `GEOMETRYCOLLECTION`.
+
+Format:
+
+`ST_GeomCollFromText (Wkt: String)`
+
+`ST_GeomCollFromText (Wkt: String, srid: Integer)`
+
+Since: `vTBD`
+
+SQL Example:
+
+```sql
+SELECT ST_GeomCollFromText('GEOMETRYCOLLECTION (POINT (50 50), LINESTRING (20 
30, 40 60, 80 90), POLYGON ((30 10, 40 20, 30 20, 30 10), (35 15, 45 15, 40 25, 
35 15)))')
+```
+
+Output:
+
+```
+GEOMETRYCOLLECTION (POINT (50 50), LINESTRING (20 30, 40 60, 80 90), POLYGON 
((30 10, 40 20, 30 20, 30 10), (35 15, 45 15, 40 25, 35 15)))
+```
+
+## ST_GeomFromEWKB
+
+Introduction: Construct a Geometry from EWKB string or Binary. This function 
is an alias of [ST_GeomFromWKB](#st_geomfromwkb).
+
+Format:
+
+`ST_GeomFromEWKB (Wkb: String)`
+
+`ST_GeomFromEWKB (Wkb: Binary)`
+
+Since: `vTBD`
+
+SQL Example
+
+```sql
+SELECT ST_GeomFromEWKB([01 02 00 00 00 02 00 00 00 00 00 00 00 84 D6 00 C0 00 
00 00 00 80 B5 D6 BF 00 00 00 60 E1 EF F7 BF 00 00 00 80 07 5D E5 BF])
+```
+
+Output:
+
+```
+LINESTRING (-2.1047439575195312 -0.354827880859375, -1.49606454372406 
-0.6676061153411865)
+```
+
+SQL Example
+
+```sql
+SELECT 
ST_asEWKT(ST_GeomFromEWKB('01010000a0e6100000000000000000f03f000000000000f03f000000000000f03f'))
+```
+
+Output:
+
+```
+SRID=4326;POINT Z(1 1 1)
+```
+
 ## ST_GeomFromEWKT
 
 Introduction: Construct a Geometry from OGC Extended WKT
diff --git a/flink/src/main/java/org/apache/sedona/flink/Catalog.java 
b/flink/src/main/java/org/apache/sedona/flink/Catalog.java
index 591b783d0..0cea5e694 100644
--- a/flink/src/main/java/org/apache/sedona/flink/Catalog.java
+++ b/flink/src/main/java/org/apache/sedona/flink/Catalog.java
@@ -47,6 +47,7 @@ public class Catalog {
                 new Constructors.ST_GeomFromKML(),
                 new Constructors.ST_MPolyFromText(),
                 new Constructors.ST_MLineFromText(),
+                new Constructors.ST_GeomCollFromText(),
                 new Functions.GeometryType(),
                 new Functions.ST_Area(),
                 new Functions.ST_AreaSpheroid(),
diff --git 
a/flink/src/main/java/org/apache/sedona/flink/expressions/Constructors.java 
b/flink/src/main/java/org/apache/sedona/flink/expressions/Constructors.java
index 2f60623b0..a0719642f 100644
--- a/flink/src/main/java/org/apache/sedona/flink/expressions/Constructors.java
+++ b/flink/src/main/java/org/apache/sedona/flink/expressions/Constructors.java
@@ -373,4 +373,15 @@ public class Constructors {
         }
     }
 
+    public static class ST_GeomCollFromText extends ScalarFunction {
+        @DataTypeHint(value = "RAW", bridgedTo = 
org.locationtech.jts.geom.Geometry.class)
+        public Geometry eval(@DataTypeHint(value = "String") String wkt, 
@DataTypeHint("Int") Integer srid) throws ParseException {
+            return org.apache.sedona.common.Constructors.geomCollFromText(wkt, 
srid);
+        }
+        @DataTypeHint(value = "RAW", bridgedTo = 
org.locationtech.jts.geom.Geometry.class)
+        public Geometry eval(@DataTypeHint(value = "String") String wkt) 
throws ParseException {
+            return org.apache.sedona.common.Constructors.geomCollFromText(wkt, 
0);
+        }
+    }
+
 }
diff --git a/flink/src/test/java/org/apache/sedona/flink/ConstructorTest.java 
b/flink/src/test/java/org/apache/sedona/flink/ConstructorTest.java
index 693aadac4..5ec29d54f 100644
--- a/flink/src/test/java/org/apache/sedona/flink/ConstructorTest.java
+++ b/flink/src/test/java/org/apache/sedona/flink/ConstructorTest.java
@@ -559,4 +559,24 @@ public class ConstructorTest extends TestBase{
         String expectedGeom = "MULTILINESTRING ((1 2, 3 4), (4 5, 6 7))";
         assertEquals(expectedGeom, result);
     }
+
+    @Test
+    public void testGeomCollFromText() {
+        Table tbl = tableEnv.sqlQuery("SELECT 'GEOMETRYCOLLECTION (POINT (50 
50), LINESTRING (20 30, 40 60, 80 90),POLYGON ((30 10, 40 20, 30 20, 30 10), 
(35 15, 45 15, 40 25, 35 15)))' AS coll, 4326 as srid");
+        String actualColl = first(
+                
tbl.select(call(Constructors.ST_GeomCollFromText.class.getSimpleName(), 
$("coll")))
+        ).getFieldAs(0).toString();
+        String expectedColl = "GEOMETRYCOLLECTION (POINT (50 50), LINESTRING 
(20 30, 40 60, 80 90), POLYGON ((30 10, 40 20, 30 20, 30 10), (35 15, 45 15, 40 
25, 35 15)))";
+        assertEquals(expectedColl, actualColl);
+
+        actualColl = first(
+                
tbl.select(call(Constructors.ST_GeomCollFromText.class.getSimpleName(), 
$("coll"), $("srid")))
+        ).getFieldAs(0).toString();
+        assertEquals(expectedColl, actualColl);
+        int actualSrid = first(
+                
tbl.select(call(Constructors.ST_GeomCollFromText.class.getSimpleName(), 
$("coll"), $("srid")))
+                        
.as("geom").select(call(Functions.ST_SRID.class.getSimpleName(), $("geom")))
+        ).getFieldAs(0);
+        assertEquals(4326, actualSrid);
+    }
 }
diff --git a/python/sedona/sql/st_constructors.py 
b/python/sedona/sql/st_constructors.py
index 50ab1899f..f04ac9e5e 100644
--- a/python/sedona/sql/st_constructors.py
+++ b/python/sedona/sql/st_constructors.py
@@ -395,3 +395,18 @@ def ST_MLineFromText(wkt: ColumnOrName, srid: 
Optional[ColumnOrNameOrNumber] = N
     args = (wkt) if srid is None else (wkt, srid)
 
     return _call_constructor_function("ST_MLineFromText", args)
+
+@validate_argument_types
+def ST_GeomCollFromText(wkt: ColumnOrName, srid: 
Optional[ColumnOrNameOrNumber] = None) -> Column:
+    """Generate GeometryCollection geometry from a GeometryCollection WKT 
representation.
+
+    :param wkt: GeometryCollection WKT string column to generate from.
+    :type wkt: ColumnOrName
+    :param srid: SRID for the geometry
+    :type srid: ColumnOrNameOrNumber
+    :return: GeometryCollection geometry generated from the wkt column.
+    :rtype: Column
+    """
+    args = (wkt) if srid is None else (wkt, srid)
+
+    return _call_constructor_function("ST_GeomCollFromText", args)
diff --git a/python/tests/sql/test_constructor_test.py 
b/python/tests/sql/test_constructor_test.py
index cd9a30b93..302cf5d1d 100644
--- a/python/tests/sql/test_constructor_test.py
+++ b/python/tests/sql/test_constructor_test.py
@@ -190,3 +190,16 @@ class TestConstructors(TestBase):
         input_df.createOrReplaceTempView("input_wkt")
         line_df = self.spark.sql("select ST_MPolyFromText(wkt) as geom from 
input_wkt")
         assert line_df.count() == 1
+
+    def test_geom_coll_from_text(self):
+        baseDf = self.spark.sql("SELECT 'GEOMETRYCOLLECTION (POINT (50 50), 
LINESTRING (20 30, 40 60, 80 90), POLYGON ((30 10, 40 20, 30 20, 30 10), (35 
15, 45 15, 40 25, 35 15)))' as geom, 4326 as srid")
+        actual = 
baseDf.selectExpr("ST_AsText(ST_GeomCollFromText(geom))").take(1)[0][0]
+        expected = 'GEOMETRYCOLLECTION (POINT (50 50), LINESTRING (20 30, 40 
60, 80 90), POLYGON ((30 10, 40 20, 30 20, 30 10), (35 15, 45 15, 40 25, 35 
15)))'
+        assert expected == actual
+
+        actualGeom = baseDf.selectExpr("ST_GeomCollFromText(geom, srid) as 
geom")
+        actual = actualGeom.selectExpr("ST_AsText(geom)").take(1)[0][0]
+        assert expected == actual
+
+        actualSrid = actualGeom.selectExpr("ST_SRID(geom)").take(1)[0][0]
+        assert actualSrid == 4326
diff --git a/python/tests/sql/test_dataframe_api.py 
b/python/tests/sql/test_dataframe_api.py
index 0426c7414..a1450c880 100644
--- a/python/tests/sql/test_dataframe_api.py
+++ b/python/tests/sql/test_dataframe_api.py
@@ -70,6 +70,8 @@ test_configurations = [
     (stc.ST_PolygonFromEnvelope, ("minx", "miny", "maxx", "maxy"), 
"min_max_x_y", "", "POLYGON ((0 1, 0 3, 2 3, 2 1, 0 1))"),
     (stc.ST_PolygonFromEnvelope, (0.0, 1.0, 2.0, 3.0), "null", "", "POLYGON 
((0 1, 0 3, 2 3, 2 1, 0 1))"),
     (stc.ST_PolygonFromText, ("multiple_point", lambda: f.lit(',')), 
"constructor", "", "POLYGON ((0 0, 1 0, 1 1, 0 0))"),
+    (stc.ST_GeomCollFromText, ("collection",), "constructor", "", 
"GEOMETRYCOLLECTION (POINT (1 1), LINESTRING (0 0, 1 1))"),
+    (stc.ST_GeomCollFromText, ("collection", 4326), "constructor", 
"ST_SRID(geom)", 4326),
 
     # functions
     (stf.GeometryType, ("line",), "linestring_geom", "", "LINESTRING"),
@@ -268,6 +270,8 @@ wrong_type_configurations = [
     (stc.ST_PolygonFromEnvelope, ("", "", "", None)),
     (stc.ST_PolygonFromText, (None, "")),
     (stc.ST_PolygonFromText, ("", None)),
+    (stc.ST_PolygonFromText, (None, None)),
+    (stc.ST_PolygonFromText, ("", None)),
 
     # functions
     (stf.ST_3DDistance, (None, "")),
@@ -444,6 +448,7 @@ class TestDataFrameAPI(TestBase):
         geojson = "{ \"type\": \"Feature\", \"properties\": { \"prop\": \"01\" 
}, \"geometry\": { \"type\": \"Point\", \"coordinates\": [ 0.0, 1.0 ] }},"
         gml_string = "<gml:LineString 
srsName=\"EPSG:4269\"><gml:coordinates>-71.16,42.25 -71.17,42.25 
-71.18,42.25</gml:coordinates></gml:LineString>"
         kml_string = "<LineString><coordinates>-71.16,42.26 
-71.17,42.26</coordinates></LineString>"
+        wktCollection = 'GEOMETRYCOLLECTION(POINT(1 1), LINESTRING(0 0, 1 1)))'
 
         if request.param == "constructor":
             return TestDataFrameAPI.spark.sql("SELECT null").selectExpr(
@@ -459,7 +464,8 @@ class TestDataFrameAPI(TestBase):
                 f"'{geojson}' AS geojson",
                 "'s00twy01mt' AS geohash",
                 f"'{gml_string}' AS gml",
-                f"'{kml_string}' AS kml"
+                f"'{kml_string}' AS kml",
+                f"'{wktCollection}' AS collection"
             )
         elif request.param == "point_geom":
             return TestDataFrameAPI.spark.sql("SELECT ST_Point(0.0, 1.0) AS 
point")
diff --git 
a/snowflake-tester/src/test/java/org/apache/sedona/snowflake/snowsql/TestConstructors.java
 
b/snowflake-tester/src/test/java/org/apache/sedona/snowflake/snowsql/TestConstructors.java
index c22d36814..d8a4f7edb 100644
--- 
a/snowflake-tester/src/test/java/org/apache/sedona/snowflake/snowsql/TestConstructors.java
+++ 
b/snowflake-tester/src/test/java/org/apache/sedona/snowflake/snowsql/TestConstructors.java
@@ -200,6 +200,20 @@ public class TestConstructors extends TestBase{
                 "MULTIPOLYGON (((1 2, 3 4, 5 6, 1 2)), ((7 8, 9 10, 11 12, 7 
8)))"
         );
     }
+
+    @Test
+    public void test_ST_GeomCollFromText() {
+        registerUDF("ST_GeomCollFromText", String.class);
+        verifySqlSingleRes(
+                "select 
sedona.ST_AsText(sedona.ST_GeomCollFromText('GEOMETRYCOLLECTION (POINT (50 50), 
LINESTRING (20 30, 40 60, 80 90), POLYGON ((30 10, 40 20, 30 20, 30 10), (35 
15, 45 15, 40 25, 35 15)))'))",
+                "GEOMETRYCOLLECTION (POINT (50 50), LINESTRING (20 30, 40 60, 
80 90), POLYGON ((30 10, 40 20, 30 20, 30 10), (35 15, 45 15, 40 25, 35 15)))"
+        );
+        registerUDF("ST_GeomCollFromText", String.class, int.class);
+        verifySqlSingleRes(
+                "select 
sedona.ST_SRID(sedona.ST_GeomCollFromText('GEOMETRYCOLLECTION (POINT (50 50), 
LINESTRING (20 30, 40 60, 80 90), POLYGON ((30 10, 40 20, 30 20, 30 10), (35 
15, 45 15, 40 25, 35 15)))',4269))",
+                4269
+        );
+    }
     @Test
     public void test_ST_Point() {
         registerUDF("ST_Point", double.class, double.class);
diff --git 
a/snowflake/src/main/java/org/apache/sedona/snowflake/snowsql/UDFs.java 
b/snowflake/src/main/java/org/apache/sedona/snowflake/snowsql/UDFs.java
index a184cc6ec..b3e2570cd 100644
--- a/snowflake/src/main/java/org/apache/sedona/snowflake/snowsql/UDFs.java
+++ b/snowflake/src/main/java/org/apache/sedona/snowflake/snowsql/UDFs.java
@@ -837,6 +837,20 @@ public class UDFs {
         );
     }
 
+    @UDFAnnotations.ParamMeta(argNames = {"wkt", "srid"})
+    public static byte[] ST_GeomCollFromText(String wkt, int srid) throws 
ParseException {
+        return GeometrySerde.serialize(
+                Constructors.geomCollFromText(wkt, srid)
+        );
+    }
+
+    @UDFAnnotations.ParamMeta(argNames = {"wkt", "srid"})
+    public static byte[] ST_GeomCollFromText(String wkt) throws ParseException 
{
+        return GeometrySerde.serialize(
+                Constructors.geomCollFromText(wkt, 0)
+        );
+    }
+
     @UDFAnnotations.ParamMeta(argNames = {"shell"})
     public static byte[] ST_MakePolygon(byte[] shell) {
         return GeometrySerde.serialize(
diff --git 
a/spark/common/src/main/scala/org/apache/sedona/sql/UDF/Catalog.scala 
b/spark/common/src/main/scala/org/apache/sedona/sql/UDF/Catalog.scala
index f3b46011d..502ae1ace 100644
--- a/spark/common/src/main/scala/org/apache/sedona/sql/UDF/Catalog.scala
+++ b/spark/common/src/main/scala/org/apache/sedona/sql/UDF/Catalog.scala
@@ -182,6 +182,7 @@ object Catalog {
     function[ST_LineFromMultiPoint](),
     function[ST_MPolyFromText](0),
     function[ST_MLineFromText](0),
+    function[ST_GeomCollFromText](0),
     function[ST_Split](),
     function[ST_S2CellIDs](),
     function[ST_S2ToGeom](),
diff --git 
a/spark/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/Constructors.scala
 
b/spark/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/Constructors.scala
index cdbe0a5c9..45d9c3162 100644
--- 
a/spark/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/Constructors.scala
+++ 
b/spark/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/Constructors.scala
@@ -454,3 +454,11 @@ case class ST_MLineFromText(inputExpressions: 
Seq[Expression])
     copy(inputExpressions = newChildren)
   }
 }
+
+case class ST_GeomCollFromText(inputExpressions: Seq[Expression])
+  extends InferredExpression(Constructors.geomCollFromText _) {
+
+  protected def withNewChildrenInternal(newChildren: IndexedSeq[Expression]) = 
{
+    copy(inputExpressions = newChildren)
+  }
+}
diff --git 
a/spark/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/st_constructors.scala
 
b/spark/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/st_constructors.scala
index 5b52df90b..b3a8f8500 100644
--- 
a/spark/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/st_constructors.scala
+++ 
b/spark/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/st_constructors.scala
@@ -161,4 +161,9 @@ object st_constructors extends DataFrameAPI {
   def ST_MLineFromText(wkt: Column, srid: Column): Column = 
wrapExpression[ST_MLineFromText](wkt, srid)
 
   def ST_MLineFromText(wkt: String, srid: Int): Column = 
wrapExpression[ST_MLineFromText](wkt, srid)
+
+  def ST_GeomCollFromText(wkt: Column): Column = 
wrapExpression[ST_GeomCollFromText](wkt, 0)
+  def ST_GeomCollFromText(wkt: String): Column = 
wrapExpression[ST_GeomCollFromText](wkt, 0)
+  def ST_GeomCollFromText(wkt: Column, srid: Column): Column = 
wrapExpression[ST_GeomCollFromText](wkt, srid)
+  def ST_GeomCollFromText(wkt: String, srid: Int): Column = 
wrapExpression[ST_GeomCollFromText](wkt, srid)
 }
diff --git 
a/spark/common/src/test/scala/org/apache/sedona/sql/constructorTestScala.scala 
b/spark/common/src/test/scala/org/apache/sedona/sql/constructorTestScala.scala
index d989eb611..aec9408f7 100644
--- 
a/spark/common/src/test/scala/org/apache/sedona/sql/constructorTestScala.scala
+++ 
b/spark/common/src/test/scala/org/apache/sedona/sql/constructorTestScala.scala
@@ -423,5 +423,18 @@ class constructorTestScala extends TestBaseScala {
       var mLineDf = sparkSession.sql("select 
ST_MPolyFromText('MULTIPOLYGON(((-70.916 42.1002,-70.9468 42.0946,-70.9765 
42.0872 )))',4269)")
       assert(mLineDf.count() == 1)
     }
+
+    it("Passed ST_GeomCollFromText") {
+      val baseDf = sparkSession.sql("SELECT 'GEOMETRYCOLLECTION (POINT (50 
50), LINESTRING (20 30, 40 60, 80 90), POLYGON ((30 10, 40 20, 30 20, 30 10), 
(35 15, 45 15, 40 25, 35 15)))' as geom, 4326 as srid")
+      var actual = 
baseDf.selectExpr("ST_GeomCollFromText(geom)").first().get(0).asInstanceOf[Geometry].toText
+      val expected = "GEOMETRYCOLLECTION (POINT (50 50), LINESTRING (20 30, 40 
60, 80 90), POLYGON ((30 10, 40 20, 30 20, 30 10), (35 15, 45 15, 40 25, 35 
15)))"
+      assert(expected.equals(actual))
+
+      val actualGeom = baseDf.selectExpr("ST_GeomCollFromText(geom, 
srid)").first().get(0).asInstanceOf[Geometry]
+      actual = actualGeom.toText
+      assert(expected.equals(actual))
+      val actualSrid = actualGeom.getSRID
+      assert(4326 == actualSrid)
+    }
   }
 }
diff --git 
a/spark/common/src/test/scala/org/apache/sedona/sql/dataFrameAPITestScala.scala 
b/spark/common/src/test/scala/org/apache/sedona/sql/dataFrameAPITestScala.scala
index 1fa25d270..5074707f6 100644
--- 
a/spark/common/src/test/scala/org/apache/sedona/sql/dataFrameAPITestScala.scala
+++ 
b/spark/common/src/test/scala/org/apache/sedona/sql/dataFrameAPITestScala.scala
@@ -246,6 +246,19 @@ class dataFrameAPITestScala extends TestBaseScala {
       assert(actualResult == expectedResult)
     }
 
+    it("Passed ST_GeomCollFromText") {
+      val df = sparkSession.sql("SELECT 'GEOMETRYCOLLECTION (POINT (50 50), 
LINESTRING (20 30, 40 60, 80 90), POLYGON ((30 10, 40 20, 30 20, 30 10), (35 
15, 45 15, 40 25, 35 15)))' as geom")
+      var actual = 
df.select(ST_GeomCollFromText("geom")).first().get(0).asInstanceOf[Geometry].toText
+      val expected = "GEOMETRYCOLLECTION (POINT (50 50), LINESTRING (20 30, 40 
60, 80 90), POLYGON ((30 10, 40 20, 30 20, 30 10), (35 15, 45 15, 40 25, 35 
15)))"
+      assert(expected == actual)
+
+      val actualGeom = df.select(ST_GeomCollFromText("geom", 
4326)).first().get(0).asInstanceOf[Geometry]
+      actual = actualGeom.toText
+      assert(actual == expected)
+      val actualSrid = actualGeom.getSRID
+      assert(4326 == actualSrid)
+    }
+
     it("passed st_geomfromgeohash") {
       val df = sparkSession.sql("SELECT 's00twy01mt' AS 
geohash").select(ST_GeomFromGeoHash("geohash", 4))
       val actualResult = df.take(1)(0).get(0).asInstanceOf[Geometry].toText()

Reply via email to