This is an automated email from the ASF dual-hosted git repository.
zabetak 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 18fc8f9ec8c HIVE-29538: AssertionError in StatefulFunctionsChecker
when compiling queries with NVL/COALESCE/IF over field access on ARRAY<STRUCT>
(#6402)
18fc8f9ec8c is described below
commit 18fc8f9ec8c3287a154ca3ff9ec4be96a3fd27b9
Author: gopigowtham <[email protected]>
AuthorDate: Fri Apr 3 17:48:48 2026 +0530
HIVE-29538: AssertionError in StatefulFunctionsChecker when compiling
queries with NVL/COALESCE/IF over field access on ARRAY<STRUCT> (#6402)
---
.../hive/ql/parse/type/HiveFunctionHelper.java | 7 +----
.../hive/ql/parse/type/TestHiveFunctionHelper.java | 33 ++++++++++++++++++++--
.../clientpositive/cbo_component_access_if.q | 11 ++++++++
.../llap/cbo_component_access_if.q.out | 28 ++++++++++++++++++
4 files changed, 71 insertions(+), 8 deletions(-)
diff --git
a/ql/src/java/org/apache/hadoop/hive/ql/parse/type/HiveFunctionHelper.java
b/ql/src/java/org/apache/hadoop/hive/ql/parse/type/HiveFunctionHelper.java
index dbf9741d378..556388c7191 100644
--- a/ql/src/java/org/apache/hadoop/hive/ql/parse/type/HiveFunctionHelper.java
+++ b/ql/src/java/org/apache/hadoop/hive/ql/parse/type/HiveFunctionHelper.java
@@ -345,12 +345,7 @@ public Void visitCall(final RexCall call) {
// doing this check.
GenericUDF nodeUDF = SqlFunctionConverter.getHiveUDF(
call.getOperator(), call.getType(), call.getOperands().size());
- if (nodeUDF == null) {
- throw new AssertionError("Cannot retrieve function " +
call.getOperator().getName()
- + " within StatefulFunctionsChecker");
- }
- // Stateful?
- if (FunctionRegistry.isStateful(nodeUDF)) {
+ if (nodeUDF != null && FunctionRegistry.isStateful(nodeUDF)) {
throw new Util.FoundOne(call);
}
return super.visitCall(call);
diff --git
a/ql/src/test/org/apache/hadoop/hive/ql/parse/type/TestHiveFunctionHelper.java
b/ql/src/test/org/apache/hadoop/hive/ql/parse/type/TestHiveFunctionHelper.java
index 2e7acf6f002..a116d94f093 100644
---
a/ql/src/test/org/apache/hadoop/hive/ql/parse/type/TestHiveFunctionHelper.java
+++
b/ql/src/test/org/apache/hadoop/hive/ql/parse/type/TestHiveFunctionHelper.java
@@ -18,13 +18,18 @@
package org.apache.hadoop.hive.ql.parse.type;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
import org.apache.calcite.jdbc.JavaTypeFactoryImpl;
import org.apache.calcite.rel.type.RelDataTypeFactory;
import org.apache.calcite.rex.RexBuilder;
import org.apache.calcite.rex.RexCall;
import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.sql.SqlKind;
import org.apache.calcite.sql.fun.SqlStdOperatorTable;
+import org.apache.hadoop.hive.ql.exec.FunctionInfo;
+import
org.apache.hadoop.hive.ql.optimizer.calcite.reloperators.HiveComponentAccess;
import org.apache.hadoop.hive.ql.parse.SemanticException;
import com.google.common.collect.Lists;
@@ -41,9 +46,9 @@ public void testGetUDTFFunction() throws SemanticException {
RelDataTypeFactory typeFactory = new JavaTypeFactoryImpl();
RexBuilder rexBuilder = new RexBuilder(typeFactory);
List<RexNode> operands =
- Lists.newArrayList(rexBuilder.makeLiteral("hello"),
rexBuilder.makeLiteral("world"));
+ Lists.newArrayList(rexBuilder.makeLiteral("hello"),
rexBuilder.makeLiteral("world"));
List<RexNode> arrayNode =
-
Lists.newArrayList(rexBuilder.makeCall(SqlStdOperatorTable.ARRAY_VALUE_CONSTRUCTOR,
operands));
+
Lists.newArrayList(rexBuilder.makeCall(SqlStdOperatorTable.ARRAY_VALUE_CONSTRUCTOR,
operands));
FunctionHelper functionHelper = new HiveFunctionHelper(rexBuilder);
RexCall explodeNode = (RexCall) functionHelper.getUDTFFunction("explode",
arrayNode);
@@ -62,4 +67,28 @@ public void testGetUDTFFunctionThrowingException() throws
SemanticException {
// 'upper' is not a udtf so should throw exception
functionHelper.getUDTFFunction("upper", operands);
}
+
+ @Test
+ public void testCoalesceWithComponentAccessDoesNotAssert() throws
SemanticException {
+ RelDataTypeFactory typeFactory = new JavaTypeFactoryImpl();
+ RexBuilder rexBuilder = new RexBuilder(typeFactory);
+ FunctionHelper functionHelper = new HiveFunctionHelper(rexBuilder);
+
+ // Simulate nested field access over a collection, which is represented in
Calcite by
+ // a COMPONENT_ACCESS operator and can appear inside NVL/COALESCE rewrites
to CASE.
+ RexNode array =
+ rexBuilder.makeCall(SqlStdOperatorTable.ARRAY_VALUE_CONSTRUCTOR,
+ Lists.newArrayList(rexBuilder.makeLiteral("hello")));
+ RexNode componentAccess =
+ rexBuilder.makeCall(array.getType().getComponentType(),
HiveComponentAccess.COMPONENT_ACCESS,
+ Lists.newArrayList(array));
+
+ FunctionInfo fi = functionHelper.getFunctionInfo("coalesce");
+ List<RexNode> inputs = Lists.newArrayList(componentAccess,
rexBuilder.makeNullLiteral(componentAccess.getType()));
+ RexNode expr = functionHelper.getExpression("coalesce", fi, inputs,
componentAccess.getType());
+ assertNotNull(expr);
+ assertTrue(expr instanceof RexCall);
+ // COALESCE is rewritten to CASE; the stateful-functions checker walks
this tree.
+ assertEquals(SqlKind.CASE, ((RexCall) expr).getOperator().getKind());
+ }
}
diff --git a/ql/src/test/queries/clientpositive/cbo_component_access_if.q
b/ql/src/test/queries/clientpositive/cbo_component_access_if.q
new file mode 100644
index 00000000000..c21561fe56b
--- /dev/null
+++ b/ql/src/test/queries/clientpositive/cbo_component_access_if.q
@@ -0,0 +1,11 @@
+-- HIVE-29538: AssertionError in StatefulFunctionsChecker when Calcite
introduces COMPONENT_ACCESS
+
+-- Single-level nesting: array-of-struct field projection uses
COMPONENT_ACCESS.
+CREATE TABLE cbo_component_access_if_tbl (
+ `jobs` array<struct<code:string>>
+) STORED AS ORC;
+
+-- `if(...)` is rewritten to CASE and triggers checkForStatefulFunctions.
+EXPLAIN CBO
+SELECT if(concat_ws(',', `jobs`.code) = '', null, concat_ws(',', `jobs`.code))
AS codes
+FROM cbo_component_access_if_tbl;
diff --git
a/ql/src/test/results/clientpositive/llap/cbo_component_access_if.q.out
b/ql/src/test/results/clientpositive/llap/cbo_component_access_if.q.out
new file mode 100644
index 00000000000..b7d732b542b
--- /dev/null
+++ b/ql/src/test/results/clientpositive/llap/cbo_component_access_if.q.out
@@ -0,0 +1,28 @@
+PREHOOK: query: CREATE TABLE cbo_component_access_if_tbl (
+ `jobs` array<struct<code:string>>
+) STORED AS ORC
+PREHOOK: type: CREATETABLE
+PREHOOK: Output: database:default
+PREHOOK: Output: default@cbo_component_access_if_tbl
+POSTHOOK: query: CREATE TABLE cbo_component_access_if_tbl (
+ `jobs` array<struct<code:string>>
+) STORED AS ORC
+POSTHOOK: type: CREATETABLE
+POSTHOOK: Output: database:default
+POSTHOOK: Output: default@cbo_component_access_if_tbl
+PREHOOK: query: EXPLAIN CBO
+SELECT if(concat_ws(',', `jobs`.code) = '', null, concat_ws(',', `jobs`.code))
AS codes
+FROM cbo_component_access_if_tbl
+PREHOOK: type: QUERY
+PREHOOK: Input: default@cbo_component_access_if_tbl
+#### A masked pattern was here ####
+POSTHOOK: query: EXPLAIN CBO
+SELECT if(concat_ws(',', `jobs`.code) = '', null, concat_ws(',', `jobs`.code))
AS codes
+FROM cbo_component_access_if_tbl
+POSTHOOK: type: QUERY
+POSTHOOK: Input: default@cbo_component_access_if_tbl
+#### A masked pattern was here ####
+CBO PLAN:
+HiveProject(codes=[CASE(=(concat_ws(_UTF-16LE',':VARCHAR(2147483647) CHARACTER
SET "UTF-16LE", COMPONENT_ACCESS($0).code), _UTF-16LE''),
null:VARCHAR(2147483647) CHARACTER SET "UTF-16LE",
concat_ws(_UTF-16LE',':VARCHAR(2147483647) CHARACTER SET "UTF-16LE",
COMPONENT_ACCESS($0).code))])
+ HiveTableScan(table=[[default, cbo_component_access_if_tbl]],
table:alias=[cbo_component_access_if_tbl])
+