This is an automated email from the ASF dual-hosted git repository.
wenchen 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 8b5c1bbc1257 [SPARK-55638][SPARK][GEO][SQL] Refactor WKT serialization
in GeometryModel
8b5c1bbc1257 is described below
commit 8b5c1bbc125709e722bf1a3d06fa51e3f235f062
Author: Uros Bojanic <[email protected]>
AuthorDate: Mon Feb 23 21:57:19 2026 +0800
[SPARK-55638][SPARK][GEO][SQL] Refactor WKT serialization in GeometryModel
### What changes were proposed in this pull request?
Adds a public `toWKT` method in `GeometryModel` to separate concerns from
`toString`.
### Why are the changes needed?
This way, callers can have a clearly defined way to obtain the WKT geo
value representation.
### Does this PR introduce _any_ user-facing change?
No.
### How was this patch tested?
Updates all WKT writer tests to call `toWKT()` directly.
### Was this patch authored or co-authored using generative AI tooling?
No.
Closes #54414 from uros-db/geo-model-toString.
Authored-by: Uros Bojanic <[email protected]>
Signed-off-by: Wenchen Fan <[email protected]>
---
.../sql/catalyst/util/geo/GeometryCollection.java | 2 +-
.../spark/sql/catalyst/util/geo/GeometryModel.java | 19 +++-
.../spark/sql/catalyst/util/geo/WktWriterTest.java | 126 +++++++++++----------
3 files changed, 78 insertions(+), 69 deletions(-)
diff --git
a/sql/catalyst/src/main/java/org/apache/spark/sql/catalyst/util/geo/GeometryCollection.java
b/sql/catalyst/src/main/java/org/apache/spark/sql/catalyst/util/geo/GeometryCollection.java
index 6aebff7905bf..4e586ca748a6 100644
---
a/sql/catalyst/src/main/java/org/apache/spark/sql/catalyst/util/geo/GeometryCollection.java
+++
b/sql/catalyst/src/main/java/org/apache/spark/sql/catalyst/util/geo/GeometryCollection.java
@@ -53,7 +53,7 @@ class GeometryCollection extends GeometryModel {
if (i > 0) {
sb.append(",");
}
- geometries.get(i).toWkt(sb);
+ geometries.get(i).appendWkt(sb);
}
}
}
diff --git
a/sql/catalyst/src/main/java/org/apache/spark/sql/catalyst/util/geo/GeometryModel.java
b/sql/catalyst/src/main/java/org/apache/spark/sql/catalyst/util/geo/GeometryModel.java
index c323228a5c27..6975d870c7b9 100644
---
a/sql/catalyst/src/main/java/org/apache/spark/sql/catalyst/util/geo/GeometryModel.java
+++
b/sql/catalyst/src/main/java/org/apache/spark/sql/catalyst/util/geo/GeometryModel.java
@@ -201,7 +201,7 @@ public abstract class GeometryModel {
* If the geometry is empty, it simply appends " EMPTY" in place of the
coordinate values:
* - POINT EMPTY, LINESTRING M EMPTY, POLYGON ZM EMPTY, etc.
*/
- protected void toWkt(StringBuilder sb) {
+ protected void appendWkt(StringBuilder sb) {
sb.append(typeId.getWktName());
appendDimensionSuffix(sb);
if (isEmpty()) {
@@ -227,15 +227,22 @@ public abstract class GeometryModel {
/**
* Appends the geometry-specific WKT (Well-Known Text) content. Note that
this utility method
- * is invoked by `toWkt` when the current geometry is not empty. All
GeometryModel subclasses
- * must implement this method in order to provide their specific WKT content.
+ * is invoked by `appendWkt` when the current geometry is not empty. All the
GeometryModel
+ * subclasses must implement this method in order to provide their specific
WKT content.
*/
protected abstract void appendWktContent(StringBuilder sb);
- @Override
- public String toString() {
+ /**
+ * Returns the WKT (Well-Known Text) representation of this geometry as a
String.
+ */
+ public String toWkt() {
StringBuilder sb = new StringBuilder();
- toWkt(sb);
+ appendWkt(sb);
return sb.toString();
}
+
+ @Override
+ public String toString() {
+ return toWkt();
+ }
}
diff --git
a/sql/catalyst/src/test/java/org/apache/spark/sql/catalyst/util/geo/WktWriterTest.java
b/sql/catalyst/src/test/java/org/apache/spark/sql/catalyst/util/geo/WktWriterTest.java
index 34e45e1c6b5b..de165a64bf61 100644
---
a/sql/catalyst/src/test/java/org/apache/spark/sql/catalyst/util/geo/WktWriterTest.java
+++
b/sql/catalyst/src/test/java/org/apache/spark/sql/catalyst/util/geo/WktWriterTest.java
@@ -31,9 +31,9 @@ public class WktWriterTest extends WkbTestBase {
/** Tests for: POINT */
@Test
- public void testEmptyPointToString() {
+ public void testEmptyPointToWkt() {
Point point = new Point(new double[]{Double.NaN, Double.NaN}, 0);
- String wkt = point.toString();
+ String wkt = point.toWkt();
Assertions.assertEquals("POINT EMPTY", wkt);
}
@@ -41,63 +41,63 @@ public class WktWriterTest extends WkbTestBase {
public void testPointWithZeroCoordinate() {
// 0.0 should be normalized to "0".
Point point = new Point(new double[]{0.0, 0.0}, 0);
- Assertions.assertEquals("POINT(0 0)", point.toString());
+ Assertions.assertEquals("POINT(0 0)", point.toWkt());
}
@Test
public void testPointWithNegativeZeroCoordinate() {
// -0.0 should be normalized to "0" (not "-0" or "-0.0").
Point point = new Point(new double[]{-0.0, -0.0}, 0);
- Assertions.assertEquals("POINT(0 0)", point.toString());
+ Assertions.assertEquals("POINT(0 0)", point.toWkt());
}
@Test
public void testPointWithLargeIntegerCoordinateBeyondLongRange() {
// For very large values WKT should use scientific notation.
Point point = new Point(new double[]{1.2e19, -3.4e19}, 0);
- String wkt = point.toString();
+ String wkt = point.toWkt();
Assertions.assertEquals("POINT(1.2E19 -3.4E19)", wkt);
}
@Test
public void testPointWithDoubleMaxValue() {
Point point = new Point(new double[]{Double.MAX_VALUE, -Double.MAX_VALUE},
0);
- String wkt = point.toString();
+ String wkt = point.toWkt();
Assertions.assertEquals("POINT(1.7976931348623157E308
-1.7976931348623157E308)", wkt);
}
@Test
- public void testPointToString() {
+ public void testPointToWkt() {
Point point = new Point(new double[]{1.0, 2.0}, 0);
- String wkt = point.toString();
+ String wkt = point.toWkt();
Assertions.assertEquals("POINT(1 2)", wkt);
}
@Test
- public void testPointZToString() {
+ public void testPointZToWkt() {
Point point = new Point(new double[]{1.0, 2.0, 3.0}, 0, true, false);
- String wkt = point.toString();
+ String wkt = point.toWkt();
Assertions.assertEquals("POINT Z (1 2 3)", wkt);
}
@Test
- public void testPointMToString() {
+ public void testPointMToWkt() {
Point point = new Point(new double[]{1.0, 2.0, 4.0}, 0, false, true);
- String wkt = point.toString();
+ String wkt = point.toWkt();
Assertions.assertEquals("POINT M (1 2 4)", wkt);
}
@Test
- public void testPointZMToString() {
+ public void testPointZMToWkt() {
Point point = new Point(new double[]{1.0, 2.0, 3.0, 4.0}, 0, true, true);
- String wkt = point.toString();
+ String wkt = point.toWkt();
Assertions.assertEquals("POINT ZM (1 2 3 4)", wkt);
}
@Test
- public void testPointWithNegativeCoordinatesToString() {
+ public void testPointWithNegativeCoordinatesToWkt() {
Point point = new Point(new double[]{-180.0, -90.0}, 0);
- String wkt = point.toString();
+ String wkt = point.toWkt();
Assertions.assertEquals("POINT(-180 -90)", wkt);
}
@@ -113,54 +113,54 @@ public class WktWriterTest extends WkbTestBase {
/** Tests for: LINESTRING */
@Test
- public void testEmptyLineStringToString() {
+ public void testEmptyLineStringToWkt() {
LineString lineString = new LineString(Arrays.asList(), 0, false, false);
- String wkt = lineString.toString();
+ String wkt = lineString.toWkt();
Assertions.assertEquals("LINESTRING EMPTY", wkt);
}
@Test
- public void testLineStringToString() {
+ public void testLineStringToWkt() {
List<Point> points = Arrays.asList(
new Point(new double[]{0.0, 0.0}, 0),
new Point(new double[]{1.0, 1.0}, 0),
new Point(new double[]{2.0, 2.0}, 0)
);
LineString lineString = new LineString(points, 0, false, false);
- String wkt = lineString.toString();
+ String wkt = lineString.toWkt();
Assertions.assertEquals("LINESTRING(0 0,1 1,2 2)", wkt);
}
@Test
- public void testLineStringZToString() {
+ public void testLineStringZToWkt() {
List<Point> points = Arrays.asList(
new Point(new double[]{0.0, 0.0, 0.0}, 0, true, false),
new Point(new double[]{1.0, 1.0, 1.0}, 0, true, false)
);
LineString lineString = new LineString(points, 0, true, false);
- String wkt = lineString.toString();
+ String wkt = lineString.toWkt();
Assertions.assertEquals("LINESTRING Z (0 0 0,1 1 1)", wkt);
}
@Test
- public void testLineStringMToString() {
+ public void testLineStringMToWkt() {
List<Point> points = Arrays.asList(
new Point(new double[]{0.0, 0.0, 10.0}, 0, false, true),
new Point(new double[]{1.0, 1.0, 20.0}, 0, false, true)
);
LineString lineString = new LineString(points, 0, false, true);
- String wkt = lineString.toString();
+ String wkt = lineString.toWkt();
Assertions.assertEquals("LINESTRING M (0 0 10,1 1 20)", wkt);
}
@Test
- public void testLineStringZMToString() {
+ public void testLineStringZMToWkt() {
List<Point> points = Arrays.asList(
new Point(new double[]{0.0, 0.0, 0.0, 10.0}, 0, true, true),
new Point(new double[]{1.0, 1.0, 1.0, 20.0}, 0, true, true)
);
LineString lineString = new LineString(points, 0, true, true);
- String wkt = lineString.toString();
+ String wkt = lineString.toWkt();
Assertions.assertEquals("LINESTRING ZM (0 0 0 10,1 1 1 20)", wkt);
}
@@ -173,21 +173,21 @@ public class WktWriterTest extends WkbTestBase {
);
LineString lineString = new LineString(points, 0, false, false);
IllegalArgumentException e = Assertions.assertThrows(
- IllegalArgumentException.class, lineString::toString);
+ IllegalArgumentException.class, lineString::toWkt);
Assertions.assertEquals("Coordinate value must not be NaN.",
e.getMessage());
}
/** Tests for: POLYGON */
@Test
- public void testEmptyPolygonToString() {
+ public void testEmptyPolygonToWkt() {
Polygon polygon = new Polygon(Arrays.asList(), 0, false, false);
- String wkt = polygon.toString();
+ String wkt = polygon.toWkt();
Assertions.assertEquals("POLYGON EMPTY", wkt);
}
@Test
- public void testPolygonToString() {
+ public void testPolygonToWkt() {
List<Point> ringPoints = Arrays.asList(
new Point(new double[]{0.0, 0.0}, 0),
new Point(new double[]{4.0, 0.0}, 0),
@@ -197,12 +197,12 @@ public class WktWriterTest extends WkbTestBase {
);
Ring ring = new Ring(ringPoints);
Polygon polygon = new Polygon(Arrays.asList(ring), 0, false, false);
- String wkt = polygon.toString();
+ String wkt = polygon.toWkt();
Assertions.assertEquals("POLYGON((0 0,4 0,4 4,0 4,0 0))", wkt);
}
@Test
- public void testPolygonWithHoleToString() {
+ public void testPolygonWithHoleToWkt() {
// Exterior ring
List<Point> exteriorPoints = Arrays.asList(
new Point(new double[]{0.0, 0.0}, 0),
@@ -224,13 +224,13 @@ public class WktWriterTest extends WkbTestBase {
Ring interiorRing = new Ring(interiorPoints);
Polygon polygon = new Polygon(Arrays.asList(exteriorRing, interiorRing),
0, false, false);
- String wkt = polygon.toString();
+ String wkt = polygon.toWkt();
Assertions.assertEquals(
"POLYGON((0 0,10 0,10 10,0 10,0 0),(2 2,8 2,8 8,2 8,2 2))", wkt);
}
@Test
- public void testPolygonZToString() {
+ public void testPolygonZToWkt() {
List<Point> ringPoints = Arrays.asList(
new Point(new double[]{0.0, 0.0, 0.0}, 0, true, false),
new Point(new double[]{4.0, 0.0, 0.0}, 0, true, false),
@@ -240,7 +240,7 @@ public class WktWriterTest extends WkbTestBase {
);
Ring ring = new Ring(ringPoints);
Polygon polygon = new Polygon(Arrays.asList(ring), 0, true, false);
- String wkt = polygon.toString();
+ String wkt = polygon.toWkt();
Assertions.assertEquals("POLYGON Z ((0 0 0,4 0 0,4 4 0,0 4 0,0 0 0))",
wkt);
}
@@ -255,53 +255,53 @@ public class WktWriterTest extends WkbTestBase {
Ring ring = new Ring(ringPoints);
Polygon polygon = new Polygon(List.of(ring), 0, false, false);
IllegalArgumentException e = Assertions.assertThrows(
- IllegalArgumentException.class, polygon::toString);
+ IllegalArgumentException.class, polygon::toWkt);
Assertions.assertEquals("Coordinate value must not be NaN.",
e.getMessage());
}
/** Tests for: MULTIPOINT */
@Test
- public void testEmptyMultiPointToString() {
+ public void testEmptyMultiPointToWkt() {
MultiPoint multiPoint = new MultiPoint(Arrays.asList(), 0, false, false);
- String wkt = multiPoint.toString();
+ String wkt = multiPoint.toWkt();
Assertions.assertEquals("MULTIPOINT EMPTY", wkt);
}
@Test
- public void testMultiPointToString() {
+ public void testMultiPointToWkt() {
List<Point> points = Arrays.asList(
new Point(new double[]{0.0, 0.0}, 0),
new Point(new double[]{1.0, 1.0}, 0),
new Point(new double[]{2.0, 2.0}, 0)
);
MultiPoint multiPoint = new MultiPoint(points, 0, false, false);
- String wkt = multiPoint.toString();
+ String wkt = multiPoint.toWkt();
Assertions.assertEquals("MULTIPOINT((0 0),(1 1),(2 2))", wkt);
}
@Test
- public void testMultiPointZToString() {
+ public void testMultiPointZToWkt() {
List<Point> points = Arrays.asList(
new Point(new double[]{0.0, 0.0, 0.0}, 0, true, false),
new Point(new double[]{1.0, 1.0, 1.0}, 0, true, false)
);
MultiPoint multiPoint = new MultiPoint(points, 0, true, false);
- String wkt = multiPoint.toString();
+ String wkt = multiPoint.toWkt();
Assertions.assertEquals("MULTIPOINT Z ((0 0 0),(1 1 1))", wkt);
}
/** Tests for: MULTILINESTRING */
@Test
- public void testEmptyMultiLineStringToString() {
+ public void testEmptyMultiLineStringToWkt() {
MultiLineString multiLineString = new MultiLineString(Arrays.asList(), 0,
false, false);
- String wkt = multiLineString.toString();
+ String wkt = multiLineString.toWkt();
Assertions.assertEquals("MULTILINESTRING EMPTY", wkt);
}
@Test
- public void testMultiLineStringToString() {
+ public void testMultiLineStringToWkt() {
List<Point> ls1Points = Arrays.asList(
new Point(new double[]{0.0, 0.0}, 0),
new Point(new double[]{1.0, 1.0}, 0)
@@ -315,12 +315,12 @@ public class WktWriterTest extends WkbTestBase {
LineString ls2 = new LineString(ls2Points, 0, false, false);
MultiLineString multiLineString = new MultiLineString(Arrays.asList(ls1,
ls2), 0, false, false);
- String wkt = multiLineString.toString();
+ String wkt = multiLineString.toWkt();
Assertions.assertEquals("MULTILINESTRING((0 0,1 1),(2 2,3 3))", wkt);
}
@Test
- public void testMultiLineStringZToString() {
+ public void testMultiLineStringZToWkt() {
List<Point> ls1Points = Arrays.asList(
new Point(new double[]{0.0, 0.0, 0.0}, 0, true, false),
new Point(new double[]{1.0, 1.0, 1.0}, 0, true, false)
@@ -334,21 +334,21 @@ public class WktWriterTest extends WkbTestBase {
LineString ls2 = new LineString(ls2Points, 0, true, false);
MultiLineString multiLineString = new MultiLineString(Arrays.asList(ls1,
ls2), 0, true, false);
- String wkt = multiLineString.toString();
+ String wkt = multiLineString.toWkt();
Assertions.assertEquals("MULTILINESTRING Z ((0 0 0,1 1 1),(2 2 2,3 3 3))",
wkt);
}
/** Tests for: MULTIPOLYGON */
@Test
- public void testEmptyMultiPolygonToString() {
+ public void testEmptyMultiPolygonToWkt() {
MultiPolygon multiPolygon = new MultiPolygon(Arrays.asList(), 0, false,
false);
- String wkt = multiPolygon.toString();
+ String wkt = multiPolygon.toWkt();
Assertions.assertEquals("MULTIPOLYGON EMPTY", wkt);
}
@Test
- public void testMultiPolygonToString() {
+ public void testMultiPolygonToWkt() {
// First polygon
List<Point> poly1Points = Arrays.asList(
new Point(new double[]{0.0, 0.0}, 0),
@@ -370,13 +370,13 @@ public class WktWriterTest extends WkbTestBase {
Polygon poly2 = new Polygon(Arrays.asList(new Ring(poly2Points)), 0,
false, false);
MultiPolygon multiPolygon = new MultiPolygon(Arrays.asList(poly1, poly2),
0, false, false);
- String wkt = multiPolygon.toString();
+ String wkt = multiPolygon.toWkt();
Assertions.assertEquals(
"MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((2 2,3 2,3 3,2 3,2 2)))", wkt);
}
@Test
- public void testMultiPolygonZToString() {
+ public void testMultiPolygonZToWkt() {
List<Point> poly1Points = Arrays.asList(
new Point(new double[]{0.0, 0.0, 0.0}, 0, true, false),
new Point(new double[]{1.0, 0.0, 0.0}, 0, true, false),
@@ -387,21 +387,21 @@ public class WktWriterTest extends WkbTestBase {
Polygon poly1 = new Polygon(Arrays.asList(new Ring(poly1Points)), 0, true,
false);
MultiPolygon multiPolygon = new MultiPolygon(Arrays.asList(poly1), 0,
true, false);
- String wkt = multiPolygon.toString();
+ String wkt = multiPolygon.toWkt();
Assertions.assertEquals("MULTIPOLYGON Z (((0 0 0,1 0 0,1 1 0,0 1 0,0 0
0)))", wkt);
}
/** Tests for: GEOMETRYCOLLECTION */
@Test
- public void testEmptyGeometryCollectionToString() {
+ public void testEmptyGeometryCollectionToWkt() {
GeometryCollection collection = new GeometryCollection(Arrays.asList(), 0,
false, false);
- String wkt = collection.toString();
+ String wkt = collection.toWkt();
Assertions.assertEquals("GEOMETRYCOLLECTION EMPTY", wkt);
}
@Test
- public void testGeometryCollectionToString() {
+ public void testGeometryCollectionToWkt() {
Point point = new Point(new double[]{1.0, 2.0}, 0);
List<Point> lsPoints = Arrays.asList(
@@ -412,12 +412,12 @@ public class WktWriterTest extends WkbTestBase {
GeometryCollection collection = new GeometryCollection(
Arrays.asList(point, lineString), 0, false, false);
- String wkt = collection.toString();
+ String wkt = collection.toWkt();
Assertions.assertEquals("GEOMETRYCOLLECTION(POINT(1 2),LINESTRING(0 0,1
1))", wkt);
}
@Test
- public void testGeometryCollectionZToString() {
+ public void testGeometryCollectionZToWkt() {
Point point = new Point(new double[]{1.0, 2.0, 3.0}, 0, true, false);
List<Point> lsPoints = Arrays.asList(
@@ -428,13 +428,13 @@ public class WktWriterTest extends WkbTestBase {
GeometryCollection collection = new GeometryCollection(
Arrays.asList(point, lineString), 0, true, false);
- String wkt = collection.toString();
+ String wkt = collection.toWkt();
Assertions.assertEquals(
"GEOMETRYCOLLECTION Z (POINT Z (1 2 3),LINESTRING Z (0 0 0,1 1 1))",
wkt);
}
@Test
- public void testNestedGeometryCollectionToString() {
+ public void testNestedGeometryCollectionToWkt() {
Point point = new Point(new double[]{1.0, 2.0}, 0);
List<Point> lsPoints = Arrays.asList(
@@ -448,7 +448,7 @@ public class WktWriterTest extends WkbTestBase {
GeometryCollection outerCollection = new GeometryCollection(
Arrays.asList(innerCollection, lineString), 0, false, false);
- String wkt = outerCollection.toString();
+ String wkt = outerCollection.toWkt();
Assertions.assertEquals(
"GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(POINT(1 2)),LINESTRING(0 0,1
1))", wkt);
}
@@ -863,6 +863,8 @@ public class WktWriterTest extends WkbTestBase {
String wkbHex = testCase[1];
byte[] wkbBytes = hexToBytes(wkbHex);
GeometryModel geom = reader.read(wkbBytes);
+ Assertions.assertEquals(expectedWkt, geom.toWkt());
+ // The `toString` method returns the same WKT as `toWkt`.
Assertions.assertEquals(expectedWkt, geom.toString());
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]