3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
19 package org
.apache
.hadoop
.hbase
.client
;
22 import java
.io
.IOException
;
23 import java
.nio
.ByteBuffer
;
24 import java
.util
.ArrayList
;
25 import java
.util
.HashMap
;
26 import java
.util
.List
;
28 import java
.util
.NavigableSet
;
30 import java
.util
.TreeMap
;
31 import java
.util
.TreeSet
;
33 import org
.apache
.hadoop
.hbase
.HConstants
;
34 import org
.apache
.yetus
.audience
.InterfaceAudience
;
35 import org
.slf4j
.Logger
;
36 import org
.slf4j
.LoggerFactory
;
37 import org
.apache
.hadoop
.hbase
.filter
.Filter
;
38 import org
.apache
.hadoop
.hbase
.io
.TimeRange
;
39 import org
.apache
.hadoop
.hbase
.security
.access
.Permission
;
40 import org
.apache
.hadoop
.hbase
.security
.visibility
.Authorizations
;
41 import org
.apache
.hadoop
.hbase
.util
.Bytes
;
44 * Used to perform Get operations on a single row.
46 * To get everything for a row, instantiate a Get object with the row to get.
47 * To further narrow the scope of what to Get, use the methods below.
49 * To get all columns from specific families, execute {@link #addFamily(byte[]) addFamily}
50 * for each family to retrieve.
52 * To get specific columns, execute {@link #addColumn(byte[], byte[]) addColumn}
53 * for each column to retrieve.
55 * To only retrieve columns within a specific range of version timestamps,
56 * execute {@link #setTimeRange(long, long) setTimeRange}.
58 * To only retrieve columns with a specific timestamp, execute
59 * {@link #setTimestamp(long) setTimestamp}.
61 * To limit the number of versions of each column to be returned, execute
62 * {@link #readVersions(int) readVersions}.
64 * To add a filter, call {@link #setFilter(Filter) setFilter}.
66 @InterfaceAudience.Public
67 public class Get
extends Query
implements Row
{
68 private static final Logger LOG
= LoggerFactory
.getLogger(Get
.class);
70 private byte [] row
= null;
71 private int maxVersions
= 1;
72 private boolean cacheBlocks
= true;
73 private int storeLimit
= -1;
74 private int storeOffset
= 0;
75 private TimeRange tr
= TimeRange
.allTime();
76 private boolean checkExistenceOnly
= false;
77 private Map
<byte [], NavigableSet
<byte []>> familyMap
= new TreeMap
<>(Bytes
.BYTES_COMPARATOR
);
80 * Create a Get operation for the specified row.
82 * If no further operations are done, this will get the latest version of
83 * all columns in all families of the specified row.
86 public Get(byte [] row
) {
87 Mutation
.checkRow(row
);
99 this.setFilter(get
.getFilter());
100 this.setReplicaId(get
.getReplicaId());
101 this.setConsistency(get
.getConsistency());
103 this.cacheBlocks
= get
.getCacheBlocks();
104 this.maxVersions
= get
.getMaxVersions();
105 this.storeLimit
= get
.getMaxResultsPerColumnFamily();
106 this.storeOffset
= get
.getRowOffsetPerColumnFamily();
107 this.tr
= get
.getTimeRange();
108 this.checkExistenceOnly
= get
.isCheckExistenceOnly();
109 this.loadColumnFamiliesOnDemand
= get
.getLoadColumnFamiliesOnDemandValue();
110 Map
<byte[], NavigableSet
<byte[]>> fams
= get
.getFamilyMap();
111 for (Map
.Entry
<byte[],NavigableSet
<byte[]>> entry
: fams
.entrySet()) {
112 byte [] fam
= entry
.getKey();
113 NavigableSet
<byte[]> cols
= entry
.getValue();
114 if (cols
!= null && cols
.size() > 0) {
115 for (byte[] col
: cols
) {
122 for (Map
.Entry
<String
, byte[]> attr
: get
.getAttributesMap().entrySet()) {
123 setAttribute(attr
.getKey(), attr
.getValue());
125 for (Map
.Entry
<byte[], TimeRange
> entry
: get
.getColumnFamilyTimeRange().entrySet()) {
126 TimeRange tr
= entry
.getValue();
127 setColumnFamilyTimeRange(entry
.getKey(), tr
.getMin(), tr
.getMax());
129 super.setPriority(get
.getPriority());
133 * Create a Get operation for the specified row.
138 public Get(byte[] row
, int rowOffset
, int rowLength
) {
139 Mutation
.checkRow(row
, rowOffset
, rowLength
);
140 this.row
= Bytes
.copy(row
, rowOffset
, rowLength
);
144 * Create a Get operation for the specified row.
147 public Get(ByteBuffer row
) {
148 Mutation
.checkRow(row
);
149 this.row
= new byte[row
.remaining()];
153 public boolean isCheckExistenceOnly() {
154 return checkExistenceOnly
;
157 public Get
setCheckExistenceOnly(boolean checkExistenceOnly
) {
158 this.checkExistenceOnly
= checkExistenceOnly
;
163 * Get all columns from the specified family.
165 * Overrides previous calls to addColumn for this family.
166 * @param family family name
167 * @return the Get object
169 public Get
addFamily(byte [] family
) {
170 familyMap
.remove(family
);
171 familyMap
.put(family
, null);
176 * Get the column from the specific family with the specified qualifier.
178 * Overrides previous calls to addFamily for this family.
179 * @param family family name
180 * @param qualifier column qualifier
181 * @return the Get objec
183 public Get
addColumn(byte [] family
, byte [] qualifier
) {
184 NavigableSet
<byte []> set
= familyMap
.get(family
);
186 set
= new TreeSet
<>(Bytes
.BYTES_COMPARATOR
);
187 familyMap
.put(family
, set
);
189 if (qualifier
== null) {
190 qualifier
= HConstants
.EMPTY_BYTE_ARRAY
;
197 * Get versions of columns only within the specified timestamp range,
198 * [minStamp, maxStamp).
199 * @param minStamp minimum timestamp value, inclusive
200 * @param maxStamp maximum timestamp value, exclusive
201 * @return this for invocation chaining
203 public Get
setTimeRange(long minStamp
, long maxStamp
) throws IOException
{
204 tr
= TimeRange
.between(minStamp
, maxStamp
);
209 * Get versions of columns with the specified timestamp.
210 * @param timestamp version timestamp
211 * @return this for invocation chaining
213 public Get
setTimestamp(long timestamp
) {
215 tr
= TimeRange
.at(timestamp
);
216 } catch(Exception e
) {
217 // This should never happen, unless integer overflow or something extremely wrong...
218 LOG
.error("TimeRange failed, likely caused by integer overflow. ", e
);
225 public Get
setColumnFamilyTimeRange(byte[] cf
, long minStamp
, long maxStamp
) {
226 return (Get
) super.setColumnFamilyTimeRange(cf
, minStamp
, maxStamp
);
230 * Get all available versions.
231 * @return this for invocation chaining
233 public Get
readAllVersions() {
234 this.maxVersions
= Integer
.MAX_VALUE
;
239 * Get up to the specified number of versions of each column.
240 * @param versions specified number of versions for each column
241 * @throws IOException if invalid number of versions
242 * @return this for invocation chaining
244 public Get
readVersions(int versions
) throws IOException
{
246 throw new IOException("versions must be positive");
248 this.maxVersions
= versions
;
253 public Get
setLoadColumnFamiliesOnDemand(boolean value
) {
254 return (Get
) super.setLoadColumnFamiliesOnDemand(value
);
258 * Set the maximum number of values to return per row per Column Family
259 * @param limit the maximum number of values returned / row / CF
260 * @return this for invocation chaining
262 public Get
setMaxResultsPerColumnFamily(int limit
) {
263 this.storeLimit
= limit
;
268 * Set offset for the row per Column Family. This offset is only within a particular row/CF
269 * combination. It gets reset back to zero when we move to the next row or CF.
270 * @param offset is the number of kvs that will be skipped.
271 * @return this for invocation chaining
273 public Get
setRowOffsetPerColumnFamily(int offset
) {
274 this.storeOffset
= offset
;
279 public Get
setFilter(Filter filter
) {
280 super.setFilter(filter
);
287 * Set whether blocks should be cached for this Get.
289 * This is true by default. When true, default settings of the table and
290 * family are used (this will never override caching blocks if the block
291 * cache is disabled for that family or entirely).
293 * @param cacheBlocks if false, default settings are overridden and blocks
296 public Get
setCacheBlocks(boolean cacheBlocks
) {
297 this.cacheBlocks
= cacheBlocks
;
302 * Get whether blocks should be cached for this Get.
303 * @return true if default caching should be used, false if blocks should not
306 public boolean getCacheBlocks() {
311 * Method for retrieving the get's row
315 public byte [] getRow() {
320 * Method for retrieving the get's maximum number of version
321 * @return the maximum number of version to fetch for this get
323 public int getMaxVersions() {
324 return this.maxVersions
;
328 * Method for retrieving the get's maximum number of values
329 * to return per Column Family
330 * @return the maximum number of values to fetch per CF
332 public int getMaxResultsPerColumnFamily() {
333 return this.storeLimit
;
337 * Method for retrieving the get's offset per row per column
338 * family (#kvs to be skipped)
339 * @return the row offset
341 public int getRowOffsetPerColumnFamily() {
342 return this.storeOffset
;
346 * Method for retrieving the get's TimeRange
349 public TimeRange
getTimeRange() {
354 * Method for retrieving the keys in the familyMap
355 * @return keys in the current familyMap
357 public Set
<byte[]> familySet() {
358 return this.familyMap
.keySet();
362 * Method for retrieving the number of families to get from
363 * @return number of families
365 public int numFamilies() {
366 return this.familyMap
.size();
370 * Method for checking if any families have been inserted into this Get
371 * @return true if familyMap is non empty false otherwise
373 public boolean hasFamilies() {
374 return !this.familyMap
.isEmpty();
378 * Method for retrieving the get's familyMap
381 public Map
<byte[],NavigableSet
<byte[]>> getFamilyMap() {
382 return this.familyMap
;
386 * Compile the table and column family (i.e. schema) information
387 * into a String. Useful for parsing and aggregation by debugging,
388 * logging, and administration tools.
392 public Map
<String
, Object
> getFingerprint() {
393 Map
<String
, Object
> map
= new HashMap
<>();
394 List
<String
> families
= new ArrayList
<>(this.familyMap
.entrySet().size());
395 map
.put("families", families
);
396 for (Map
.Entry
<byte [], NavigableSet
<byte[]>> entry
:
397 this.familyMap
.entrySet()) {
398 families
.add(Bytes
.toStringBinary(entry
.getKey()));
404 * Compile the details beyond the scope of getFingerprint (row, columns,
405 * timestamps, etc.) into a Map along with the fingerprinted information.
406 * Useful for debugging, logging, and administration tools.
407 * @param maxCols a limit on the number of columns output prior to truncation
411 public Map
<String
, Object
> toMap(int maxCols
) {
412 // we start with the fingerprint map and build on top of it.
413 Map
<String
, Object
> map
= getFingerprint();
414 // replace the fingerprint's simple list of families with a
415 // map from column families to lists of qualifiers and kv details
416 Map
<String
, List
<String
>> columns
= new HashMap
<>();
417 map
.put("families", columns
);
418 // add scalar information first
419 map
.put("row", Bytes
.toStringBinary(this.row
));
420 map
.put("maxVersions", this.maxVersions
);
421 map
.put("cacheBlocks", this.cacheBlocks
);
422 List
<Long
> timeRange
= new ArrayList
<>(2);
423 timeRange
.add(this.tr
.getMin());
424 timeRange
.add(this.tr
.getMax());
425 map
.put("timeRange", timeRange
);
427 // iterate through affected families and add details
428 for (Map
.Entry
<byte [], NavigableSet
<byte[]>> entry
:
429 this.familyMap
.entrySet()) {
430 List
<String
> familyList
= new ArrayList
<>();
431 columns
.put(Bytes
.toStringBinary(entry
.getKey()), familyList
);
432 if(entry
.getValue() == null) {
435 familyList
.add("ALL");
437 colCount
+= entry
.getValue().size();
441 for (byte [] column
: entry
.getValue()) {
442 if (--maxCols
<= 0) {
445 familyList
.add(Bytes
.toStringBinary(column
));
449 map
.put("totalColumns", colCount
);
450 if (this.filter
!= null) {
451 map
.put("filter", this.filter
.toString());
454 if (getId() != null) {
455 map
.put("id", getId());
461 public int hashCode() {
462 // TODO: This is wrong. Can't have two gets the same just because on same row. But it
463 // matches how equals works currently and gets rid of the findbugs warning.
464 return Bytes
.hashCode(this.getRow());
468 public boolean equals(Object obj
) {
472 if (obj
== null || getClass() != obj
.getClass()) {
475 Row other
= (Row
) obj
;
476 // TODO: This is wrong. Can't have two gets the same just because on same row.
477 return Row
.COMPARATOR
.compare(this, other
) == 0;
481 public Get
setAttribute(String name
, byte[] value
) {
482 return (Get
) super.setAttribute(name
, value
);
486 public Get
setId(String id
) {
487 return (Get
) super.setId(id
);
491 public Get
setAuthorizations(Authorizations authorizations
) {
492 return (Get
) super.setAuthorizations(authorizations
);
496 public Get
setACL(Map
<String
, Permission
> perms
) {
497 return (Get
) super.setACL(perms
);
501 public Get
setACL(String user
, Permission perms
) {
502 return (Get
) super.setACL(user
, perms
);
506 public Get
setConsistency(Consistency consistency
) {
507 return (Get
) super.setConsistency(consistency
);
511 public Get
setReplicaId(int Id
) {
512 return (Get
) super.setReplicaId(Id
);
516 public Get
setIsolationLevel(IsolationLevel level
) {
517 return (Get
) super.setIsolationLevel(level
);
521 public Get
setPriority(int priority
) {
522 return (Get
) super.setPriority(priority
);