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

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


The following commit(s) were added to refs/heads/master by this push:
     new 85c83dd90 [SEDONA-590] [SEDONA-592] Add ST_GeomCollFromText, 
ST_MPointFromText (#1463)
85c83dd90 is described below

commit 85c83dd90a577d19132f1f0223466fecb33643fb
Author: Jia Yu <[email protected]>
AuthorDate: Fri Jun 7 13:17:39 2024 -0700

    [SEDONA-590] [SEDONA-592] Add ST_GeomCollFromText, ST_MPointFromText (#1463)
    
    * [TASK-238] Add ST_GeomCollFromText (#171)
    
    * Update version
    
    * [TASK-151] Add ST_MPointFromText (#174)
    
    * Update version
    
    ---------
    
    Co-authored-by: Furqaan Khan <[email protected]>
---
 .../org/apache/sedona/common/Constructors.java     | 16 +++++
 .../org/apache/sedona/common/ConstructorsTest.java | 31 ++++++++
 docs/api/flink/Constructor.md                      | 84 ++++++++++++++++++++++
 docs/api/snowflake/vector-data/Constructor.md      | 78 ++++++++++++++++++++
 docs/api/sql/Constructor.md                        | 84 ++++++++++++++++++++++
 .../main/java/org/apache/sedona/flink/Catalog.java |  2 +
 .../sedona/flink/expressions/Constructors.java     | 22 ++++++
 .../org/apache/sedona/flink/ConstructorTest.java   | 40 +++++++++++
 python/sedona/sql/st_constructors.py               | 30 ++++++++
 python/tests/sql/test_constructor_test.py          | 26 +++++++
 python/tests/sql/test_dataframe_api.py             | 27 ++++---
 .../sedona/snowflake/snowsql/TestConstructors.java | 29 ++++++++
 .../org/apache/sedona/snowflake/snowsql/UDFs.java  | 28 ++++++++
 .../scala/org/apache/sedona/sql/UDF/Catalog.scala  |  2 +
 .../sql/sedona_sql/expressions/Constructors.scala  | 16 +++++
 .../sedona_sql/expressions/st_constructors.scala   | 10 +++
 .../apache/sedona/sql/constructorTestScala.scala   | 26 +++++++
 .../apache/sedona/sql/dataFrameAPITestScala.scala  | 26 +++++++
 18 files changed, 568 insertions(+), 9 deletions(-)

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..910d650e5 100644
--- a/common/src/main/java/org/apache/sedona/common/Constructors.java
+++ b/common/src/main/java/org/apache/sedona/common/Constructors.java
@@ -92,6 +92,14 @@ public class Constructors {
         return geom;
     }
 
+    public static Geometry mPointFromText(String wkt, int srid) throws 
ParseException {
+        if (wkt == null || !wkt.startsWith("MULTIPOINT")) {
+            return null;
+        }
+        GeometryFactory geometryFactory = new GeometryFactory(new 
PrecisionModel(), srid);
+        return new WKTReader(geometryFactory).read(wkt);
+    }
+
     public static Geometry mLineFromText(String wkt, int srid) throws 
ParseException {
         if (wkt == null || !wkt.startsWith("MULTILINESTRING")) {
             return null;
@@ -108,6 +116,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..2aaa51d20 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,37 @@ public class ConstructorsTest {
 
     }
 
+    @Test
+    public void mPointFromText() throws ParseException {
+        assertNull(Constructors.mPointFromText(null, 0));
+        assertNull(Constructors.mPointFromText("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.mPointFromText("MULTIPOINT ((10 10), (20 
20), (30 30))", 0);
+        assertEquals(0,geom.getSRID());
+        assertEquals("MULTIPOINT ((10 10), (20 20), (30 30))",geom.toText());
+
+        geom = Constructors.mPointFromText("MULTIPOINT ((10 10), (20 20), (30 
30))", 3306);
+        assertEquals(3306,geom.getSRID());
+        assertEquals("MULTIPOINT ((10 10), (20 20), (30 30))"
+                ,geom.toText());
+    }
+
+    @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..0e63af55b 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: `v1.6.1`
+
+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: `v1.6.1`
+
+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
@@ -406,6 +466,30 @@ Output:
 MULTILINESTRING ((1 2, 3 4), (4 5, 6 7))
 ```
 
+## ST_MPointFromText
+
+Introduction: Constructs a MultiPoint 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 `MULTIPOINT`.
+
+Format:
+
+`ST_MPointFromText (Wkt: String)`
+
+`ST_MPointFromText (Wkt: String, srid: Integer)`
+
+Since: `v1.6.1`
+
+SQL Example:
+
+```sql
+SELECT ST_MPointFromText('MULTIPOINT ((10 10), (20 20), (30 30))')
+```
+
+Output:
+
+```
+MULTIPOINT ((10 10), (20 20), (30 30))
+```
+
 ## ST_MPolyFromText
 
 Introduction: Construct a MultiPolygon from Text and Optional SRID
diff --git a/docs/api/snowflake/vector-data/Constructor.md 
b/docs/api/snowflake/vector-data/Constructor.md
index f35972a30..feff729e6 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
@@ -374,6 +430,28 @@ Output:
 MULTILINESTRING ((1 2, 3 4), (4 5, 6 7))
 ```
 
+## ST_MPointFromText
+
+Introduction: Constructs a MultiPoint 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 `MULTIPOINT`.
+
+Format:
+
+`ST_MPointFromText (Wkt: String)`
+
+`ST_MPointFromText (Wkt: String, srid: Integer)`
+
+SQL Example:
+
+```sql
+SELECT ST_MPointFromText('MULTIPOINT ((10 10), (20 20), (30 30))')
+```
+
+Output:
+
+```
+MULTIPOINT ((10 10), (20 20), (30 30))
+```
+
 ## ST_MPolyFromText
 
 Introduction: Construct a MultiPolygon from Wkt. If srid is not set, it 
defaults to 0 (unknown).
diff --git a/docs/api/sql/Constructor.md b/docs/api/sql/Constructor.md
index e3ca74631..33a5947ae 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: `v1.6.1`
+
+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: `v1.6.1`
+
+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
@@ -461,6 +521,30 @@ Output:
 MULTILINESTRING ((1 2, 3 4), (4 5, 6 7))
 ```
 
+## ST_MPointFromText
+
+Introduction: Constructs a MultiPoint 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 `MULTIPOINT`.
+
+Format:
+
+`ST_MPointFromText (Wkt: String)`
+
+`ST_MPointFromText (Wkt: String, srid: Integer)`
+
+Since: `v1.6.1`
+
+SQL Example:
+
+```sql
+SELECT ST_MPointFromText('MULTIPOINT ((10 10), (20 20), (30 30))')
+```
+
+Output:
+
+```
+MULTIPOINT ((10 10), (20 20), (30 30))
+```
+
 ## ST_MPolyFromText
 
 Introduction: Construct a MultiPolygon from Wkt. If srid is not set, it 
defaults to 0 (unknown).
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..0241d4032 100644
--- a/flink/src/main/java/org/apache/sedona/flink/Catalog.java
+++ b/flink/src/main/java/org/apache/sedona/flink/Catalog.java
@@ -45,8 +45,10 @@ public class Catalog {
                 new Constructors.ST_GeomFromGeoHash(),
                 new Constructors.ST_GeomFromGML(),
                 new Constructors.ST_GeomFromKML(),
+                new Constructors.ST_MPointFromText(),
                 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..3b4778f68 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,26 @@ public class Constructors {
         }
     }
 
+    public static class ST_MPointFromText 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.mPointFromText(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.mPointFromText(wkt, 
0);
+        }
+    }
+
+    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..bd39f758f 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,44 @@ public class ConstructorTest extends TestBase{
         String expectedGeom = "MULTILINESTRING ((1 2, 3 4), (4 5, 6 7))";
         assertEquals(expectedGeom, result);
     }
+
+    @Test
+    public void testMPointFromText() {
+        Table tbl = tableEnv.sqlQuery("SELECT 'MULTIPOINT ((10 10), (20 20), 
(30 30))' AS coll, 4326 as srid");
+        String actualColl = first(
+                
tbl.select(call(Constructors.ST_MPointFromText.class.getSimpleName(), 
$("coll")))
+        ).getFieldAs(0).toString();
+        String expectedColl = "MULTIPOINT ((10 10), (20 20), (30 30))";
+        assertEquals(expectedColl, actualColl);
+
+        actualColl = first(
+                
tbl.select(call(Constructors.ST_MPointFromText.class.getSimpleName(), 
$("coll"), $("srid")))
+        ).getFieldAs(0).toString();
+        assertEquals(expectedColl, actualColl);
+        int actualSrid = first(
+                
tbl.select(call(Constructors.ST_MPointFromText.class.getSimpleName(), 
$("coll"), $("srid")))
+                        
.as("geom").select(call(Functions.ST_SRID.class.getSimpleName(), $("geom")))
+        ).getFieldAs(0);
+        assertEquals(4326, actualSrid);
+    }
+
+    @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..3842d72d2 100644
--- a/python/sedona/sql/st_constructors.py
+++ b/python/sedona/sql/st_constructors.py
@@ -395,3 +395,33 @@ 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_MPointFromText(wkt: ColumnOrName, srid: Optional[ColumnOrNameOrNumber] 
= None) -> Column:
+    """Generate MultiPoint geometry from a MultiPoint WKT representation.
+
+    :param wkt: MultiPoint WKT string column to generate from.
+    :type wkt: ColumnOrName
+    :param srid: SRID for the geometry
+    :type srid: ColumnOrNameOrNumber
+    :return: MultiPoint geometry generated from the wkt column.
+    :rtype: Column
+    """
+    args = (wkt) if srid is None else (wkt, srid)
+
+    return _call_constructor_function("ST_MPointFromText", 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..91ea7802e 100644
--- a/python/tests/sql/test_constructor_test.py
+++ b/python/tests/sql/test_constructor_test.py
@@ -190,3 +190,29 @@ 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_mpoint_from_text(self):
+        baseDf = self.spark.sql("SELECT 'MULTIPOINT ((10 10), (20 20), (30 
30))' as geom, 4326 as srid")
+        actual = 
baseDf.selectExpr("ST_AsText(ST_MPointFromText(geom))").take(1)[0][0]
+        expected = 'MULTIPOINT ((10 10), (20 20), (30 30))'
+        assert expected == actual
+
+        actualGeom = baseDf.selectExpr("ST_MPointFromText(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
+
+    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..bdee4108b 100644
--- a/python/tests/sql/test_dataframe_api.py
+++ b/python/tests/sql/test_dataframe_api.py
@@ -60,16 +60,16 @@ test_configurations = [
     (stc.ST_MPolyFromText, ("mpoly", 4326), "constructor", "" , "MULTIPOLYGON 
(((0 0, 20 0, 20 20, 0 20, 0 0), (5 5, 5 7, 7 7, 7 5, 5 5)))"),
     (stc.ST_MLineFromText, ("mline", ), "constructor", "" , "MULTILINESTRING 
((1 2, 3 4), (4 5, 6 7))"),
     (stc.ST_MLineFromText, ("mline", 4326), "constructor", "" , 
"MULTILINESTRING ((1 2, 3 4), (4 5, 6 7))"),
-    (stc.ST_PointM, ("x", "y", "m", "srid"), "x_y_z_m_srid", 
"ST_AsEWKT(geom)", "SRID=4326;POINT ZM(1 2 0 100.9)"),
-    (stc.ST_PointZM, ("x", "y", "z", "m", "srid"), "x_y_z_m_srid", "", "POINT 
Z (1 2 3)"),
-    (stc.ST_PointFromGeoHash, ("geohash", 4), "constructor", 
"ST_ReducePrecision(geom, 2)", "POINT (0.88 0.97)"),
-    (stc.ST_PointFromGeoHash, ("geohash",), "constructor", 
"ST_ReducePrecision(geom, 2)", "POINT (1 1)"),
+    (stc.ST_MPointFromText, ("mpoint", ), "constructor", "" , "MULTIPOINT (10 
10, 20 20, 30 30)"),
+    (stc.ST_MPointFromText, ("mpoint", 4326), "constructor", "" , "MULTIPOINT 
(10 10, 20 20, 30 30)"),
     (stc.ST_PointFromText, ("single_point", lambda: f.lit(',')), 
"constructor", "", "POINT (0 1)"),
     (stc.ST_PointFromWKB, ("wkbPoint",), "constructor", "", "POINT (10 15)"),
     (stc.ST_MakePoint, ("x", "y", "z"), "constructor", "", "POINT Z (0 1 2)"),
     (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"),
@@ -262,12 +262,15 @@ wrong_type_configurations = [
     (stc.ST_PointFromText, (None, "")),
     (stc.ST_PointFromText, ("", None)),
     (stc.ST_PointFromWKB, (None,)),
+    (stc.ST_MPointFromText, (None,)),
     (stc.ST_PolygonFromEnvelope, (None, "", "", "")),
     (stc.ST_PolygonFromEnvelope, ("", None, "", "")),
     (stc.ST_PolygonFromEnvelope, ("", "", None, "")),
     (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, "")),
@@ -437,13 +440,16 @@ class TestDataFrameAPI(TestBase):
 
     @pytest.fixture
     def base_df(self, request):
-        mpoly = 'MULTIPOLYGON(((0 0 ,20 0 ,20 20 ,0 20 ,0 0 ),(5 5 ,5 7 ,7 7 
,7 5 ,5 5)))'
-        mline = 'MULTILINESTRING((1 2, 3 4), (4 5, 6 7))'
         wkbLine = 
'0102000000020000000000000084d600c00000000080b5d6bf00000060e1eff7bf00000080075de5bf'
         wkbPoint = '010100000000000000000024400000000000002e40'
+        wkb = 
'0102000000020000000000000084d600c00000000080b5d6bf00000060e1eff7bf00000080075de5bf'
+        mpoly = 'MULTIPOLYGON(((0 0 ,20 0 ,20 20 ,0 20 ,0 0 ),(5 5 ,5 7 ,7 7 
,7 5 ,5 5)))'
+        mline = 'MULTILINESTRING((1 2, 3 4), (4 5, 6 7))'
+        mpoint = 'MULTIPOINT ((10 10), (20 20), (30 30))'
         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(
@@ -452,14 +458,17 @@ class TestDataFrameAPI(TestBase):
                 "2.0 AS z",
                 "'0.0,1.0' AS single_point",
                 "'0.0,0.0,1.0,0.0,1.0,1.0,0.0,0.0' AS multiple_point",
-                f"'{mpoly}' AS mpoly",
-                f"'{mline}' AS mline",
                 f"X'{wkbLine}' AS wkbLine",
                 f"X'{wkbPoint}' AS wkbPoint",
+                f"X'{wkb}' AS wkb",
+                f"'{mpoly}' AS mpoly",
+                f"'{mline}' AS mline",
+                f"'{mpoint}' AS mpoint",
                 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..c6b8b2ba1 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,35 @@ 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_MPointFromText() {
+        registerUDF("ST_MPointFromText", String.class);
+        registerUDF("ST_SRID", byte[].class);
+        verifySqlSingleRes(
+                "select sedona.ST_AsText(sedona.ST_MPointFromText('MULTIPOINT 
((10 10), (20 20), (30 30))'))",
+                "MULTIPOINT ((10 10), (20 20), (30 30))"
+        );
+        registerUDF("ST_MPointFromText", String.class, int.class);
+        verifySqlSingleRes(
+                "select sedona.ST_SRID(sedona.ST_MPointFromText('MULTIPOINT 
((10 10), (20 20), (30 30))',4269))",
+                4269
+        );
+    }
+
+    @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..fa498697a 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,34 @@ public class UDFs {
         );
     }
 
+    @UDFAnnotations.ParamMeta(argNames = {"wkt", "srid"})
+    public static byte[] ST_MPointFromText(String wkt, int srid) throws 
ParseException {
+        return GeometrySerde.serialize(
+                Constructors.mPointFromText(wkt, srid)
+        );
+    }
+
+    @UDFAnnotations.ParamMeta(argNames = {"wkt"})
+    public static byte[] ST_MPointFromText(String wkt) throws ParseException {
+        return GeometrySerde.serialize(
+                Constructors.mPointFromText(wkt, 0)
+        );
+    }
+
+    @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..42babb795 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
@@ -180,8 +180,10 @@ object Catalog {
     function[ST_CollectionExtract](defaultArgs = null),
     function[ST_Normalize](),
     function[ST_LineFromMultiPoint](),
+    function[ST_MPointFromText](0),
     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..d192df654 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,19 @@ case class ST_MLineFromText(inputExpressions: 
Seq[Expression])
     copy(inputExpressions = newChildren)
   }
 }
+
+case class ST_MPointFromText(inputExpressions: Seq[Expression])
+  extends InferredExpression(Constructors.mPointFromText _) {
+
+  protected def withNewChildrenInternal(newChildren: IndexedSeq[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..6002e8c9a 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,14 @@ 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)
+
+  def ST_MPointFromText(wkt: Column): Column = 
wrapExpression[ST_MPointFromText](wkt, 0)
+  def ST_MPointFromText(wkt: String): Column = 
wrapExpression[ST_MPointFromText](wkt, 0)
+  def ST_MPointFromText(wkt: Column, srid: Column): Column = 
wrapExpression[ST_MPointFromText](wkt, srid)
+  def ST_MPointFromText(wkt: String, srid: Int): Column = 
wrapExpression[ST_MPointFromText](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..66a94dae6 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,31 @@ 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_MPointFromText") {
+      val baseDf = sparkSession.sql("SELECT 'MULTIPOINT ((10 10), (20 20), (30 
30))' as geom, 4326 as srid")
+      var actual = 
baseDf.selectExpr("ST_MPointFromText(geom)").first().get(0).asInstanceOf[Geometry].toText
+      val expected = "MULTIPOINT ((10 10), (20 20), (30 30))"
+      assert(expected.equals(actual))
+
+      val actualGeom = baseDf.selectExpr("ST_MPointFromText(geom, 
srid)").first().get(0).asInstanceOf[Geometry]
+      actual = actualGeom.toText
+      assert(expected.equals(actual))
+      val actualSrid = actualGeom.getSRID
+      assert(4326 == actualSrid)
+    }
+
+    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..94a2a6059 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,32 @@ class dataFrameAPITestScala extends TestBaseScala {
       assert(actualResult == expectedResult)
     }
 
+    it("Passed ST_MPointFromText()") {
+      val df = sparkSession.sql("SELECT 'MULTIPOINT ((10 10), (20 20), (30 
30))' as geom")
+      var actual = 
df.select(ST_MPointFromText("geom")).first().get(0).asInstanceOf[Geometry].toText
+      val expected = "MULTIPOINT ((10 10), (20 20), (30 30))"
+      assert(expected == actual)
+
+      val actualGeom = df.select(ST_MPointFromText("geom", 
4326)).first().get(0).asInstanceOf[Geometry]
+      actual = actualGeom.toText
+      assert(actual == expected)
+      val actualSrid = actualGeom.getSRID
+      assert(4326 == actualSrid)
+    }
+
+    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