This is an automated email from the ASF dual-hosted git repository. xiangfu 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 17e1aa11a4 Fix chained literal functions evaluation (#12248) 17e1aa11a4 is described below commit 17e1aa11a40db55959e97b300dc7d2b836669f0d Author: Xiang Fu <xiangfu.1...@gmail.com> AuthorDate: Thu Jan 18 13:40:39 2024 -0800 Fix chained literal functions evaluation (#12248) --- .../rel/rules/PinotEvaluateLiteralRule.java | 23 +++++- .../resources/queries/LiteralEvaluationPlans.json | 93 ++++++++++++++++++++++ 2 files changed, 113 insertions(+), 3 deletions(-) diff --git a/pinot-query-planner/src/main/java/org/apache/calcite/rel/rules/PinotEvaluateLiteralRule.java b/pinot-query-planner/src/main/java/org/apache/calcite/rel/rules/PinotEvaluateLiteralRule.java index ea0d531faa..9cbaed6773 100644 --- a/pinot-query-planner/src/main/java/org/apache/calcite/rel/rules/PinotEvaluateLiteralRule.java +++ b/pinot-query-planner/src/main/java/org/apache/calcite/rel/rules/PinotEvaluateLiteralRule.java @@ -129,7 +129,11 @@ public class PinotEvaluateLiteralRule { public RexNode visitCall(RexCall call) { RexCall visitedCall = (RexCall) super.visitCall(call); // Check if all operands are RexLiteral - if (visitedCall.operands.stream().allMatch(operand -> operand instanceof RexLiteral)) { + if (visitedCall.operands.stream().allMatch(operand -> + operand instanceof RexLiteral + || (operand instanceof RexCall && ((RexCall) operand).getOperands().stream() + .allMatch(op -> op instanceof RexLiteral)) + )) { return evaluateLiteralOnlyFunction(visitedCall, _rexBuilder); } else { return visitedCall; @@ -144,7 +148,9 @@ public class PinotEvaluateLiteralRule { private static RexNode evaluateLiteralOnlyFunction(RexCall rexCall, RexBuilder rexBuilder) { String functionName = PinotRuleUtils.extractFunctionName(rexCall); List<RexNode> operands = rexCall.getOperands(); - assert operands.stream().allMatch(operand -> operand instanceof RexLiteral); + assert operands.stream().allMatch(operand -> operand instanceof RexLiteral + || (operand instanceof RexCall && ((RexCall) operand).getOperands().stream() + .allMatch(op -> op instanceof RexLiteral))); int numOperands = operands.size(); FunctionInfo functionInfo = FunctionRegistry.getFunctionInfo(functionName, numOperands); if (functionInfo == null) { @@ -153,7 +159,18 @@ public class PinotEvaluateLiteralRule { } Object[] arguments = new Object[numOperands]; for (int i = 0; i < numOperands; i++) { - arguments[i] = getLiteralValue((RexLiteral) operands.get(i)); + RexNode rexNode = operands.get(i); + if (rexNode instanceof RexCall + && ((RexCall) rexNode).getOperator().getName().equalsIgnoreCase("CAST")) { + // this must be a cast function + RexCall operand = (RexCall) rexNode; + arguments[i] = getLiteralValue((RexLiteral) operand.getOperands().get(0)); + } else if (rexNode instanceof RexLiteral) { + arguments[i] = getLiteralValue((RexLiteral) rexNode); + } else { + // Function operands cannot be evaluated, skip + return rexCall; + } } RelDataType rexNodeType = rexCall.getType(); Object resultValue; diff --git a/pinot-query-planner/src/test/resources/queries/LiteralEvaluationPlans.json b/pinot-query-planner/src/test/resources/queries/LiteralEvaluationPlans.json index 902648f1cc..cbbfa67d9e 100644 --- a/pinot-query-planner/src/test/resources/queries/LiteralEvaluationPlans.json +++ b/pinot-query-planner/src/test/resources/queries/LiteralEvaluationPlans.json @@ -160,6 +160,99 @@ "\n" ] }, + { + "description": "select two functions chaining", + "sql": "EXPLAIN PLAN FOR SELECT ToEpochDays(fromDateTime('1970-01-15', 'yyyy-MM-dd')) FROM a", + "output": [ + "Execution Plan", + "\nLogicalProject(EXPR$0=[14:BIGINT])", + "\n LogicalTableScan(table=[[a]])", + "\n" + ] + }, + { + "description": "select two functions chaining with one more arithmetic function", + "sql": "EXPLAIN PLAN FOR SELECT 1 + ToEpochDays(fromDateTime('1970-01-15', 'yyyy-MM-dd')) FROM a", + "output": [ + "Execution Plan", + "\nLogicalProject(EXPR$0=[15.0:BIGINT])", + "\n LogicalTableScan(table=[[a]])", + "\n" + ] + }, + { + "description": "select int array literal", + "sql": "EXPLAIN PLAN FOR SELECT ARRAY[1,2,3] FROM a", + "output": [ + "Execution Plan", + "\nLogicalProject(EXPR$0=[ARRAY(1, 2, 3)])", + "\n LogicalTableScan(table=[[a]])", + "\n" + ] + }, + { + "description": "select int array literal", + "sql": "EXPLAIN PLAN FOR SELECT ARRAY[1,2,3]", + "output": [ + "Execution Plan", + "\nLogicalProject(EXPR$0=[ARRAY(1, 2, 3)])", + "\n LogicalValues(tuples=[[{ 0 }]])", + "\n" + ] + }, + { + "description": "select float array literal", + "sql": "EXPLAIN PLAN FOR SELECT ARRAY[0.1,0.2,0.3] FROM a", + "output": [ + "Execution Plan", + "\nLogicalProject(EXPR$0=[ARRAY(0.1:DECIMAL(2, 1), 0.2:DECIMAL(2, 1), 0.3:DECIMAL(2, 1))])", + "\n LogicalTableScan(table=[[a]])", + "\n" + ] + }, + { + "description": "select float array literal", + "sql": "EXPLAIN PLAN FOR SELECT ARRAY[0.1,0.2,0.3]", + "output": [ + "Execution Plan", + "\nLogicalProject(EXPR$0=[ARRAY(0.1:DECIMAL(2, 1), 0.2:DECIMAL(2, 1), 0.3:DECIMAL(2, 1))])", + "\n LogicalValues(tuples=[[{ 0 }]])", + "\n" + ] + }, + { + "description": "select string array literal", + "sql": "EXPLAIN PLAN FOR SELECT ARRAY['a','b','c'] FROM a", + "output": [ + "Execution Plan", + "\nLogicalProject(EXPR$0=[ARRAY(_UTF-8'a', _UTF-8'b', _UTF-8'c')])", + "\n LogicalTableScan(table=[[a]])", + "\n" + ] + }, + { + "description": "select string array literal", + "sql": "EXPLAIN PLAN FOR SELECT ARRAY['a','b','c']", + "output": [ + "Execution Plan", + "\nLogicalProject(EXPR$0=[ARRAY(_UTF-8'a', _UTF-8'b', _UTF-8'c')])", + "\n LogicalValues(tuples=[[{ 0 }]])", + "\n" + ] + }, + { + "description": "filter with two functions chaining", + "sql": "EXPLAIN PLAN FOR SELECT count(*) FROM a WHERE col1 > ToEpochDays(fromDateTime('1970-01-15', 'yyyy-MM-dd'))", + "output": [ + "Execution Plan", + "\nLogicalAggregate(group=[{}], agg#0=[COUNT($0)])", + "\n PinotLogicalExchange(distribution=[hash])", + "\n LogicalAggregate(group=[{}], agg#0=[COUNT()])", + "\n LogicalFilter(condition=[>(CAST($0):BIGINT NOT NULL, 14)])", + "\n LogicalTableScan(table=[[a]])", + "\n" + ] + }, { "description": "select non-exist literal function", "sql": "EXPLAIN PLAN FOR Select nonExistFun(1,2) FROM a", --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@pinot.apache.org For additional commands, e-mail: commits-h...@pinot.apache.org