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.args;
22
23 import org.apache.expreval.expr.ExpressionTree;
24 import org.apache.expreval.expr.var.NamedParameter;
25 import org.apache.hadoop.hbase.client.Get;
26 import org.apache.hadoop.hbase.client.Scan;
27 import org.apache.hadoop.hbase.client.tableindexed.IndexSpecification;
28 import org.apache.hadoop.hbase.filter.Filter;
29 import org.apache.hadoop.hbase.hbql.client.HBqlException;
30 import org.apache.hadoop.hbase.hbql.client.Util;
31 import org.apache.hadoop.hbase.hbql.filter.InstrumentedFilter;
32 import org.apache.hadoop.hbase.hbql.filter.PageFilter;
33 import org.apache.hadoop.hbase.hbql.filter.RecordFilter;
34 import org.apache.hadoop.hbase.hbql.impl.HConnectionImpl;
35 import org.apache.hadoop.hbase.hbql.impl.Utils;
36 import org.apache.hadoop.hbase.hbql.mapping.ColumnAttrib;
37 import org.apache.hadoop.hbase.hbql.mapping.Mapping;
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.select.RowRequest;
41 import org.apache.hadoop.hbase.hbql.util.Lists;
42 import org.apache.hadoop.hbase.hbql.util.Sets;
43
44 import java.util.List;
45 import java.util.Set;
46
47 public class WithArgs {
48
49 private String indexName = null;
50 private KeyRangeArgs keyRangeArgs = null;
51 private TimestampArgs timestampArgs = null;
52 private VersionArgs versionArgs = null;
53 private ScannerCacheArgs scannerCacheArgs = null;
54 private LimitArgs limitArgs = null;
55 private boolean verbose = false;
56 private ExpressionTree clientExpressionTree = null;
57 private ExpressionTree serverExpressionTree = null;
58 private MappingContext mappingContext = null;
59
60
61 private final Set<String> multipleSetValues = Sets.newHashSet();
62
63 public void setMappingContext(final MappingContext mappingContext) throws HBqlException {
64
65 this.mappingContext = mappingContext;
66
67 this.validateNoDuplicateWithArgs();
68
69 if (this.getKeyRangeArgs() == null)
70 this.setKeyRangeArgs(new KeyRangeArgs());
71
72 this.getKeyRangeArgs().setMappingContext(this.getMappingContext());
73
74 if (this.getTimestampArgs() != null)
75 this.getTimestampArgs().setMappingContext(this.getMappingContext());
76
77 if (this.getVersionArgs() != null)
78 this.getVersionArgs().setMappingContext(this.getMappingContext());
79
80 if (this.getLimitArgs() != null)
81 this.getLimitArgs().setMappingContext(this.getMappingContext());
82
83 if (this.getServerExpressionTree() != null) {
84 this.getServerExpressionTree().setMappingContext(this.getMappingContext());
85 this.getServerExpressionTree().setUseResultData(false);
86 }
87
88 if (this.getClientExpressionTree() != null) {
89 this.getClientExpressionTree().setMappingContext(this.getMappingContext());
90 this.getClientExpressionTree().setUseResultData(true);
91 }
92 }
93
94 public void validate(final HConnectionImpl conn, final TableMapping mapping) throws HBqlException {
95 if (conn != null) {
96 if (this.hasAnIndex())
97 conn.validateIndexExistsForTable(this.getIndexName(), mapping.getTableName());
98 }
99 }
100
101 public void validateArgTypes() throws HBqlException {
102
103 if (this.getKeyRangeArgs() != null)
104 this.getKeyRangeArgs().validate();
105
106 if (this.getTimestampArgs() != null)
107 this.getTimestampArgs().validate();
108
109 if (this.getVersionArgs() != null)
110 this.getVersionArgs().validate();
111
112 if (this.getLimitArgs() != null)
113 this.getLimitArgs().validate();
114 }
115
116 private void validateNoDuplicateWithArgs() throws HBqlException {
117 if (this.multipleSetValues.size() > 0) {
118 final StringBuilder sbuf = new StringBuilder();
119 boolean firstTime = true;
120 for (final String str : this.multipleSetValues) {
121 if (!firstTime)
122 sbuf.append(", ");
123 sbuf.append(str);
124 firstTime = false;
125 }
126 throw new HBqlException("Select args specificed multiple times: " + sbuf);
127 }
128 }
129
130 private MappingContext getMappingContext() {
131 return this.mappingContext;
132 }
133
134 private void addError(final String str) {
135 this.multipleSetValues.add(str);
136 }
137
138 public KeyRangeArgs getKeyRangeArgs() {
139 return this.keyRangeArgs;
140 }
141
142 public void setIndexName(final String indexName) {
143 this.indexName = indexName;
144 }
145
146 public String getIndexName() {
147 return this.indexName;
148 }
149
150 public boolean hasAnIndex() {
151 return Utils.isValidString(this.getIndexName());
152 }
153
154 public void setKeyRangeArgs(final KeyRangeArgs keyRangeArgs) {
155 if (this.getKeyRangeArgs() != null)
156 this.addError("Keys");
157 this.keyRangeArgs = keyRangeArgs;
158 }
159
160 private TimestampArgs getTimestampArgs() {
161 return this.timestampArgs;
162 }
163
164 public void setTimestampArgs(final TimestampArgs timestampArgs) {
165 if (this.getTimestampArgs() != null)
166 this.addError("Time Range");
167 this.timestampArgs = timestampArgs;
168 }
169
170 private VersionArgs getVersionArgs() {
171 return this.versionArgs;
172 }
173
174 public void setVersionArgs(final VersionArgs versionArgs) {
175 if (this.getVersionArgs() != null)
176 this.addError("Version");
177 this.versionArgs = versionArgs;
178 }
179
180 private ScannerCacheArgs getScannerCacheArgs() {
181 return this.scannerCacheArgs;
182 }
183
184 public void setScannerCacheArgs(final ScannerCacheArgs scannerCacheArgs) {
185 if (this.getVersionArgs() != null)
186 this.addError("Scanner_Cache_Size");
187 this.scannerCacheArgs = scannerCacheArgs;
188 }
189
190 public LimitArgs getLimitArgs() {
191 return this.limitArgs;
192 }
193
194 public void setLimitArgs(final LimitArgs limitArgs) {
195 if (this.getLimitArgs() != null)
196 this.addError("Limit");
197 this.limitArgs = limitArgs;
198 }
199
200 public boolean getVerbose() {
201 return this.verbose;
202 }
203
204 public void setVerbose(final boolean verbose) {
205 this.verbose = verbose;
206 }
207
208 public ExpressionTree getClientExpressionTree() {
209 return this.clientExpressionTree;
210 }
211
212 public void setClientExpressionTree(final ExpressionTree clientExpressionTree) {
213 if (this.getClientExpressionTree() != null)
214 this.addError("Client Where");
215 this.clientExpressionTree = clientExpressionTree;
216 }
217
218 public ExpressionTree getServerExpressionTree() {
219 return this.serverExpressionTree;
220 }
221
222 public void setServerExpressionTree(final ExpressionTree serverExpressionTree) {
223 if (this.getServerExpressionTree() != null)
224 this.addError("Server Where");
225 this.serverExpressionTree = serverExpressionTree;
226 }
227
228 public long getLimit() throws HBqlException {
229 return (this.getLimitArgs() != null) ? this.getLimitArgs().getValue() : 0;
230 }
231
232 public String asString() {
233
234 final StringBuilder sbuf = new StringBuilder("WITH ");
235
236 if (this.getKeyRangeArgs() != null)
237 sbuf.append(this.getKeyRangeArgs().asString() + "\n");
238
239 if (this.getTimestampArgs() != null)
240 sbuf.append(this.getTimestampArgs().asString() + "\n");
241
242 if (this.getVersionArgs() != null)
243 sbuf.append(this.getVersionArgs().asString() + "\n");
244
245 if (this.getScannerCacheArgs() != null)
246 sbuf.append(this.getScannerCacheArgs().asString() + "\n");
247
248 if (this.getLimitArgs() != null)
249 sbuf.append(this.getLimitArgs().asString() + "\n");
250
251 if (this.getServerExpressionTree() != null)
252 sbuf.append("SERVER FILTER " + this.getServerExpressionTree().asString() + "\n");
253
254 if (this.getClientExpressionTree() != null)
255 sbuf.append("CLIENT FILTER " + this.getClientExpressionTree().asString() + "\n");
256
257 return sbuf.toString();
258 }
259
260 public List<NamedParameter> getParameterList() {
261
262 final List<NamedParameter> parameterList = Lists.newArrayList();
263
264 if (this.getKeyRangeArgs() != null)
265 parameterList.addAll(this.getKeyRangeArgs().getParameterList());
266
267 if (this.getTimestampArgs() != null)
268 parameterList.addAll(this.getTimestampArgs().getParameterList());
269
270 if (this.getVersionArgs() != null)
271 parameterList.addAll(this.getVersionArgs().getParameterList());
272
273 if (this.getScannerCacheArgs() != null)
274 parameterList.addAll(this.getScannerCacheArgs().getParameterList());
275
276 if (this.getLimitArgs() != null)
277 parameterList.addAll(this.getLimitArgs().getParameterList());
278
279 if (this.getServerExpressionTree() != null)
280 parameterList.addAll(this.getServerExpressionTree().getParameterList());
281
282 if (this.getClientExpressionTree() != null)
283 parameterList.addAll(this.getClientExpressionTree().getParameterList());
284
285 return parameterList;
286 }
287
288 public void reset() {
289
290 if (this.getKeyRangeArgs() != null)
291 this.getKeyRangeArgs().reset();
292
293 if (this.getTimestampArgs() != null)
294 this.getTimestampArgs().reset();
295
296 if (this.getVersionArgs() != null)
297 this.getVersionArgs().reset();
298
299 if (this.getScannerCacheArgs() != null)
300 this.getScannerCacheArgs().reset();
301
302 if (this.getLimitArgs() != null)
303 this.getLimitArgs().reset();
304
305 if (this.getServerExpressionTree() != null)
306 this.getServerExpressionTree().reset();
307
308 if (this.getClientExpressionTree() != null)
309 this.getClientExpressionTree().reset();
310 }
311
312 public int setParameter(final String name, final Object val) throws HBqlException {
313
314 int cnt = 0;
315
316 if (this.getKeyRangeArgs() != null)
317 cnt += this.getKeyRangeArgs().setParameter(name, val);
318
319 if (this.getTimestampArgs() != null)
320 cnt += this.getTimestampArgs().setParameter(name, val);
321
322 if (this.getVersionArgs() != null)
323 cnt += this.getVersionArgs().setParameter(name, val);
324
325 if (this.getScannerCacheArgs() != null)
326 cnt += this.getScannerCacheArgs().setParameter(name, val);
327
328 if (this.getLimitArgs() != null)
329 cnt += this.getLimitArgs().setParameter(name, val);
330
331 if (this.getServerExpressionTree() != null)
332 cnt += this.getServerExpressionTree().setParameter(name, val);
333
334 if (this.getClientExpressionTree() != null)
335 cnt += this.getClientExpressionTree().setParameter(name, val);
336
337 return cnt;
338 }
339
340 public Filter getFilterForTableIndex() throws HBqlException {
341 if (this.getServerExpressionTree() != null)
342 return this.getServerExpressionTree().getFilter();
343 else
344 return null;
345 }
346
347 public byte[][] getColumnsUsedInIndexWhereExpr() {
348 final byte[][] indexColumns;
349 final Set<ColumnAttrib> columnAttribs = this.getColumnsUsedInServerWhereExpr();
350 if (columnAttribs.size() == 0) {
351 indexColumns = null;
352 }
353 else {
354 final List<String> columnList = Lists.newArrayList();
355 for (final ColumnAttrib columnAttrib : columnAttribs) {
356
357 if (!columnAttrib.isAKeyAttrib())
358 columnList.add(columnAttrib.isASelectFamilyAttrib() ? columnAttrib.getFamilyName()
359 : columnAttrib.getFamilyQualifiedName());
360 }
361
362 indexColumns = Util.getStringsAsBytes(columnList);
363 }
364 return indexColumns;
365 }
366
367 private Set<ColumnAttrib> getColumnsUsedInServerWhereExpr() {
368 final Set<ColumnAttrib> serverAttribs = Sets.newHashSet();
369 if (this.getServerExpressionTree() != null)
370 serverAttribs.addAll(this.getServerExpressionTree().getAttribsUsedInExpr());
371 return serverAttribs;
372 }
373
374 private Set<ColumnAttrib> getColumnsUsedInClientWhereExpr() {
375 final Set<ColumnAttrib> clientAttribs = Sets.newHashSet();
376 if (this.getClientExpressionTree() != null)
377 clientAttribs.addAll(this.getClientExpressionTree().getAttribsUsedInExpr());
378 return clientAttribs;
379 }
380
381 public Set<ColumnAttrib> getColumnsUsedInAllWhereExprs() {
382 final Set<ColumnAttrib> allAttribs = Sets.newHashSet();
383 allAttribs.addAll(this.getColumnsUsedInServerWhereExpr());
384 allAttribs.addAll(this.getColumnsUsedInClientWhereExpr());
385 return allAttribs;
386 }
387
388
389 public List<RowRequest> getRowRequestList(final HConnectionImpl conn,
390 final Mapping mapping,
391 final Set<ColumnAttrib> columnAttribs) throws HBqlException {
392
393 final ColumnAttrib keyAttrib;
394
395 if (this.hasAnIndex()) {
396
397 final IndexSpecification index = conn.getIndexForTable(this.getIndexName(), mapping.getTableName());
398 final byte[][] cols = index.getIndexedColumns();
399 final String indexedColumName = new String(cols[0]);
400 keyAttrib = mapping.getAttribByVariableName(indexedColumName);
401 }
402 else {
403 keyAttrib = mapping.getKeyAttrib();
404 }
405
406 final List<RowRequest> retval = Lists.newArrayList();
407
408 for (final KeyRange keyRange : this.getKeyRangeArgs().getKeyRangeList()) {
409 final List<RowRequest> rowRequestList = keyRange.getRowRequestList(this, keyAttrib, columnAttribs);
410 retval.addAll(rowRequestList);
411 }
412
413 return retval;
414 }
415
416 public void setGetArgs(final Get get, final Set<ColumnAttrib> columnAttribs) throws HBqlException {
417
418
419
420
421 for (final ColumnAttrib attrib : columnAttribs) {
422 if (!attrib.isAKeyAttrib() && !attrib.isASelectFamilyAttrib())
423 get.addColumn(attrib.getFamilyNameAsBytes(), attrib.getColumnNameAsBytes());
424 }
425
426 for (final ColumnAttrib attrib : columnAttribs) {
427 if (!attrib.isAKeyAttrib() && attrib.isASelectFamilyAttrib())
428 get.addFamily(attrib.getFamilyNameAsBytes());
429 }
430
431 if (this.getTimestampArgs() != null)
432 this.getTimestampArgs().setTimeStamp(get);
433
434 if (this.getVersionArgs() != null)
435 this.getVersionArgs().setMaxVersions(get);
436
437
438
439 final Filter filter = this.getServerFilter(false);
440 if (filter != null)
441 get.setFilter(filter);
442 }
443
444 public void setScanArgs(final Scan scan, final Set<ColumnAttrib> columnAttribs) throws HBqlException {
445
446
447
448
449 for (final ColumnAttrib attrib : columnAttribs) {
450 if (!attrib.isAKeyAttrib() && !attrib.isASelectFamilyAttrib())
451 scan.addColumn(attrib.getFamilyNameAsBytes(), attrib.getColumnNameAsBytes());
452 }
453
454 for (final ColumnAttrib attrib : columnAttribs) {
455 if (!attrib.isAKeyAttrib() && attrib.isASelectFamilyAttrib())
456 scan.addFamily(attrib.getFamilyNameAsBytes());
457 }
458
459 if (this.getTimestampArgs() != null)
460 this.getTimestampArgs().setTimeStamp(scan);
461
462 if (this.getVersionArgs() != null)
463 this.getVersionArgs().setMaxVersions(scan);
464
465 if (this.getScannerCacheArgs() != null)
466 this.getScannerCacheArgs().setScannerCacheSize(scan);
467
468 final Filter filter = this.getServerFilter(true);
469 if (filter != null)
470 scan.setFilter(filter);
471 }
472
473 private Filter getServerFilter(final boolean applyLimit) throws HBqlException {
474
475 Filter exprFilter = null;
476
477 if (this.getServerExpressionTree() != null) {
478 try {
479 exprFilter = this.getServerExpressionTree().getFilter();
480 }
481 catch (HBqlException e) {
482
483
484 this.getServerExpressionTree().setMappingContext(this.getMappingContext());
485 exprFilter = RecordFilter.newRecordFilter(this.getServerExpressionTree());
486 }
487
488 if (exprFilter != null && exprFilter instanceof InstrumentedFilter) {
489 ((InstrumentedFilter)exprFilter).setVerbose(this.getVerbose());
490 }
491 }
492
493
494 if (applyLimit && this.getLimit() > 0) {
495 final InstrumentedFilter filter = new PageFilter(this.getLimit(), exprFilter);
496 filter.setVerbose(this.getVerbose());
497 return filter;
498 }
499 else {
500 return exprFilter;
501 }
502 }
503
504 public int getMaxVersions() throws HBqlException {
505 return this.getVersionArgs() != null ? this.getVersionArgs().getMaxVersions() : Integer.MAX_VALUE;
506 }
507 }