This is an automated email from the ASF dual-hosted git repository.
cloud-fan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/spark.git
The following commit(s) were added to refs/heads/master by this push:
new bae066b57c0f [SPARK-56682][GEO][CONNECT][PYTHON][SQL] Extend the
ST_AsBinary function to take optional endianness
bae066b57c0f is described below
commit bae066b57c0fa3bc8400f1bd5fd69c67a8682c65
Author: Uros Bojanic <[email protected]>
AuthorDate: Sat May 9 03:01:27 2026 +0800
[SPARK-56682][GEO][CONNECT][PYTHON][SQL] Extend the ST_AsBinary function to
take optional endianness
### What changes were proposed in this pull request?
Extend the geometry & geography WKB writer function in SQL, Scala, and
PySpark to take an optional second argument - the endianness:
`st_asbinary(geo[, endianness])`.
Arguments:
- `geo` - A geospatial value, either a GEOGRAPHY or a GEOMETRY.
- `endianness` - The optional endianness of the output WKB.
### Why are the changes needed?
The `ST_AsBinary` function should take an optional endianness value for the
output WKB.
### Does this PR introduce _any_ user-facing change?
Yes, the `st_asbinary` function now takes an optional second argument (the
endianness).
### How was this patch tested?
Added new tests for the catalyst expression, SQL function, Scala function,
and PySpark function.
### Was this patch authored or co-authored using generative AI tooling?
No.
Closes #55631 from uros-db/geo-ST_AsBinary_endianness.
Lead-authored-by: Uros Bojanic <[email protected]>
Co-authored-by: Wenchen Fan <[email protected]>
Signed-off-by: Wenchen Fan <[email protected]>
---
.../src/main/resources/error/error-conditions.json | 6 +
python/pyspark/errors/error-conditions.json | 6 +
python/pyspark/sql/connect/functions/builtin.py | 8 +-
python/pyspark/sql/functions/builtin.py | 34 +++-
python/pyspark/sql/tests/test_functions.py | 16 +-
.../scala/org/apache/spark/sql/functions.scala | 18 ++
.../org/apache/spark/sql/catalyst/util/Geo.java | 1 -
.../apache/spark/sql/catalyst/util/Geography.java | 5 -
.../apache/spark/sql/catalyst/util/Geometry.java | 5 -
.../apache/spark/sql/catalyst/util/STUtils.java | 21 ++-
.../catalyst/expressions/st/stExpressions.scala | 39 ++--
.../spark/sql/errors/QueryExecutionErrors.scala | 8 +
.../sql/catalyst/CatalystTypeConvertersSuite.scala | 28 +--
.../sql/catalyst/util/GeographyExecutionSuite.java | 6 +-
.../sql/catalyst/util/GeometryExecutionSuite.java | 6 +-
.../spark/sql/catalyst/util/StUtilsSuite.java | 7 +-
.../sql-functions/sql-expression-schema.md | 6 +-
.../analyzer-results/st-functions.sql.out | 183 ++++++++++++++++--
.../resources/sql-tests/inputs/st-functions.sql | 27 +++
.../sql-tests/results/st-functions.sql.out | 208 ++++++++++++++++++++-
.../org/apache/spark/sql/STExpressionsSuite.scala | 52 ++++--
.../org/apache/spark/sql/STFunctionsSuite.scala | 35 +++-
22 files changed, 622 insertions(+), 103 deletions(-)
diff --git a/common/utils/src/main/resources/error/error-conditions.json
b/common/utils/src/main/resources/error/error-conditions.json
index 48a9f57b75dd..95f0c303e35f 100644
--- a/common/utils/src/main/resources/error/error-conditions.json
+++ b/common/utils/src/main/resources/error/error-conditions.json
@@ -7032,6 +7032,12 @@
],
"sqlState" : "22023"
},
+ "ST_INVALID_ENDIANNESS_VALUE" : {
+ "message" : [
+ "Endianness '<endianness>' must be either 'NDR' (little-endian) or 'XDR'
(big-endian)."
+ ],
+ "sqlState" : "22023"
+ },
"ST_INVALID_SRID_VALUE" : {
"message" : [
"Invalid or unsupported SRID (spatial reference identifier) value:
<srid>."
diff --git a/python/pyspark/errors/error-conditions.json
b/python/pyspark/errors/error-conditions.json
index 808127772f72..485d48b6d7d5 100644
--- a/python/pyspark/errors/error-conditions.json
+++ b/python/pyspark/errors/error-conditions.json
@@ -958,6 +958,12 @@
],
"sqlState" : "22023"
},
+ "ST_INVALID_ENDIANNESS_VALUE" : {
+ "message" : [
+ "Endianness '<endianness>' must be either 'NDR' (little-endian) or 'XDR'
(big-endian)."
+ ],
+ "sqlState" : "22023"
+ },
"ST_INVALID_SRID_VALUE" : {
"message" : [
"Invalid or unsupported SRID (spatial reference identifier) value:
<srid>."
diff --git a/python/pyspark/sql/connect/functions/builtin.py
b/python/pyspark/sql/connect/functions/builtin.py
index 76e3f40a101a..22e52d91232c 100644
--- a/python/pyspark/sql/connect/functions/builtin.py
+++ b/python/pyspark/sql/connect/functions/builtin.py
@@ -5417,8 +5417,12 @@ bitmap_and_agg.__doc__ =
pysparkfuncs.bitmap_and_agg.__doc__
# Geospatial ST Functions
-def st_asbinary(geo: "ColumnOrName") -> Column:
- return _invoke_function_over_columns("st_asbinary", geo)
+def st_asbinary(geo: "ColumnOrName", endianness: Optional["ColumnOrName"] =
None) -> Column:
+ if endianness is None:
+ return _invoke_function_over_columns("st_asbinary", geo)
+ else:
+ _endianness = lit(endianness) if isinstance(endianness, str) else
endianness
+ return _invoke_function_over_columns("st_asbinary", geo, _endianness)
st_asbinary.__doc__ = pysparkfuncs.st_asbinary.__doc__
diff --git a/python/pyspark/sql/functions/builtin.py
b/python/pyspark/sql/functions/builtin.py
index 5e0fd250c8a9..be948a22a30f 100644
--- a/python/pyspark/sql/functions/builtin.py
+++ b/python/pyspark/sql/functions/builtin.py
@@ -26379,15 +26379,21 @@ def bucket(numBuckets: Union[Column, int], col:
"ColumnOrName") -> Column:
@_try_remote_functions
-def st_asbinary(geo: "ColumnOrName") -> Column:
+def st_asbinary(geo: "ColumnOrName", endianness: Optional["ColumnOrName"] =
None) -> Column:
"""Returns the input GEOGRAPHY or GEOMETRY value in WKB format.
.. versionadded:: 4.1.0
+ .. versionchanged:: 4.2.0
+ Added the optional `endianness` parameter.
+
Parameters
----------
geo : :class:`~pyspark.sql.Column` or str
A geospatial value, either a GEOGRAPHY or a GEOMETRY.
+ endianness : :class:`~pyspark.sql.Column` or str, optional
+ The optional endianness of the output WKB, 'NDR' for little-endian
(default) or 'XDR' for
+ big-endian.
Examples
--------
@@ -26396,15 +26402,31 @@ def st_asbinary(geo: "ColumnOrName") -> Column:
>>> from pyspark.sql import functions as sf
>>> df =
spark.createDataFrame([(bytes.fromhex('0101000000000000000000F03F0000000000000040'),)],
['wkb']) # noqa
>>> df.select(sf.hex(sf.st_asbinary(sf.st_geogfromwkb('wkb')))).collect()
-
[Row(hex(st_asbinary(st_geogfromwkb(wkb)))='0101000000000000000000F03F0000000000000040')]
+ [Row(hex(st_asbinary(st_geogfromwkb(wkb),
NDR))='0101000000000000000000F03F0000000000000040')]
Example 2: Getting WKB from GEOMETRY.
>>> from pyspark.sql import functions as sf
>>> df =
spark.createDataFrame([(bytes.fromhex('0101000000000000000000F03F0000000000000040'),)],
['wkb']) # noqa
>>> df.select(sf.hex(sf.st_asbinary(sf.st_geomfromwkb('wkb')))).collect()
- [Row(hex(st_asbinary(st_geomfromwkb(wkb,
0)))='0101000000000000000000F03F0000000000000040')]
+ [Row(hex(st_asbinary(st_geomfromwkb(wkb, 0),
NDR))='0101000000000000000000F03F0000000000000040')]
+
+ Example 3: Getting WKB (little-endian) from GEOGRAPHY.
+ >>> from pyspark.sql import functions as sf
+ >>> df =
spark.createDataFrame([(bytes.fromhex('0101000000000000000000F03F0000000000000040'),)],
['wkb']) # noqa
+ >>> df.select(sf.hex(sf.st_asbinary(sf.st_geogfromwkb('wkb'),
'NDR'))).collect()
+ [Row(hex(st_asbinary(st_geogfromwkb(wkb),
NDR))='0101000000000000000000F03F0000000000000040')]
+
+ Example 4: Getting WKB (big-endian) from GEOMETRY.
+ >>> from pyspark.sql import functions as sf
+ >>> df =
spark.createDataFrame([(bytes.fromhex('0101000000000000000000F03F0000000000000040'),)],
['wkb']) # noqa
+ >>> df.select(sf.hex(sf.st_asbinary(sf.st_geomfromwkb('wkb'),
'XDR'))).collect()
+ [Row(hex(st_asbinary(st_geomfromwkb(wkb, 0),
XDR))='00000000013FF00000000000004000000000000000')]
"""
- return _invoke_function_over_columns("st_asbinary", geo)
+ if endianness is None:
+ return _invoke_function_over_columns("st_asbinary", geo)
+ else:
+ _endianness = lit(endianness) if isinstance(endianness, str) else
endianness
+ return _invoke_function_over_columns("st_asbinary", geo, _endianness)
@_try_remote_functions
@@ -26423,7 +26445,7 @@ def st_geogfromwkb(wkb: "ColumnOrName") -> Column:
>>> from pyspark.sql import functions as sf
>>> df =
spark.createDataFrame([(bytes.fromhex('0101000000000000000000F03F0000000000000040'),)],
['wkb']) # noqa
>>> df.select(sf.hex(sf.st_asbinary(sf.st_geogfromwkb('wkb')))).collect()
-
[Row(hex(st_asbinary(st_geogfromwkb(wkb)))='0101000000000000000000F03F0000000000000040')]
+ [Row(hex(st_asbinary(st_geogfromwkb(wkb),
NDR))='0101000000000000000000F03F0000000000000040')]
"""
return _invoke_function_over_columns("st_geogfromwkb", wkb)
@@ -26448,7 +26470,7 @@ def st_geomfromwkb(
>>> from pyspark.sql import functions as sf
>>> df =
spark.createDataFrame([(bytes.fromhex('0101000000000000000000F03F0000000000000040'),)],
['wkb']) # noqa
>>> df.select(sf.hex(sf.st_asbinary(sf.st_geomfromwkb('wkb')))).collect()
- [Row(hex(st_asbinary(st_geomfromwkb(wkb,
0)))='0101000000000000000000F03F0000000000000040')]
+ [Row(hex(st_asbinary(st_geomfromwkb(wkb, 0),
NDR))='0101000000000000000000F03F0000000000000040')]
"""
if srid is None:
return _invoke_function_over_columns("st_geomfromwkb", wkb)
diff --git a/python/pyspark/sql/tests/test_functions.py
b/python/pyspark/sql/tests/test_functions.py
index 417e93760ef3..75824d3ebe49 100644
--- a/python/pyspark/sql/tests/test_functions.py
+++ b/python/pyspark/sql/tests/test_functions.py
@@ -3848,16 +3848,28 @@ class FunctionsTestsMixin:
def test_st_asbinary(self):
df = self.spark.createDataFrame(
- [(bytes.fromhex("0101000000000000000000F03F0000000000000040"),)],
- ["wkb"],
+ [(bytes.fromhex("0101000000000000000000F03F0000000000000040"),
"XDR")],
+ ["wkb", "end"],
)
results = df.select(
F.hex(F.st_asbinary(F.st_geogfromwkb("wkb"))),
+ F.hex(F.st_asbinary(F.st_geogfromwkb("wkb"), "NDR")),
+ F.hex(F.st_asbinary(F.st_geogfromwkb("wkb"), "XDR")),
+ F.hex(F.st_asbinary(F.st_geogfromwkb("wkb"), F.col("end"))),
F.hex(F.st_asbinary(F.st_geomfromwkb("wkb"))),
+ F.hex(F.st_asbinary(F.st_geomfromwkb("wkb"), "NDR")),
+ F.hex(F.st_asbinary(F.st_geomfromwkb("wkb"), "XDR")),
+ F.hex(F.st_asbinary(F.st_geomfromwkb("wkb"), F.col("end"))),
).collect()
expected = Row(
"0101000000000000000000F03F0000000000000040",
"0101000000000000000000F03F0000000000000040",
+ "00000000013FF00000000000004000000000000000",
+ "00000000013FF00000000000004000000000000000",
+ "0101000000000000000000F03F0000000000000040",
+ "0101000000000000000000F03F0000000000000040",
+ "00000000013FF00000000000004000000000000000",
+ "00000000013FF00000000000004000000000000000",
)
self.assertEqual(results, [expected])
diff --git a/sql/api/src/main/scala/org/apache/spark/sql/functions.scala
b/sql/api/src/main/scala/org/apache/spark/sql/functions.scala
index ccc7820d5d95..4ad731f6d8b0 100644
--- a/sql/api/src/main/scala/org/apache/spark/sql/functions.scala
+++ b/sql/api/src/main/scala/org/apache/spark/sql/functions.scala
@@ -11166,6 +11166,24 @@ object functions {
def st_asbinary(geo: Column): Column =
Column.fn("st_asbinary", geo)
+ /**
+ * Returns the input GEOGRAPHY or GEOMETRY value in WKB format using the
specified endianness.
+ *
+ * @group st_funcs
+ * @since 4.2.0
+ */
+ def st_asbinary(geo: Column, endianness: Column): Column =
+ Column.fn("st_asbinary", geo, endianness)
+
+ /**
+ * Returns the input GEOGRAPHY or GEOMETRY value in WKB format using the
specified endianness.
+ *
+ * @group st_funcs
+ * @since 4.2.0
+ */
+ def st_asbinary(geo: Column, endianness: String): Column =
+ Column.fn("st_asbinary", geo, lit(endianness))
+
/**
* Parses the WKB description of a geography and returns the corresponding
GEOGRAPHY value.
*
diff --git
a/sql/catalyst/src/main/java/org/apache/spark/sql/catalyst/util/Geo.java
b/sql/catalyst/src/main/java/org/apache/spark/sql/catalyst/util/Geo.java
index bf723a8efef9..1002cdd28a77 100644
--- a/sql/catalyst/src/main/java/org/apache/spark/sql/catalyst/util/Geo.java
+++ b/sql/catalyst/src/main/java/org/apache/spark/sql/catalyst/util/Geo.java
@@ -58,7 +58,6 @@ interface Geo {
/** Binary converters. */
// Returns the Well-Known Binary (WKB) representation of the geo object.
- byte[] toWkb();
byte[] toWkb(ByteOrder endianness);
// Returns the Extended Well-Known Binary (EWKB) representation of the geo
object.
diff --git
a/sql/catalyst/src/main/java/org/apache/spark/sql/catalyst/util/Geography.java
b/sql/catalyst/src/main/java/org/apache/spark/sql/catalyst/util/Geography.java
index f446d71d5a5b..dd5b69a12e7a 100644
---
a/sql/catalyst/src/main/java/org/apache/spark/sql/catalyst/util/Geography.java
+++
b/sql/catalyst/src/main/java/org/apache/spark/sql/catalyst/util/Geography.java
@@ -129,11 +129,6 @@ public final class Geography implements Geo {
/** Geography binary standard format converters: WKB and EWKB. */
- @Override
- public byte[] toWkb() {
- return toWkbInternal(DEFAULT_ENDIANNESS);
- }
-
@Override
public byte[] toWkb(ByteOrder endianness) {
return toWkbInternal(endianness);
diff --git
a/sql/catalyst/src/main/java/org/apache/spark/sql/catalyst/util/Geometry.java
b/sql/catalyst/src/main/java/org/apache/spark/sql/catalyst/util/Geometry.java
index 58be589b86ff..74cbb9d3b418 100644
---
a/sql/catalyst/src/main/java/org/apache/spark/sql/catalyst/util/Geometry.java
+++
b/sql/catalyst/src/main/java/org/apache/spark/sql/catalyst/util/Geometry.java
@@ -129,11 +129,6 @@ public final class Geometry implements Geo {
/** Geometry binary standard format converters: WKB and EWKB. */
- @Override
- public byte[] toWkb() {
- return toWkbInternal(DEFAULT_ENDIANNESS);
- }
-
@Override
public byte[] toWkb(ByteOrder endianness) {
return toWkbInternal(endianness);
diff --git
a/sql/catalyst/src/main/java/org/apache/spark/sql/catalyst/util/STUtils.java
b/sql/catalyst/src/main/java/org/apache/spark/sql/catalyst/util/STUtils.java
index 4026bbb2c22d..c5d57fd08fed 100644
--- a/sql/catalyst/src/main/java/org/apache/spark/sql/catalyst/util/STUtils.java
+++ b/sql/catalyst/src/main/java/org/apache/spark/sql/catalyst/util/STUtils.java
@@ -25,6 +25,8 @@ import org.apache.spark.unsafe.types.GeographyVal;
import org.apache.spark.unsafe.types.GeometryVal;
import org.apache.spark.unsafe.types.UTF8String;
+import java.nio.ByteOrder;
+
// This class defines static methods that used to implement ST expressions
using `StaticInvoke`.
public final class STUtils {
@@ -112,13 +114,28 @@ public final class STUtils {
/** Methods for implementing ST expressions. */
+ private static ByteOrder parseEndianness(UTF8String endianness) {
+ String endiannessString = endianness.toString();
+ if (endiannessString.equalsIgnoreCase("NDR")) return
ByteOrder.LITTLE_ENDIAN;
+ if (endiannessString.equalsIgnoreCase("XDR")) return ByteOrder.BIG_ENDIAN;
+ throw
QueryExecutionErrors.stInvalidArgumentErrorInvalidEndiannessValue(endiannessString);
+ }
+
// ST_AsBinary
public static byte[] stAsBinary(GeographyVal geo) {
- return fromPhysVal(geo).toWkb();
+ return fromPhysVal(geo).toWkb(ByteOrder.LITTLE_ENDIAN);
+ }
+
+ public static byte[] stAsBinary(GeographyVal geo, UTF8String endianness) {
+ return fromPhysVal(geo).toWkb(parseEndianness(endianness));
}
public static byte[] stAsBinary(GeometryVal geo) {
- return fromPhysVal(geo).toWkb();
+ return fromPhysVal(geo).toWkb(ByteOrder.LITTLE_ENDIAN);
+ }
+
+ public static byte[] stAsBinary(GeometryVal geo, UTF8String endianness) {
+ return fromPhysVal(geo).toWkb(parseEndianness(endianness));
}
// ST_AsEWKT
diff --git
a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/st/stExpressions.scala
b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/st/stExpressions.scala
index 986c0ef3a2ef..4e9a783b1b73 100755
---
a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/st/stExpressions.scala
+++
b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/st/stExpressions.scala
@@ -24,6 +24,7 @@ import org.apache.spark.sql.catalyst.expressions.objects._
import org.apache.spark.sql.catalyst.trees._
import org.apache.spark.sql.catalyst.util.{Geography, Geometry, STUtils}
import org.apache.spark.sql.internal.SQLConf
+import org.apache.spark.sql.internal.types.StringTypeWithCollation
import org.apache.spark.sql.types._
/**
@@ -51,55 +52,69 @@ sealed trait GeospatialInputTypes extends
ImplicitCastInputTypes {
private[sql] object ExpressionDefaults {
val DEFAULT_GEOGRAPHY_SRID: Int = Geography.DEFAULT_SRID
val DEFAULT_GEOMETRY_SRID: Int = Geometry.DEFAULT_SRID
+ val DEFAULT_WKB_ENDIANNESS: String = "NDR"
}
/** ST writer expressions. */
/**
- * Returns the input GEOGRAPHY or GEOMETRY value in WKB format.
+ * Returns the input GEOGRAPHY or GEOMETRY value in WKB format using the
specified endianness, if
+ * provided. If no endianness is provided, it defaults to little endian.
* See
https://en.wikipedia.org/wiki/Well-known_text_representation_of_geometry#Well-known_binary
* for more details on the WKB format.
*/
@ExpressionDescription(
- usage = "_FUNC_(geo) - Returns the geospatial value (value of type GEOGRAPHY
or GEOMETRY) "
- + "in WKB format.",
+ usage = "_FUNC_(geo[, endianness]) - Returns the geospatial value (value of
type GEOGRAPHY or "
+ + "GEOMETRY) in WKB format using the specified endianness ('NDR' for
little-endian, 'XDR' for "
+ + "big-endian), if provided. Defaults to little-endian encoding.",
arguments = """
Arguments:
* geo - A geospatial value, either a GEOGRAPHY or a GEOMETRY.
+ * endianness - The optional endianness of the output WKB, 'NDR' for
little-endian (default)
+ or 'XDR' for big-endian.
""",
examples = """
Examples:
> SELECT
hex(_FUNC_(st_geogfromwkb(X'0101000000000000000000F03F0000000000000040')));
0101000000000000000000F03F0000000000000040
- > SELECT
hex(_FUNC_(st_geomfromwkb(X'0101000000000000000000F03F0000000000000040')));
- 0101000000000000000000F03F0000000000000040
+ > SELECT
hex(_FUNC_(st_geomfromwkb(X'0101000000000000000000F03F0000000000000040'),
'XDR'));
+ 00000000013FF00000000000004000000000000000
""",
since = "4.1.0",
group = "st_funcs"
)
-case class ST_AsBinary(geo: Expression)
+case class ST_AsBinary(geo: Expression, endianness: Expression)
extends RuntimeReplaceable
with GeospatialInputTypes
- with UnaryLike[Expression] {
+ with BinaryLike[Expression] {
+
+ // If no endianness is given, default to little-endian encoding which is
represented by "NDR".
+ def this(geo: Expression) = {
+ this(geo, Literal(ExpressionDefaults.DEFAULT_WKB_ENDIANNESS))
+ }
override def inputTypes: Seq[AbstractDataType] = Seq(
- TypeCollection(GeographyType, GeometryType)
+ TypeCollection(GeographyType, GeometryType),
+ StringTypeWithCollation(supportsTrimCollation = true)
)
override lazy val replacement: Expression = StaticInvoke(
classOf[STUtils],
BinaryType,
"stAsBinary",
- Seq(geo),
+ Seq(geo, endianness),
returnNullable = false
)
override def prettyName: String = "st_asbinary"
- override def child: Expression = geo
+ override def left: Expression = geo
- override protected def withNewChildInternal(newChild: Expression):
ST_AsBinary =
- copy(geo = newChild)
+ override def right: Expression = endianness
+
+ override protected def withNewChildrenInternal(
+ newLeft: Expression,
+ newRight: Expression): ST_AsBinary = copy(geo = newLeft, endianness =
newRight)
}
/** ST reader expressions. */
diff --git
a/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryExecutionErrors.scala
b/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryExecutionErrors.scala
index 84fb16521105..0aa830827687 100644
---
a/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryExecutionErrors.scala
+++
b/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryExecutionErrors.scala
@@ -666,6 +666,14 @@ private[sql] object QueryExecutionErrors extends
QueryErrorsBase with ExecutionE
summary = "")
}
+ def stInvalidArgumentErrorInvalidEndiannessValue(
+ endianness: String): SparkIllegalArgumentException = {
+ new SparkIllegalArgumentException(
+ errorClass = "ST_INVALID_ENDIANNESS_VALUE",
+ messageParameters = Map("endianness" -> endianness)
+ )
+ }
+
def stInvalidSridValueError(srid: String): SparkIllegalArgumentException = {
new SparkIllegalArgumentException(
errorClass = "ST_INVALID_SRID_VALUE",
diff --git
a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/CatalystTypeConvertersSuite.scala
b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/CatalystTypeConvertersSuite.scala
index 9f4ce6797cf8..b730a6c27a3b 100644
---
a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/CatalystTypeConvertersSuite.scala
+++
b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/CatalystTypeConvertersSuite.scala
@@ -459,12 +459,14 @@ class CatalystTypeConvertersSuite extends SparkFunSuite
with SQLHelper {
private val pointWkb: Array[Byte] =
"010100000000000000000031400000000000001C40"
.grouped(2).map(Integer.parseInt(_, 16).toByte).toArray
+ private val NDR: UTF8String = UTF8String.fromString("NDR")
+
test("converting Geometry to GeometryType via convertToCatalyst") {
val geom = Geometry.fromWKB(pointWkb, 0)
val result = CatalystTypeConverters.convertToCatalyst(geom)
assert(result.isInstanceOf[GeometryVal])
val resultVal = result.asInstanceOf[GeometryVal]
- assert(java.util.Arrays.equals(STUtils.stAsBinary(resultVal), pointWkb))
+ assert(java.util.Arrays.equals(STUtils.stAsBinary(resultVal, NDR),
pointWkb))
assert(STUtils.stSrid(resultVal) === 0)
}
@@ -473,7 +475,7 @@ class CatalystTypeConvertersSuite extends SparkFunSuite
with SQLHelper {
val result = CatalystTypeConverters.convertToCatalyst(geom)
assert(result.isInstanceOf[GeometryVal])
val resultVal = result.asInstanceOf[GeometryVal]
- assert(java.util.Arrays.equals(STUtils.stAsBinary(resultVal), pointWkb))
+ assert(java.util.Arrays.equals(STUtils.stAsBinary(resultVal, NDR),
pointWkb))
assert(STUtils.stSrid(resultVal) === 4326)
}
@@ -482,7 +484,7 @@ class CatalystTypeConvertersSuite extends SparkFunSuite
with SQLHelper {
val result = CatalystTypeConverters.convertToCatalyst(geog)
assert(result.isInstanceOf[GeographyVal])
val resultVal = result.asInstanceOf[GeographyVal]
- assert(java.util.Arrays.equals(STUtils.stAsBinary(resultVal), pointWkb))
+ assert(java.util.Arrays.equals(STUtils.stAsBinary(resultVal, NDR),
pointWkb))
assert(STUtils.stSrid(resultVal) === 4326)
}
@@ -508,7 +510,7 @@ class CatalystTypeConvertersSuite extends SparkFunSuite
with SQLHelper {
val result = converter(geom)
assert(result.isInstanceOf[GeometryVal])
val resultVal = result.asInstanceOf[GeometryVal]
- assert(java.util.Arrays.equals(STUtils.stAsBinary(resultVal), pointWkb))
+ assert(java.util.Arrays.equals(STUtils.stAsBinary(resultVal, NDR),
pointWkb))
assert(STUtils.stSrid(resultVal) === 0)
}
@@ -519,7 +521,7 @@ class CatalystTypeConvertersSuite extends SparkFunSuite
with SQLHelper {
val result = converter(geog)
assert(result.isInstanceOf[GeographyVal])
val resultVal = result.asInstanceOf[GeographyVal]
- assert(java.util.Arrays.equals(STUtils.stAsBinary(resultVal), pointWkb))
+ assert(java.util.Arrays.equals(STUtils.stAsBinary(resultVal, NDR),
pointWkb))
assert(STUtils.stSrid(resultVal) === 4326)
}
@@ -581,7 +583,7 @@ class CatalystTypeConvertersSuite extends SparkFunSuite
with SQLHelper {
val element = array.get(0, GeometryType("ANY"))
assert(element.isInstanceOf[GeometryVal])
assert(java.util.Arrays.equals(
- STUtils.stAsBinary(element.asInstanceOf[GeometryVal]), pointWkb))
+ STUtils.stAsBinary(element.asInstanceOf[GeometryVal], NDR), pointWkb))
}
test("convertToCatalyst with Geometry nested in Array") {
@@ -593,7 +595,7 @@ class CatalystTypeConvertersSuite extends SparkFunSuite
with SQLHelper {
val element = array.get(0, GeometryType("ANY"))
assert(element.isInstanceOf[GeometryVal])
assert(java.util.Arrays.equals(
- STUtils.stAsBinary(element.asInstanceOf[GeometryVal]), pointWkb))
+ STUtils.stAsBinary(element.asInstanceOf[GeometryVal], NDR), pointWkb))
}
test("convertToCatalyst with Geometry nested in Map") {
@@ -604,7 +606,7 @@ class CatalystTypeConvertersSuite extends SparkFunSuite
with SQLHelper {
val value = mapData.valueArray.get(0, GeometryType("ANY"))
assert(value.isInstanceOf[GeometryVal])
assert(java.util.Arrays.equals(
- STUtils.stAsBinary(value.asInstanceOf[GeometryVal]), pointWkb))
+ STUtils.stAsBinary(value.asInstanceOf[GeometryVal], NDR), pointWkb))
}
test("convertToCatalyst with Geometry nested in Row") {
@@ -614,7 +616,7 @@ class CatalystTypeConvertersSuite extends SparkFunSuite
with SQLHelper {
val element = result.asInstanceOf[InternalRow].get(0, GeometryType("ANY"))
assert(element.isInstanceOf[GeometryVal])
assert(java.util.Arrays.equals(
- STUtils.stAsBinary(element.asInstanceOf[GeometryVal]), pointWkb))
+ STUtils.stAsBinary(element.asInstanceOf[GeometryVal], NDR), pointWkb))
}
test("convertToCatalyst with Geography nested in Seq") {
@@ -626,7 +628,7 @@ class CatalystTypeConvertersSuite extends SparkFunSuite
with SQLHelper {
val element = array.get(0, GeographyType("ANY"))
assert(element.isInstanceOf[GeographyVal])
assert(java.util.Arrays.equals(
- STUtils.stAsBinary(element.asInstanceOf[GeographyVal]), pointWkb))
+ STUtils.stAsBinary(element.asInstanceOf[GeographyVal], NDR), pointWkb))
}
test("convertToCatalyst with Geography nested in Array") {
@@ -638,7 +640,7 @@ class CatalystTypeConvertersSuite extends SparkFunSuite
with SQLHelper {
val element = array.get(0, GeographyType("ANY"))
assert(element.isInstanceOf[GeographyVal])
assert(java.util.Arrays.equals(
- STUtils.stAsBinary(element.asInstanceOf[GeographyVal]), pointWkb))
+ STUtils.stAsBinary(element.asInstanceOf[GeographyVal], NDR), pointWkb))
}
test("convertToCatalyst with Geography nested in Map") {
@@ -649,7 +651,7 @@ class CatalystTypeConvertersSuite extends SparkFunSuite
with SQLHelper {
val value = mapData.valueArray.get(0, GeographyType("ANY"))
assert(value.isInstanceOf[GeographyVal])
assert(java.util.Arrays.equals(
- STUtils.stAsBinary(value.asInstanceOf[GeographyVal]), pointWkb))
+ STUtils.stAsBinary(value.asInstanceOf[GeographyVal], NDR), pointWkb))
}
test("convertToCatalyst with Geography nested in Row") {
@@ -659,6 +661,6 @@ class CatalystTypeConvertersSuite extends SparkFunSuite
with SQLHelper {
val element = result.asInstanceOf[InternalRow].get(0, GeographyType("ANY"))
assert(element.isInstanceOf[GeographyVal])
assert(java.util.Arrays.equals(
- STUtils.stAsBinary(element.asInstanceOf[GeographyVal]), pointWkb))
+ STUtils.stAsBinary(element.asInstanceOf[GeographyVal], NDR), pointWkb))
}
}
diff --git
a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/GeographyExecutionSuite.java
b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/GeographyExecutionSuite.java
index fece3e36bc59..537aa96f7026 100644
---
a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/GeographyExecutionSuite.java
+++
b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/GeographyExecutionSuite.java
@@ -101,7 +101,7 @@ class GeographyExecutionSuite {
byte[] wkb = getTestWKBPoint();
Geography geography = Geography.fromWkb(wkb, 4326);
assertNotNull(geography);
- assertArrayEquals(wkb, geography.toWkb());
+ assertArrayEquals(wkb, geography.toWkb(ByteOrder.LITTLE_ENDIAN));
assertEquals(4326, geography.srid());
}
@@ -110,7 +110,7 @@ class GeographyExecutionSuite {
byte[] wkb = getTestWKBPoint();
Geography geography = Geography.fromWkb(wkb);
assertNotNull(geography);
- assertArrayEquals(wkb, geography.toWkb());
+ assertArrayEquals(wkb, geography.toWkb(ByteOrder.LITTLE_ENDIAN));
assertEquals(4326, geography.srid());
}
@@ -178,7 +178,7 @@ class GeographyExecutionSuite {
Geography geography = Geography.fromBytes(testGeographyVal);
// WKB value (endianness: NDR) corresponding to WKT: POINT(1 2).
byte[] wkb =
HexFormat.of().parseHex("0101000000000000000000f03f0000000000000040");
- assertArrayEquals(wkb, geography.toWkb());
+ assertArrayEquals(wkb, geography.toWkb(ByteOrder.LITTLE_ENDIAN));
}
@Test
diff --git
a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/GeometryExecutionSuite.java
b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/GeometryExecutionSuite.java
index 5d0b11e969ad..7258f5915558 100644
---
a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/GeometryExecutionSuite.java
+++
b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/GeometryExecutionSuite.java
@@ -113,7 +113,7 @@ class GeometryExecutionSuite {
byte[] wkb = getTestWKBPoint();
Geometry geometry = Geometry.fromWkb(wkb, 4326);
assertNotNull(geometry);
- assertArrayEquals(wkb, geometry.toWkb());
+ assertArrayEquals(wkb, geometry.toWkb(ByteOrder.LITTLE_ENDIAN));
assertEquals(4326, geometry.srid());
}
@@ -124,7 +124,7 @@ class GeometryExecutionSuite {
// Once we implement the appropriate parsing logic, this test should be
updated accordingly.
Geometry geometry = Geometry.fromWkb(wkb);
assertNotNull(geometry);
- assertArrayEquals(wkb, geometry.toWkb());
+ assertArrayEquals(wkb, geometry.toWkb(ByteOrder.LITTLE_ENDIAN));
assertEquals(0, geometry.srid());
}
@@ -192,7 +192,7 @@ class GeometryExecutionSuite {
Geometry geometry = Geometry.fromBytes(testGeometryVal);
// WKB value (endianness: NDR) corresponding to WKT: POINT(1 2).
byte[] wkb =
HexFormat.of().parseHex("0101000000000000000000f03f0000000000000040");
- assertArrayEquals(wkb, geometry.toWkb());
+ assertArrayEquals(wkb, geometry.toWkb(ByteOrder.LITTLE_ENDIAN));
}
@Test
diff --git
a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/StUtilsSuite.java
b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/StUtilsSuite.java
index aa1b4735cf62..c3a806d897dd 100644
---
a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/StUtilsSuite.java
+++
b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/StUtilsSuite.java
@@ -20,6 +20,7 @@ package org.apache.spark.sql.catalyst.util;
import org.apache.spark.SparkIllegalArgumentException;
import org.apache.spark.unsafe.types.GeographyVal;
import org.apache.spark.unsafe.types.GeometryVal;
+import org.apache.spark.unsafe.types.UTF8String;
import org.junit.jupiter.api.Test;
import java.nio.ByteBuffer;
@@ -38,6 +39,8 @@ class STUtilsSuite {
private final byte[] testWkb = new byte[] {0x01, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00,
0x00, 0x00, 0x00, (byte)0xF0, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x40};
+ private final UTF8String ENDIANNESS_NDR = UTF8String.fromString("NDR");
+
// A sample Geography byte array for testing purposes, representing a
POINT(1 2) with SRID 4326.
private final int testGeographySrid = 4326;
private final byte[] testGeographyBytes;
@@ -111,7 +114,7 @@ class STUtilsSuite {
@Test
void testStAsBinaryGeography() {
GeographyVal geographyVal = GeographyVal.fromBytes(testGeographyBytes);
- byte[] geographyWkb = STUtils.stAsBinary(geographyVal);
+ byte[] geographyWkb = STUtils.stAsBinary(geographyVal, ENDIANNESS_NDR);
assertNotNull(geographyWkb);
assertArrayEquals(testWkb, geographyWkb);
}
@@ -119,7 +122,7 @@ class STUtilsSuite {
@Test
void testStAsBinaryGeometry() {
GeometryVal geometryVal = GeometryVal.fromBytes(testGeometryBytes);
- byte[] geometryWkb = STUtils.stAsBinary(geometryVal);
+ byte[] geometryWkb = STUtils.stAsBinary(geometryVal, ENDIANNESS_NDR);
assertNotNull(geometryWkb);
assertArrayEquals(testWkb, geometryWkb);
}
diff --git a/sql/core/src/test/resources/sql-functions/sql-expression-schema.md
b/sql/core/src/test/resources/sql-functions/sql-expression-schema.md
index b195f7615687..c56db6c9b7e3 100644
--- a/sql/core/src/test/resources/sql-functions/sql-expression-schema.md
+++ b/sql/core/src/test/resources/sql-functions/sql-expression-schema.md
@@ -537,9 +537,9 @@
| org.apache.spark.sql.catalyst.expressions.aggregate.VariancePop | var_pop |
SELECT var_pop(col) FROM VALUES (1), (2), (3) AS tab(col) |
struct<var_pop(col):double> |
| org.apache.spark.sql.catalyst.expressions.aggregate.VarianceSamp | var_samp
| SELECT var_samp(col) FROM VALUES (1), (2), (3) AS tab(col) |
struct<var_samp(col):double> |
| org.apache.spark.sql.catalyst.expressions.aggregate.VarianceSamp | variance
| SELECT variance(col) FROM VALUES (1), (2), (3) AS tab(col) |
struct<variance(col):double> |
-| org.apache.spark.sql.catalyst.expressions.st.ST_AsBinary | st_asbinary |
SELECT
hex(st_asbinary(st_geogfromwkb(X'0101000000000000000000F03F0000000000000040')))
|
struct<hex(st_asbinary(st_geogfromwkb(X'0101000000000000000000F03F0000000000000040'))):string>
|
-| org.apache.spark.sql.catalyst.expressions.st.ST_GeogFromWKB | st_geogfromwkb
| SELECT
hex(st_asbinary(st_geogfromwkb(X'0101000000000000000000F03F0000000000000040')))
|
struct<hex(st_asbinary(st_geogfromwkb(X'0101000000000000000000F03F0000000000000040'))):string>
|
-| org.apache.spark.sql.catalyst.expressions.st.ST_GeomFromWKB | st_geomfromwkb
| SELECT
hex(st_asbinary(st_geomfromwkb(X'0101000000000000000000F03F0000000000000040')))
|
struct<hex(st_asbinary(st_geomfromwkb(X'0101000000000000000000F03F0000000000000040',
0))):string> |
+| org.apache.spark.sql.catalyst.expressions.st.ST_AsBinary | st_asbinary |
SELECT
hex(st_asbinary(st_geogfromwkb(X'0101000000000000000000F03F0000000000000040')))
|
struct<hex(st_asbinary(st_geogfromwkb(X'0101000000000000000000F03F0000000000000040'),
NDR)):string> |
+| org.apache.spark.sql.catalyst.expressions.st.ST_GeogFromWKB | st_geogfromwkb
| SELECT
hex(st_asbinary(st_geogfromwkb(X'0101000000000000000000F03F0000000000000040')))
|
struct<hex(st_asbinary(st_geogfromwkb(X'0101000000000000000000F03F0000000000000040'),
NDR)):string> |
+| org.apache.spark.sql.catalyst.expressions.st.ST_GeomFromWKB | st_geomfromwkb
| SELECT
hex(st_asbinary(st_geomfromwkb(X'0101000000000000000000F03F0000000000000040')))
|
struct<hex(st_asbinary(st_geomfromwkb(X'0101000000000000000000F03F0000000000000040',
0), NDR)):string> |
| org.apache.spark.sql.catalyst.expressions.st.ST_SetSrid | st_setsrid |
SELECT
st_srid(st_setsrid(ST_GeogFromWKB(X'0101000000000000000000F03F0000000000000040'),
4326)) |
struct<st_srid(st_setsrid(st_geogfromwkb(X'0101000000000000000000F03F0000000000000040'),
4326)):int> |
| org.apache.spark.sql.catalyst.expressions.st.ST_Srid | st_srid | SELECT
st_srid(st_geogfromwkb(X'0101000000000000000000F03F0000000000000040')) |
struct<st_srid(st_geogfromwkb(X'0101000000000000000000F03F0000000000000040')):int>
|
| org.apache.spark.sql.catalyst.expressions.variant.IsValidVariant |
is_valid_variant | SELECT is_valid_variant(parse_json('null')) |
struct<is_valid_variant(parse_json(null)):boolean> |
diff --git
a/sql/core/src/test/resources/sql-tests/analyzer-results/st-functions.sql.out
b/sql/core/src/test/resources/sql-tests/analyzer-results/st-functions.sql.out
index 34969f43e1f7..dd30adde9843 100644
---
a/sql/core/src/test/resources/sql-tests/analyzer-results/st-functions.sql.out
+++
b/sql/core/src/test/resources/sql-tests/analyzer-results/st-functions.sql.out
@@ -224,7 +224,7 @@ org.apache.spark.sql.catalyst.ExtendedAnalysisException
-- !query
SELECT
hex(ST_AsBinary(CAST(ST_GeogFromWKB(X'0101000000000000000000f03f0000000000000040')
AS GEOGRAPHY(ANY)))) AS result
-- !query analysis
-Project
[hex(st_asbinary(cast(st_geogfromwkb(0x0101000000000000000000F03F0000000000000040)
as geography(any)))) AS result#x]
+Project
[hex(st_asbinary(cast(st_geogfromwkb(0x0101000000000000000000F03F0000000000000040)
as geography(any)), NDR)) AS result#x]
+- OneRowRelation
@@ -253,7 +253,7 @@ org.apache.spark.sql.catalyst.ExtendedAnalysisException
-- !query
SELECT
hex(ST_AsBinary(CAST(ST_GeogFromWKB(X'0101000000000000000000f03f0000000000000040')
AS GEOMETRY(4326)))) AS result
-- !query analysis
-Project
[hex(st_asbinary(cast(st_geogfromwkb(0x0101000000000000000000F03F0000000000000040)
as geometry(4326)))) AS result#x]
+Project
[hex(st_asbinary(cast(st_geogfromwkb(0x0101000000000000000000F03F0000000000000040)
as geometry(4326)), NDR)) AS result#x]
+- OneRowRelation
@@ -282,7 +282,7 @@ org.apache.spark.sql.catalyst.ExtendedAnalysisException
-- !query
SELECT
hex(ST_AsBinary(CAST(ST_GeomFromWKB(X'0101000000000000000000f03f0000000000000040')
AS GEOMETRY(ANY)))) AS result
-- !query analysis
-Project
[hex(st_asbinary(cast(st_geomfromwkb(0x0101000000000000000000F03F0000000000000040,
0) as geometry(any)))) AS result#x]
+Project
[hex(st_asbinary(cast(st_geomfromwkb(0x0101000000000000000000F03F0000000000000040,
0) as geometry(any)), NDR)) AS result#x]
+- OneRowRelation
@@ -311,7 +311,7 @@ org.apache.spark.sql.catalyst.ExtendedAnalysisException
-- !query
SELECT
hex(ST_AsBinary(CAST(ST_GeomFromWKB(X'0101000000000000000000f03f0000000000000040',
4326) AS GEOGRAPHY(4326)))) AS result
-- !query analysis
-Project
[hex(st_asbinary(cast(st_geomfromwkb(0x0101000000000000000000F03F0000000000000040,
4326) as geography(4326)))) AS result#x]
+Project
[hex(st_asbinary(cast(st_geomfromwkb(0x0101000000000000000000F03F0000000000000040,
4326) as geography(4326)), NDR)) AS result#x]
+- OneRowRelation
@@ -491,28 +491,28 @@ Project [typeof(if (isnotnull(wkb#x))
cast(st_geomfromwkb(wkb#x, 0) as geometry(
-- !query
SELECT
hex(ST_AsBinary(ST_GeogFromWKB(X'0101000000000000000000f03f0000000000000040')))
AS result
-- !query analysis
-Project
[hex(st_asbinary(st_geogfromwkb(0x0101000000000000000000F03F0000000000000040)))
AS result#x]
+Project
[hex(st_asbinary(st_geogfromwkb(0x0101000000000000000000F03F0000000000000040),
NDR)) AS result#x]
+- OneRowRelation
-- !query
SELECT
hex(ST_AsBinary(ST_GeomFromWKB(X'0101000000000000000000f03f0000000000000040')))
AS result
-- !query analysis
-Project
[hex(st_asbinary(st_geomfromwkb(0x0101000000000000000000F03F0000000000000040,
0))) AS result#x]
+Project
[hex(st_asbinary(st_geomfromwkb(0x0101000000000000000000F03F0000000000000040,
0), NDR)) AS result#x]
+- OneRowRelation
-- !query
SELECT ST_AsBinary(ST_GeogFromWKB(NULL))
-- !query analysis
-Project [st_asbinary(st_geogfromwkb(cast(null as binary))) AS
st_asbinary(st_geogfromwkb(NULL))#x]
+Project [st_asbinary(st_geogfromwkb(cast(null as binary)), NDR) AS
st_asbinary(st_geogfromwkb(NULL), NDR)#x]
+- OneRowRelation
-- !query
SELECT
hex(ST_AsBinary(ST_GeogFromWKB(X'0101000000000000000000F03F0000000000000040')))
-- !query analysis
-Project
[hex(st_asbinary(st_geogfromwkb(0x0101000000000000000000F03F0000000000000040)))
AS
hex(st_asbinary(st_geogfromwkb(X'0101000000000000000000F03F0000000000000040')))#x]
+Project
[hex(st_asbinary(st_geogfromwkb(0x0101000000000000000000F03F0000000000000040),
NDR)) AS
hex(st_asbinary(st_geogfromwkb(X'0101000000000000000000F03F0000000000000040'),
NDR))#x]
+- OneRowRelation
@@ -536,7 +536,7 @@ Aggregate [count(1) AS count(1)#xL]
SELECT COUNT(*) FROM geodata WHERE ST_AsBinary(ST_GeogFromWKB(wkb)) <> wkb
-- !query analysis
Aggregate [count(1) AS count(1)#xL]
-+- Filter NOT (st_asbinary(st_geogfromwkb(wkb#x)) = wkb#x)
++- Filter NOT (st_asbinary(st_geogfromwkb(wkb#x), NDR) = wkb#x)
+- SubqueryAlias spark_catalog.default.geodata
+- Relation spark_catalog.default.geodata[wkb#x] parquet
@@ -544,35 +544,35 @@ Aggregate [count(1) AS count(1)#xL]
-- !query
SELECT ST_AsBinary(ST_GeomFromWKB(NULL))
-- !query analysis
-Project [st_asbinary(st_geomfromwkb(cast(null as binary), 0)) AS
st_asbinary(st_geomfromwkb(NULL, 0))#x]
+Project [st_asbinary(st_geomfromwkb(cast(null as binary), 0), NDR) AS
st_asbinary(st_geomfromwkb(NULL, 0), NDR)#x]
+- OneRowRelation
-- !query
SELECT
hex(ST_AsBinary(ST_GeomFromWKB(X'0101000000000000000000F03F0000000000000040')))
-- !query analysis
-Project
[hex(st_asbinary(st_geomfromwkb(0x0101000000000000000000F03F0000000000000040,
0))) AS
hex(st_asbinary(st_geomfromwkb(X'0101000000000000000000F03F0000000000000040',
0)))#x]
+Project
[hex(st_asbinary(st_geomfromwkb(0x0101000000000000000000F03F0000000000000040,
0), NDR)) AS
hex(st_asbinary(st_geomfromwkb(X'0101000000000000000000F03F0000000000000040',
0), NDR))#x]
+- OneRowRelation
-- !query
SELECT
hex(ST_AsBinary(ST_GeomFromWKB(X'0101000000000000000000F03F0000000000000040',
0)))
-- !query analysis
-Project
[hex(st_asbinary(st_geomfromwkb(0x0101000000000000000000F03F0000000000000040,
0))) AS
hex(st_asbinary(st_geomfromwkb(X'0101000000000000000000F03F0000000000000040',
0)))#x]
+Project
[hex(st_asbinary(st_geomfromwkb(0x0101000000000000000000F03F0000000000000040,
0), NDR)) AS
hex(st_asbinary(st_geomfromwkb(X'0101000000000000000000F03F0000000000000040',
0), NDR))#x]
+- OneRowRelation
-- !query
SELECT
hex(ST_AsBinary(ST_GeomFromWKB(X'0101000000000000000000F03F0000000000000040',
3857)))
-- !query analysis
-Project
[hex(st_asbinary(st_geomfromwkb(0x0101000000000000000000F03F0000000000000040,
3857))) AS
hex(st_asbinary(st_geomfromwkb(X'0101000000000000000000F03F0000000000000040',
3857)))#x]
+Project
[hex(st_asbinary(st_geomfromwkb(0x0101000000000000000000F03F0000000000000040,
3857), NDR)) AS
hex(st_asbinary(st_geomfromwkb(X'0101000000000000000000F03F0000000000000040',
3857), NDR))#x]
+- OneRowRelation
-- !query
SELECT
hex(ST_AsBinary(ST_GeomFromWKB(X'0101000000000000000000F03F0000000000000040',
4326)))
-- !query analysis
-Project
[hex(st_asbinary(st_geomfromwkb(0x0101000000000000000000F03F0000000000000040,
4326))) AS
hex(st_asbinary(st_geomfromwkb(X'0101000000000000000000F03F0000000000000040',
4326)))#x]
+Project
[hex(st_asbinary(st_geomfromwkb(0x0101000000000000000000F03F0000000000000040,
4326), NDR)) AS
hex(st_asbinary(st_geomfromwkb(X'0101000000000000000000F03F0000000000000040',
4326), NDR))#x]
+- OneRowRelation
@@ -638,7 +638,7 @@ Aggregate [count(1) AS count(1)#xL]
SELECT COUNT(*) FROM geodata WHERE ST_AsBinary(ST_GeomFromWKB(wkb)) <> wkb
-- !query analysis
Aggregate [count(1) AS count(1)#xL]
-+- Filter NOT (st_asbinary(st_geomfromwkb(wkb#x, 0)) = wkb#x)
++- Filter NOT (st_asbinary(st_geomfromwkb(wkb#x, 0), NDR) = wkb#x)
+- SubqueryAlias spark_catalog.default.geodata
+- Relation spark_catalog.default.geodata[wkb#x] parquet
@@ -647,7 +647,7 @@ Aggregate [count(1) AS count(1)#xL]
SELECT COUNT(*) FROM geodata WHERE ST_AsBinary(ST_GeomFromWKB(wkb, 4326)) <>
wkb
-- !query analysis
Aggregate [count(1) AS count(1)#xL]
-+- Filter NOT (st_asbinary(st_geomfromwkb(wkb#x, 4326)) = wkb#x)
++- Filter NOT (st_asbinary(st_geomfromwkb(wkb#x, 4326), NDR) = wkb#x)
+- SubqueryAlias spark_catalog.default.geodata
+- Relation spark_catalog.default.geodata[wkb#x] parquet
@@ -665,6 +665,157 @@ org.apache.spark.SparkIllegalArgumentException
}
+-- !query
+SELECT ST_AsBinary(NULL)
+-- !query analysis
+Project [st_asbinary(cast(null as geography(any)), NDR) AS st_asbinary(NULL,
NDR)#x]
++- OneRowRelation
+
+
+-- !query
+SELECT
hex(ST_AsBinary(ST_GeogFromWKB(X'0101000000000000000000F03F0000000000000040')))
+-- !query analysis
+Project
[hex(st_asbinary(st_geogfromwkb(0x0101000000000000000000F03F0000000000000040),
NDR)) AS
hex(st_asbinary(st_geogfromwkb(X'0101000000000000000000F03F0000000000000040'),
NDR))#x]
++- OneRowRelation
+
+
+-- !query
+SELECT
hex(ST_AsBinary(ST_GeogFromWKB(X'00000000013FF00000000000004000000000000000'),
'NDR'))
+-- !query analysis
+Project
[hex(st_asbinary(st_geogfromwkb(0x00000000013FF00000000000004000000000000000),
NDR)) AS
hex(st_asbinary(st_geogfromwkb(X'00000000013FF00000000000004000000000000000'),
NDR))#x]
++- OneRowRelation
+
+
+-- !query
+SELECT
hex(ST_AsBinary(ST_GeogFromWKB(X'0101000000000000000000F03F0000000000000040'),
'XDR'))
+-- !query analysis
+Project
[hex(st_asbinary(st_geogfromwkb(0x0101000000000000000000F03F0000000000000040),
XDR)) AS
hex(st_asbinary(st_geogfromwkb(X'0101000000000000000000F03F0000000000000040'),
XDR))#x]
++- OneRowRelation
+
+
+-- !query
+SELECT
hex(ST_AsBinary(ST_GeomFromWKB(X'0101000000000000000000F03F0000000000000040')))
+-- !query analysis
+Project
[hex(st_asbinary(st_geomfromwkb(0x0101000000000000000000F03F0000000000000040,
0), NDR)) AS
hex(st_asbinary(st_geomfromwkb(X'0101000000000000000000F03F0000000000000040',
0), NDR))#x]
++- OneRowRelation
+
+
+-- !query
+SELECT
hex(ST_AsBinary(ST_GeomFromWKB(X'00000000013FF00000000000004000000000000000'),
'NDR'))
+-- !query analysis
+Project
[hex(st_asbinary(st_geomfromwkb(0x00000000013FF00000000000004000000000000000,
0), NDR)) AS
hex(st_asbinary(st_geomfromwkb(X'00000000013FF00000000000004000000000000000',
0), NDR))#x]
++- OneRowRelation
+
+
+-- !query
+SELECT
hex(ST_AsBinary(ST_GeomFromWKB(X'0101000000000000000000F03F0000000000000040'),
'XDR'))
+-- !query analysis
+Project
[hex(st_asbinary(st_geomfromwkb(0x0101000000000000000000F03F0000000000000040,
0), XDR)) AS
hex(st_asbinary(st_geomfromwkb(X'0101000000000000000000F03F0000000000000040',
0), XDR))#x]
++- OneRowRelation
+
+
+-- !query
+SELECT
ST_AsBinary(ST_GeogFromWKB(X'0101000000000000000000F03F0000000000000040'), '')
+-- !query analysis
+Project
[st_asbinary(st_geogfromwkb(0x0101000000000000000000F03F0000000000000040), ) AS
st_asbinary(st_geogfromwkb(X'0101000000000000000000F03F0000000000000040'), )#x]
++- OneRowRelation
+
+
+-- !query
+SELECT
ST_AsBinary(ST_GeogFromWKB(X'0101000000000000000000F03F0000000000000040'),
'ABC')
+-- !query analysis
+Project
[st_asbinary(st_geogfromwkb(0x0101000000000000000000F03F0000000000000040), ABC)
AS st_asbinary(st_geogfromwkb(X'0101000000000000000000F03F0000000000000040'),
ABC)#x]
++- OneRowRelation
+
+
+-- !query
+SELECT
ST_AsBinary(ST_GeogFromWKB(X'0101000000000000000000F03F0000000000000040'),
'big-endian')
+-- !query analysis
+Project
[st_asbinary(st_geogfromwkb(0x0101000000000000000000F03F0000000000000040),
big-endian) AS
st_asbinary(st_geogfromwkb(X'0101000000000000000000F03F0000000000000040'),
big-endian)#x]
++- OneRowRelation
+
+
+-- !query
+SELECT COUNT(*) FROM geodata WHERE ST_AsBinary(ST_GeogFromWKB(wkb)) <> wkb
+-- !query analysis
+Aggregate [count(1) AS count(1)#xL]
++- Filter NOT (st_asbinary(st_geogfromwkb(wkb#x), NDR) = wkb#x)
+ +- SubqueryAlias spark_catalog.default.geodata
+ +- Relation spark_catalog.default.geodata[wkb#x] parquet
+
+
+-- !query
+SELECT COUNT(*) FROM geodata WHERE ST_AsBinary(ST_GeogFromWKB(wkb), 'NDR') <>
wkb
+-- !query analysis
+Aggregate [count(1) AS count(1)#xL]
++- Filter NOT (st_asbinary(st_geogfromwkb(wkb#x), NDR) = wkb#x)
+ +- SubqueryAlias spark_catalog.default.geodata
+ +- Relation spark_catalog.default.geodata[wkb#x] parquet
+
+
+-- !query
+SELECT COUNT(*) FROM geodata WHERE ST_AsBinary(ST_GeogFromWKB(wkb), 'XDR') =
wkb
+-- !query analysis
+Aggregate [count(1) AS count(1)#xL]
++- Filter (st_asbinary(st_geogfromwkb(wkb#x), XDR) = wkb#x)
+ +- SubqueryAlias spark_catalog.default.geodata
+ +- Relation spark_catalog.default.geodata[wkb#x] parquet
+
+
+-- !query
+SELECT COUNT(*) FROM geodata WHERE ST_AsBinary(ST_GeomFromWKB(wkb)) <> wkb
+-- !query analysis
+Aggregate [count(1) AS count(1)#xL]
++- Filter NOT (st_asbinary(st_geomfromwkb(wkb#x, 0), NDR) = wkb#x)
+ +- SubqueryAlias spark_catalog.default.geodata
+ +- Relation spark_catalog.default.geodata[wkb#x] parquet
+
+
+-- !query
+SELECT COUNT(*) FROM geodata WHERE ST_AsBinary(ST_GeomFromWKB(wkb), 'NDR') <>
wkb
+-- !query analysis
+Aggregate [count(1) AS count(1)#xL]
++- Filter NOT (st_asbinary(st_geomfromwkb(wkb#x, 0), NDR) = wkb#x)
+ +- SubqueryAlias spark_catalog.default.geodata
+ +- Relation spark_catalog.default.geodata[wkb#x] parquet
+
+
+-- !query
+SELECT COUNT(*) FROM geodata WHERE ST_AsBinary(ST_GeomFromWKB(wkb), 'XDR') =
wkb
+-- !query analysis
+Aggregate [count(1) AS count(1)#xL]
++- Filter (st_asbinary(st_geomfromwkb(wkb#x, 0), XDR) = wkb#x)
+ +- SubqueryAlias spark_catalog.default.geodata
+ +- Relation spark_catalog.default.geodata[wkb#x] parquet
+
+
+-- !query
+SELECT COUNT(*) FROM geodata WHERE ST_AsBinary(ST_GeogFromWKB(wkb), '') IS NOT
NULL
+-- !query analysis
+Aggregate [count(1) AS count(1)#xL]
++- Filter isnotnull(st_asbinary(st_geogfromwkb(wkb#x), ))
+ +- SubqueryAlias spark_catalog.default.geodata
+ +- Relation spark_catalog.default.geodata[wkb#x] parquet
+
+
+-- !query
+SELECT COUNT(*) FROM geodata WHERE ST_AsBinary(ST_GeogFromWKB(wkb), 'ABC') IS
NOT NULL
+-- !query analysis
+Aggregate [count(1) AS count(1)#xL]
++- Filter isnotnull(st_asbinary(st_geogfromwkb(wkb#x), ABC))
+ +- SubqueryAlias spark_catalog.default.geodata
+ +- Relation spark_catalog.default.geodata[wkb#x] parquet
+
+
+-- !query
+SELECT COUNT(*) FROM geodata WHERE ST_AsBinary(ST_GeogFromWKB(wkb),
'big-endian') IS NOT NULL
+-- !query analysis
+Aggregate [count(1) AS count(1)#xL]
++- Filter isnotnull(st_asbinary(st_geogfromwkb(wkb#x), big-endian))
+ +- SubqueryAlias spark_catalog.default.geodata
+ +- Relation spark_catalog.default.geodata[wkb#x] parquet
+
+
-- !query
SELECT ST_Srid(NULL)
-- !query analysis
diff --git a/sql/core/src/test/resources/sql-tests/inputs/st-functions.sql
b/sql/core/src/test/resources/sql-tests/inputs/st-functions.sql
index 0db835bc7e85..62b9a1b8f614 100644
--- a/sql/core/src/test/resources/sql-tests/inputs/st-functions.sql
+++ b/sql/core/src/test/resources/sql-tests/inputs/st-functions.sql
@@ -137,6 +137,33 @@ SELECT COUNT(*) FROM geodata WHERE
ST_AsBinary(ST_GeomFromWKB(wkb, 4326)) <> wkb
-- Error handling: invalid SRID.
SELECT COUNT(*) FROM geodata WHERE ST_GeomFromWKB(wkb, 1);
+---- ST_AsBinary
+
+-- 1. Driver-level queries.
+SELECT ST_AsBinary(NULL);
+SELECT
hex(ST_AsBinary(ST_GeogFromWKB(X'0101000000000000000000F03F0000000000000040')));
+SELECT
hex(ST_AsBinary(ST_GeogFromWKB(X'00000000013FF00000000000004000000000000000'),
'NDR'));
+SELECT
hex(ST_AsBinary(ST_GeogFromWKB(X'0101000000000000000000F03F0000000000000040'),
'XDR'));
+SELECT
hex(ST_AsBinary(ST_GeomFromWKB(X'0101000000000000000000F03F0000000000000040')));
+SELECT
hex(ST_AsBinary(ST_GeomFromWKB(X'00000000013FF00000000000004000000000000000'),
'NDR'));
+SELECT
hex(ST_AsBinary(ST_GeomFromWKB(X'0101000000000000000000F03F0000000000000040'),
'XDR'));
+-- Error handling: invalid endianness.
+SELECT
ST_AsBinary(ST_GeogFromWKB(X'0101000000000000000000F03F0000000000000040'), '');
+SELECT
ST_AsBinary(ST_GeogFromWKB(X'0101000000000000000000F03F0000000000000040'),
'ABC');
+SELECT
ST_AsBinary(ST_GeogFromWKB(X'0101000000000000000000F03F0000000000000040'),
'big-endian');
+
+-- 2. Table-level queries.
+SELECT COUNT(*) FROM geodata WHERE ST_AsBinary(ST_GeogFromWKB(wkb)) <> wkb;
+SELECT COUNT(*) FROM geodata WHERE ST_AsBinary(ST_GeogFromWKB(wkb), 'NDR') <>
wkb;
+SELECT COUNT(*) FROM geodata WHERE ST_AsBinary(ST_GeogFromWKB(wkb), 'XDR') =
wkb;
+SELECT COUNT(*) FROM geodata WHERE ST_AsBinary(ST_GeomFromWKB(wkb)) <> wkb;
+SELECT COUNT(*) FROM geodata WHERE ST_AsBinary(ST_GeomFromWKB(wkb), 'NDR') <>
wkb;
+SELECT COUNT(*) FROM geodata WHERE ST_AsBinary(ST_GeomFromWKB(wkb), 'XDR') =
wkb;
+-- Error handling: invalid endianness.
+SELECT COUNT(*) FROM geodata WHERE ST_AsBinary(ST_GeogFromWKB(wkb), '') IS NOT
NULL;
+SELECT COUNT(*) FROM geodata WHERE ST_AsBinary(ST_GeogFromWKB(wkb), 'ABC') IS
NOT NULL;
+SELECT COUNT(*) FROM geodata WHERE ST_AsBinary(ST_GeogFromWKB(wkb),
'big-endian') IS NOT NULL;
+
------ ST accessor expressions
---- ST_Srid
diff --git a/sql/core/src/test/resources/sql-tests/results/st-functions.sql.out
b/sql/core/src/test/resources/sql-tests/results/st-functions.sql.out
index 11ca99bc2304..e9cc3242225a 100644
--- a/sql/core/src/test/resources/sql-tests/results/st-functions.sql.out
+++ b/sql/core/src/test/resources/sql-tests/results/st-functions.sql.out
@@ -574,7 +574,7 @@ struct<result:string>
-- !query
SELECT ST_AsBinary(ST_GeogFromWKB(NULL))
-- !query schema
-struct<st_asbinary(st_geogfromwkb(NULL)):binary>
+struct<st_asbinary(st_geogfromwkb(NULL), NDR):binary>
-- !query output
NULL
@@ -582,7 +582,7 @@ NULL
-- !query
SELECT
hex(ST_AsBinary(ST_GeogFromWKB(X'0101000000000000000000F03F0000000000000040')))
-- !query schema
-struct<hex(st_asbinary(st_geogfromwkb(X'0101000000000000000000F03F0000000000000040'))):string>
+struct<hex(st_asbinary(st_geogfromwkb(X'0101000000000000000000F03F0000000000000040'),
NDR)):string>
-- !query output
0101000000000000000000F03F0000000000000040
@@ -622,7 +622,7 @@ struct<count(1):bigint>
-- !query
SELECT ST_AsBinary(ST_GeomFromWKB(NULL))
-- !query schema
-struct<st_asbinary(st_geomfromwkb(NULL, 0)):binary>
+struct<st_asbinary(st_geomfromwkb(NULL, 0), NDR):binary>
-- !query output
NULL
@@ -630,7 +630,7 @@ NULL
-- !query
SELECT
hex(ST_AsBinary(ST_GeomFromWKB(X'0101000000000000000000F03F0000000000000040')))
-- !query schema
-struct<hex(st_asbinary(st_geomfromwkb(X'0101000000000000000000F03F0000000000000040',
0))):string>
+struct<hex(st_asbinary(st_geomfromwkb(X'0101000000000000000000F03F0000000000000040',
0), NDR)):string>
-- !query output
0101000000000000000000F03F0000000000000040
@@ -638,7 +638,7 @@
struct<hex(st_asbinary(st_geomfromwkb(X'0101000000000000000000F03F00000000000000
-- !query
SELECT
hex(ST_AsBinary(ST_GeomFromWKB(X'0101000000000000000000F03F0000000000000040',
0)))
-- !query schema
-struct<hex(st_asbinary(st_geomfromwkb(X'0101000000000000000000F03F0000000000000040',
0))):string>
+struct<hex(st_asbinary(st_geomfromwkb(X'0101000000000000000000F03F0000000000000040',
0), NDR)):string>
-- !query output
0101000000000000000000F03F0000000000000040
@@ -646,7 +646,7 @@
struct<hex(st_asbinary(st_geomfromwkb(X'0101000000000000000000F03F00000000000000
-- !query
SELECT
hex(ST_AsBinary(ST_GeomFromWKB(X'0101000000000000000000F03F0000000000000040',
3857)))
-- !query schema
-struct<hex(st_asbinary(st_geomfromwkb(X'0101000000000000000000F03F0000000000000040',
3857))):string>
+struct<hex(st_asbinary(st_geomfromwkb(X'0101000000000000000000F03F0000000000000040',
3857), NDR)):string>
-- !query output
0101000000000000000000F03F0000000000000040
@@ -654,7 +654,7 @@
struct<hex(st_asbinary(st_geomfromwkb(X'0101000000000000000000F03F00000000000000
-- !query
SELECT
hex(ST_AsBinary(ST_GeomFromWKB(X'0101000000000000000000F03F0000000000000040',
4326)))
-- !query schema
-struct<hex(st_asbinary(st_geomfromwkb(X'0101000000000000000000F03F0000000000000040',
4326))):string>
+struct<hex(st_asbinary(st_geomfromwkb(X'0101000000000000000000F03F0000000000000040',
4326), NDR)):string>
-- !query output
0101000000000000000000F03F0000000000000040
@@ -768,6 +768,200 @@ org.apache.spark.SparkIllegalArgumentException
}
+-- !query
+SELECT ST_AsBinary(NULL)
+-- !query schema
+struct<st_asbinary(NULL, NDR):binary>
+-- !query output
+NULL
+
+
+-- !query
+SELECT
hex(ST_AsBinary(ST_GeogFromWKB(X'0101000000000000000000F03F0000000000000040')))
+-- !query schema
+struct<hex(st_asbinary(st_geogfromwkb(X'0101000000000000000000F03F0000000000000040'),
NDR)):string>
+-- !query output
+0101000000000000000000F03F0000000000000040
+
+
+-- !query
+SELECT
hex(ST_AsBinary(ST_GeogFromWKB(X'00000000013FF00000000000004000000000000000'),
'NDR'))
+-- !query schema
+struct<hex(st_asbinary(st_geogfromwkb(X'00000000013FF00000000000004000000000000000'),
NDR)):string>
+-- !query output
+0101000000000000000000F03F0000000000000040
+
+
+-- !query
+SELECT
hex(ST_AsBinary(ST_GeogFromWKB(X'0101000000000000000000F03F0000000000000040'),
'XDR'))
+-- !query schema
+struct<hex(st_asbinary(st_geogfromwkb(X'0101000000000000000000F03F0000000000000040'),
XDR)):string>
+-- !query output
+00000000013FF00000000000004000000000000000
+
+
+-- !query
+SELECT
hex(ST_AsBinary(ST_GeomFromWKB(X'0101000000000000000000F03F0000000000000040')))
+-- !query schema
+struct<hex(st_asbinary(st_geomfromwkb(X'0101000000000000000000F03F0000000000000040',
0), NDR)):string>
+-- !query output
+0101000000000000000000F03F0000000000000040
+
+
+-- !query
+SELECT
hex(ST_AsBinary(ST_GeomFromWKB(X'00000000013FF00000000000004000000000000000'),
'NDR'))
+-- !query schema
+struct<hex(st_asbinary(st_geomfromwkb(X'00000000013FF00000000000004000000000000000',
0), NDR)):string>
+-- !query output
+0101000000000000000000F03F0000000000000040
+
+
+-- !query
+SELECT
hex(ST_AsBinary(ST_GeomFromWKB(X'0101000000000000000000F03F0000000000000040'),
'XDR'))
+-- !query schema
+struct<hex(st_asbinary(st_geomfromwkb(X'0101000000000000000000F03F0000000000000040',
0), XDR)):string>
+-- !query output
+00000000013FF00000000000004000000000000000
+
+
+-- !query
+SELECT
ST_AsBinary(ST_GeogFromWKB(X'0101000000000000000000F03F0000000000000040'), '')
+-- !query schema
+struct<>
+-- !query output
+org.apache.spark.SparkIllegalArgumentException
+{
+ "errorClass" : "ST_INVALID_ENDIANNESS_VALUE",
+ "sqlState" : "22023",
+ "messageParameters" : {
+ "endianness" : ""
+ }
+}
+
+
+-- !query
+SELECT
ST_AsBinary(ST_GeogFromWKB(X'0101000000000000000000F03F0000000000000040'),
'ABC')
+-- !query schema
+struct<>
+-- !query output
+org.apache.spark.SparkIllegalArgumentException
+{
+ "errorClass" : "ST_INVALID_ENDIANNESS_VALUE",
+ "sqlState" : "22023",
+ "messageParameters" : {
+ "endianness" : "ABC"
+ }
+}
+
+
+-- !query
+SELECT
ST_AsBinary(ST_GeogFromWKB(X'0101000000000000000000F03F0000000000000040'),
'big-endian')
+-- !query schema
+struct<>
+-- !query output
+org.apache.spark.SparkIllegalArgumentException
+{
+ "errorClass" : "ST_INVALID_ENDIANNESS_VALUE",
+ "sqlState" : "22023",
+ "messageParameters" : {
+ "endianness" : "big-endian"
+ }
+}
+
+
+-- !query
+SELECT COUNT(*) FROM geodata WHERE ST_AsBinary(ST_GeogFromWKB(wkb)) <> wkb
+-- !query schema
+struct<count(1):bigint>
+-- !query output
+0
+
+
+-- !query
+SELECT COUNT(*) FROM geodata WHERE ST_AsBinary(ST_GeogFromWKB(wkb), 'NDR') <>
wkb
+-- !query schema
+struct<count(1):bigint>
+-- !query output
+0
+
+
+-- !query
+SELECT COUNT(*) FROM geodata WHERE ST_AsBinary(ST_GeogFromWKB(wkb), 'XDR') =
wkb
+-- !query schema
+struct<count(1):bigint>
+-- !query output
+0
+
+
+-- !query
+SELECT COUNT(*) FROM geodata WHERE ST_AsBinary(ST_GeomFromWKB(wkb)) <> wkb
+-- !query schema
+struct<count(1):bigint>
+-- !query output
+0
+
+
+-- !query
+SELECT COUNT(*) FROM geodata WHERE ST_AsBinary(ST_GeomFromWKB(wkb), 'NDR') <>
wkb
+-- !query schema
+struct<count(1):bigint>
+-- !query output
+0
+
+
+-- !query
+SELECT COUNT(*) FROM geodata WHERE ST_AsBinary(ST_GeomFromWKB(wkb), 'XDR') =
wkb
+-- !query schema
+struct<count(1):bigint>
+-- !query output
+0
+
+
+-- !query
+SELECT COUNT(*) FROM geodata WHERE ST_AsBinary(ST_GeogFromWKB(wkb), '') IS NOT
NULL
+-- !query schema
+struct<>
+-- !query output
+org.apache.spark.SparkIllegalArgumentException
+{
+ "errorClass" : "ST_INVALID_ENDIANNESS_VALUE",
+ "sqlState" : "22023",
+ "messageParameters" : {
+ "endianness" : ""
+ }
+}
+
+
+-- !query
+SELECT COUNT(*) FROM geodata WHERE ST_AsBinary(ST_GeogFromWKB(wkb), 'ABC') IS
NOT NULL
+-- !query schema
+struct<>
+-- !query output
+org.apache.spark.SparkIllegalArgumentException
+{
+ "errorClass" : "ST_INVALID_ENDIANNESS_VALUE",
+ "sqlState" : "22023",
+ "messageParameters" : {
+ "endianness" : "ABC"
+ }
+}
+
+
+-- !query
+SELECT COUNT(*) FROM geodata WHERE ST_AsBinary(ST_GeogFromWKB(wkb),
'big-endian') IS NOT NULL
+-- !query schema
+struct<>
+-- !query output
+org.apache.spark.SparkIllegalArgumentException
+{
+ "errorClass" : "ST_INVALID_ENDIANNESS_VALUE",
+ "sqlState" : "22023",
+ "messageParameters" : {
+ "endianness" : "big-endian"
+ }
+}
+
+
-- !query
SELECT ST_Srid(NULL)
-- !query schema
diff --git
a/sql/core/src/test/scala/org/apache/spark/sql/STExpressionsSuite.scala
b/sql/core/src/test/scala/org/apache/spark/sql/STExpressionsSuite.scala
index 3406a7109de7..7deb30cf9e9c 100644
--- a/sql/core/src/test/scala/org/apache/spark/sql/STExpressionsSuite.scala
+++ b/sql/core/src/test/scala/org/apache/spark/sql/STExpressionsSuite.scala
@@ -106,11 +106,11 @@ class STExpressionsSuite
// Construct the input GEOGRAPHY expression.
val geogExpr = ST_GeogFromWKB(wkbLiteral)
assert(geogExpr.dataType.sameType(defaultGeographyType))
- checkEvaluation(ST_AsBinary(geogExpr), wkb)
+ checkEvaluation(new ST_AsBinary(geogExpr), wkb)
// Cast the GEOGRAPHY with fixed SRID to GEOGRAPHY with mixed SRID.
val castExpr = Cast(geogExpr, mixedSridGeographyType)
assert(castExpr.dataType.sameType(mixedSridGeographyType))
- checkEvaluation(ST_AsBinary(castExpr), wkb)
+ checkEvaluation(new ST_AsBinary(castExpr), wkb)
// Construct the input GEOGRAPHY SQL query, using WKB literal.
val geogQueryLit: String = s"ST_GeogFromWKB(X'$wkbString')"
@@ -146,11 +146,11 @@ class STExpressionsSuite
// Construct the input GEOMETRY expression.
val geomExpr = new ST_GeomFromWKB(wkbLiteral)
assert(geomExpr.dataType.sameType(defaultGeometryType))
- checkEvaluation(ST_AsBinary(geomExpr), wkb)
+ checkEvaluation(new ST_AsBinary(geomExpr), wkb)
// Cast the GEOMETRY with fixed SRID to GEOMETRY with mixed SRID.
val castExpr = Cast(geomExpr, mixedSridGeometryType)
assert(castExpr.dataType.sameType(mixedSridGeometryType))
- checkEvaluation(ST_AsBinary(castExpr), wkb)
+ checkEvaluation(new ST_AsBinary(castExpr), wkb)
// Construct the input GEOMETRY SQL query, using WKB literal.
val geomQueryLit: String = s"ST_GeomFromWKB(X'$wkbString')"
@@ -475,16 +475,42 @@ class STExpressionsSuite
test("ST_AsBinary") {
// Test data: WKB representation of POINT(1 2).
- val wkb =
Hex.unhex("0101000000000000000000F03F0000000000000040".getBytes())
- val wkbLiteral = Literal.create(wkb, BinaryType)
+ val wkbNdr =
Hex.unhex("0101000000000000000000F03F0000000000000040".getBytes())
+ val wkbXdr =
Hex.unhex("00000000013FF00000000000004000000000000000".getBytes())
+ val wkbLiteral = Literal.create(wkbNdr, BinaryType)
+ val endiannessNdr = Literal.create("NDR")
+ val endiannessXdr = Literal.create("XDR")
// ST_GeogFromWKB and ST_AsBinary.
val geographyExpression = ST_GeogFromWKB(wkbLiteral)
assert(geographyExpression.dataType.sameType(defaultGeographyType))
- checkEvaluation(ST_AsBinary(geographyExpression), wkb)
+ checkEvaluation(new ST_AsBinary(geographyExpression), wkbNdr)
+ checkEvaluation(ST_AsBinary(geographyExpression, endiannessNdr), wkbNdr)
+ checkEvaluation(ST_AsBinary(geographyExpression, Literal.create("nDr")),
wkbNdr)
+ checkEvaluation(ST_AsBinary(geographyExpression, endiannessXdr), wkbXdr)
// ST_GeomFromWKB and ST_AsBinary.
val geometryExpression = new ST_GeomFromWKB(wkbLiteral)
assert(geometryExpression.dataType.sameType(defaultGeometryType))
- checkEvaluation(ST_AsBinary(geometryExpression), wkb)
+ checkEvaluation(new ST_AsBinary(geometryExpression), wkbNdr)
+ checkEvaluation(ST_AsBinary(geometryExpression, endiannessNdr), wkbNdr)
+ checkEvaluation(ST_AsBinary(geometryExpression, endiannessXdr), wkbXdr)
+ checkEvaluation(ST_AsBinary(geometryExpression, Literal.create("XdR")),
wkbXdr)
+ // Test NULL handling.
+ checkEvaluation(new ST_AsBinary(Literal.create(null,
defaultGeographyType)), null)
+ checkEvaluation(ST_AsBinary(Literal.create(null, defaultGeographyType),
endiannessNdr), null)
+ checkEvaluation(new ST_AsBinary(Literal.create(null,
defaultGeometryType)), null)
+ checkEvaluation(ST_AsBinary(Literal.create(null, defaultGeometryType),
endiannessXdr), null)
+ checkEvaluation(ST_AsBinary(geographyExpression, Literal.create(null,
StringType)), null)
+ checkEvaluation(ST_AsBinary(geometryExpression, Literal.create(null,
StringType)), null)
+ // Test invalid endianness.
+ Seq(geographyExpression, geometryExpression).foreach { expr =>
+ checkError(
+ exception = intercept[SparkIllegalArgumentException] {
+ ST_AsBinary(expr, Literal.create("ABC")).eval()
+ },
+ condition = "ST_INVALID_ENDIANNESS_VALUE",
+ parameters = Map("endianness" -> "ABC")
+ )
+ }
}
test("ST_GeogFromWKB - expressions") {
@@ -494,7 +520,7 @@ class STExpressionsSuite
// ST_GeogFromWKB with default SRID.
val geographyExpression = ST_GeogFromWKB(wkbLiteral)
assert(geographyExpression.dataType.sameType(defaultGeographyType))
- checkEvaluation(ST_AsBinary(geographyExpression), wkb)
+ checkEvaluation(new ST_AsBinary(geographyExpression), wkb)
checkEvaluation(ST_Srid(geographyExpression), defaultGeographySrid)
// ST_GeogFromWKB with NULL input.
val nullLiteral = Literal.create(null, BinaryType)
@@ -523,11 +549,11 @@ class STExpressionsSuite
// ST_GeomFromWKB with default SRID.
val geometryExpressionNoSrid = new ST_GeomFromWKB(wkbLiteral)
assert(geometryExpressionNoSrid.dataType.sameType(defaultGeometryType))
- checkEvaluation(ST_AsBinary(geometryExpressionNoSrid), wkb)
+ checkEvaluation(new ST_AsBinary(geometryExpressionNoSrid), wkb)
// ST_GeomFromWKB with valid SRID.
val geometryExpressionValidSrid = ST_GeomFromWKB(wkbLiteral,
validSridLiteral)
assert(geometryExpressionValidSrid.dataType.sameType(GeometryType(validSrid)))
- checkEvaluation(ST_AsBinary(geometryExpressionValidSrid), wkb)
+ checkEvaluation(new ST_AsBinary(geometryExpressionValidSrid), wkb)
// ST_GeomFromWKB with invalid SRID.
val geometryExpressionInvalidSrid = ST_GeomFromWKB(wkbLiteral,
invalidSridLiteral)
checkError(
@@ -638,7 +664,7 @@ class STExpressionsSuite
// ST_SetSrid on GEOGRAPHY expression.
val geogLit = ST_SetSrid(geographyLiteral, sridLiteral)
assert(geogLit.dataType.sameType(GeographyType(srid)))
- checkEvaluation(ST_AsBinary(geogLit), wkb)
+ checkEvaluation(new ST_AsBinary(geogLit), wkb)
val geogLitSrid = ST_Srid(geogLit)
assert(geogLitSrid.dataType.sameType(IntegerType))
checkEvaluation(geogLitSrid, srid)
@@ -662,7 +688,7 @@ class STExpressionsSuite
// ST_SetSrid on GEOMETRY expression.
val geomLit = ST_SetSrid(geometryLiteral, sridLiteral)
assert(geomLit.dataType.sameType(GeometryType(srid)))
- checkEvaluation(ST_AsBinary(geomLit), wkb)
+ checkEvaluation(new ST_AsBinary(geomLit), wkb)
val geomLitSrid = ST_Srid(geomLit)
assert(geomLitSrid.dataType.sameType(IntegerType))
checkEvaluation(geomLitSrid, srid)
diff --git
a/sql/core/src/test/scala/org/apache/spark/sql/STFunctionsSuite.scala
b/sql/core/src/test/scala/org/apache/spark/sql/STFunctionsSuite.scala
index 6cb8894ae525..7cd0d84df8c2 100644
--- a/sql/core/src/test/scala/org/apache/spark/sql/STFunctionsSuite.scala
+++ b/sql/core/src/test/scala/org/apache/spark/sql/STFunctionsSuite.scala
@@ -30,18 +30,37 @@ class STFunctionsSuite extends SharedSparkSession {
test("st_asbinary") {
// Test data: Well-Known Binary (WKB) representations.
- val df = Seq[(String)](
- (
- "0101000000000000000000f03f0000000000000040"
- )).toDF("wkb")
+ val wkbNdr = "0101000000000000000000f03f0000000000000040"
+ val wkbXdr = "00000000013ff00000000000004000000000000000"
+ val df = Seq[(String, String, String, String)](
+ (wkbNdr, wkbXdr, "NDR", "XDR")
+ ).toDF("wkbNDR", "wkbXDR", "endNDR", "endXDR")
// ST_GeogFromWKB/ST_GeomFromWKB and ST_AsBinary.
checkAnswer(
df.select(
- lower(hex(st_asbinary(st_geogfromwkb(unhex($"wkb"))))).as("col0"),
- lower(hex(st_asbinary(st_geomfromwkb(unhex($"wkb"))))).as("col1")),
+ lower(hex(st_asbinary(st_geogfromwkb(unhex($"wkbNDR"))))),
+ lower(hex(st_asbinary(st_geogfromwkb(unhex($"wkbNDR")), "NDR"))),
+ lower(hex(st_asbinary(st_geogfromwkb(unhex($"wkbNDR")), $"endNDR"))),
+ lower(hex(st_asbinary(st_geogfromwkb(unhex($"wkbNDR")), "XDR"))),
+ lower(hex(st_asbinary(st_geogfromwkb(unhex($"wkbNDR")), $"endXDR"))),
+ lower(hex(st_asbinary(st_geogfromwkb(unhex($"wkbXDR"))))),
+ lower(hex(st_asbinary(st_geogfromwkb(unhex($"wkbXDR")), "NDR"))),
+ lower(hex(st_asbinary(st_geogfromwkb(unhex($"wkbXDR")), $"endNDR"))),
+ lower(hex(st_asbinary(st_geogfromwkb(unhex($"wkbXDR")), "XDR"))),
+ lower(hex(st_asbinary(st_geogfromwkb(unhex($"wkbXDR")), $"endXDR"))),
+ lower(hex(st_asbinary(st_geomfromwkb(unhex($"wkbNDR"))))),
+ lower(hex(st_asbinary(st_geomfromwkb(unhex($"wkbNDR")), "NDR"))),
+ lower(hex(st_asbinary(st_geomfromwkb(unhex($"wkbNDR")), $"endNDR"))),
+ lower(hex(st_asbinary(st_geomfromwkb(unhex($"wkbNDR")), "XDR"))),
+ lower(hex(st_asbinary(st_geomfromwkb(unhex($"wkbNDR")), $"endXDR"))),
+ lower(hex(st_asbinary(st_geomfromwkb(unhex($"wkbXDR"))))),
+ lower(hex(st_asbinary(st_geomfromwkb(unhex($"wkbXDR")), "NDR"))),
+ lower(hex(st_asbinary(st_geomfromwkb(unhex($"wkbXDR")), $"endNDR"))),
+ lower(hex(st_asbinary(st_geomfromwkb(unhex($"wkbXDR")), "XDR"))),
+ lower(hex(st_asbinary(st_geomfromwkb(unhex($"wkbXDR")), $"endXDR")))),
Row(
- "0101000000000000000000f03f0000000000000040",
- "0101000000000000000000f03f0000000000000040"))
+ wkbNdr, wkbNdr, wkbNdr, wkbXdr, wkbXdr, wkbNdr, wkbNdr, wkbNdr,
wkbXdr, wkbXdr,
+ wkbNdr, wkbNdr, wkbNdr, wkbXdr, wkbXdr, wkbNdr, wkbNdr, wkbNdr,
wkbXdr, wkbXdr))
}
test("st_geogfromwkb") {
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]