This is an automated email from the ASF dual-hosted git repository.
morrysnow pushed a commit to branch branch-2.1
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/branch-2.1 by this push:
new 0c39b888048 [Improvement](expr) fold child when const expr not folded
(#38493) (#38961)
0c39b888048 is described below
commit 0c39b8880486a991efa9c73b84d98620af570a98
Author: LiBinfeng <[email protected]>
AuthorDate: Mon Aug 12 15:13:48 2024 +0800
[Improvement](expr) fold child when const expr not folded (#38493) (#38961)
cherry-pick from master 38493
1. fold child when const expr not folded
2. do not fold function `sleep`
3. move all exceptional expression into shouldSkipFold
before
mysql [test]>explain select sleep(sign(1)*100);
+-----------------------------------------------+
| Explain String(Nereids Planner) |
+-----------------------------------------------+
| PLAN FRAGMENT 0 |
| OUTPUT EXPRS: |
| sleep(cast((sign(1.0) * 100) as INT))[#0] |
| PARTITION: UNPARTITIONED |
| |
| HAS_COLO_PLAN_NODE: false |
| |
| VRESULT SINK |
| MYSQL_PROTOCAL |
| |
| 0:VUNION(32) |
| constant exprs: |
| sleep(CAST((sign(1) * 100) AS int)) |
+-----------------------------------------------+
13 rows in set (15.02 sec)
mysql [test]>select sleep(sign(1)*100);
+-----------------------------------------------------+
| sleep(cast((sign(cast(1 as DOUBLE)) * 100) as INT)) |
+-----------------------------------------------------+
| 1 |
+-----------------------------------------------------+
1 row in set (1 min 55.34 sec)
after
mysql [test]>explain select sleep(sign(1)*100);
+---------------------------------+
| Explain String(Nereids Planner) |
+---------------------------------+
| PLAN FRAGMENT 0 |
| OUTPUT EXPRS: |
| sleep(100)[#0] |
| PARTITION: UNPARTITIONED |
| |
| HAS_COLO_PLAN_NODE: false |
| |
| VRESULT SINK |
| MYSQL_PROTOCAL |
| |
| 0:VUNION(32) |
| constant exprs: |
| sleep(100) |
+---------------------------------+
13 rows in set (0.23 sec)
mysql [test]> select sleep(sign(1)*100);
+-----------------------------------------------------+
| sleep(cast((sign(cast(1 as DOUBLE)) * 100) as INT)) |
+-----------------------------------------------------+
| 1 |
+-----------------------------------------------------+
1 row in set (1 min 40.37 sec)
Co-authored-by: Pxl <[email protected]>
---
.../expression/rules/FoldConstantRuleOnBE.java | 102 ++++++++++++---------
.../fold_constant/fold_constant_by_be.out | 18 ++++
.../fold_constant/fold_constant_by_be.groovy | 11 ++-
.../aggregate/select_random_distributed_tbl.groovy | 3 +-
4 files changed, 89 insertions(+), 45 deletions(-)
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/FoldConstantRuleOnBE.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/FoldConstantRuleOnBE.java
index 706d384be53..7b6446aaf37 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/FoldConstantRuleOnBE.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/FoldConstantRuleOnBE.java
@@ -37,7 +37,10 @@ import
org.apache.doris.nereids.trees.expressions.ArrayItemReference;
import org.apache.doris.nereids.trees.expressions.Cast;
import org.apache.doris.nereids.trees.expressions.Expression;
import org.apache.doris.nereids.trees.expressions.Match;
+import org.apache.doris.nereids.trees.expressions.functions.BoundFunction;
import
org.apache.doris.nereids.trees.expressions.functions.generator.TableGeneratingFunction;
+import org.apache.doris.nereids.trees.expressions.functions.scalar.NonNullable;
+import org.apache.doris.nereids.trees.expressions.functions.scalar.Nullable;
import org.apache.doris.nereids.trees.expressions.functions.scalar.Sleep;
import org.apache.doris.nereids.trees.expressions.literal.ArrayLiteral;
import org.apache.doris.nereids.trees.expressions.literal.BigIntLiteral;
@@ -55,7 +58,6 @@ import
org.apache.doris.nereids.trees.expressions.literal.LargeIntLiteral;
import org.apache.doris.nereids.trees.expressions.literal.Literal;
import org.apache.doris.nereids.trees.expressions.literal.MapLiteral;
import org.apache.doris.nereids.trees.expressions.literal.NullLiteral;
-import org.apache.doris.nereids.trees.expressions.literal.NumericLiteral;
import org.apache.doris.nereids.trees.expressions.literal.SmallIntLiteral;
import org.apache.doris.nereids.trees.expressions.literal.StringLiteral;
import org.apache.doris.nereids.trees.expressions.literal.StructLiteral;
@@ -157,7 +159,11 @@ public class FoldConstantRuleOnBE implements
ExpressionPatternRuleFactory {
Expression root, Map<String, Expression> constMap, Map<String,
Expression> resultMap) {
for (Entry<String, Expression> entry : constMap.entrySet()) {
if (entry.getValue().equals(root)) {
- return resultMap.get(entry.getKey());
+ if (resultMap.containsKey(entry.getKey())) {
+ return resultMap.get(entry.getKey());
+ } else {
+ return root;
+ }
}
}
List<Expression> newChildren = new ArrayList<>();
@@ -174,38 +180,7 @@ public class FoldConstantRuleOnBE implements
ExpressionPatternRuleFactory {
private static void collectConst(Expression expr, Map<String, Expression>
constMap,
Map<String, TExpr> tExprMap, IdGenerator<ExprId> idGenerator) {
- if (expr.isConstant()) {
- // Do not constant fold cast(null as dataType) because we cannot
preserve the
- // cast-to-types and that can lead to query failures, e.g., CTAS
- if (expr instanceof Cast) {
- if (((Cast) expr).child().isNullLiteral()) {
- return;
- }
- if (skipSleepFunction(((Cast) expr).child())) {
- return;
- }
- }
- // skip literal expr
- if (expr.isLiteral()) {
- return;
- }
- // eg: avg_state(1) return is agg function serialize data
- // and some type can't find a literal to represent.
- // time type: need add a time literal in nereids
- // IPv6 type: need get a library to output the compressed address
format
- if (expr.getDataType().isAggStateType() ||
expr.getDataType().isObjectType()
- || expr.getDataType().isVariantType() ||
expr.getDataType().isTimeLikeType()
- || expr.getDataType().isIPv6Type()) {
- return;
- }
- // first need pass PlanTranslatorContext value,
- // and ArrayItemReference translate, can't findColumnRef
- // Match need give more info rather then as left child a NULL, in
- // match_phrase_prefix/MATCH_PHRASE/MATCH_PHRASE/MATCH_ANY
- if (skipSleepFunction(expr) || (expr instanceof
TableGeneratingFunction)
- || (expr instanceof ArrayItemReference) || (expr
instanceof Match)) {
- return;
- }
+ if (expr.isConstant() && !shouldSkipFold(expr)) {
String id = idGenerator.getNextId().toString();
constMap.put(id, expr);
Expr staleExpr;
@@ -229,17 +204,58 @@ public class FoldConstantRuleOnBE implements
ExpressionPatternRuleFactory {
}
}
- // if sleep(5) will cause rpc timeout
- private static boolean skipSleepFunction(Expression expr) {
+ // Some expressions should not do constant folding
+ private static boolean shouldSkipFold(Expression expr) {
+ // Skip literal expr
+ if (expr.isLiteral()) {
+ return true;
+ }
+
+ // Frontend can not represent those types
+ if (expr.getDataType().isAggStateType() ||
expr.getDataType().isObjectType()
+ || expr.getDataType().isVariantType() ||
expr.getDataType().isTimeLikeType()
+ || expr.getDataType().isIPv6Type()) {
+ return true;
+ }
+
+ // Frontend can not represent geo types
+ if (expr instanceof BoundFunction && ((BoundFunction)
expr).getName().toLowerCase().startsWith("st_")) {
+ return true;
+ }
+
+ // TableGeneratingFunction need pass PlanTranslatorContext value
+ if (expr instanceof TableGeneratingFunction) {
+ return true;
+ }
+
+ // ArrayItemReference translate can't findColumnRef
+ if (expr instanceof ArrayItemReference) {
+ return true;
+ }
+
+ // Match need give more info rather then as left child a NULL, in
+ // match_phrase_prefix/MATCH_PHRASE/MATCH_PHRASE/MATCH_ANY
+ if (expr instanceof Match) {
+ return true;
+ }
+
+ // sleep will cause rpc timeout
if (expr instanceof Sleep) {
- Expression param = expr.child(0);
- if (param instanceof Cast) {
- param = param.child(0);
- }
- if (param instanceof NumericLiteral) {
- return ((NumericLiteral) param).getDouble() >= 5.0;
- }
+ return true;
+ }
+
+ // Do not constant fold cast(null as dataType) because we cannot
preserve the
+ // cast-to-types and that can lead to query failures, e.g., CTAS
+ if (expr instanceof Cast && ((Cast) expr).child().isNullLiteral()) {
+ return true;
}
+
+ // This kind of function is often used to change the attributes of
columns.
+ // Folding will make it impossible to construct columns such as
nullable(1).
+ if (expr instanceof Nullable || expr instanceof NonNullable) {
+ return true;
+ }
+
return false;
}
diff --git
a/regression-test/data/nereids_p0/expression/fold_constant/fold_constant_by_be.out
b/regression-test/data/nereids_p0/expression/fold_constant/fold_constant_by_be.out
index 4ec7c146d7a..db738cf543f 100644
---
a/regression-test/data/nereids_p0/expression/fold_constant/fold_constant_by_be.out
+++
b/regression-test/data/nereids_p0/expression/fold_constant/fold_constant_by_be.out
@@ -2,3 +2,21 @@
-- !sql_1 --
80000
+-- !sql --
+PLAN FRAGMENT 0
+ OUTPUT EXPRS:
+ sleep(100)[#0]
+ PARTITION: UNPARTITIONED
+
+ HAS_COLO_PLAN_NODE: false
+
+ VRESULT SINK
+ MYSQL_PROTOCAL
+
+ 0:VUNION(32)
+ constant exprs:
+ sleep(100)
+
+-- !sql --
+true
+
diff --git
a/regression-test/suites/nereids_p0/expression/fold_constant/fold_constant_by_be.groovy
b/regression-test/suites/nereids_p0/expression/fold_constant/fold_constant_by_be.groovy
index e1162c662b9..10882287ad7 100644
---
a/regression-test/suites/nereids_p0/expression/fold_constant/fold_constant_by_be.groovy
+++
b/regression-test/suites/nereids_p0/expression/fold_constant/fold_constant_by_be.groovy
@@ -40,4 +40,13 @@ suite("fold_constant_by_be") {
sql """ INSERT INTO str_tb VALUES (2, repeat("test1111", 10000)); """
qt_sql_1 """ select length(v1) from str_tb; """
-}
\ No newline at end of file
+
+ def res1 = sql " select /*+SET_VAR(enable_fold_constant_by_be=true)*/
ST_CIRCLE(121.510651, 31.234391, 1918.0); "
+ def res2 = sql " select /*+SET_VAR(enable_fold_constant_by_be=false)*/
ST_CIRCLE(121.510651, 31.234391, 1918.0); "
+ log.info("result: {}, {}", res1, res2)
+ assertEquals(res1[0][0], res2[0][0])
+
+ qt_sql "explain select sleep(sign(1)*100);"
+ sql 'set query_timeout=12;'
+ qt_sql "select sleep(sign(1)*10);"
+}
diff --git
a/regression-test/suites/query_p0/aggregate/select_random_distributed_tbl.groovy
b/regression-test/suites/query_p0/aggregate/select_random_distributed_tbl.groovy
index 439559aa5e0..983c625c1ef 100644
---
a/regression-test/suites/query_p0/aggregate/select_random_distributed_tbl.groovy
+++
b/regression-test/suites/query_p0/aggregate/select_random_distributed_tbl.groovy
@@ -41,8 +41,9 @@ suite("select_random_distributed_tbl") {
"replication_allocation" = "tag.location.default: 1"
);
"""
-
+ sql 'set enable_fold_constant_by_be=true'
sql """ insert into ${tableName}
values(1,"a",1,1,1,avg_state(1),hll_hash(1),bitmap_hash(1),to_quantile_state(1,
2048)) """
+ sql 'set enable_fold_constant_by_be=false'
sql """ insert into ${tableName}
values(1,"a",2,2,2,avg_state(2),hll_hash(2),bitmap_hash(2),to_quantile_state(2,
2048)) """
sql """ insert into ${tableName}
values(1,"a",3,3,3,avg_state(3),hll_hash(3),bitmap_hash(3),to_quantile_state(3,
2048)) """
sql """ insert into ${tableName}
values(2,"b",4,4,4,avg_state(4),hll_hash(4),bitmap_hash(4),to_quantile_state(4,
2048)) """
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]