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 +====
