1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.apache.hadoop.hbase.hbql.statement.select;
22
23 import org.apache.expreval.client.NullColumnValueException;
24 import org.apache.expreval.client.ResultMissingColumnException;
25 import org.apache.expreval.expr.MultipleExpressionContext;
26 import org.apache.expreval.expr.node.GenericValue;
27 import org.apache.expreval.expr.var.DelegateColumn;
28 import org.apache.hadoop.hbase.client.Result;
29 import org.apache.hadoop.hbase.hbql.client.HBqlException;
30 import org.apache.hadoop.hbase.hbql.client.HConnection;
31 import org.apache.hadoop.hbase.hbql.client.HRecord;
32 import org.apache.hadoop.hbase.hbql.impl.AggregateValue;
33 import org.apache.hadoop.hbase.hbql.impl.HConnectionImpl;
34 import org.apache.hadoop.hbase.hbql.impl.HRecordImpl;
35 import org.apache.hadoop.hbase.hbql.impl.Utils;
36 import org.apache.hadoop.hbase.hbql.io.IO;
37 import org.apache.hadoop.hbase.hbql.mapping.ColumnAttrib;
38 import org.apache.hadoop.hbase.hbql.mapping.MappingContext;
39 import org.apache.hadoop.hbase.hbql.mapping.TableMapping;
40 import org.apache.hadoop.hbase.hbql.statement.SelectStatement;
41
42 import java.util.Collection;
43 import java.util.Map;
44 import java.util.NavigableMap;
45
46 public class SelectExpressionContext extends MultipleExpressionContext implements SelectElement {
47
48 private String asName;
49
50 private ColumnAttrib columnAttrib = null;
51 private String familyName = null;
52 private String columnName = null;
53 private byte[] familyNameBytes = null;
54 private byte[] columnNameBytes = null;
55
56 private SelectExpressionContext(final GenericValue genericValue, final String asName) {
57 super(null, genericValue);
58 this.asName = asName;
59 }
60
61 public static SelectExpressionContext newExpression(final GenericValue expr, final String as) {
62 return new SelectExpressionContext(expr, as);
63 }
64
65 public String getAsName() {
66 return this.asName;
67 }
68
69 private ColumnAttrib getColumnAttrib() {
70 return this.columnAttrib;
71 }
72
73 private String getFamilyName() {
74 return this.familyName;
75 }
76
77 private String getColumnName() {
78 return this.columnName;
79 }
80
81 private byte[] getFamilyNameBytes() {
82 return this.familyNameBytes;
83 }
84
85 private byte[] getColumnNameBytes() {
86 return this.columnNameBytes;
87 }
88
89 public boolean isAnAggregateElement() {
90 return this.getGenericValue().isAnAggregateValue();
91 }
92
93 private GenericValue getGenericValue() {
94 return this.getGenericValue(0);
95 }
96
97 public void initAggregateValue(final AggregateValue aggregateValue) throws HBqlException {
98 this.getGenericValue().initAggregateValue(aggregateValue);
99 }
100
101 public void applyResultToAggregateValue(final AggregateValue aggregateValue,
102 final Result result) throws HBqlException,
103 ResultMissingColumnException,
104 NullColumnValueException {
105 this.getGenericValue().applyResultToAggregateValue(aggregateValue, result);
106 }
107
108 public String getElementName() {
109 if (this.hasAsName())
110 return this.getAsName();
111 return this.getColumnAttrib().getFamilyQualifiedName();
112 }
113
114 public boolean isAFamilySelect() {
115 return false;
116 }
117
118 public boolean hasAsName() {
119 return Utils.isValidString(this.getAsName());
120 }
121
122 public boolean isADelegateColumnReference() {
123 return this.getGenericValue() instanceof DelegateColumn;
124 }
125
126 public boolean isAConstant() {
127 return this.getGenericValue().isAConstant();
128 }
129
130 public boolean isDefaultKeyword() {
131 return this.getGenericValue().isDefaultKeyword();
132 }
133
134 public boolean hasAColumnReference() {
135 return this.getGenericValue().hasAColumnReference();
136 }
137
138 public boolean isAKeyValue() {
139 if (!this.isADelegateColumnReference())
140 return false;
141
142 if (this.getColumnAttrib() != null)
143 return this.getColumnAttrib().isAKeyAttrib();
144
145 return false;
146 }
147
148 public Class<? extends GenericValue> getExpressionType() throws HBqlException {
149 return this.getGenericValue().validateTypes(null, false);
150 }
151
152 public void validate(final MappingContext mappingContext, final HConnection connection) throws HBqlException {
153
154 this.setMappingContext(mappingContext);
155
156
157
158
159 if (this.isADelegateColumnReference()) {
160 final String name = ((DelegateColumn)this.getGenericValue()).getVariableName();
161 this.columnAttrib = this.getResultAccessor().getColumnAttribByName(name);
162
163 if (this.getColumnAttrib() != null) {
164 this.familyName = this.getColumnAttrib().getFamilyName();
165 this.columnName = this.getColumnAttrib().getColumnName();
166 }
167 else {
168 if (!name.contains(":"))
169 throw new HBqlException("Unknown select value: " + name);
170 final String[] strs = name.split(":");
171 this.familyName = strs[0];
172 this.columnName = strs[1];
173 final Collection<String> families = this.getTableMapping().getMappingFamilyNames();
174 if (!families.contains(this.getFamilyName()))
175 throw new HBqlException("Unknown family name: " + this.getFamilyName());
176 }
177
178 this.familyNameBytes = IO.getSerialization().getStringAsBytes(this.getFamilyName());
179 this.columnNameBytes = IO.getSerialization().getStringAsBytes(this.getColumnName());
180 }
181 }
182
183 public void assignAsNamesForExpressions(final SelectStatement selectStatement) {
184
185 if (!this.isADelegateColumnReference() && !this.hasAsName()) {
186 while (true) {
187
188 final String newAsName = selectStatement.getNextExpressionName();
189 if (!selectStatement.hasAsName(newAsName)) {
190 this.asName = newAsName;
191 break;
192 }
193 }
194 }
195 }
196
197 private String getSelectName() {
198 return this.hasAsName() ? this.getAsName() : this.getFamilyName() + ":" + this.getColumnName();
199 }
200
201 private byte[] getResultCurrentValue(final Result result) {
202
203 final NavigableMap<byte[], byte[]> columnMap = result.getFamilyMap(this.getFamilyNameBytes());
204
205
206 if (columnMap == null)
207 return null;
208 else
209 return columnMap.get(this.getColumnNameBytes());
210 }
211
212 private void assignCalculation(final HConnectionImpl conn,
213 final Object obj,
214 final Result result) throws HBqlException {
215
216 final String name = this.getAsName();
217 final ColumnAttrib attrib = this.getResultAccessor().getColumnAttribByName(name);
218
219 final Object elementValue = this.getValue(conn, result);
220
221 if (attrib == null) {
222
223
224 if (!(obj instanceof HRecord))
225 return;
226
227 ((HRecordImpl)obj).setCurrentValue(name, 0, elementValue, false);
228 }
229 else {
230 attrib.setCurrentValue(obj, 0, elementValue);
231 }
232 }
233
234 public void assignSelectValue(final HConnectionImpl conn,
235 final Object obj,
236 final int maxVerions,
237 final Result result) throws HBqlException {
238
239 if (obj instanceof HRecordImpl) {
240 final HRecordImpl record = (HRecordImpl)obj;
241 record.addNameToPositionList(this.getSelectName());
242 }
243
244 if (this.isAKeyValue())
245 return;
246
247
248 if (!this.isADelegateColumnReference()) {
249 this.assignCalculation(conn, obj, result);
250 return;
251 }
252
253 final TableMapping tableMapping = this.getTableMapping();
254
255
256 if (this.getColumnAttrib() == null) {
257 final ColumnAttrib unMappedAttrib = tableMapping.getUnMappedAttrib(this.getFamilyName());
258 if (unMappedAttrib != null) {
259 final byte[] b = result.getValue(this.getFamilyNameBytes(), this.getColumnNameBytes());
260 unMappedAttrib.setUnMappedCurrentValue(obj, this.getSelectName(), b);
261 }
262 }
263 else {
264 if (this.getColumnAttrib().isACurrentValue()) {
265 final byte[] b = result.getValue(this.getFamilyNameBytes(), this.getColumnNameBytes());
266 this.getColumnAttrib().setCurrentValue(obj, 0, b);
267 }
268 }
269
270
271 if (maxVerions > 1) {
272
273
274 if (this.getColumnAttrib() != null && !this.getColumnAttrib().isAVersionValue())
275 return;
276
277 final NavigableMap<byte[], NavigableMap<byte[], NavigableMap<Long, byte[]>>> familyMap = result.getMap();
278 final NavigableMap<byte[], NavigableMap<Long, byte[]>> columnMap = familyMap.get(this.getFamilyNameBytes());
279
280 if (columnMap == null)
281 return;
282
283 final NavigableMap<Long, byte[]> timeStampMap = columnMap.get(this.getColumnNameBytes());
284
285 if (this.getColumnAttrib() == null) {
286 final ColumnAttrib unMappedAttrib = tableMapping.getUnMappedAttrib(this.getFamilyName());
287 if (unMappedAttrib != null)
288 unMappedAttrib.setUnMappedVersionMap(obj, this.getSelectName(), timeStampMap);
289 }
290 else {
291 final Map<Long, Object> mapVal = this.getColumnAttrib().getVersionMap(obj);
292 for (final Long timestamp : timeStampMap.keySet()) {
293 final byte[] b = timeStampMap.get(timestamp);
294 final Object val = this.getColumnAttrib().getValueFromBytes(obj, b);
295 mapVal.put(timestamp, val);
296 }
297 }
298 }
299 }
300
301 public AggregateValue newAggregateValue() throws HBqlException {
302 return new AggregateValue(this.getSelectName(), this);
303 }
304
305 public Object getValue(final HConnectionImpl conn, final Result result) throws HBqlException {
306 try {
307 return this.evaluate(conn, 0, this.allowColumns(), false, result);
308 }
309 catch (ResultMissingColumnException e) {
310 return null;
311 }
312 catch (NullColumnValueException e) {
313 return null;
314 }
315 }
316
317 public String asString() {
318 return this.getGenericValue().asString();
319 }
320
321 public boolean useResultData() {
322 return true;
323 }
324
325 public boolean allowColumns() {
326 return true;
327 }
328 }