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

joemcdonnell pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/impala.git

commit bd214f0cf7ede1a140b8685df4122d3f677804b4
Author: Steve Carlin <[email protected]>
AuthorDate: Thu Feb 19 18:04:30 2026 -0800

    IMPALA-14758: Calcite planner: Return value with "in" and case statement 
crashes server.
    
    The following query was crashing the server with the Calcite planner:
    
    SELECT a.id, a.int_col, a.string_col FROM alltypessmall a
    WHERE 1 NOT IN
        (SELECT CASE WHEN id = 1 then null ELSE id END FROM alltypestiny)
    
    The AnalyzedInPredicate was setting the savedFunction before the case
    statement was analyzed. At this point, the case statement had an invalid
    type for its return type.  The getFunction() for the in clause was
    being set to null which caused bad things to happen on the server.
    
    The fn_ variable is now set at analyze time when the case statement
    is assured to have a return type.
    
    Change-Id: I397b8e3438d8f5d59725bed6fc166f842596818f
    Reviewed-on: http://gerrit.cloudera.org:8080/24006
    Reviewed-by: Impala Public Jenkins <[email protected]>
    Tested-by: Impala Public Jenkins <[email protected]>
---
 .../impala/calcite/functions/AnalyzedInPredicate.java      | 14 ++------------
 .../apache/impala/calcite/functions/RexCallConverter.java  |  8 ++++----
 .../functional-query/queries/QueryTest/calcite.test        |  9 +++++++++
 3 files changed, 15 insertions(+), 16 deletions(-)

diff --git 
a/java/calcite-planner/src/main/java/org/apache/impala/calcite/functions/AnalyzedInPredicate.java
 
b/java/calcite-planner/src/main/java/org/apache/impala/calcite/functions/AnalyzedInPredicate.java
index d81251d77..dd61446c1 100644
--- 
a/java/calcite-planner/src/main/java/org/apache/impala/calcite/functions/AnalyzedInPredicate.java
+++ 
b/java/calcite-planner/src/main/java/org/apache/impala/calcite/functions/AnalyzedInPredicate.java
@@ -40,24 +40,14 @@ public class AnalyzedInPredicate extends InPredicate {
   protected static final Logger LOG =
       LoggerFactory.getLogger(AnalyzedInPredicate.class.getName());
 
-  // Need to save the function because it is known at constructor time. The
-  // resetAnalyzeState() method can be called at various points which could
-  // set the fn_ member to null. So we save the function in the savedFunction_
-  // variable so it can be properly set in analyzeImpl()
-  private final Function savedFunction_;
-
-  public AnalyzedInPredicate(RexCall call, List<Expr> params, Analyzer 
analyzer)
+  public AnalyzedInPredicate(RexCall call, List<Expr> params)
       throws AnalysisException {
     super(params.get(0), params.subList(1, params.size()),
         call.getKind().equals(SqlKind.NOT_IN));
-    this.savedFunction_ = getFunction(analyzer, true);
-
-    this.type_ = Type.BOOLEAN;
   }
 
   public AnalyzedInPredicate(AnalyzedInPredicate other) {
     super(other);
-    this.savedFunction_ = other.savedFunction_;
   }
 
   @Override
@@ -68,7 +58,7 @@ public class AnalyzedInPredicate extends InPredicate {
   @Override
   protected void analyzeImpl(Analyzer analyzer) throws AnalysisException {
     this.computeSelectivity();
-    this.fn_ = savedFunction_;
+    this.fn_ = getFunction(analyzer, true);
     this.type_ = Type.BOOLEAN;
   }
 
diff --git 
a/java/calcite-planner/src/main/java/org/apache/impala/calcite/functions/RexCallConverter.java
 
b/java/calcite-planner/src/main/java/org/apache/impala/calcite/functions/RexCallConverter.java
index 60c39018b..f71a67ba6 100644
--- 
a/java/calcite-planner/src/main/java/org/apache/impala/calcite/functions/RexCallConverter.java
+++ 
b/java/calcite-planner/src/main/java/org/apache/impala/calcite/functions/RexCallConverter.java
@@ -86,14 +86,14 @@ public class RexCallConverter {
       case CAST:
         return createCastExpr(rexCall, params, analyzer);
       case NOT_IN:
-        return createInExpr(rexCall, params, analyzer);
+        return createInExpr(rexCall, params);
       case IS_NULL:
         return new IsNullPredicate(params.get(0), false);
       case IS_NOT_NULL:
         return new IsNullPredicate(params.get(0), true);
       case OTHER:
         if (rexCall.getOperator() instanceof ImpalaInOperator) {
-          return createInExpr(rexCall, params, analyzer);
+          return createInExpr(rexCall, params);
         }
     }
 
@@ -183,9 +183,9 @@ public class RexCallConverter {
   /**
    * Create In Expr
    */
-  private static Expr createInExpr(RexCall call, List<Expr> params, Analyzer 
analyzer
+  private static Expr createInExpr(RexCall call, List<Expr> params
       ) throws ImpalaException {
-    return new AnalyzedInPredicate(call, params, analyzer);
+    return new AnalyzedInPredicate(call, params);
   }
 
   private static Expr createCastExpr(RexCall call, List<Expr> params, Analyzer 
analyzer)
diff --git a/testdata/workloads/functional-query/queries/QueryTest/calcite.test 
b/testdata/workloads/functional-query/queries/QueryTest/calcite.test
index 0b68eab33..ce34c1839 100644
--- a/testdata/workloads/functional-query/queries/QueryTest/calcite.test
+++ b/testdata/workloads/functional-query/queries/QueryTest/calcite.test
@@ -1224,3 +1224,12 @@ string
 ---- RUNTIME_PROFILE
 row_regex: .*PlannerType: CalcitePlanner.*
 ====
+---- QUERY
+# IMPALA-14758: make sure server doesn't crash
+# can probably remove this test once tests are run through
+# jenkins, since this is repeated in a different file.
+SELECT a.id, a.int_col, a.string_col FROM functional.alltypessmall a
+WHERE 1 NOT IN
+(SELECT CASE WHEN id = 1 then null ELSE id END FROM functional.alltypestiny);
+---- RESULTS
+====

Reply via email to