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