You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sedona.apache.org by ji...@apache.org on 2024/01/06 07:30:43 UTC

(sedona) branch snowflake-geojson-overload updated: Add ST_SubDivideExplodeV2 implementation but it is not supported in Snowflake

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

jiayu pushed a commit to branch snowflake-geojson-overload
in repository https://gitbox.apache.org/repos/asf/sedona.git


The following commit(s) were added to refs/heads/snowflake-geojson-overload by this push:
     new a059a1258 Add ST_SubDivideExplodeV2 implementation but it is not supported in Snowflake
a059a1258 is described below

commit a059a1258849b0cdbacf1eec2accdfb381d32201
Author: Jia Yu <ji...@apache.org>
AuthorDate: Fri Jan 5 23:30:38 2024 -0800

    Add ST_SubDivideExplodeV2 implementation but it is not supported in Snowflake
---
 .../snowflake/snowsql/ddl/UDTFDDLGenerator.java    | 24 ++++++---
 .../snowsql/udtfs/ST_SubDivideExplodeV2.java       | 60 ++++++++++++++++++++++
 2 files changed, 76 insertions(+), 8 deletions(-)

diff --git a/snowflake/src/main/java/org/apache/sedona/snowflake/snowsql/ddl/UDTFDDLGenerator.java b/snowflake/src/main/java/org/apache/sedona/snowflake/snowsql/ddl/UDTFDDLGenerator.java
index c4710ce53..3424d3661 100644
--- a/snowflake/src/main/java/org/apache/sedona/snowflake/snowsql/ddl/UDTFDDLGenerator.java
+++ b/snowflake/src/main/java/org/apache/sedona/snowflake/snowsql/ddl/UDTFDDLGenerator.java
@@ -31,7 +31,11 @@ public class UDTFDDLGenerator {
             ST_Envelope_Aggr.class,
             ST_Union_Aggr.class,
             ST_Collect.class,
-            ST_Dump.class
+            ST_Dump.class,
+            // ST_SubDivideExplodeV2 is not supported in Snowflake.
+            // The error message is "java.lang.RuntimeException: net.snowflake.client.jdbc.SnowflakeSQLException: Data type GEOMETRY is not supported in non-SQL UDTF return type."
+            // Keep this comment here for future reference.
+//            ST_SubDivideExplodeV2.class
     };
 
     public static String formatUDTFDDL(
@@ -39,6 +43,7 @@ public class UDTFDDLGenerator {
             String schemaName,
             Parameter[] argTypesRaw,
             String[] argNames,
+            String[] argTypesCustom,
             String returnType,
             String stageName,
             String handlerName,
@@ -59,7 +64,7 @@ public class UDTFDDLGenerator {
         ).replace(
                 "{KW_SCHEMA_NAME}", schemaName
         ).replace(
-                "{KW_ARG_SPEC}", ArgSpecBuilder.args(argTypesRaw, argNames, new String[]{})
+                "{KW_ARG_SPEC}", ArgSpecBuilder.args(argTypesRaw, argNames, argTypesCustom)
         ).replace(
                 "{KW_RETURN_TYPE}", returnType
         ).replace(
@@ -77,7 +82,7 @@ public class UDTFDDLGenerator {
         );
         if (isNativeApp) {
             ddl += "\n";
-            ddl += "GRANT USAGE ON FUNCTION " + schemaName + "." + functionName + "(" + ArgSpecBuilder.argTypes(argTypesRaw, new String[]{}) + ") TO APPLICATION ROLE " + appRoleName + ";";
+            ddl += "GRANT USAGE ON FUNCTION " + schemaName + "." + functionName + "(" + ArgSpecBuilder.argTypes(argTypesRaw, argTypesCustom) + ") TO APPLICATION ROLE " + appRoleName + ";";
         }
         return ddl;
     }
@@ -88,20 +93,23 @@ public class UDTFDDLGenerator {
         Class outputRowClass = Arrays.stream(c.getDeclaredClasses()).filter(
                 cls -> cls.getName().endsWith("OutputRow")
         ).findFirst().get();
-        String returnTypes = Arrays.stream(outputRowClass.getFields()).map(
-                field -> field.getName() + " " + Constants.snowflakeTypeMap.get(field.getType().getTypeName())
-        ).collect(Collectors.joining(", "));
+
         Method processMethod = Arrays.stream(c.getDeclaredMethods()).filter(m -> m.getName().equals("process")).findFirst().get();
-        Parameter[] paramTypes = processMethod.getParameters();
+        Parameter[] argTypesRaw = processMethod.getParameters();
         String[] argNames = funcProps.argNames();
+        String[] argTypesCustom = funcProps.argTypes();
+        String returnTypes = Arrays.stream(outputRowClass.getFields()).map(
+                field -> field.getName() + " " + Constants.snowflakeTypeMap.get(funcProps.returnTypes().isEmpty()? field.getType().getTypeName() : funcProps.returnTypes())
+        ).collect(Collectors.joining(", "));
         String handlerName = c.getPackage().getName() + "." + c.getSimpleName();
         String null_input_conf = c.isAnnotationPresent(UDTFAnnotations.CallOnNull.class) ? "CALLED ON NULL INPUT" : "RETURNS NULL ON NULL INPUT";
         String immutable_conf = c.isAnnotationPresent(UDTFAnnotations.Volatile.class) ? "VOLATILE" : "IMMUTABLE";
         return formatUDTFDDL(
                 funcProps.name(),
                 configs.getOrDefault("schema", "sedona"),
-                paramTypes,
+                argTypesRaw,
                 argNames,
+                argTypesCustom,
                 returnTypes,
                 stageName,
                 handlerName,
diff --git a/snowflake/src/main/java/org/apache/sedona/snowflake/snowsql/udtfs/ST_SubDivideExplodeV2.java b/snowflake/src/main/java/org/apache/sedona/snowflake/snowsql/udtfs/ST_SubDivideExplodeV2.java
new file mode 100644
index 000000000..da25e5980
--- /dev/null
+++ b/snowflake/src/main/java/org/apache/sedona/snowflake/snowsql/udtfs/ST_SubDivideExplodeV2.java
@@ -0,0 +1,60 @@
+/**
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sedona.snowflake.snowsql.udtfs;
+
+import org.apache.sedona.common.Functions;
+import org.apache.sedona.snowflake.snowsql.GeometrySerde;
+import org.apache.sedona.snowflake.snowsql.annotations.UDTFAnnotations;
+import org.locationtech.jts.geom.Geometry;
+import org.locationtech.jts.geom.GeometryFactory;
+import org.locationtech.jts.io.ParseException;
+
+import java.util.stream.Stream;
+
+/**
+ * This class is a copy of ST_SubDivideExplode.java, but with the input and output types changed to Snowflake Geometry
+ * Unfortunately, Data type GEOMETRY is not supported in non-SQL UDTF return type.
+ * Just keep this class here for future reference.
+ * The error message is "java.lang.RuntimeException: net.snowflake.client.jdbc.SnowflakeSQLException: Data type GEOMETRY is not supported in non-SQL UDTF return type."
+ */
+@UDTFAnnotations.TabularFunc(name = "ST_SubDivideExplode", argNames = {"geom", "maxVertices"}, argTypes = {"Geometry", "int"}, returnTypes = "Geometry")
+public class ST_SubDivideExplodeV2
+{
+
+    public static final GeometryFactory geometryFactory = new GeometryFactory();
+
+    public static class OutputRow {
+
+        public String geom;
+
+        public OutputRow(String geom) {
+            this.geom = geom;
+        }
+    }
+
+    public static Class getOutputClass() {
+        return OutputRow.class;
+    }
+
+    public ST_SubDivideExplodeV2() {
+    }
+
+    public Stream<OutputRow> process(String geometry, int maxVertices) throws ParseException {
+        Geometry[] geometries = Functions.subDivide(
+                GeometrySerde.deserGeoJson(geometry),
+                maxVertices
+        );
+        return Stream.of(geometries).map(g -> new OutputRow(GeometrySerde.serGeoJson(g)));
+    }
+}