1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.apache.expreval.expr.compare;
22
23 import org.apache.commons.logging.Log;
24 import org.apache.commons.logging.LogFactory;
25 import org.apache.expreval.client.NullColumnValueException;
26 import org.apache.expreval.client.ResultMissingColumnException;
27 import org.apache.expreval.expr.Operator;
28 import org.apache.expreval.expr.node.GenericValue;
29 import org.apache.expreval.expr.node.NumberValue;
30 import org.apache.expreval.expr.var.DelegateColumn;
31 import org.apache.expreval.expr.var.GenericColumn;
32 import org.apache.hadoop.hbase.filter.CompareFilter;
33 import org.apache.hadoop.hbase.filter.Filter;
34 import org.apache.hadoop.hbase.filter.WritableByteArrayComparable;
35 import org.apache.hadoop.hbase.hbql.client.HBqlException;
36 import org.apache.hadoop.hbase.hbql.impl.HConnectionImpl;
37 import org.apache.hadoop.hbase.hbql.impl.Utils;
38 import org.apache.hadoop.hbase.hbql.io.IO;
39 import org.apache.hadoop.hbase.hbql.mapping.FieldType;
40
41 import java.io.DataInput;
42 import java.io.DataOutput;
43 import java.io.IOException;
44
45 public class NumberCompare extends GenericCompare {
46
47 private static final Log LOG = LogFactory.getLog(NumberCompare.class);
48
49 public NumberCompare(final GenericValue arg0, final Operator operator, final GenericValue arg1) {
50 super(arg0, operator, arg1);
51 }
52
53 public Class<? extends GenericValue> validateTypes(final GenericValue parentExpr,
54 final boolean allowCollections) throws HBqlException {
55 return this.validateType(NumberValue.class);
56 }
57
58 public Boolean getValue(final HConnectionImpl conn, final Object object) throws HBqlException,
59 ResultMissingColumnException,
60 NullColumnValueException {
61 final Object obj0 = this.getValue(0, conn, object);
62 final Object obj1 = this.getValue(1, conn, object);
63
64 this.validateNumericArgTypes(obj0, obj1);
65
66 if (!this.useDecimal()) {
67
68 final long val0 = ((Number)obj0).longValue();
69 final long val1 = ((Number)obj1).longValue();
70
71 switch (this.getOperator()) {
72 case EQ:
73 return val0 == val1;
74 case GT:
75 return val0 > val1;
76 case GTEQ:
77 return val0 >= val1;
78 case LT:
79 return val0 < val1;
80 case LTEQ:
81 return val0 <= val1;
82 case NOTEQ:
83 return val0 != val1;
84 default:
85 throw new HBqlException("Invalid operator: " + this.getOperator());
86 }
87 }
88 else {
89
90 final double val0 = ((Number)obj0).doubleValue();
91 final double val1 = ((Number)obj1).doubleValue();
92
93 switch (this.getOperator()) {
94 case EQ:
95 return val0 == val1;
96 case GT:
97 return val0 > val1;
98 case GTEQ:
99 return val0 >= val1;
100 case LT:
101 return val0 < val1;
102 case LTEQ:
103 return val0 <= val1;
104 case NOTEQ:
105 return val0 != val1;
106 default:
107 throw new HBqlException("Invalid operator: " + this.getOperator());
108 }
109 }
110 }
111
112 public Filter getFilter() throws HBqlException {
113
114 this.validateArgsForCompareFilter();
115
116 final GenericColumn<? extends GenericValue> column;
117 final Object constant;
118 final CompareFilter.CompareOp compareOp;
119 final WritableByteArrayComparable comparator;
120
121 if (this.getExprArg(0).isAColumnReference()) {
122 column = ((DelegateColumn)this.getExprArg(0)).getTypedColumn();
123 constant = this.getConstantValue(1);
124 compareOp = this.getOperator().getCompareOpLeft();
125 }
126 else {
127 column = ((DelegateColumn)this.getExprArg(1)).getTypedColumn();
128 constant = this.getConstantValue(0);
129 compareOp = this.getOperator().getCompareOpRight();
130 }
131
132 this.validateNumericArgTypes(constant);
133
134 if (!this.useDecimal()) {
135 final long val = ((Number)constant).longValue();
136 comparator = new LongComparable(column.getColumnAttrib().getFieldType(), val);
137 }
138 else {
139 final double val = ((Number)constant).doubleValue();
140 comparator = new DoubleComparable(column.getColumnAttrib().getFieldType(), val);
141 }
142
143 return this.newSingleColumnValueFilter(column.getColumnAttrib(), compareOp, comparator);
144 }
145
146 private static abstract class NumberComparable<T> extends GenericComparable<T> {
147
148 private FieldType fieldType;
149
150 protected void setFieldType(final FieldType fieldType) {
151 this.fieldType = fieldType;
152 }
153
154 protected FieldType getFieldType() {
155 return this.fieldType;
156 }
157
158 protected void setValueInBytes(final Number val) throws IOException {
159 try {
160 this.setValueInBytes(IO.getSerialization().getNumberEqualityBytes(this.getFieldType(), val));
161 }
162 catch (HBqlException e) {
163 throw new IOException(e.getMessage());
164 }
165 }
166 }
167
168 private static class LongComparable extends NumberComparable<Long> {
169
170 public LongComparable() {
171 }
172
173 public LongComparable(final FieldType fieldType, final long value) {
174 this.setFieldType(fieldType);
175 this.setTypedValue(value);
176 }
177
178 public int compareTo(final byte[] bytes) {
179
180 if (this.equalValues(bytes))
181 return 0;
182
183 try {
184 long columnValue = IO.getSerialization().getNumberFromBytes(this.getFieldType(), bytes).longValue();
185
186 final long val = this.getTypedValue();
187 if (columnValue == val)
188 return 0;
189 else
190 return (columnValue > val) ? -1 : 1;
191 }
192 catch (HBqlException e) {
193 e.printStackTrace();
194 Utils.logException(LOG, e);
195 return 1;
196 }
197 }
198
199 public void write(final DataOutput dataOutput) throws IOException {
200 dataOutput.writeUTF(this.getFieldType().name());
201 dataOutput.writeLong(this.getTypedValue());
202 }
203
204 public void readFields(final DataInput dataInput) throws IOException {
205 this.setFieldType(FieldType.valueOf(dataInput.readUTF()));
206 this.setTypedValue(dataInput.readLong());
207
208 this.setValueInBytes(this.getTypedValue());
209 }
210 }
211
212 private static class DoubleComparable extends NumberComparable<Double> {
213
214 public DoubleComparable() {
215 }
216
217 public DoubleComparable(final FieldType fieldType, final double value) {
218 this.setFieldType(fieldType);
219 this.setTypedValue(value);
220 }
221
222 public int compareTo(final byte[] bytes) {
223
224 if (this.equalValues(bytes))
225 return 0;
226
227 try {
228 double columnValue = IO.getSerialization().getNumberFromBytes(this.getFieldType(), bytes).doubleValue();
229
230 final double val = this.getTypedValue();
231 if (columnValue == val)
232 return 0;
233 else
234 return (columnValue > val) ? -1 : 1;
235 }
236 catch (HBqlException e) {
237 e.printStackTrace();
238 Utils.logException(LOG, e);
239 return 1;
240 }
241 }
242
243 public void write(final DataOutput dataOutput) throws IOException {
244 dataOutput.writeUTF(this.getFieldType().name());
245 dataOutput.writeDouble(this.getTypedValue());
246 }
247
248 public void readFields(final DataInput dataInput) throws IOException {
249 this.setFieldType(FieldType.valueOf(dataInput.readUTF()));
250 this.setTypedValue(dataInput.readDouble());
251
252 this.setValueInBytes(this.getTypedValue());
253 }
254 }
255 }