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

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


The following commit(s) were added to refs/heads/master by this push:
     new 946bbe467de HIVE-29447: Incorrect nullability inference when 
transforming SEARCH expression back to disjunctions (#6318)
946bbe467de is described below

commit 946bbe467de4625462d515789c69b7540a6ce0b7
Author: Krisztian Kasa <[email protected]>
AuthorDate: Thu Feb 19 10:57:52 2026 +0100

    HIVE-29447: Incorrect nullability inference when transforming SEARCH 
expression back to disjunctions (#6318)
---
 .../ql/optimizer/calcite/SearchTransformer.java    | 13 +++-
 ql/src/test/queries/clientpositive/cbo_search.q    | 25 ++++++++
 .../results/clientpositive/llap/cbo_search.q.out   | 72 ++++++++++++++++++++++
 3 files changed, 107 insertions(+), 3 deletions(-)

diff --git 
a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/SearchTransformer.java
 
b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/SearchTransformer.java
index 5357521270f..8ea25a91a0b 100644
--- 
a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/SearchTransformer.java
+++ 
b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/SearchTransformer.java
@@ -59,14 +59,16 @@ public class SearchTransformer<C extends Comparable<C>> {
   private final RexNode ref;
   private final Sarg<C> sarg;
   private final RexUnknownAs unknownContext;
-  protected final RelDataType type;
+  protected final RelDataType operandType;
+  protected final RelDataType expressionType;
 
   public SearchTransformer(RexBuilder rexBuilder, RexCall search, final 
RexUnknownAs unknownContext) {
     this.rexBuilder = rexBuilder;
     ref = search.getOperands().get(0);
     RexLiteral literal = (RexLiteral) search.operands.get(1);
     sarg = Objects.requireNonNull(literal.getValueAs(Sarg.class), "Sarg");
-    type = literal.getType();
+    operandType = literal.getType();
+    expressionType = search.getType();
     this.unknownContext = unknownContext;
   }
 
@@ -74,7 +76,7 @@ public RexNode transform() {
     PerfLogger perfLogger = SessionState.getPerfLogger();
     perfLogger.perfLogBegin(this.getClass().getName(), 
PerfLogger.SEARCH_TRANSFORMER);
 
-    RangeConverter<C> consumer = new RangeConverter<>(rexBuilder, type, ref);
+    RangeConverter<C> consumer = new RangeConverter<>(rexBuilder, operandType, 
ref);
     RangeSets.forEach(sarg.rangeSet, consumer);
 
     List<RexNode> orList = new ArrayList<>();
@@ -101,6 +103,11 @@ public RexNode transform() {
       x = RexUtil.composeConjunction(rexBuilder, Arrays.asList(notNull, x));
     }
     perfLogger.perfLogEnd(this.getClass().getName(), 
PerfLogger.SEARCH_TRANSFORMER);
+
+    if (!expressionType.equals(x.getType()) && x instanceof RexCall 
transformedCall) {
+      x = rexBuilder.makeCall(expressionType, transformedCall.getOperator(), 
transformedCall.getOperands());
+    }
+
     return x;
   }
 
diff --git a/ql/src/test/queries/clientpositive/cbo_search.q 
b/ql/src/test/queries/clientpositive/cbo_search.q
new file mode 100644
index 00000000000..48937f31163
--- /dev/null
+++ b/ql/src/test/queries/clientpositive/cbo_search.q
@@ -0,0 +1,25 @@
+CREATE TABLE main_table (
+    id_col STRING,
+    join_key STRING,
+    int_col_to_test INT,
+    misc_attr STRING
+);
+
+CREATE TABLE lookup_table (
+    lookup_key STRING,
+    replacement_val INT
+);
+
+-- Test search to disjuncts conversion when search is in a Project
+EXPLAIN CBO
+SELECT
+    CASE
+        WHEN base.int_col_to_test IS NULL
+             OR base.int_col_to_test = ''
+             OR base.int_col_to_test = 0
+        THEN COALESCE(lkup.replacement_val, 0)
+        ELSE base.int_col_to_test
+    END AS final_calculated_column
+FROM main_table base
+JOIN lookup_table lkup ON base.join_key = lkup.lookup_key
+;
diff --git a/ql/src/test/results/clientpositive/llap/cbo_search.q.out 
b/ql/src/test/results/clientpositive/llap/cbo_search.q.out
new file mode 100644
index 00000000000..6db5539b571
--- /dev/null
+++ b/ql/src/test/results/clientpositive/llap/cbo_search.q.out
@@ -0,0 +1,72 @@
+PREHOOK: query: CREATE TABLE main_table (
+    id_col STRING,
+    join_key STRING,
+    int_col_to_test INT,
+    misc_attr STRING
+)
+PREHOOK: type: CREATETABLE
+PREHOOK: Output: database:default
+PREHOOK: Output: default@main_table
+POSTHOOK: query: CREATE TABLE main_table (
+    id_col STRING,
+    join_key STRING,
+    int_col_to_test INT,
+    misc_attr STRING
+)
+POSTHOOK: type: CREATETABLE
+POSTHOOK: Output: database:default
+POSTHOOK: Output: default@main_table
+PREHOOK: query: CREATE TABLE lookup_table (
+    lookup_key STRING,
+    replacement_val INT
+)
+PREHOOK: type: CREATETABLE
+PREHOOK: Output: database:default
+PREHOOK: Output: default@lookup_table
+POSTHOOK: query: CREATE TABLE lookup_table (
+    lookup_key STRING,
+    replacement_val INT
+)
+POSTHOOK: type: CREATETABLE
+POSTHOOK: Output: database:default
+POSTHOOK: Output: default@lookup_table
+PREHOOK: query: EXPLAIN CBO
+SELECT
+    CASE
+        WHEN base.int_col_to_test IS NULL
+             OR base.int_col_to_test = ''
+             OR base.int_col_to_test = 0
+        THEN COALESCE(lkup.replacement_val, 0)
+        ELSE base.int_col_to_test
+    END AS final_calculated_column
+FROM main_table base
+JOIN lookup_table lkup ON base.join_key = lkup.lookup_key
+PREHOOK: type: QUERY
+PREHOOK: Input: default@lookup_table
+PREHOOK: Input: default@main_table
+#### A masked pattern was here ####
+POSTHOOK: query: EXPLAIN CBO
+SELECT
+    CASE
+        WHEN base.int_col_to_test IS NULL
+             OR base.int_col_to_test = ''
+             OR base.int_col_to_test = 0
+        THEN COALESCE(lkup.replacement_val, 0)
+        ELSE base.int_col_to_test
+    END AS final_calculated_column
+FROM main_table base
+JOIN lookup_table lkup ON base.join_key = lkup.lookup_key
+POSTHOOK: type: QUERY
+POSTHOOK: Input: default@lookup_table
+POSTHOOK: Input: default@main_table
+#### A masked pattern was here ####
+CBO PLAN:
+HiveProject(final_calculated_column=[CASE($2, $4, $1)])
+  HiveJoin(condition=[=($0, $3)], joinType=[inner], algorithm=[none], 
cost=[not available])
+    HiveProject(join_key=[$1], int_col_to_test=[$2], EXPR$0=[OR(IS NULL($2), 
=($2, 0))])
+      HiveFilter(condition=[IS NOT NULL($1)])
+        HiveTableScan(table=[[default, main_table]], table:alias=[base])
+    HiveProject(lookup_key=[$0], EXPR$0=[CASE(IS NOT NULL($1), $1, 0)])
+      HiveFilter(condition=[IS NOT NULL($0)])
+        HiveTableScan(table=[[default, lookup_table]], table:alias=[lkup])
+

Reply via email to