Fix bug that <=> operator and in operator get wrong result (#1516)

* Fix bug that <=> operator and in operator get wrong result

* Add some comment to get_result_for_null

* Add an new Binary Operator to replace is_safe_for_null for handleing '<=>' operator

* Add EQ_FOR_NULL to TExprOpcode

* Remove macro definition last backslash
This commit is contained in:
chenhao
2019-07-30 11:17:53 +08:00
committed by GitHub
parent 97718a35a2
commit 2cb82c57bb
7 changed files with 215 additions and 15 deletions

View File

@ -3640,7 +3640,7 @@ comparison_predicate ::=
| expr:e1 GREATERTHAN:op expr:e2
{: RESULT = new BinaryPredicate(BinaryPredicate.Operator.GT, e1, e2); :}
| expr:e1 LESSTHAN EQUAL GREATERTHAN:op expr:e2
{: RESULT = new BinaryPredicate(BinaryPredicate.Operator.EQ, e1, e2); :}
{: RESULT = new BinaryPredicate(BinaryPredicate.Operator.EQ_FOR_NULL, e1, e2); :}
;
like_predicate ::=

View File

@ -56,7 +56,8 @@ public class BinaryPredicate extends Predicate implements Writable {
LE("<=", "le", TExprOpcode.LE),
GE(">=", "ge", TExprOpcode.GE),
LT("<", "lt", TExprOpcode.LT),
GT(">", "gt", TExprOpcode.GT);
GT(">", "gt", TExprOpcode.GT),
EQ_FOR_NULL("<=>", "eq_for_null", TExprOpcode.EQ_FOR_NULL);
private final String description;
private final String name;
@ -97,6 +98,8 @@ public class BinaryPredicate extends Predicate implements Writable {
return GT;
case GT:
return LE;
case EQ_FOR_NULL:
return this;
}
return null;
}
@ -115,6 +118,8 @@ public class BinaryPredicate extends Predicate implements Writable {
return GT;
case GT:
return LT;
case EQ_FOR_NULL:
return EQ_FOR_NULL;
// case DISTINCT_FROM: return DISTINCT_FROM;
// case NOT_DISTINCT: return NOT_DISTINCT;
// case NULL_MATCHING_EQ:
@ -124,7 +129,7 @@ public class BinaryPredicate extends Predicate implements Writable {
}
}
public boolean isEquivalence() { return this == EQ; };
public boolean isEquivalence() { return this == EQ || this == EQ_FOR_NULL; };
public boolean isUnequivalence() { return this == NE; }
}
@ -132,7 +137,7 @@ public class BinaryPredicate extends Predicate implements Writable {
private Operator op;
// check if left is slot and right isnot slot.
private Boolean slotIsleft = null;
// for restoring
public BinaryPredicate() {
super();
@ -172,6 +177,8 @@ public class BinaryPredicate extends Predicate implements Writable {
Operator.LT.getName(), Lists.newArrayList(t, t), Type.BOOLEAN));
functionSet.addBuiltin(ScalarFunction.createBuiltinOperator(
Operator.GT.getName(), Lists.newArrayList(t, t), Type.BOOLEAN));
functionSet.addBuiltin(ScalarFunction.createBuiltinOperator(
Operator.EQ_FOR_NULL.getName(), Lists.newArrayList(t, t), Type.BOOLEAN));
}
}
@ -368,6 +375,7 @@ public class BinaryPredicate extends Predicate implements Writable {
slotRef = (SlotRef) getChild(1).getChild(0);
}
}
if (slotRef != null && slotRef.getSlotId() == id) {
slotIsleft = false;
return getChild(0);
@ -507,13 +515,24 @@ public class BinaryPredicate extends Predicate implements Writable {
}
private Expr compareLiteral(LiteralExpr first, LiteralExpr second) throws AnalysisException {
if (first instanceof NullLiteral || second instanceof NullLiteral) {
return new NullLiteral();
final boolean isFirstNull = (first instanceof NullLiteral);
final boolean isSecondNull = (second instanceof NullLiteral);
if (op == Operator.EQ_FOR_NULL) {
if (isFirstNull && isSecondNull) {
return new BoolLiteral(true);
} else if (isFirstNull || isSecondNull) {
return new BoolLiteral(false);
}
} else {
if (isFirstNull || isSecondNull){
return new NullLiteral();
}
}
final int compareResult = first.compareLiteral(second);
switch(op) {
case EQ:
case EQ_FOR_NULL:
return new BoolLiteral(compareResult == 0);
case GE:
return new BoolLiteral(compareResult == 1 || compareResult == 0);

View File

@ -248,10 +248,18 @@ public class InPredicate extends Predicate {
return this;
}
if (leftChildValue instanceof NullLiteral) {
return leftChildValue;
}
List<Expr> inListChildren = children.subList(1, children.size());
if (inListChildren.contains(leftChildValue)) {
return new BoolLiteral(true);
} else {
final NullLiteral nullLiteral = new NullLiteral();
if (inListChildren.contains(nullLiteral)) {
return nullLiteral;
}
return new BoolLiteral(false);
}
}