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 c7e9695cfd7e9c..f9c978e81111e6 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 @@ -39,6 +39,8 @@ 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; @@ -56,7 +58,6 @@ 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; @@ -161,7 +162,11 @@ private static Expression replace( Expression root, Map constMap, Map resultMap) { for (Entry 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 newChildren = new ArrayList<>(); @@ -178,38 +183,7 @@ private static Expression replace( private static void collectConst(Expression expr, Map constMap, Map tExprMap, IdGenerator 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 (shouldSkipFold(((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 (shouldSkipFold(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; @@ -233,23 +207,58 @@ private static void collectConst(Expression expr, Map constM } } - // if sleep(5) will cause rpc timeout + // 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; - } - } else if (expr instanceof BoundFunction - && ((BoundFunction) expr).getName().toLowerCase().startsWith("st_")) { - // FIXME: remove this when we fixed serde of Geo types - LOG.warn("GeoFunction {} now don't support constant fold on BE", - ((BoundFunction) expr).getName()); 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 4ec7c146d7a716..db738cf543f20c 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 e09a554a3f814d..5cc91428394502 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 @@ -45,4 +45,8 @@ suite("fold_constant_by_be") { 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);" } \ No newline at end of file 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 439559aa5e0e92..983c625c1ef1cf 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)) """