This is an automated email from the ASF dual-hosted git repository.
yashmayya pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pinot.git
The following commit(s) were added to refs/heads/master by this push:
new 005c5ab64b6 Fix Unknown nodes in multi-stage EXPLAIN when asking
servers (#19766)
005c5ab64b6 is described below
commit 005c5ab64b6b7e09a3dadea4ebeae358081f0a23
Author: Yash Mayya <[email protected]>
AuthorDate: Tue Oct 6 18:11:51 2026 -0700
Fix Unknown nodes in multi-stage EXPLAIN when asking servers (#19766)
---
.../planner/logical/PlanNodeToRelConverter.java | 2 +-
.../query/planner/logical/RexExpressionUtils.java | 38 +++++++++++++++-------
.../planner/logical/RexExpressionUtilsTest.java | 21 ++++++++++++
3 files changed, 48 insertions(+), 13 deletions(-)
diff --git
a/pinot-query-planner/src/main/java/org/apache/pinot/query/planner/logical/PlanNodeToRelConverter.java
b/pinot-query-planner/src/main/java/org/apache/pinot/query/planner/logical/PlanNodeToRelConverter.java
index fe16e9ba70d..973d502e7b3 100644
---
a/pinot-query-planner/src/main/java/org/apache/pinot/query/planner/logical/PlanNodeToRelConverter.java
+++
b/pinot-query-planner/src/main/java/org/apache/pinot/query/planner/logical/PlanNodeToRelConverter.java
@@ -360,7 +360,7 @@ public final class PlanNodeToRelConverter {
List<Window.RexWinAggCall> aggCalls = new ArrayList<>();
for (RexExpression.FunctionCall funCall : node.getAggCalls()) {
- SqlAggFunction aggFunction =
RexExpressionUtils.getAggFunction(funCall, _builder.getCluster());
+ SqlAggFunction aggFunction =
RexExpressionUtils.getAggFunction(funCall);
List<RexExpression> functionOperands = funCall.getFunctionOperands();
List<RexNode> operands = new ArrayList<>(functionOperands.size());
for (RexExpression functionOperand : functionOperands) {
diff --git
a/pinot-query-planner/src/main/java/org/apache/pinot/query/planner/logical/RexExpressionUtils.java
b/pinot-query-planner/src/main/java/org/apache/pinot/query/planner/logical/RexExpressionUtils.java
index 73c6ca8bb5f..278e34ac074 100644
---
a/pinot-query-planner/src/main/java/org/apache/pinot/query/planner/logical/RexExpressionUtils.java
+++
b/pinot-query-planner/src/main/java/org/apache/pinot/query/planner/logical/RexExpressionUtils.java
@@ -32,7 +32,6 @@ import java.util.Set;
import java.util.UUID;
import javax.annotation.Nullable;
import org.apache.calcite.avatica.util.ByteString;
-import org.apache.calcite.plan.RelOptCluster;
import org.apache.calcite.rel.core.AggregateCall;
import org.apache.calcite.rel.core.Window;
import org.apache.calcite.rex.RexBuilder;
@@ -54,6 +53,7 @@ import org.apache.calcite.util.NlsString;
import org.apache.calcite.util.Sarg;
import org.apache.calcite.util.TimestampString;
import org.apache.pinot.calcite.rex.PinotSealedSearchOperator;
+import org.apache.pinot.calcite.sql.fun.PinotOperatorTable;
import org.apache.pinot.common.function.scalar.arithmetic.NegateScalarFunction;
import org.apache.pinot.common.utils.DataSchema.ColumnDataType;
import org.apache.pinot.spi.utils.BooleanUtils;
@@ -93,10 +93,7 @@ public class RexExpressionUtils {
operands.add(toRexNode(builder, functionOperand));
}
String functionName = rexExpression.getFunctionName();
- SqlIdentifier sqlIdentifier = new SqlIdentifier(functionName,
SqlParserPos.ZERO);
- ArrayList<SqlOperator> operators = new ArrayList<>();
- builder.getCluster().getRexBuilder().getOpTab()
- .lookupOperatorOverloads(sqlIdentifier, null, SqlSyntax.FUNCTION,
operators, SqlNameMatchers.liberal());
+ List<SqlOperator> operators = lookupOperators(functionName);
if (operators.isEmpty()) {
throw new IllegalArgumentException("No operator found for function: " +
functionName);
@@ -105,6 +102,10 @@ public class RexExpressionUtils {
LOGGER.info("Multiple operators found for function: {}, using the first
one", functionName);
}
SqlOperator operator = operators.get(0);
+ if (operator.kind == SqlKind.IN) {
+ // Calcite creates IN as SEARCH
+ return builder.in(operands.get(0), operands.subList(1, operands.size()));
+ }
return builder.call(operator, operands);
}
@@ -169,18 +170,14 @@ public class RexExpressionUtils {
for (RexExpression functionOperand : functionOperands) {
operands.add(toRexNode(builder, functionOperand));
}
- SqlAggFunction sqlAggFunction = getAggFunction(functionCall,
builder.getCluster());
+ SqlAggFunction sqlAggFunction = getAggFunction(functionCall);
return builder.aggregateCall(sqlAggFunction, operands);
}
- public static SqlAggFunction getAggFunction(RexExpression.FunctionCall
functionCall, RelOptCluster cluster) {
- // TODO: This needs to be improved.
+ public static SqlAggFunction getAggFunction(RexExpression.FunctionCall
functionCall) {
String functionName = functionCall.getFunctionName();
- SqlIdentifier sqlIdentifier = new SqlIdentifier(functionName,
SqlParserPos.ZERO);
- ArrayList<SqlOperator> operators = new ArrayList<>();
- cluster.getRexBuilder().getOpTab()
- .lookupOperatorOverloads(sqlIdentifier, null, SqlSyntax.FUNCTION,
operators, SqlNameMatchers.liberal());
+ List<SqlOperator> operators = lookupOperators(functionName);
ArrayList<SqlAggFunction> aggFunctions = new ArrayList<>(operators.size());
for (SqlOperator operator : operators) {
@@ -197,6 +194,23 @@ public class RexExpressionUtils {
return aggFunctions.get(0);
}
+ /// Looks up the operators for a function name from [#getFunctionName],
which uses the [SqlKind] name for most
+ /// standard operators, e.g. `SUM0` for `$SUM0`. Null handling does not
change how these names resolve.
+ private static List<SqlOperator> lookupOperators(String functionName) {
+ PinotOperatorTable operatorTable = PinotOperatorTable.instance(true);
+ List<SqlOperator> operators = new ArrayList<>();
+ operatorTable.lookupOperatorOverloads(new SqlIdentifier(functionName,
SqlParserPos.ZERO), null,
+ SqlSyntax.FUNCTION, operators, SqlNameMatchers.liberal());
+ if (operators.isEmpty()) {
+ for (SqlOperator operator : operatorTable.getOperatorList()) {
+ if (operator.kind.name().equals(functionName)) {
+ operators.add(operator);
+ }
+ }
+ }
+ return operators;
+ }
+
public static RexExpression fromRexNode(RexNode rexNode) {
if (rexNode instanceof RexInputRef) {
return fromRexInputRef((RexInputRef) rexNode);
diff --git
a/pinot-query-planner/src/test/java/org/apache/pinot/query/planner/logical/RexExpressionUtilsTest.java
b/pinot-query-planner/src/test/java/org/apache/pinot/query/planner/logical/RexExpressionUtilsTest.java
index 70a7199f479..0d5355c3627 100644
---
a/pinot-query-planner/src/test/java/org/apache/pinot/query/planner/logical/RexExpressionUtilsTest.java
+++
b/pinot-query-planner/src/test/java/org/apache/pinot/query/planner/logical/RexExpressionUtilsTest.java
@@ -45,6 +45,9 @@ import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertSame;
+
/// Tests for RexExpressionUtils, focusing on the handleSearch method and null
handling.
public class RexExpressionUtilsTest {
@@ -71,6 +74,24 @@ public class RexExpressionUtilsTest {
Assert.assertEquals(roundTrip.getValue(), uuid);
}
+ @Test
+ public void testSqlKindFunctionNames() {
+ // Plan nodes name most standard operators by SqlKind, e.g. DIVIDE for "/"
and SUM0 for "$SUM0"
+ RelBuilder relBuilder =
RelBuilder.create(Frameworks.newConfigBuilder().build()).values(new
String[]{"a"}, 1.0);
+ RexExpression input = new RexExpression.InputRef(0);
+ List<RexExpression> inOperands = List.of(input, new
RexExpression.Literal(ColumnDataType.DOUBLE, 1.0),
+ new RexExpression.Literal(ColumnDataType.DOUBLE, 2.0));
+ for (RexExpression call : List.of(
+ new RexExpression.FunctionCall(ColumnDataType.DOUBLE,
SqlKind.DIVIDE.name(), List.of(input, input)),
+ new RexExpression.FunctionCall(ColumnDataType.BOOLEAN,
SqlKind.IN.name(), inOperands),
+ new RexExpression.FunctionCall(ColumnDataType.BOOLEAN,
SqlKind.NOT_IN.name(), inOperands))) {
+
assertEquals(RexExpressionUtils.fromRexNode(RexExpressionUtils.toRexNode(relBuilder,
call)), call);
+ }
+ RexExpression.FunctionCall sum0 =
+ new RexExpression.FunctionCall(ColumnDataType.DOUBLE,
SqlKind.SUM0.name(), List.of(input));
+ assertSame(RexExpressionUtils.getAggFunction(sum0),
SqlStdOperatorTable.SUM0);
+ }
+
@Test
public void testHandleSearchNullLiteralInWithNullAsUnknown() {
// Test: NULL IN (1, 2, 3) (when nullAs = UNKNOWN)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]