From c49060a50bfbf0a379a0fc560bbe7085eefd6135 Mon Sep 17 00:00:00 2001 From: morrySnow <101034200+morrySnow@users.noreply.github.com> Date: Thu, 25 May 2023 11:21:12 +0800 Subject: [PATCH] [fix](Nereids) the rule of fold constant for logical operator (#20017) the rule of constant folding on Logical Operator is: true and true -> true true and false -> false false and false -> false true and x -> x false and x -> false null and true -> null null and false -> false null and null -> null null and x -> null and x true or true -> true true or false -> true false or false -> false true or x -> true false or x -> false or x null or true -> true null or false -> null null or null -> null null or x -> null or x --- .../rules/FoldConstantRuleOnFE.java | 69 ++++++++++++++----- .../rules/expression/FoldConstantTest.java | 4 ++ 2 files changed, 55 insertions(+), 18 deletions(-) diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/FoldConstantRuleOnFE.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/FoldConstantRuleOnFE.java index d014958937..2451b72be5 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/FoldConstantRuleOnFE.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/FoldConstantRuleOnFE.java @@ -218,50 +218,83 @@ public class FoldConstantRuleOnFE extends AbstractExpressionRewriteRule { @Override public Expression visitAnd(And and, ExpressionRewriteContext context) { List nonTrueLiteral = Lists.newArrayList(); + int nullCount = 0; for (Expression e : and.children()) { e = e.accept(this, context); if (BooleanLiteral.FALSE.equals(e)) { return BooleanLiteral.FALSE; } else if (e instanceof NullLiteral) { - return e; + nullCount++; + nonTrueLiteral.add(e); } else if (!BooleanLiteral.TRUE.equals(e)) { nonTrueLiteral.add(e); } } - if (nonTrueLiteral.isEmpty()) { - return BooleanLiteral.TRUE; + + if (nullCount == 0) { + switch (nonTrueLiteral.size()) { + case 0: + // true and true + return BooleanLiteral.TRUE; + case 1: + // true and x + return nonTrueLiteral.get(0); + default: + // x and y + return and.withChildren(nonTrueLiteral); + } + } else if (nullCount == 1) { + if (nonTrueLiteral.size() == 1) { + // null and true + return new NullLiteral(BooleanType.INSTANCE); + } + // null and x + return and.withChildren(nonTrueLiteral); + } else { + // null and null + return new NullLiteral(BooleanType.INSTANCE); } - if (nonTrueLiteral.size() == 1) { - return nonTrueLiteral.get(0); - } - return and.withChildren(nonTrueLiteral); } @Override public Expression visitOr(Or or, ExpressionRewriteContext context) { List nonFalseLiteral = Lists.newArrayList(); - boolean hasNull = false; + int nullCount = 0; for (Expression e : or.children()) { e = e.accept(this, context); if (BooleanLiteral.TRUE.equals(e)) { return BooleanLiteral.TRUE; } else if (e instanceof NullLiteral) { - hasNull = true; + nullCount++; + nonFalseLiteral.add(e); } else if (!BooleanLiteral.FALSE.equals(e)) { nonFalseLiteral.add(e); } } - if (nonFalseLiteral.isEmpty()) { - if (hasNull) { - return new NullLiteral(BooleanType.INSTANCE); - } else { - return BooleanLiteral.FALSE; + + if (nullCount == 0) { + switch (nonFalseLiteral.size()) { + case 0: + // false or false + return BooleanLiteral.FALSE; + case 1: + // false or x + return nonFalseLiteral.get(0); + default: + // x or y + return or.withChildren(nonFalseLiteral); } + } else if (nullCount == 1) { + if (nonFalseLiteral.size() == 1) { + // null or false + return new NullLiteral(BooleanType.INSTANCE); + } + // null or x + return or.withChildren(nonFalseLiteral); + } else { + // null or null + return new NullLiteral(BooleanType.INSTANCE); } - if (nonFalseLiteral.size() == 1) { - return nonFalseLiteral.get(0); - } - return or.withChildren(nonFalseLiteral); } @Override diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/FoldConstantTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/FoldConstantTest.java index a38a20bf92..8f66c9fc30 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/FoldConstantTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/FoldConstantTest.java @@ -112,10 +112,14 @@ public class FoldConstantTest extends ExpressionRewriteTestHelper { assertRewriteAfterTypeCoercion("true and null", "null"); assertRewriteAfterTypeCoercion("false and null", "false"); + assertRewriteAfterTypeCoercion("null and IA is null", "null and IA is null"); assertRewriteAfterTypeCoercion("true or null", "true"); assertRewriteAfterTypeCoercion("false or null", "null"); + assertRewriteAfterTypeCoercion("null or IA is null", "null or IA is null"); assertRewriteAfterTypeCoercion("null and null", "null"); + assertRewriteAfterTypeCoercion("null or null", "null"); + } @Test