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 <[email protected]>
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: [email protected]
For additional commands, e-mail: [email protected]