[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
This commit is contained in:
morrySnow
2023-05-25 11:21:12 +08:00
committed by GitHub
parent 8149b757c4
commit c49060a50b
2 changed files with 55 additions and 18 deletions

View File

@ -218,50 +218,83 @@ public class FoldConstantRuleOnFE extends AbstractExpressionRewriteRule {
@Override
public Expression visitAnd(And and, ExpressionRewriteContext context) {
List<Expression> 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<Expression> 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

View File

@ -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