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 a85373670 [SEDONA-576] Add ST_HasZ (#1450)
a85373670 is described below
commit a8537367066779312e0006e78a46f4b449a6366e
Author: Jia Yu <[email protected]>
AuthorDate: Sat Jun 1 23:40:22 2024 -0700
[SEDONA-576] Add ST_HasZ (#1450)
* feat: add ST_HasZ
* fix: type
* fix: typo
* fix: snowflake tests
* fix: old broken snowflake tests
* fix: old broken snowflake tests
* fix: old broken snowflake tests
Co-authored-by: Furqaan Khan <[email protected]>
---
.../java/org/apache/sedona/common/Functions.java | 5 +++++
.../org/apache/sedona/common/FunctionsTest.java | 15 +++++++++++++++
docs/api/flink/Function.md | 22 ++++++++++++++++++++++
docs/api/snowflake/vector-data/Function.md | 20 ++++++++++++++++++++
docs/api/sql/Function.md | 22 ++++++++++++++++++++++
.../main/java/org/apache/sedona/flink/Catalog.java | 1 +
.../apache/sedona/flink/expressions/Functions.java | 8 ++++++++
.../java/org/apache/sedona/flink/FunctionTest.java | 7 +++++++
python/sedona/sql/st_functions.py | 11 +++++++++++
python/tests/sql/test_dataframe_api.py | 2 ++
python/tests/sql/test_function.py | 5 +++++
.../sedona/snowflake/snowsql/TestFunctions.java | 16 ++++++++++++----
.../sedona/snowflake/snowsql/TestFunctionsV2.java | 9 +++++++++
.../org/apache/sedona/snowflake/snowsql/UDFs.java | 7 +++++++
.../apache/sedona/snowflake/snowsql/UDFsV2.java | 7 +++++++
.../scala/org/apache/sedona/sql/UDF/Catalog.scala | 1 +
.../sql/sedona_sql/expressions/Functions.scala | 8 ++++++++
.../sql/sedona_sql/expressions/st_functions.scala | 3 +++
.../apache/sedona/sql/dataFrameAPITestScala.scala | 6 ++++++
.../org/apache/sedona/sql/functionTestScala.scala | 6 ++++++
20 files changed, 177 insertions(+), 4 deletions(-)
diff --git a/common/src/main/java/org/apache/sedona/common/Functions.java
b/common/src/main/java/org/apache/sedona/common/Functions.java
index 774a2bfe3..79be14b83 100644
--- a/common/src/main/java/org/apache/sedona/common/Functions.java
+++ b/common/src/main/java/org/apache/sedona/common/Functions.java
@@ -483,6 +483,11 @@ public class Functions {
return !Double.isNaN(coord.getM());
}
+ public static boolean hasZ(Geometry geom) {
+ Coordinate coord = geom.getCoordinate();
+ return !Double.isNaN(coord.getZ());
+ }
+
public static Geometry flipCoordinates(Geometry geometry) {
GeomUtils.flipCoordinates(geometry);
return geometry;
diff --git a/common/src/test/java/org/apache/sedona/common/FunctionsTest.java
b/common/src/test/java/org/apache/sedona/common/FunctionsTest.java
index 4fe7d1578..700ebeef3 100644
--- a/common/src/test/java/org/apache/sedona/common/FunctionsTest.java
+++ b/common/src/test/java/org/apache/sedona/common/FunctionsTest.java
@@ -408,6 +408,21 @@ public class FunctionsTest extends TestBase {
assertEquals(actualResult, expectedResult);
}
+ @Test
+ public void hasZ() throws ParseException {
+ Geometry geom = Constructors.geomFromWKT("POINT ZM(1 2 3 4)", 0);
+ assertTrue(Functions.hasZ(geom));
+
+ geom = Constructors.geomFromWKT("POINT(1 2)", 0);
+ assertFalse(Functions.hasZ(geom));
+
+ geom = Constructors.geomFromWKT("POINT(34 25)", 0);
+ assertFalse(Functions.hasZ(geom));
+
+ geom = Constructors.geomFromWKT("POLYGON ZM ((30 10 5 1, 40 40 10 2,
20 40 15 3, 10 20 20 4, 30 10 5 1))", 0);
+ assertTrue(Functions.hasZ(geom));
+ }
+
@Test
public void hasM() throws ParseException {
Geometry geom = Constructors.geomFromWKT("POINT ZM(1 2 3 4)", 0);
diff --git a/docs/api/flink/Function.md b/docs/api/flink/Function.md
index 28726f8b6..38b631e5a 100644
--- a/docs/api/flink/Function.md
+++ b/docs/api/flink/Function.md
@@ -1574,6 +1574,28 @@ Output:
True
```
+## ST_HasZ
+
+Introduction: Checks for the presence of Z coordinate values representing
measures or linear references. Returns true if the input geometry includes an Z
coordinate, false otherwise.
+
+Format: `ST_HasZ(geom: Geometry)`
+
+Since: `vTBD`
+
+SQL Example
+
+```sql
+SELECT ST_HasZ(
+ ST_GeomFromWKT('LINESTRING Z (30 10 5, 40 40 10, 20 40 15, 10 20 20)')
+)
+```
+
+Output:
+
+```
+True
+```
+
## ST_HausdorffDistance
Introduction: Returns a discretized (and hence approximate) [Hausdorff
distance](https://en.wikipedia.org/wiki/Hausdorff_distance) between the given 2
geometries.
diff --git a/docs/api/snowflake/vector-data/Function.md
b/docs/api/snowflake/vector-data/Function.md
index 54afc40d6..bda335535 100644
--- a/docs/api/snowflake/vector-data/Function.md
+++ b/docs/api/snowflake/vector-data/Function.md
@@ -1125,6 +1125,26 @@ SELECT ST_GeometryType(polygondf.countyshape)
FROM polygondf
```
+## ST_HasZ
+
+Introduction: Checks for the presence of Z coordinate values representing
measures or linear references. Returns true if the input geometry includes an Z
coordinate, false otherwise.
+
+Format: `ST_HasZ(geom: Geometry)`
+
+SQL Example
+
+```sql
+SELECT ST_HasZ(
+ ST_GeomFromWKT('LINESTRING Z (30 10 5, 40 40 10, 20 40 15, 10 20 20)')
+)
+```
+
+Output:
+
+```
+True
+```
+
## ST_HausdorffDistance
Introduction: Returns a discretized (and hence approximate) [Hausdorff
distance](https://en.wikipedia.org/wiki/Hausdorff_distance) between the given 2
geometries.
diff --git a/docs/api/sql/Function.md b/docs/api/sql/Function.md
index a09573fa3..b8080dfd2 100644
--- a/docs/api/sql/Function.md
+++ b/docs/api/sql/Function.md
@@ -1580,6 +1580,28 @@ Output:
True
```
+## ST_HasZ
+
+Introduction: Checks for the presence of Z coordinate values representing
measures or linear references. Returns true if the input geometry includes an Z
coordinate, false otherwise.
+
+Format: `ST_HasZ(geom: Geometry)`
+
+Since: `vTBD`
+
+SQL Example
+
+```sql
+SELECT ST_HasZ(
+ ST_GeomFromWKT('LINESTRING Z (30 10 5, 40 40 10, 20 40 15, 10 20 20)')
+)
+```
+
+Output:
+
+```
+True
+```
+
## ST_HausdorffDistance
Introduction: Returns a discretized (and hence approximate) [Hausdorff
distance](https://en.wikipedia.org/wiki/Hausdorff_distance) between the given 2
geometries.
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 234e58b59..05ed2d35d 100644
--- a/flink/src/main/java/org/apache/sedona/flink/Catalog.java
+++ b/flink/src/main/java/org/apache/sedona/flink/Catalog.java
@@ -128,6 +128,7 @@ public class Catalog {
new Functions.ST_LineFromMultiPoint(),
new Functions.ST_LineMerge(),
new Functions.ST_LineSubstring(),
+ new Functions.ST_HasZ(),
new Functions.ST_HasM(),
new Functions.ST_M(),
new Functions.ST_MMin(),
diff --git
a/flink/src/main/java/org/apache/sedona/flink/expressions/Functions.java
b/flink/src/main/java/org/apache/sedona/flink/expressions/Functions.java
index 7397087c5..001cbb627 100644
--- a/flink/src/main/java/org/apache/sedona/flink/expressions/Functions.java
+++ b/flink/src/main/java/org/apache/sedona/flink/expressions/Functions.java
@@ -757,6 +757,14 @@ public class Functions {
}
}
+ public static class ST_HasZ extends ScalarFunction {
+ @DataTypeHint("Boolean")
+ public Boolean eval(@DataTypeHint(value = "RAW", bridgedTo =
org.locationtech.jts.geom.Geometry.class) Object o) {
+ Geometry geom = (Geometry) o;
+ return org.apache.sedona.common.Functions.hasZ(geom);
+ }
+ }
+
public static class ST_M extends ScalarFunction {
@DataTypeHint("Double")
public Double eval(@DataTypeHint(value = "RAW", bridgedTo =
org.locationtech.jts.geom.Geometry.class) Object o) {
diff --git a/flink/src/test/java/org/apache/sedona/flink/FunctionTest.java
b/flink/src/test/java/org/apache/sedona/flink/FunctionTest.java
index 9d4d6bb79..99781c4d1 100644
--- a/flink/src/test/java/org/apache/sedona/flink/FunctionTest.java
+++ b/flink/src/test/java/org/apache/sedona/flink/FunctionTest.java
@@ -699,6 +699,13 @@ public class FunctionTest extends TestBase{
assertEquals(7.89, first(pointTable).getField(0));
}
+ @Test
+ public void testHasZ() {
+ Table polyTable = tableEnv.sqlQuery("SELECT ST_GeomFromWKT('POLYGON ZM
((30 10 5 1, 40 40 10 2, 20 40 15 3, 10 20 20 4, 30 10 5 1))') as poly");
+ boolean actual = (boolean)
first(polyTable.select(call(Functions.ST_HasZ.class.getSimpleName(),
$("poly")))).getField(0);
+ assertTrue(actual);
+ }
+
@Test
public void testHasM() {
Table polyTable = tableEnv.sqlQuery("SELECT ST_GeomFromWKT('POLYGON ZM
((30 10 5 1, 40 40 10 2, 20 40 15 3, 10 20 20 4, 30 10 5 1))') as poly");
diff --git a/python/sedona/sql/st_functions.py
b/python/sedona/sql/st_functions.py
index 07814947a..f65141f95 100644
--- a/python/sedona/sql/st_functions.py
+++ b/python/sedona/sql/st_functions.py
@@ -857,6 +857,17 @@ def ST_LineSubstring(line_string: ColumnOrName,
start_fraction: ColumnOrNameOrNu
"""
return _call_st_function("ST_LineSubstring", (line_string, start_fraction,
end_fraction))
+@validate_argument_types
+def ST_HasZ(geom: ColumnOrName) -> Column:
+ """Check whether geometry has Z coordinate
+
+ :param geom: Geometry
+ :type geom: ColumnOrName
+ :return: True if geometry has Z coordinate, else False
+ :rtype: Column
+ """
+ return _call_st_function("ST_HasZ", geom)
+
@validate_argument_types
def ST_HasM(geom: ColumnOrName) -> Column:
"""Check whether geometry has M coordinate
diff --git a/python/tests/sql/test_dataframe_api.py
b/python/tests/sql/test_dataframe_api.py
index 420a26ed1..f88818ea7 100644
--- a/python/tests/sql/test_dataframe_api.py
+++ b/python/tests/sql/test_dataframe_api.py
@@ -148,6 +148,7 @@ test_configurations = [
(stf.ST_LineLocatePoint, ("line", "point"), "line_and_point", "", 0.5),
(stf.ST_LineMerge, ("geom",), "multiline_geom", "", "LINESTRING (0 0, 1 0,
1 1, 0 0)"),
(stf.ST_LineSubstring, ("line", 0.5, 1.0), "linestring_geom", "",
"LINESTRING (2.5 0, 3 0, 4 0, 5 0)"),
+ (stf.ST_HasZ, ("a",), "two_points", "", True),
(stf.ST_HasM, ("point",), "4D_point", "", True),
(stf.ST_M, ("point",), "4D_point", "", 4.0),
(stf.ST_MMin, ("line",), "4D_line", "", -1.0),
@@ -322,6 +323,7 @@ wrong_type_configurations = [
(stf.ST_LineSubstring, (None, 0.5, 1.0)),
(stf.ST_LineSubstring, ("", None, 1.0)),
(stf.ST_LineSubstring, ("", 0.5, None)),
+ (stf.ST_HasZ, (None,)),
(stf.ST_HasM, (None,)),
(stf.ST_M, (None,)),
(stf.ST_MMin, (None,)),
diff --git a/python/tests/sql/test_function.py
b/python/tests/sql/test_function.py
index 1df5e8508..0d6bde534 100644
--- a/python/tests/sql/test_function.py
+++ b/python/tests/sql/test_function.py
@@ -931,6 +931,11 @@ class TestPredicateJoin(TestBase):
# Then
assert subdivided.count() == 16
+ def test_st_has_z(self):
+ baseDf = self.spark.sql("SELECT ST_GeomFromWKT('POLYGON Z ((30 10 5,
40 40 10, 20 40 15, 10 20 20, 30 10 5))') as poly")
+ actual = baseDf.selectExpr("ST_HasZ(poly)")
+ assert actual
+
def test_st_has_m(self):
baseDf = self.spark.sql("SELECT ST_GeomFromWKT('POLYGON ZM ((30 10 5
1, 40 40 10 2, 20 40 15 3, 10 20 20 4, 30 10 5 1))') as poly")
actual = baseDf.selectExpr("ST_HasM(poly)")
diff --git
a/snowflake-tester/src/test/java/org/apache/sedona/snowflake/snowsql/TestFunctions.java
b/snowflake-tester/src/test/java/org/apache/sedona/snowflake/snowsql/TestFunctions.java
index a83645497..c682c869f 100644
---
a/snowflake-tester/src/test/java/org/apache/sedona/snowflake/snowsql/TestFunctions.java
+++
b/snowflake-tester/src/test/java/org/apache/sedona/snowflake/snowsql/TestFunctions.java
@@ -192,10 +192,9 @@ public class TestFunctions extends TestBase {
);
registerUDF("ST_Buffer", byte[].class, double.class, boolean.class);
registerUDF("ST_ReducePrecision", byte[].class, int.class);
- registerUDF("ST_Area", byte[].class);
verifySqlSingleRes(
- "select
sedona.ST_Area(sedona.ST_ReducePrecision(sedona.ST_GeomFromText(sedona.ST_AsText(sedona.ST_Buffer(sedona.ST_GeomFromText('LINESTRING(0.05
15, -0.05 15)'), 10000, true))), 8))",
- 0.04424254827358593
+ "select
sedona.ST_AsText(sedona.ST_ReducePrecision(sedona.ST_Buffer(sedona.ST_GeomFromText('LINESTRING(5
15, -5 15)'), 100, true), 4))",
+ "POLYGON ((-5.0002 14.9991, -5.0003 14.9992, -5.0005 14.9993,
-5.0006 14.9994, -5.0007 14.9995, -5.0008 14.9997, -5.0009 14.9998, -5.0009 15,
-5.0009 15.0002, -5.0008 15.0003, -5.0007 15.0005, -5.0006 15.0006, -5.0005
15.0007, -5.0003 15.0008, -5.0002 15.0009, -5 15.0009, 5 15.0009, 5.0002
15.0009, 5.0003 15.0008, 5.0005 15.0007, 5.0006 15.0006, 5.0007 15.0005, 5.0008
15.0003, 5.0009 15.0002, 5.0009 15, 5.0009 14.9998, 5.0008 14.9997, 5.0007
14.9995, 5.0006 14.9994, 5.000 [...]
);
}
@@ -409,6 +408,15 @@ public class TestFunctions extends TestBase {
);
}
+ @Test
+ public void test_ST_HasZ() {
+ registerUDF("ST_HasZ", byte[].class);
+ verifySqlSingleRes(
+ "SELECT sedona.ST_HasZ(sedona.ST_GeomFromText('POINT Z(1 2
3)'))",
+ true
+ );
+ }
+
@Test
public void test_ST_HausdorffDistance() {
registerUDF("ST_HausdorffDistance", byte[].class, byte[].class);
@@ -831,7 +839,7 @@ public class TestFunctions extends TestBase {
public void test_ST_Snap() {
registerUDF("ST_Snap", byte[].class, byte[].class, double.class);
verifySqlSingleRes(
- "SELECT
sedona.ST_AsText(sedona.ST_Snap(sedona.ST_GeomFromText('POLYGON((2.6 12.5, 2.6
20.0, 12.6 20.0, 12.6 12.5, 2.6 12.5 ))'), sedona.ST_GeomFromText('LINESTRING
(0.5 10.7, 5.4 8.4, 10.1 10.0)'), 2.525))",
+ "SELECT
sedona.ST_AsText(sedona.ST_Snap(sedona.ST_GeomFromWKT('POLYGON((2.6 12.5, 2.6
20.0, 12.6 20.0, 12.6 12.5, 2.6 12.5 ))'), sedona.ST_GeomFromWKT('LINESTRING
(0.5 10.7, 5.4 8.4, 10.1 10.0)'), 2.525))",
"POLYGON ((2.6 12.5, 2.6 20, 12.6 20, 12.6 12.5, 10.1 10, 2.6
12.5))"
);
}
diff --git
a/snowflake-tester/src/test/java/org/apache/sedona/snowflake/snowsql/TestFunctionsV2.java
b/snowflake-tester/src/test/java/org/apache/sedona/snowflake/snowsql/TestFunctionsV2.java
index 299cbcdc9..0be3705c1 100644
---
a/snowflake-tester/src/test/java/org/apache/sedona/snowflake/snowsql/TestFunctionsV2.java
+++
b/snowflake-tester/src/test/java/org/apache/sedona/snowflake/snowsql/TestFunctionsV2.java
@@ -400,6 +400,15 @@ public class TestFunctionsV2
);
}
+ @Test
+ public void test_ST_HasZ() {
+ registerUDFV2("ST_HasZ", String.class);
+ verifySqlSingleRes(
+ "SELECT sedona.ST_HasZ(ST_GeomFromText('POINT Z(1 2 3)'))",
+ true
+ );
+ }
+
@Test
public void test_ST_HausdorffDistance() {
registerUDFV2("ST_HausdorffDistance", String.class, String.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 a4ed232b6..d5f2d4a82 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
@@ -547,6 +547,13 @@ public class UDFs {
);
}
+ @UDFAnnotations.ParamMeta(argNames = {"geometry"})
+ public static boolean ST_HasZ(byte[] geometry) {
+ return Functions.hasZ(
+ GeometrySerde.deserialize(geometry)
+ );
+ }
+
@UDFAnnotations.ParamMeta(argNames = {"geom1", "geom2"})
public static double ST_HausdorffDistance(byte[] geom1, byte[] geom2)
{
diff --git
a/snowflake/src/main/java/org/apache/sedona/snowflake/snowsql/UDFsV2.java
b/snowflake/src/main/java/org/apache/sedona/snowflake/snowsql/UDFsV2.java
index 08bad21ec..b5b485757 100644
--- a/snowflake/src/main/java/org/apache/sedona/snowflake/snowsql/UDFsV2.java
+++ b/snowflake/src/main/java/org/apache/sedona/snowflake/snowsql/UDFsV2.java
@@ -478,6 +478,13 @@ public class UDFsV2
);
}
+ @UDFAnnotations.ParamMeta(argNames = {"geometry"}, argTypes = {"Geometry"})
+ public static boolean ST_HasZ(String geometry) {
+ return Functions.hasZ(
+ GeometrySerde.deserGeoJson(geometry)
+ );
+ }
+
@UDFAnnotations.ParamMeta(argNames = {"geom1", "geom2"}, argTypes =
{"Geometry", "Geometry"})
public static double ST_HausdorffDistance(String geom1, String geom2)
{
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 a411f67b7..05c0b7de8 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
@@ -114,6 +114,7 @@ object Catalog {
function[ST_Snap](),
function[ST_ClosestPoint](),
function[ST_Boundary](),
+ function[ST_HasZ](),
function[ST_HasM](),
function[ST_M](),
function[ST_MMin](),
diff --git
a/spark/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/Functions.scala
b/spark/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/Functions.scala
index 21613b37c..b4cb02502 100644
---
a/spark/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/Functions.scala
+++
b/spark/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/Functions.scala
@@ -511,6 +511,14 @@ case class ST_MinimumBoundingCircle(inputExpressions:
Seq[Expression])
}
}
+case class ST_HasZ(inputExpressions: Seq[Expression])
+ extends InferredExpression(Functions.hasZ _) {
+
+ protected def withNewChildrenInternal(newChildren: IndexedSeq[Expression]) =
{
+ copy(inputExpressions = newChildren)
+ }
+}
+
case class ST_HasM(inputExpressions: Seq[Expression])
extends InferredExpression(Functions.hasM _) {
diff --git
a/spark/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/st_functions.scala
b/spark/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/st_functions.scala
index 65cec5a29..b93aeb972 100644
---
a/spark/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/st_functions.scala
+++
b/spark/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/st_functions.scala
@@ -212,6 +212,9 @@ object st_functions extends DataFrameAPI {
def ST_LineSubstring(lineString: Column, startFraction: Column, endFraction:
Column): Column = wrapExpression[ST_LineSubstring](lineString, startFraction,
endFraction)
def ST_LineSubstring(lineString: String, startFraction: Double, endFraction:
Double): Column = wrapExpression[ST_LineSubstring](lineString, startFraction,
endFraction)
+ def ST_HasZ(geoms: Column): Column = wrapExpression[ST_HasZ](geoms)
+ def ST_HasZ(geoms: String): Column = wrapExpression[ST_HasZ](geoms)
+
def ST_HasM(geoms: Column): Column = wrapExpression[ST_HasM](geoms)
def ST_HasM(geoms: String): Column = wrapExpression[ST_HasM](geoms)
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 70e7201dd..daf7c1ee5 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
@@ -52,6 +52,12 @@ class dataFrameAPITestScala extends TestBaseScala {
assert(actualResult == expectedResult)
}
+ it("Passed ST_HasZ") {
+ val baseDf = sparkSession.sql("SELECT ST_GeomFromWKT('POLYGON Z ((30 10
5, 40 40 10, 20 40 15, 10 20 20, 30 10 5))') as poly")
+ val actual = baseDf.select(ST_HasZ("poly")).first().getBoolean(0)
+ assert(actual)
+ }
+
it("Passed ST_HasM") {
val baseDf = sparkSession.sql("SELECT ST_GeomFromWKT('POLYGON ZM ((30 10
5 1, 40 40 10 2, 20 40 15 3, 10 20 20 4, 30 10 5 1))') as poly")
val actual = baseDf.select(ST_HasM("poly")).first().getBoolean(0)
diff --git
a/spark/common/src/test/scala/org/apache/sedona/sql/functionTestScala.scala
b/spark/common/src/test/scala/org/apache/sedona/sql/functionTestScala.scala
index 98f4975ea..7da6fbc41 100644
--- a/spark/common/src/test/scala/org/apache/sedona/sql/functionTestScala.scala
+++ b/spark/common/src/test/scala/org/apache/sedona/sql/functionTestScala.scala
@@ -385,6 +385,12 @@ class functionTestScala extends TestBaseScala with
Matchers with GeometrySample
assert(!testtable.take(1)(0).get(1).asInstanceOf[Boolean])
}
+ it("Passed ST_HasZ") {
+ val baseDf = sparkSession.sql("SELECT ST_GeomFromWKT('POLYGON Z ((30 10
5, 40 40 10, 20 40 15, 10 20 20, 30 10 5))') as poly")
+ val actual = baseDf.selectExpr("ST_HasZ(poly)").first().getBoolean(0)
+ assert(actual)
+ }
+
it("Passed ST_HasM") {
val baseDf = sparkSession.sql("SELECT ST_GeomFromWKT('POLYGON ZM ((30 10
5 1, 40 40 10 2, 20 40 15 3, 10 20 20 4, 30 10 5 1))') as poly")
val actual = baseDf.selectExpr("ST_HasM(poly)").first().getBoolean(0)