1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.tikv.common.expression;
19
20 import static com.google.common.base.Preconditions.checkArgument;
21 import static java.util.Objects.requireNonNull;
22 import static org.tikv.common.expression.ComparisonBinaryExpression.Operator.*;
23
24 import com.google.common.collect.ImmutableList;
25 import java.util.List;
26 import java.util.Objects;
27 import org.tikv.common.exception.TiExpressionException;
28 import org.tikv.common.key.TypedKey;
29 import org.tikv.common.types.DataType;
30 import org.tikv.common.types.IntegerType;
31
32 public class ComparisonBinaryExpression extends Expression {
33 private final Expression left;
34 private final Expression right;
35 private final Operator compOperator;
36 private transient NormalizedPredicate normalizedPredicate;
37
38 public ComparisonBinaryExpression(Operator operator, Expression left, Expression right) {
39 super(IntegerType.BOOLEAN);
40 this.resolved = true;
41 this.left = requireNonNull(left, "left expression is null");
42 this.right = requireNonNull(right, "right expression is null");
43 this.compOperator = requireNonNull(operator, "type is null");
44 }
45
46 public static ComparisonBinaryExpression equal(Expression left, Expression right) {
47 return new ComparisonBinaryExpression(EQUAL, left, right);
48 }
49
50 public static ComparisonBinaryExpression notEqual(Expression left, Expression right) {
51 return new ComparisonBinaryExpression(NOT_EQUAL, left, right);
52 }
53
54 public static ComparisonBinaryExpression lessThan(Expression left, Expression right) {
55 return new ComparisonBinaryExpression(LESS_THAN, left, right);
56 }
57
58 public static ComparisonBinaryExpression lessEqual(Expression left, Expression right) {
59 return new ComparisonBinaryExpression(LESS_EQUAL, left, right);
60 }
61
62 public static ComparisonBinaryExpression greaterThan(Expression left, Expression right) {
63 return new ComparisonBinaryExpression(GREATER_THAN, left, right);
64 }
65
66 public static ComparisonBinaryExpression greaterEqual(Expression left, Expression right) {
67 return new ComparisonBinaryExpression(GREATER_EQUAL, left, right);
68 }
69
70 @Override
71 public List<Expression> getChildren() {
72 return ImmutableList.of(left, right);
73 }
74
75 @Override
76 public <R, C> R accept(Visitor<R, C> visitor, C context) {
77 return visitor.visit(this, context);
78 }
79
80 public Expression getLeft() {
81 return left;
82 }
83
84 public Expression getRight() {
85 return right;
86 }
87
88 public Operator getComparisonType() {
89 return compOperator;
90 }
91
92 public NormalizedPredicate normalize() {
93 if (normalizedPredicate != null) {
94 return normalizedPredicate;
95 }
96 if (getLeft() instanceof Constant && getRight() instanceof ColumnRef) {
97 Constant left = (Constant) getLeft();
98 ColumnRef right = (ColumnRef) getRight();
99 Operator newOperator;
100 switch (getComparisonType()) {
101 case EQUAL:
102 newOperator = EQUAL;
103 break;
104 case LESS_EQUAL:
105 newOperator = GREATER_EQUAL;
106 break;
107 case LESS_THAN:
108 newOperator = GREATER_THAN;
109 break;
110 case GREATER_EQUAL:
111 newOperator = LESS_EQUAL;
112 break;
113 case GREATER_THAN:
114 newOperator = LESS_THAN;
115 break;
116 case NOT_EQUAL:
117 newOperator = NOT_EQUAL;
118 break;
119 default:
120 throw new TiExpressionException(
121 String.format(
122 "PredicateNormalizer is not able to process type %s", getComparisonType()));
123 }
124 ComparisonBinaryExpression newExpression =
125 new ComparisonBinaryExpression(newOperator, right, left);
126 normalizedPredicate = new NormalizedPredicate(newExpression);
127 return normalizedPredicate;
128 } else if (getRight() instanceof Constant && getLeft() instanceof ColumnRef) {
129 normalizedPredicate = new NormalizedPredicate(this);
130 return normalizedPredicate;
131 } else {
132 return null;
133 }
134 }
135
136 @Override
137 public String toString() {
138 return String.format("[%s %s %s]", getLeft(), getComparisonType(), getRight());
139 }
140
141 @Override
142 public boolean equals(Object other) {
143 if (this == other) {
144 return true;
145 }
146 if (!(other instanceof ComparisonBinaryExpression)) {
147 return false;
148 }
149
150 ComparisonBinaryExpression that = (ComparisonBinaryExpression) other;
151 return (compOperator == that.compOperator)
152 && Objects.equals(left, that.left)
153 && Objects.equals(right, that.right);
154 }
155
156 @Override
157 public int hashCode() {
158 return Objects.hash(compOperator, left, right);
159 }
160
161 public enum Operator {
162 EQUAL,
163 NOT_EQUAL,
164 LESS_THAN,
165 LESS_EQUAL,
166 GREATER_THAN,
167 GREATER_EQUAL
168 }
169
170 public static class NormalizedPredicate {
171 private final ComparisonBinaryExpression pred;
172 private TypedKey key;
173
174 NormalizedPredicate(ComparisonBinaryExpression pred) {
175 checkArgument(pred.getLeft() instanceof ColumnRef);
176 checkArgument(pred.getRight() instanceof Constant);
177 this.pred = pred;
178 }
179
180 public ColumnRef getColumnRef() {
181 return (ColumnRef) pred.getLeft();
182 }
183
184 public Constant getValue() {
185 return (Constant) pred.getRight();
186 }
187
188 public Operator getType() {
189 return pred.getComparisonType();
190 }
191
192 TypedKey getTypedLiteral() {
193 return getTypedLiteral(DataType.UNSPECIFIED_LEN);
194 }
195
196 public TypedKey getTypedLiteral(int prefixLength) {
197 if (key == null) {
198 DataType colRefType = getColumnRef().getDataType();
199 key = TypedKey.toTypedKey(getValue().getValue(), colRefType, prefixLength);
200 }
201 return key;
202 }
203 }
204 }