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

mihaibudiu 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 69d1b8ff7c [CALCITE-7720] Scalar subquery with ROW ARRAY fails in code 
generation
69d1b8ff7c is described below

commit 69d1b8ff7caae15fddd52766f3cf5e2472e0a2b9
Author: Mihai Budiu <[email protected]>
AuthorDate: Fri Aug 14 10:54:57 2026 -0700

    [CALCITE-7720] Scalar subquery with ROW ARRAY fails in code generation
    
    Signed-off-by: Mihai Budiu <[email protected]>
---
 .../adapter/enumerable/RexToLixTranslator.java     | 15 +++-
 core/src/test/resources/sql/struct.iq              | 83 ++++++++++++++++++++++
 2 files changed, 96 insertions(+), 2 deletions(-)

diff --git 
a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexToLixTranslator.java
 
b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexToLixTranslator.java
index cf9cbde5e3..f102fd69d7 100644
--- 
a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexToLixTranslator.java
+++ 
b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexToLixTranslator.java
@@ -1552,13 +1552,24 @@ private static Expression scaleValue(
     return result;
   }
 
+  /** Returns the Java type of a local variable that holds a value of a given 
type.
+   *
+   * <p>For the reasoning behind this implementation
+   *
+   * @see org.apache.calcite.jdbc.JavaTypeFactoryImpl.SyntheticRecordType
+   * @see JavaTypeFactory#getJavaClass(RelDataType) */
+  private Type javaVariableType(RelDataType type) {
+    final Type javaType = typeFactory.getJavaClass(type);
+    return javaType instanceof Class ? javaType : Object.class;
+  }
+
   /**
    * Returns an {@code Expression} for null literal without losing its type
    * information.
    */
   private ConstantExpression getTypedNullLiteral(RexLiteral literal) {
     assert literal.isNull();
-    Type javaClass = typeFactory.getJavaClass(literal.getType());
+    Type javaClass = javaVariableType(literal.getType());
     switch (literal.getType().getSqlTypeName()) {
     case DATE:
     case TIME:
@@ -1674,7 +1685,7 @@ private Result implementPrev(RexCall call) {
    * }
    */
   private Result implementCaseWhen(RexCall call) {
-    final Type returnType = typeFactory.getJavaClass(call.getType());
+    final Type returnType = javaVariableType(call.getType());
     final ParameterExpression valueVariable =
         Expressions.parameter(returnType,
             list.newName("case_when_value"));
diff --git a/core/src/test/resources/sql/struct.iq 
b/core/src/test/resources/sql/struct.iq
index bf25d4cadb..08c8762050 100644
--- a/core/src/test/resources/sql/struct.iq
+++ b/core/src/test/resources/sql/struct.iq
@@ -337,4 +337,87 @@ select row(emp.*, dept.*).deptno0 from emp join dept on 
emp.deptno = dept.deptno
 
 !ok
 
+# [CALCITE-7720] Scalar subquery with ROW ARRAY fails in code generation.
+
+# A scalar sub-query that returns an element of an array of ROW.
+select (select t.arr[1] from (values (0))) as v
+from (select ARRAY[ROW(1, 2)] as arr) as t;
++--------+
+| V      |
++--------+
+| {1, 2} |
++--------+
+(1 row)
+
+!ok
+
+# The same element access, without a sub-query
+select t.arr[1] as v from (select ARRAY[ROW(1, 2)] as arr) as t;
++--------+
+| V      |
++--------+
+| {1, 2} |
++--------+
+(1 row)
+
+!ok
+
+# A CASE whose result is a ROW
+select case when x = 1 then ROW(1, 2) else ROW(3, 4) end as v
+from (values (1)) as t(x);
++--------+
+| V      |
++--------+
+| {1, 2} |
++--------+
+(1 row)
+
+!ok
+
+# A CASE whose result is an element of an array of ROW
+select case when x = 1 then arr[1] else arr[2] end as v
+from (values (1)) as t(x), (select ARRAY[ROW(1, 2), ROW(3, 4)] as arr) as u;
++--------+
+| V      |
++--------+
+| {1, 2} |
++--------+
+(1 row)
+
+!ok
+
+# A field access that returns a ROW
+select t.arr[1]."EXPR$0" as v from (select ARRAY[ROW(ROW(1, 2), 3)] as arr) as 
t;
++--------+
+| V      |
++--------+
+| {1, 2} |
++--------+
+(1 row)
+
+!ok
+
+# A field access on a ROW column that returns a ROW
+select t.r."EXPR$0" as v from (select ROW(ROW(1, 2), 3) as r) as t;
++--------+
+| V      |
++--------+
+| {1, 2} |
++--------+
+(1 row)
+
+!ok
+
+# A CASE that returns a ROW obtained by a field access
+select case when x = 1 then t.arr[1]."EXPR$0" else ROW(9, 9) end as v
+from (values (1)) as t2(x), (select ARRAY[ROW(ROW(1, 2), 3)] as arr) as t;
++--------+
+| V      |
++--------+
+| {1, 2} |
++--------+
+(1 row)
+
+!ok
+
 # End struct.iq

Reply via email to