Hi all,
Sorry if this is the wrong list.

I have a question regarding CALCITE-4382: "CompileException on table
with array of struct column". I've been playing with the code, and
I've managed to make nested arrays and structs of all kinds work. I'd
like to merge the work to github, but I'm pretty sure it's not in a
state that is merge ready, and I'd like to ask this group for some
help on that.

The primary change is to EnumerationTableScan.fieldExpression(). The
important part of the diff:
-        final MethodCallExpression e2 =
-                Expressions.call(BuiltInMethod.AS_ENUMERABLE2.method, e);
-        final Expression e3 = elementPhysType.convertTo(e2,
JavaRowFormat.LIST);
-        return Expressions.call(e3, BuiltInMethod.ENUMERABLE_TO_LIST.method);
+        final Expression e2 = toEnumerable(e);
+        return Expressions.call(e2, BuiltInMethod.ENUMERABLE_TO_LIST.method);

My changes in brief:

First, the value in the array is List, but the (static) type of the
Expression is Object, and so I had to enhance this code. I used
toEnumerable and enhanced it to do the right thing.

Second, I entirely removed all reference to the physical-type and the
physical-type convert. It works for my simple test case, but this
makes me very worried that I'm doing something wrong. However, I've
looked over some of the history of the file (including the comment in
this function), and it seems like there was a conscious effort to
change all sql Arrays to java.util.List, and so maybe the conversion
from physical type to List has already happened somewhere else(?).

Including full diff against head at end of message.

PS: I notice that nested values for nested arrays returned from
AvaticaResultSet are sometimes java.util.List and sometimes
java.sql.Array. I barely looked into this, and it might be a bug in
Avatica.

$ git diff | cat -
diff --git 
a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableTableScan.java
b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableTableScan.java
index 3f3d95f..cfeb7c3 100644
--- 
a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableTableScan.java
+++ 
b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableTableScan.java
@@ -16,7 +16,6 @@
  */
 package org.apache.calcite.adapter.enumerable;

-import org.apache.calcite.adapter.java.JavaTypeFactory;
 import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.interpreter.Row;
 import org.apache.calcite.linq4j.Enumerable;
@@ -25,7 +24,6 @@
 import org.apache.calcite.linq4j.tree.Blocks;
 import org.apache.calcite.linq4j.tree.Expression;
 import org.apache.calcite.linq4j.tree.Expressions;
-import org.apache.calcite.linq4j.tree.MethodCallExpression;
 import org.apache.calcite.linq4j.tree.ParameterExpression;
 import org.apache.calcite.linq4j.tree.Primitive;
 import org.apache.calcite.linq4j.tree.Types;
@@ -211,7 +209,9 @@ private Expression getExpression(PhysType physType) {

   private static Expression toEnumerable(Expression expression) {
     final Type type = expression.getType();
-    if (Types.isArray(type)) {
+    if (Types.isAssignableFrom(Enumerable.class, type)) {
+      return expression;
+    } else if (Types.isArray(type)) {
       if (requireNonNull(toClass(type).getComponentType()).isPrimitive()) {
         expression =
             Expressions.call(BuiltInMethod.AS_LIST.method, expression);
@@ -227,8 +227,9 @@ private static Expression toEnumerable(Expression
expression) {
       // evaluated directly.
       return Expressions.call(expression,
           BuiltInMethod.QUERYABLE_AS_ENUMERABLE.method);
+    } else {
+      return Expressions.call(BuiltInMethod.TO_ENUMERABLE.method, expression);
     }
-    return expression;
   }

   private Expression toRows(PhysType physType, Expression expression) {
@@ -273,14 +274,8 @@ private Expression
fieldExpression(ParameterExpression row_, int i,
         // the consumer does not know the element type.
         // The standard element type is List.
         // We need to convert to a List<List>.
-        final JavaTypeFactory typeFactory =
-                (JavaTypeFactory) getCluster().getTypeFactory();
-        final PhysType elementPhysType = PhysTypeImpl.of(
-                typeFactory, fieldType, JavaRowFormat.CUSTOM);
-        final MethodCallExpression e2 =
-                Expressions.call(BuiltInMethod.AS_ENUMERABLE2.method, e);
-        final Expression e3 = elementPhysType.convertTo(e2,
JavaRowFormat.LIST);
-        return Expressions.call(e3, BuiltInMethod.ENUMERABLE_TO_LIST.method);
+        final Expression e2 = toEnumerable(e);
+        return Expressions.call(e2, BuiltInMethod.ENUMERABLE_TO_LIST.method);
       } else {
         return e;
       }
diff --git a/core/src/main/java/org/apache/calcite/runtime/Utilities.java
b/core/src/main/java/org/apache/calcite/runtime/Utilities.java
index 458a07c..360e75e 100644
--- a/core/src/main/java/org/apache/calcite/runtime/Utilities.java
+++ b/core/src/main/java/org/apache/calcite/runtime/Utilities.java
@@ -16,6 +16,9 @@
  */
 package org.apache.calcite.runtime;

+import org.apache.calcite.linq4j.Enumerable;
+import org.apache.calcite.linq4j.Linq4j;
+
 import org.checkerframework.checker.nullness.qual.Nullable;

 import java.text.Collator;
@@ -260,4 +263,23 @@ public static Collator generateCollator(Locale
locale, int strength) {
     collator.setStrength(strength);
     return collator;
   }
+
+  public static Enumerable toEnumerable(@Nullable Object v0) {
+    if (v0 == null) {
+      return null;
+    } else if (v0 instanceof Enumerable) {
+      return (Enumerable) v0;
+    } else if (v0 instanceof java.util.List) {
+      return Linq4j.asEnumerable((java.util.List) v0);
+    } else if (v0 instanceof java.util.Collection) {
+      return Linq4j.asEnumerable((java.util.Collection) v0);
+    } else if (v0 instanceof Iterable) {
+      return Linq4j.asEnumerable((Iterable) v0);
+    } else if (v0 instanceof Object[]) {
+      return Linq4j.asEnumerable((Object[]) v0);
+    } else {
+      throw new RuntimeException("Utilities.asEnumerable: Unsupported type: "
+          + v0.getClass().getName());
+    }
+  }
 }
diff --git a/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
b/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
index e1089a8..1c3d952 100644
--- a/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
+++ b/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
@@ -280,6 +280,7 @@
   IDENTITY_SELECTOR(Functions.class, "identitySelector"),
   AS_ENUMERABLE(Linq4j.class, "asEnumerable", Object[].class),
   AS_ENUMERABLE2(Linq4j.class, "asEnumerable", Iterable.class),
+  TO_ENUMERABLE(Utilities.class, "toEnumerable", Object.class),
   ENUMERABLE_TO_LIST(ExtendedEnumerable.class, "toList"),
   AS_LIST(Primitive.class, "asList", Object.class),
   MEMORY_GET0(MemoryFactory.Memory.class, "get"),

Reply via email to