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

bchapuis pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/calcite.git


The following commit(s) were added to refs/heads/main by this push:
     new cd76712fcd [CALCITE-5281] Add ST_Explode for geometry parameter
cd76712fcd is described below

commit cd76712fcd762bd71d233229afa55792ebd72f88
Author: Bertil Chapuis <[email protected]>
AuthorDate: Fri Sep 30 00:23:49 2022 +0200

    [CALCITE-5281] Add ST_Explode for geometry parameter
---
 .../calcite/runtime/SpatialTypeFunctions.java      |  9 ++++
 .../calcite/sql/fun/SqlSpatialTypeFunctions.java   | 51 ++++++++++++++++++++++
 core/src/test/resources/sql/spatial.iq             | 19 +++++++-
 3 files changed, 78 insertions(+), 1 deletion(-)

diff --git 
a/core/src/main/java/org/apache/calcite/runtime/SpatialTypeFunctions.java 
b/core/src/main/java/org/apache/calcite/runtime/SpatialTypeFunctions.java
index 47a2d803bc..b8242f406e 100644
--- a/core/src/main/java/org/apache/calcite/runtime/SpatialTypeFunctions.java
+++ b/core/src/main/java/org/apache/calcite/runtime/SpatialTypeFunctions.java
@@ -999,6 +999,15 @@ public class SpatialTypeFunctions {
     return geom.getEnvelope();
   }
 
+  /**
+   * Explodes the {@code geom} into multiple geometries.
+   */
+  private static void ST_Explode(final Geometry geom) {
+    // This is a dummy function. We cannot include table functions in this
+    // package, because they have too many dependencies. See the real 
definition
+    // in SqlSpatialTypeFunctions.
+  }
+
   // Geometry predicates ======================================================
 
   /**
diff --git 
a/core/src/main/java/org/apache/calcite/sql/fun/SqlSpatialTypeFunctions.java 
b/core/src/main/java/org/apache/calcite/sql/fun/SqlSpatialTypeFunctions.java
index 2094afe166..7963948551 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlSpatialTypeFunctions.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlSpatialTypeFunctions.java
@@ -20,6 +20,7 @@ import org.apache.calcite.DataContext;
 import org.apache.calcite.config.CalciteConnectionConfig;
 import org.apache.calcite.linq4j.Enumerable;
 import org.apache.calcite.linq4j.Linq4j;
+import org.apache.calcite.linq4j.function.Functions;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.rel.type.RelDataTypeFactory;
 import org.apache.calcite.runtime.SpatialTypeFunctions;
@@ -50,6 +51,15 @@ public class SqlSpatialTypeFunctions {
 
   // Geometry table functions =================================================
 
+  /**
+   * Explodes the {@code geom} into multiple geometries.
+   *
+   * @see SpatialTypeFunctions ST_Explode */
+  @SuppressWarnings({"WeakerAccess", "unused"})
+  public static ScannableTable ST_Explode(Geometry geom) {
+    return new ExplodeTable(geom);
+  }
+
   /** Calculates a regular grid of polygons based on {@code geom}.
    *
    * @see SpatialTypeFunctions ST_MakeGrid */
@@ -68,6 +78,47 @@ public class SqlSpatialTypeFunctions {
     return new GridTable(geom, deltaX, deltaY, true);
   }
 
+  /** Returns the geometries of a geometry. */
+  public static class ExplodeTable implements ScannableTable {
+
+    private final Geometry geometry;
+
+    public ExplodeTable(Geometry geometry) {
+      this.geometry = geometry;
+    }
+
+    @Override public Enumerable<@Nullable Object[]> scan(DataContext root) {
+      return Linq4j.asEnumerable(
+          Functions.generate(
+            geometry.getNumGeometries(),
+            i -> new Object[] { geometry.getGeometryN(i), i }));
+    }
+
+    @Override public RelDataType getRowType(RelDataTypeFactory typeFactory) {
+      return typeFactory.builder()
+          .add("GEOM", SqlTypeName.GEOMETRY)
+          .add("INDEX", SqlTypeName.INTEGER)
+          .build();
+    }
+
+    @Override public Statistic getStatistic() {
+      return Statistics.UNKNOWN;
+    }
+
+    @Override public Schema.TableType getJdbcTableType() {
+      return Schema.TableType.TABLE;
+    }
+
+    @Override public boolean isRolledUp(String column) {
+      return false;
+    }
+
+    @Override public boolean rolledUpColumnValidInsideAgg(String column, 
SqlCall call,
+        @Nullable SqlNode parent, @Nullable CalciteConnectionConfig config) {
+      return true;
+    }
+  }
+
   /** Returns the points or rectangles in a grid that covers a given
    * geometry. */
   public static class GridTable implements ScannableTable {
diff --git a/core/src/test/resources/sql/spatial.iq 
b/core/src/test/resources/sql/spatial.iq
index 4c2f643fbd..d926ab9a4a 100644
--- a/core/src/test/resources/sql/spatial.iq
+++ b/core/src/test/resources/sql/spatial.iq
@@ -753,7 +753,24 @@ POLYGON ((0 0, 0 1, 1.0000000001 1, 1.0000000001 0, 0 0))
 !ok
 
 # ST_Explode(query [, fieldName]) Explodes the geometry-collections in the 
*fieldName* column of a query into multiple geometries
-# Not implemented
+
+SELECT t.geom, t.index FROM table(ST_Explode(ST_GeomFromText('MULTIPOINT((1 
1), (2 2), (3 3), (4 4))'))) as t(geom, index);
+GEOM, INDEX
+POINT (1 1), 0
+POINT (2 2), 1
+POINT (3 3), 2
+POINT (4 4), 3
+!ok
+
+SELECT t1.id, t2.geom, t2.index
+FROM (SELECT 1 as id, 'MULTIPOINT((1 1), (2 2))' as points UNION ALL SELECT 2 
as id, 'MULTIPOINT((3 3), (4 4))' as points) as t1,
+LATERAL table(ST_Explode(t1.points)) as t2(geom, index);
+ID, GEOM, INDEX
+1, POINT (1 1), 0
+1, POINT (2 2), 1
+2, POINT (3 3), 0
+2, POINT (4 4), 1
+!ok
 
 # ST_Extent(geom) Returns the minimum bounding box of *geom* (which may be a 
geometry-collection)
 

Reply via email to