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.betweenstmt;
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.ExpressionType;
28 import org.apache.expreval.expr.node.GenericValue;
29 import org.apache.expreval.expr.var.DelegateColumn;
30 import org.apache.expreval.expr.var.GenericColumn;
31 import org.apache.hadoop.hbase.filter.CompareFilter;
32 import org.apache.hadoop.hbase.filter.Filter;
33 import org.apache.hadoop.hbase.filter.WritableByteArrayComparable;
34 import org.apache.hadoop.hbase.hbql.client.HBqlException;
35 import org.apache.hadoop.hbase.hbql.impl.HConnectionImpl;
36 import org.apache.hadoop.hbase.hbql.impl.Utils;
37 import org.apache.hadoop.hbase.hbql.io.IO;
38 import org.apache.hadoop.hbase.hbql.mapping.FieldType;
39
40 import java.io.DataInput;
41 import java.io.DataOutput;
42 import java.io.IOException;
43
44 public class NumberBetweenStmt extends GenericBetweenStmt {
45
46 private static final Log LOG = LogFactory.getLog(NumberBetweenStmt.class);
47
48 public NumberBetweenStmt(final GenericValue arg0,
49 final boolean not,
50 final GenericValue arg1,
51 final GenericValue arg2) {
52 super(ExpressionType.NUMBERBETWEEN, not, arg0, arg1, arg2);
53 }
54
55 public Boolean getValue(final HConnectionImpl conn, final Object object) throws HBqlException,
56 ResultMissingColumnException,
57 NullColumnValueException {
58 final Object obj0 = this.getExprArg(0).getValue(conn, object);
59 final Object obj1 = this.getExprArg(1).getValue(conn, object);
60 final Object obj2 = this.getExprArg(2).getValue(conn, object);
61
62 this.validateNumericArgTypes(obj0, obj1, obj2);
63
64 final boolean retval;
65
66 if (!this.useDecimal()) {
67 final long val0 = ((Number)obj0).longValue();
68 final long val1 = ((Number)obj1).longValue();
69 final long val2 = ((Number)obj2).longValue();
70
71 retval = val0 >= val1 && val0 <= val2;
72 }
73 else {
74 final double val0 = ((Number)obj0).doubleValue();
75 final double val1 = ((Number)obj1).doubleValue();
76 final double val2 = ((Number)obj2).doubleValue();
77
78 retval = val0 >= val1 && val0 <= val2;
79 }
80
81 return (this.isNot()) ? !retval : retval;
82 }
83
84 public Filter getFilter() throws HBqlException {
85
86 this.validateArgsForBetweenFilter();
87
88 final GenericColumn<? extends GenericValue> column = ((DelegateColumn)this.getExprArg(0)).getTypedColumn();
89 final Object lowerConstant = this.getConstantValue(1);
90 final Object upperConstant = this.getConstantValue(2);
91 final WritableByteArrayComparable comparator;
92
93 this.validateNumericArgTypes(lowerConstant, upperConstant);
94
95 if (!this.useDecimal()) {
96 final long lowerVal = ((Number)lowerConstant).longValue();
97 final long upperVal = ((Number)upperConstant).longValue();
98 comparator = new LongBetweenComparable(column.getColumnAttrib().getFieldType(), lowerVal, upperVal);
99 }
100 else {
101 final double lowerVal = ((Number)lowerConstant).doubleValue();
102 final double upperVal = ((Number)upperConstant).doubleValue();
103 comparator = new DoubleBetweenComparable(column.getColumnAttrib().getFieldType(), lowerVal, upperVal);
104 }
105
106 return this.newSingleColumnValueFilter(column.getColumnAttrib(), CompareFilter.CompareOp.EQUAL, comparator);
107 }
108
109 private static abstract class NumberBetweenComparable<T> extends GenericBetweenComparable<T> {
110
111 private FieldType fieldType;
112
113 protected void setFieldType(final FieldType fieldType) {
114 this.fieldType = fieldType;
115 }
116
117 protected FieldType getFieldType() {
118 return this.fieldType;
119 }
120 }
121
122 private static class LongBetweenComparable extends NumberBetweenComparable<Long> {
123
124 public LongBetweenComparable() {
125 }
126
127 public LongBetweenComparable(final FieldType fieldType, final long lowerValue, final long upperValue) {
128 this.setFieldType(fieldType);
129 this.setLowerValue(lowerValue);
130 this.setUpperValue(upperValue);
131 }
132
133 public int compareTo(final byte[] bytes) {
134
135 try {
136 long val = IO.getSerialization().getNumberFromBytes(this.getFieldType(), bytes).longValue();
137 final double lowerVal = this.getLowerValue();
138 final double upperVal = this.getUpperValue();
139 return (val >= lowerVal && val <= upperVal) ? 0 : 1;
140 }
141 catch (HBqlException e) {
142 e.printStackTrace();
143 Utils.logException(LOG, e);
144 return 1;
145 }
146 }
147
148 public void write(final DataOutput dataOutput) throws IOException {
149 dataOutput.writeUTF(this.getFieldType().name());
150 dataOutput.writeLong(this.getLowerValue());
151 dataOutput.writeLong(this.getUpperValue());
152 }
153
154 public void readFields(final DataInput dataInput) throws IOException {
155 this.setFieldType(FieldType.valueOf(dataInput.readUTF()));
156 this.setLowerValue(dataInput.readLong());
157 this.setUpperValue(dataInput.readLong());
158 }
159 }
160
161 private static class DoubleBetweenComparable extends NumberBetweenComparable<Double> {
162
163 public DoubleBetweenComparable() {
164 }
165
166 public DoubleBetweenComparable(final FieldType fieldType, final double lowerValue, final double upperValue) {
167 this.setFieldType(fieldType);
168 this.setLowerValue(lowerValue);
169 this.setUpperValue(upperValue);
170 }
171
172 public int compareTo(final byte[] bytes) {
173
174 try {
175 double val = IO.getSerialization().getNumberFromBytes(this.getFieldType(), bytes).doubleValue();
176 final double lowerVal = this.getLowerValue();
177 final double upperVal = this.getUpperValue();
178 return (val >= lowerVal && val <= upperVal) ? 0 : 1;
179 }
180 catch (HBqlException e) {
181 e.printStackTrace();
182 Utils.logException(LOG, e);
183 return 1;
184 }
185 }
186
187 public void write(final DataOutput dataOutput) throws IOException {
188 dataOutput.writeUTF(this.getFieldType().name());
189 dataOutput.writeDouble(this.getLowerValue());
190 dataOutput.writeDouble(this.getUpperValue());
191 }
192
193 public void readFields(final DataInput dataInput) throws IOException {
194 this.setFieldType(FieldType.valueOf(dataInput.readUTF()));
195 this.setLowerValue(dataInput.readDouble());
196 this.setUpperValue(dataInput.readDouble());
197 }
198 }
199 }