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 437398834e [CALCITE-7719] Field access on an element of a ROW array 
built by a sub-query raises IllegalArgumentException
437398834e is described below

commit 437398834e49c8086a64870427214fec428684fc
Author: Mihai Budiu <[email protected]>
AuthorDate: Thu Aug 13 21:58:48 2026 -0700

    [CALCITE-7719] Field access on an element of a ROW array built by a 
sub-query raises IllegalArgumentException
    
    Signed-off-by: Mihai Budiu <[email protected]>
---
 .../java/org/apache/calcite/rex/LogicVisitor.java  | 28 ++++++++++++++++++++--
 core/src/test/resources/sql/sub-query.iq           | 13 ++++++++++
 2 files changed, 39 insertions(+), 2 deletions(-)

diff --git a/core/src/main/java/org/apache/calcite/rex/LogicVisitor.java 
b/core/src/main/java/org/apache/calcite/rex/LogicVisitor.java
index 68a0d0aa96..b18613b104 100644
--- a/core/src/main/java/org/apache/calcite/rex/LogicVisitor.java
+++ b/core/src/main/java/org/apache/calcite/rex/LogicVisitor.java
@@ -31,13 +31,20 @@
 import static java.util.Objects.requireNonNull;
 
 /**
- * Visitor pattern for traversing a tree of {@link RexNode} objects.
+ * Visitor that, given the {@link Logic} in force at the root of an
+ * expression, computes the Logic in force at every occurrence of a sought
+ * sub-expression {@code seek}.  Results are collected in {@code 
logicCollection}.
+ *
+ * <p>This value is meaningful only for expressions that evaluate to Boolean 
values.
  */
 public class LogicVisitor extends RexUnaryBiVisitor<@Nullable Logic> {
   private final RexNode seek;
   private final Collection<Logic> logicCollection;
 
-  /** Creates a LogicVisitor. */
+  /** Creates a LogicVisitor.
+   *
+   * @param seek Expression whose occurrences to find
+   * @param logicCollection Receives the Logic in force for each occurrence of 
{@code seek} */
   private LogicVisitor(RexNode seek, Collection<Logic> logicCollection) {
     super(true);
     this.seek = seek;
@@ -51,6 +58,14 @@ private LogicVisitor(RexNode seek, Collection<Logic> 
logicCollection) {
    * answer) with the fewest possibilities (that is, we prefer one that
    * returns [true as true, false as false, unknown as false] over one that
    * distinguishes false from unknown).
+   *
+   * <p>If {@code seek} occurs multiple times, the result is
+   * a single Logic that is safe for every one of them. If the occurrences
+   * are evaluated under different Logic values, the result is
+   * {@link Logic#TRUE_FALSE_UNKNOWN}, which is safe for any occurrence.
+   *
+   * @throws IllegalArgumentException if {@code seek} does not occur in
+   *   {@code nodes}
    */
   public static Logic find(Logic logic, List<RexNode> nodes,
       RexNode seek) {
@@ -74,6 +89,9 @@ public static Logic find(Logic logic, List<RexNode> nodes,
     }
   }
 
+  /** Appends to {@code logicList}, for each occurrence of {@code seek}
+   * within {@code node} in depth-first order, the Logic in force at that
+   * occurrence. */
   public static void collect(RexNode node, RexNode seek, Logic logic,
       List<Logic> logicList) {
     node.accept(new LogicVisitor(seek, logicList), logic);
@@ -137,6 +155,12 @@ public static void collect(RexNode node, RexNode seek, 
Logic logic,
 
   @Override public @Nullable Logic visitFieldAccess(RexFieldAccess fieldAccess,
       @Nullable Logic arg) {
+    // Not a Boolean value
+    Logic logic = requireNonNull(arg, "arg");
+    if (logic == Logic.TRUE) {
+      logic = Logic.TRUE_FALSE_UNKNOWN;
+    }
+    super.visitFieldAccess(fieldAccess, logic);
     return end(fieldAccess, arg);
   }
 
diff --git a/core/src/test/resources/sql/sub-query.iq 
b/core/src/test/resources/sql/sub-query.iq
index 5d1bbb7386..08c5bcf6e4 100644
--- a/core/src/test/resources/sql/sub-query.iq
+++ b/core/src/test/resources/sql/sub-query.iq
@@ -10152,3 +10152,16 @@ ORDER BY emp.ename;
 
 !ok
 # End sub-query.iq
+
+# [CALCITE-7719] Field access on an element of a ROW array built by a
+# sub-query raises IllegalArgumentException.
+select t.a[1]."EXPR$0"."EXPR$1" as v
+from (select array(select ROW(ROW(1, 2), 3) from (values (0))) as a) as t;
++---+
+| V |
++---+
+| 2 |
++---+
+(1 row)
+
+!ok

Reply via email to