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 6b2e6272e [SEDONA-579] Add ST_AsHEXEWKB (#1452)
6b2e6272e is described below
commit 6b2e6272e26eb0f699257a9de5dd88a2a8e0c06e
Author: Jia Yu <[email protected]>
AuthorDate: Sun Jun 2 00:04:42 2024 -0700
[SEDONA-579] Add ST_AsHEXEWKB (#1452)
* feat: add ST_AsHEXEWKB
* fix: snowflake tests
Co-authored-by: Furqaan Khan <[email protected]>
---
.../java/org/apache/sedona/common/Functions.java | 14 +++++++++
.../org/apache/sedona/common/utils/GeomUtils.java | 5 ++++
.../org/apache/sedona/common/FunctionsTest.java | 33 ++++++++++++++++++++++
docs/api/flink/Function.md | 32 +++++++++++++++++++++
docs/api/snowflake/vector-data/Function.md | 30 ++++++++++++++++++++
docs/api/sql/Function.md | 32 +++++++++++++++++++++
.../main/java/org/apache/sedona/flink/Catalog.java | 1 +
.../apache/sedona/flink/expressions/Functions.java | 15 ++++++++++
.../java/org/apache/sedona/flink/FunctionTest.java | 10 +++++++
python/sedona/sql/st_functions.py | 13 +++++++++
python/tests/sql/test_dataframe_api.py | 2 ++
python/tests/sql/test_function.py | 11 ++++++++
.../sedona/snowflake/snowsql/TestFunctions.java | 16 +++++++++++
.../sedona/snowflake/snowsql/TestFunctionsV2.java | 17 +++++++++++
.../org/apache/sedona/snowflake/snowsql/UDFs.java | 14 +++++++++
.../apache/sedona/snowflake/snowsql/UDFsV2.java | 14 +++++++++
.../scala/org/apache/sedona/sql/UDF/Catalog.scala | 1 +
.../sql/sedona_sql/expressions/Functions.scala | 8 ++++++
.../sql/sedona_sql/expressions/st_functions.scala | 6 ++++
.../apache/sedona/sql/dataFrameAPITestScala.scala | 12 ++++++++
.../org/apache/sedona/sql/functionTestScala.scala | 11 ++++++++
21 files changed, 297 insertions(+)
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 3f0a0d9af..d574dc8fd 100644
--- a/common/src/main/java/org/apache/sedona/common/Functions.java
+++ b/common/src/main/java/org/apache/sedona/common/Functions.java
@@ -32,6 +32,7 @@ import org.locationtech.jts.algorithm.hull.ConcaveHull;
import org.locationtech.jts.geom.*;
import org.locationtech.jts.geom.impl.CoordinateArraySequence;
import org.locationtech.jts.geom.util.GeometryFixer;
+import org.locationtech.jts.io.ByteOrderValues;
import org.locationtech.jts.io.gml2.GMLWriter;
import org.locationtech.jts.io.kml.KMLWriter;
import org.locationtech.jts.linearref.LengthIndexedLine;
@@ -553,6 +554,19 @@ public class Functions {
return GeomUtils.getEWKB(geometry);
}
+ public static String asHexEWKB(Geometry geom, String endian) {
+ if (endian.equalsIgnoreCase("NDR")) {
+ return GeomUtils.getHexEWKB(geom, ByteOrderValues.LITTLE_ENDIAN);
+ } else if (endian.equalsIgnoreCase("XDR")) {
+ return GeomUtils.getHexEWKB(geom, ByteOrderValues.BIG_ENDIAN);
+ }
+ throw new IllegalArgumentException("You must select either NDR
(little-endian) or XDR (big-endian) as the endian format.");
+ }
+
+ public static String asHexEWKB(Geometry geom) {
+ return asHexEWKB(geom, "NDR");
+ }
+
public static byte[] asWKB(Geometry geometry) {
return GeomUtils.getWKB(geometry);
}
diff --git a/common/src/main/java/org/apache/sedona/common/utils/GeomUtils.java
b/common/src/main/java/org/apache/sedona/common/utils/GeomUtils.java
index 9a4d57e91..fc36e79e5 100644
--- a/common/src/main/java/org/apache/sedona/common/utils/GeomUtils.java
+++ b/common/src/main/java/org/apache/sedona/common/utils/GeomUtils.java
@@ -177,6 +177,11 @@ public class GeomUtils {
return new WKTWriter(4).write(geometry);
}
+ public static String getHexEWKB(Geometry geometry, int endian) {
+ WKBWriter writer = new WKBWriter(GeomUtils.getDimension(geometry),
endian, geometry.getSRID() != 0);
+ return WKBWriter.toHex(writer.write(geometry));
+ }
+
public static byte[] getEWKB(Geometry geometry) {
if (geometry == null) {
return null;
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 4845e0a78..78c82ba77 100644
--- a/common/src/test/java/org/apache/sedona/common/FunctionsTest.java
+++ b/common/src/test/java/org/apache/sedona/common/FunctionsTest.java
@@ -133,6 +133,39 @@ public class FunctionsTest extends TestBase {
assertEquals(expected, geometry);
}
+ @Test
+ public void asHexEWKB() throws ParseException {
+ String[] geoms = {
+ "POINT(1 2)",
+ "LINESTRING (30 20, 20 25, 20 15, 30 20)",
+ "POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0), (5 5, 5 8, 8 8, 8 5,
5 5))"
+
+ };
+ String[] expected = {
+ //NDR - little endian
+ "0101000000000000000000F03F0000000000000040",
+
"0102000000040000000000000000003E4000000000000034400000000000003440000000000000394000000000000034400000000000002E400000000000003E400000000000003440",
+
"010300000002000000050000000000000000000000000000000000000000000000000024400000000000000000000000000000244000000000000024400000000000000000000000000000244000000000000000000000000000000000050000000000000000001440000000000000144000000000000014400000000000002040000000000000204000000000000020400000000000002040000000000000144000000000000014400000000000001440",
+
+ // XDR - big endian
+ "00000000013FF00000000000004000000000000000",
+
"000000000200000004403E0000000000004034000000000000403400000000000040390000000000004034000000000000402E000000000000403E0000000000004034000000000000",
+
"000000000300000002000000050000000000000000000000000000000040240000000000000000000000000000402400000000000040240000000000000000000000000000402400000000000000000000000000000000000000000000000000054014000000000000401400000000000040140000000000004020000000000000402000000000000040200000000000004020000000000000401400000000000040140000000000004014000000000000"
+ };
+ testAsHexEWKB(geoms, expected);
+ }
+
+ public void testAsHexEWKB(String[] geoms, String[] expected) throws
ParseException {
+ String[] endians = {"NDR", "XDR"};
+ int offset = 0;
+ for (String e: endians) {
+ for (int i = 0; i < geoms.length; i++) {
+ assertEquals(expected[i + offset],
Functions.asHexEWKB(Constructors.geomFromWKT(geoms[i], 0), e));
+ }
+ offset = 3;
+ }
+ }
+
@Test
public void pointFromWKB() throws Exception{
Geometry geometry = GEOMETRY_FACTORY.createPoint(new Coordinate(1.0,
2.0));
diff --git a/docs/api/flink/Function.md b/docs/api/flink/Function.md
index c6897e8bb..8139a090f 100644
--- a/docs/api/flink/Function.md
+++ b/docs/api/flink/Function.md
@@ -397,6 +397,38 @@ Output:
1.0,1.0 8.0,1.0 8.0,8.0 1.0,8.0 1.0,1.0
```
+## ST_AsHEXEWKB
+
+Introduction: This function returns the input geometry encoded to a text
representation in HEXEWKB format. The HEXEWKB encoding can use either
little-endian (NDR) or big-endian (XDR) byte ordering. If no encoding is
explicitly specified, the function defaults to using the little-endian (NDR)
format.
+
+Format: `ST_AsHEXEWKB(geom: Geometry, endian: String = NDR)`
+
+Since: `vTBD`
+
+SQL Example
+
+```sql
+SELECT ST_AsHEXEWKB(ST_GeomFromWKT('POINT(1 2)'), 'XDR')
+```
+
+Output:
+
+```
+00000000013FF00000000000004000000000000000
+```
+
+SQL Example
+
+```sql
+SELECT ST_AsHEXEWKB(ST_GeomFromWKT('LINESTRING (30 20, 20 25, 20 15, 30 20)'))
+```
+
+Output:
+
+```
+0102000000040000000000000000003E4000000000000034400000000000003440000000000000394000000000000034400000000000002E400000000000003E400000000000003440
+```
+
## ST_AsKML
Introduction: Return the [KML](https://www.ogc.org/standards/kml) string
representation of a geometry
diff --git a/docs/api/snowflake/vector-data/Function.md
b/docs/api/snowflake/vector-data/Function.md
index 8b175e660..676cf3736 100644
--- a/docs/api/snowflake/vector-data/Function.md
+++ b/docs/api/snowflake/vector-data/Function.md
@@ -292,6 +292,36 @@ SELECT ST_AsGML(polygondf.countyshape)
FROM polygondf
```
+## ST_AsHEXEWKB
+
+Introduction: This function returns the input geometry encoded to a text
representation in HEXEWKB format. The HEXEWKB encoding can use either
little-endian (NDR) or big-endian (XDR) byte ordering. If no encoding is
explicitly specified, the function defaults to using the little-endian (NDR)
format.
+
+Format: `ST_AsHEXEWKB(geom: Geometry, endian: String = NDR)`
+
+SQL Example
+
+```sql
+SELECT ST_AsHEXEWKB(ST_GeomFromWKT('POINT(1 2)'), 'XDR')
+```
+
+Output:
+
+```
+00000000013FF00000000000004000000000000000
+```
+
+SQL Example
+
+```sql
+SELECT ST_AsHEXEWKB(ST_GeomFromWKT('LINESTRING (30 20, 20 25, 20 15, 30 20)'))
+```
+
+Output:
+
+```
+0102000000040000000000000000003E4000000000000034400000000000003440000000000000394000000000000034400000000000002E400000000000003E400000000000003440
+```
+
## ST_AsKML
Introduction: Return the [KML](https://www.ogc.org/standards/kml) string
representation of a geometry
diff --git a/docs/api/sql/Function.md b/docs/api/sql/Function.md
index 437f38caa..182d2afbf 100644
--- a/docs/api/sql/Function.md
+++ b/docs/api/sql/Function.md
@@ -394,6 +394,38 @@ Output:
1.0,1.0 8.0,1.0 8.0,8.0 1.0,8.0 1.0,1.0
```
+## ST_AsHEXEWKB
+
+Introduction: This function returns the input geometry encoded to a text
representation in HEXEWKB format. The HEXEWKB encoding can use either
little-endian (NDR) or big-endian (XDR) byte ordering. If no encoding is
explicitly specified, the function defaults to using the little-endian (NDR)
format.
+
+Format: `ST_AsHEXEWKB(geom: Geometry, endian: String = NDR)`
+
+Since: `vTBD`
+
+SQL Example
+
+```sql
+SELECT ST_AsHEXEWKB(ST_GeomFromWKT('POINT(1 2)'), 'XDR')
+```
+
+Output:
+
+```
+00000000013FF00000000000004000000000000000
+```
+
+SQL Example
+
+```sql
+SELECT ST_AsHEXEWKB(ST_GeomFromWKT('LINESTRING (30 20, 20 25, 20 15, 30 20)'))
+```
+
+Output:
+
+```
+0102000000040000000000000000003E4000000000000034400000000000003440000000000000394000000000000034400000000000002E400000000000003E400000000000003440
+```
+
## ST_AsKML
Introduction: Return the [KML](https://www.ogc.org/standards/kml) string
representation of a geometry
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 9c54f69e0..443fbe932 100644
--- a/flink/src/main/java/org/apache/sedona/flink/Catalog.java
+++ b/flink/src/main/java/org/apache/sedona/flink/Catalog.java
@@ -96,6 +96,7 @@ public class Catalog {
new Functions.ST_ExteriorRing(),
new Functions.ST_AsEWKT(),
new Functions.ST_AsEWKB(),
+ new Functions.ST_AsHEXEWKB(),
new Functions.ST_AsText(),
new Functions.ST_AsBinary(),
new Functions.ST_AsGeoJSON(),
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 74a718ca8..0f7593181 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
@@ -515,6 +515,21 @@ public class Functions {
}
}
+ public static class ST_AsHEXEWKB extends ScalarFunction {
+ @DataTypeHint("String")
+ public String eval(@DataTypeHint(value = "RAW", bridgedTo =
org.locationtech.jts.geom.Geometry.class) Object o,
+ @DataTypeHint("String") String endian) {
+ Geometry geom = (Geometry) o;
+ return org.apache.sedona.common.Functions.asHexEWKB(geom, endian);
+ }
+
+ @DataTypeHint("String")
+ public String eval(@DataTypeHint(value = "RAW", bridgedTo =
org.locationtech.jts.geom.Geometry.class) Object o) {
+ Geometry geom = (Geometry) o;
+ return org.apache.sedona.common.Functions.asHexEWKB(geom);
+ }
+ }
+
public static class ST_AsBinary extends ScalarFunction {
@DataTypeHint("Bytes")
public byte[] 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 b230a0982..57dc92ece 100644
--- a/flink/src/test/java/org/apache/sedona/flink/FunctionTest.java
+++ b/flink/src/test/java/org/apache/sedona/flink/FunctionTest.java
@@ -612,6 +612,16 @@ public class FunctionTest extends TestBase{
assertEquals("01030000000100000005000000000000000000e0bf000000000000e0bf000000000000e0bf000000000000e03f000000000000e03f000000000000e03f000000000000e03f000000000000e0bf000000000000e0bf000000000000e0bf",
result);
}
+ @Test
+ public void testAsHEXEWKB() {
+ Table pointTable = tableEnv.sqlQuery("SELECT ST_GeomFromWKT('POINT (1
2)') AS point");
+ String result = (String)
first(pointTable.select(call(Functions.ST_AsHEXEWKB.class.getSimpleName(),
$("point"), "XDR"))).getField(0);
+ assertEquals("00000000013FF00000000000004000000000000000", result);
+
+ result = (String)
first(pointTable.select(call(Functions.ST_AsHEXEWKB.class.getSimpleName(),
$("point")))).getField(0);
+ assertEquals("0101000000000000000000F03F0000000000000040", result);
+ }
+
@Test
public void testAsBinary() {
Table polygonTable = createPolygonTable(testDataSize);
diff --git a/python/sedona/sql/st_functions.py
b/python/sedona/sql/st_functions.py
index 3560a5f73..02a3001c8 100644
--- a/python/sedona/sql/st_functions.py
+++ b/python/sedona/sql/st_functions.py
@@ -123,6 +123,19 @@ def ST_AsEWKB(geometry: ColumnOrName) -> Column:
"""
return _call_st_function("ST_AsEWKB", geometry)
+@validate_argument_types
+def ST_AsHEXEWKB(geometry: ColumnOrName, endian: Optional[ColumnOrName] =
None) -> Column:
+ """Generate the Extended Well-Known Binary representation of a geometry as
Hex string.
+
+ :param geometry: Geometry to generate EWKB for.
+ :type geometry: ColumnOrName
+ :return: Extended Well-Known Binary representation of geometry as Hex
string.
+ :rtype: Column
+ """
+ args = (geometry) if endian is None else (geometry, endian)
+
+ return _call_st_function("ST_AsHEXEWKB", args)
+
@validate_argument_types
def ST_AsEWKT(geometry: ColumnOrName) -> Column:
diff --git a/python/tests/sql/test_dataframe_api.py
b/python/tests/sql/test_dataframe_api.py
index e075af581..bd75bf16a 100644
--- a/python/tests/sql/test_dataframe_api.py
+++ b/python/tests/sql/test_dataframe_api.py
@@ -84,6 +84,7 @@ test_configurations = [
(stf.ST_AreaSpheroid, ("point",), "point_geom", "", 0.0),
(stf.ST_AsBinary, ("point",), "point_geom", "",
"01010000000000000000000000000000000000f03f"),
(stf.ST_AsEWKB, (lambda: f.expr("ST_SetSRID(point, 3021)"),),
"point_geom", "", "0101000020cd0b00000000000000000000000000000000f03f"),
+ (stf.ST_AsHEXEWKB, ("point",), "point_geom", "",
"01010000000000000000000000000000000000F03F"),
(stf.ST_AsEWKT, (lambda: f.expr("ST_SetSRID(point, 4326)"),),
"point_geom", "", "SRID=4326;POINT (0 1)"),
(stf.ST_AsGeoJSON, ("point",), "point_geom", "",
"{\"type\":\"Point\",\"coordinates\":[0.0,1.0]}"),
(stf.ST_AsGML, ("point",), "point_geom", "", "<gml:Point>\n
<gml:coordinates>\n 0.0,1.0 \n </gml:coordinates>\n</gml:Point>\n"),
@@ -265,6 +266,7 @@ wrong_type_configurations = [
(stf.ST_Area, (None,)),
(stf.ST_AsBinary, (None,)),
(stf.ST_AsEWKB, (None,)),
+ (stf.ST_AsHEXEWKB, (None,)),
(stf.ST_AsEWKT, (None,)),
(stf.ST_AsGeoJSON, (None,)),
(stf.ST_AsGML, (None,)),
diff --git a/python/tests/sql/test_function.py
b/python/tests/sql/test_function.py
index d30bb56d1..2bf755825 100644
--- a/python/tests/sql/test_function.py
+++ b/python/tests/sql/test_function.py
@@ -1492,6 +1492,17 @@ class TestPredicateJoin(TestBase):
"1, 2, 1, 2) AS geom")
actual = actual_df.selectExpr("ST_AsText(geom)").take(1)[0][0]
assert expected == actual
+
+ def test_st_ashexewkb(self):
+ expected = "0101000000000000000000F03F0000000000000040"
+ actual_df = self.spark.sql("SELECT ST_GeomFromText('POINT(1 2)') as
point")
+ actual = actual_df.selectExpr("ST_AsHEXEWKB(point)").take(1)[0][0]
+ assert expected == actual
+
+ expected = "00000000013FF00000000000004000000000000000"
+ actual = actual_df.selectExpr("ST_AsHEXEWKB(point,
'XDR')").take(1)[0][0]
+ assert expected == actual
+
def test_boundingDiagonal(self):
expected = "LINESTRING (1 0, 2 1)"
actual_df = self.spark.sql("SELECT
ST_BoundingDiagonal(ST_GeomFromText('POLYGON ((1 0, 1 1, 2 1, 2 0, "
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 c92312304..48f890e9e 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
@@ -111,6 +111,22 @@ public class TestFunctions extends TestBase {
new byte[] {1, 1, 0, 0, 32, -51, 11, 0, 0, 0, 0, 0, 0, 0, 0,
-16, 63, 0, 0, 0, 0, 0, 0, -16, 63}
);
}
+
+ @Test
+ public void test_ST_AsHEXEWKB() throws SQLException {
+ registerUDF("ST_AsHEXEWKB", byte[].class);
+ verifySqlSingleRes(
+ "select sedona.ST_AsHEXEWKB(sedona.ST_GeomFromText('POINT(1
2)'))",
+ "0101000000000000000000F03F0000000000000040"
+ );
+
+ registerUDF("ST_AsHEXEWKB", byte[].class, String.class);
+ verifySqlSingleRes(
+ "select sedona.ST_AsHEXEWKB(sedona.ST_GeomFromText('POINT(1
2)'), 'XDR')",
+ "00000000013FF00000000000004000000000000000"
+ );
+ }
+
@Test
public void test_ST_AsEWKT() {
registerUDF("ST_AsEWKT", byte[].class);
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 a917d51a4..3806c0d52 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
@@ -114,6 +114,23 @@ public class TestFunctionsV2
new byte[] {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -16, 63, 0, 0, 0,
0, 0, 0, -16, 63}
);
}
+
+ @Test
+ public void test_ST_AsHEXEWKB() throws SQLException
+ {
+ registerUDFV2("ST_AsHEXEWKB", String.class);
+ verifySqlSingleRes(
+ "select sedona.ST_AsHEXEWKB(ST_GeometryFromWKT('POINT(1 2)'))",
+ "0101000000000000000000F03F0000000000000040"
+ );
+
+ registerUDFV2("ST_AsHEXEWKB", String.class, String.class);
+ verifySqlSingleRes(
+ "select sedona.ST_AsHEXEWKB(ST_GeometryFromWKT('POINT(1 2)'),
'XDR')",
+ "00000000013FF00000000000004000000000000000"
+ );
+ }
+
@Test
public void test_ST_AsEWKT() {
registerUDFV2("ST_AsEWKT", 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 3b118a2ec..7dc314e9f 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
@@ -104,6 +104,20 @@ public class UDFs {
);
}
+ @UDFAnnotations.ParamMeta(argNames = {"geometry"})
+ public static String ST_AsHEXEWKB(byte[] geometry) {
+ return Functions.asHexEWKB(
+ GeometrySerde.deserialize(geometry)
+ );
+ }
+
+ @UDFAnnotations.ParamMeta(argNames = {"geometry", "endian"})
+ public static String ST_AsHEXEWKB(byte[] geometry, String endian) {
+ return Functions.asHexEWKB(
+ GeometrySerde.deserialize(geometry), endian
+ );
+ }
+
@UDFAnnotations.ParamMeta(argNames = {"geometry"})
public static String ST_AsEWKT(byte[] geometry) {
return Functions.asEWKT(
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 cf5b18963..a49d1ba7b 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
@@ -110,6 +110,20 @@ public class UDFsV2
);
}
+ @UDFAnnotations.ParamMeta(argNames = {"geometry"}, argTypes = {"Geometry"})
+ public static String ST_AsHEXEWKB(String geometry) {
+ return Functions.asHexEWKB(
+ GeometrySerde.deserGeoJson(geometry)
+ );
+ }
+
+ @UDFAnnotations.ParamMeta(argNames = {"geometry", "endian"}, argTypes =
{"Geometry", "String"})
+ public static String ST_AsHEXEWKB(String geometry, String endian) {
+ return Functions.asHexEWKB(
+ GeometrySerde.deserGeoJson(geometry), endian
+ );
+ }
+
@UDFAnnotations.ParamMeta(argNames = {"geometry"},
argTypes = {"Geometry"})
public static String ST_AsEWKT(String geometry) {
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 db2d0d67f..92c9ac807 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
@@ -100,6 +100,7 @@ object Catalog {
function[ST_AsGeoJSON](),
function[ST_AsBinary](),
function[ST_AsEWKB](),
+ function[ST_AsHEXEWKB](),
function[ST_AsGML](),
function[ST_AsKML](),
function[ST_SRID](),
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 4814e4967..2db5e6166 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
@@ -365,6 +365,14 @@ case class ST_AsEWKB(inputExpressions: Seq[Expression])
}
}
+case class ST_AsHEXEWKB(inputExpressions: Seq[Expression])
+ extends InferredExpression(inferrableFunction2(Functions.asHexEWKB),
inferrableFunction1(Functions.asHexEWKB)) {
+
+ protected def withNewChildrenInternal(newChildren: IndexedSeq[Expression]) =
{
+ copy(inputExpressions = newChildren)
+ }
+}
+
case class ST_SRID(inputExpressions: Seq[Expression])
extends InferredExpression(Functions.getSRID _) {
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 b935f41b7..6dbde20c9 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
@@ -43,6 +43,12 @@ object st_functions extends DataFrameAPI {
def ST_AsEWKB(geometry: Column): Column = wrapExpression[ST_AsEWKB](geometry)
def ST_AsEWKB(geometry: String): Column = wrapExpression[ST_AsEWKB](geometry)
+
+ def ST_AsHEXEWKB(geometry: Column, endian: Column): Column =
wrapExpression[ST_AsHEXEWKB](geometry, endian)
+ def ST_AsHEXEWKB(geometry: String, endian: String): Column =
wrapExpression[ST_AsHEXEWKB](geometry, endian)
+ def ST_AsHEXEWKB(geometry: Column): Column =
wrapExpression[ST_AsHEXEWKB](geometry)
+ def ST_AsHEXEWKB(geometry: String): Column =
wrapExpression[ST_AsHEXEWKB](geometry)
+
def ST_AsEWKT(geometry: Column): Column = wrapExpression[ST_AsEWKT](geometry)
def ST_AsEWKT(geometry: String): Column = wrapExpression[ST_AsEWKT](geometry)
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 8f19bac84..2548b1d3b 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
@@ -635,6 +635,18 @@ class dataFrameAPITestScala extends TestBaseScala {
assert(actualResult == expectedResult)
}
+
+ it("Passed ST_AsHEXEWKB") {
+ val baseDf = sparkSession.sql("SELECT ST_GeomFromWKT('POINT(1 2)') as
point")
+ var actual = baseDf.select(ST_AsHEXEWKB("point")).first().get(0)
+ var expected = "0101000000000000000000F03F0000000000000040"
+ assert(expected.equals(actual))
+
+ actual = baseDf.select(ST_AsHEXEWKB(col("point"),
lit("xdr"))).first().get(0)
+ expected = "00000000013FF00000000000004000000000000000"
+ assert(expected.equals(actual))
+ }
+
it("Passed ST_NPoints") {
val lineDf = sparkSession.sql("SELECT ST_GeomFromWKT('LINESTRING (0 0, 1
1)') AS geom")
val df = lineDf.select(ST_NPoints("geom"))
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 26e6e5dde..8711b3fb2 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
@@ -629,6 +629,17 @@ class functionTestScala extends TestBaseScala with
Matchers with GeometrySample
assert(Hex.encodeHexString(df.first().get(0).asInstanceOf[Array[Byte]])
== s)
}
+ it("Passed ST_AsHEXEWKB") {
+ val baseDf = sparkSession.sql("SELECT ST_GeomFromWKT('POINT(1 2)') as
point")
+ var actual = baseDf.selectExpr("ST_AsHEXEWKB(point)").first().get(0)
+ var expected = "0101000000000000000000F03F0000000000000040"
+ assert(expected.equals(actual))
+
+ actual = baseDf.selectExpr("ST_AsHEXEWKB(point, 'XDR')").first().get(0)
+ expected = "00000000013FF00000000000004000000000000000"
+ assert(expected.equals(actual))
+ }
+
it("Passed ST_AsEWKB empty geometry") {
val df = sparkSession.sql("SELECT
ST_AsEWKB(ST_SetSrid(ST_GeomFromWKT('POINT EMPTY'), 3021))")
val s = "0101000020cd0b0000000000000000f87f000000000000f87f"