1 /*
2 *
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
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
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.
18 */
19
20 package org.apache.hadoop.hbase.client;
21
22 import java.io.IOException;
23 import java.util.ArrayList;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.NavigableMap;
27 import java.util.UUID;
28
29 import org.apache.hadoop.hbase.classification.InterfaceAudience;
30 import org.apache.hadoop.hbase.classification.InterfaceStability;
31 import org.apache.hadoop.hbase.Cell;
32 import org.apache.hadoop.hbase.CellUtil;
33 import org.apache.hadoop.hbase.HConstants;
34 import org.apache.hadoop.hbase.KeyValue;
35 import org.apache.hadoop.hbase.security.access.Permission;
36 import org.apache.hadoop.hbase.security.visibility.CellVisibility;
37 import org.apache.hadoop.hbase.util.Bytes;
38
39 /**
40 * Used to perform Delete operations on a single row.
41 * <p>
42 * To delete an entire row, instantiate a Delete object with the row
43 * to delete. To further define the scope of what to delete, perform
44 * additional methods as outlined below.
45 * <p>
46 * To delete specific families, execute {@link #addFamily(byte[]) deleteFamily}
47 * for each family to delete.
48 * <p>
49 * To delete multiple versions of specific columns, execute
50 * {@link #addColumns(byte[], byte[]) deleteColumns}
51 * for each column to delete.
52 * <p>
53 * To delete specific versions of specific columns, execute
54 * {@link #addColumn(byte[], byte[], long) deleteColumn}
55 * for each column version to delete.
56 * <p>
57 * Specifying timestamps, deleteFamily and deleteColumns will delete all
58 * versions with a timestamp less than or equal to that passed. If no
59 * timestamp is specified, an entry is added with a timestamp of 'now'
60 * where 'now' is the servers's System.currentTimeMillis().
61 * Specifying a timestamp to the deleteColumn method will
62 * delete versions only with a timestamp equal to that specified.
63 * If no timestamp is passed to deleteColumn, internally, it figures the
64 * most recent cell's timestamp and adds a delete at that timestamp; i.e.
65 * it deletes the most recently added cell.
66 * <p>The timestamp passed to the constructor is used ONLY for delete of
67 * rows. For anything less -- a deleteColumn, deleteColumns or
68 * deleteFamily -- then you need to use the method overrides that take a
69 * timestamp. The constructor timestamp is not referenced.
70 */
71 @InterfaceAudience.Public
72 @InterfaceStability.Stable
73 public class Delete extends Mutation implements Comparable<Row> {
74 /**
75 * Create a Delete operation for the specified row.
76 * <p>
77 * If no further operations are done, this will delete everything
78 * associated with the specified row (all versions of all columns in all
79 * families).
80 * @param row row key
81 */
82 public Delete(byte [] row) {
83 this(row, HConstants.LATEST_TIMESTAMP);
84 }
85
86 /**
87 * Create a Delete operation for the specified row and timestamp.<p>
88 *
89 * If no further operations are done, this will delete all columns in all
90 * families of the specified row with a timestamp less than or equal to the
91 * specified timestamp.<p>
92 *
93 * This timestamp is ONLY used for a delete row operation. If specifying
94 * families or columns, you must specify each timestamp individually.
95 * @param row row key
96 * @param timestamp maximum version timestamp (only for delete row)
97 */
98 public Delete(byte [] row, long timestamp) {
99 this(row, 0, row.length, timestamp);
100 }
101
102 /**
103 * Create a Delete operation for the specified row and timestamp.<p>
104 *
105 * If no further operations are done, this will delete all columns in all
106 * families of the specified row with a timestamp less than or equal to the
107 * specified timestamp.<p>
108 *
109 * This timestamp is ONLY used for a delete row operation. If specifying
110 * families or columns, you must specify each timestamp individually.
111 * @param rowArray We make a local copy of this passed in row.
112 * @param rowOffset
113 * @param rowLength
114 */
115 public Delete(final byte [] rowArray, final int rowOffset, final int rowLength) {
116 this(rowArray, rowOffset, rowLength, HConstants.LATEST_TIMESTAMP);
117 }
118
119 /**
120 * Create a Delete operation for the specified row and timestamp.<p>
121 *
122 * If no further operations are done, this will delete all columns in all
123 * families of the specified row with a timestamp less than or equal to the
124 * specified timestamp.<p>
125 *
126 * This timestamp is ONLY used for a delete row operation. If specifying
127 * families or columns, you must specify each timestamp individually.
128 * @param rowArray We make a local copy of this passed in row.
129 * @param rowOffset
130 * @param rowLength
131 * @param ts maximum version timestamp (only for delete row)
132 */
133 public Delete(final byte [] rowArray, final int rowOffset, final int rowLength, long ts) {
134 checkRow(rowArray, rowOffset, rowLength);
135 this.row = Bytes.copy(rowArray, rowOffset, rowLength);
136 setTimestamp(ts);
137 }
138
139 /**
140 * @param d Delete to clone.
141 */
142 public Delete(final Delete d) {
143 this.row = d.getRow();
144 this.ts = d.getTimeStamp();
145 this.familyMap.putAll(d.getFamilyCellMap());
146 this.durability = d.durability;
147 for (Map.Entry<String, byte[]> entry : d.getAttributesMap().entrySet()) {
148 this.setAttribute(entry.getKey(), entry.getValue());
149 }
150 }
151
152 /**
153 * Advanced use only.
154 * Add an existing delete marker to this Delete object.
155 * @param kv An existing KeyValue of type "delete".
156 * @return this for invocation chaining
157 * @throws IOException
158 */
159 @SuppressWarnings("unchecked")
160 public Delete addDeleteMarker(Cell kv) throws IOException {
161 // TODO: Deprecate and rename 'add' so it matches how we add KVs to Puts.
162 if (!CellUtil.isDelete(kv)) {
163 throw new IOException("The recently added KeyValue is not of type "
164 + "delete. Rowkey: " + Bytes.toStringBinary(this.row));
165 }
166 if (Bytes.compareTo(this.row, 0, row.length, kv.getRowArray(),
167 kv.getRowOffset(), kv.getRowLength()) != 0) {
168 throw new WrongRowIOException("The row in " + kv.toString() +
169 " doesn't match the original one " + Bytes.toStringBinary(this.row));
170 }
171 byte [] family = CellUtil.cloneFamily(kv);
172 List<Cell> list = familyMap.get(family);
173 if (list == null) {
174 list = new ArrayList<Cell>();
175 }
176 list.add(kv);
177 familyMap.put(family, list);
178 return this;
179 }
180
181 /**
182 * Delete all versions of all columns of the specified family.
183 * <p>
184 * Overrides previous calls to deleteColumn and deleteColumns for the
185 * specified family.
186 * @param family family name
187 * @return this for invocation chaining
188 * @deprecated Since 1.0.0. Use {@link #addFamily(byte[])}
189 */
190 @Deprecated
191 public Delete deleteFamily(byte [] family) {
192 return addFamily(family);
193 }
194
195 /**
196 * Delete all versions of all columns of the specified family.
197 * <p>
198 * Overrides previous calls to deleteColumn and deleteColumns for the
199 * specified family.
200 * @param family family name
201 * @return this for invocation chaining
202 */
203 public Delete addFamily(final byte [] family) {
204 this.deleteFamily(family, this.ts);
205 return this;
206 }
207
208 /**
209 * Delete all columns of the specified family with a timestamp less than
210 * or equal to the specified timestamp.
211 * <p>
212 * Overrides previous calls to deleteColumn and deleteColumns for the
213 * specified family.
214 * @param family family name
215 * @param timestamp maximum version timestamp
216 * @return this for invocation chaining
217 * @deprecated Since 1.0.0. Use {@link #addFamily(byte[], long)}
218 */
219 @Deprecated
220 public Delete deleteFamily(byte [] family, long timestamp) {
221 return addFamily(family, timestamp);
222 }
223
224 /**
225 * Delete all columns of the specified family with a timestamp less than
226 * or equal to the specified timestamp.
227 * <p>
228 * Overrides previous calls to deleteColumn and deleteColumns for the
229 * specified family.
230 * @param family family name
231 * @param timestamp maximum version timestamp
232 * @return this for invocation chaining
233 */
234 public Delete addFamily(final byte [] family, final long timestamp) {
235 if (timestamp < 0) {
236 throw new IllegalArgumentException("Timestamp cannot be negative. ts=" + timestamp);
237 }
238 List<Cell> list = familyMap.get(family);
239 if(list == null) {
240 list = new ArrayList<Cell>();
241 } else if(!list.isEmpty()) {
242 list.clear();
243 }
244 KeyValue kv = new KeyValue(row, family, null, timestamp, KeyValue.Type.DeleteFamily);
245 list.add(kv);
246 familyMap.put(family, list);
247 return this;
248 }
249
250 /**
251 * Delete all columns of the specified family with a timestamp equal to
252 * the specified timestamp.
253 * @param family family name
254 * @param timestamp version timestamp
255 * @return this for invocation chaining
256 * @deprecated Since hbase-1.0.0. Use {@link #addFamilyVersion(byte[], long)}
257 */
258 @Deprecated
259 public Delete deleteFamilyVersion(byte [] family, long timestamp) {
260 return addFamilyVersion(family, timestamp);
261 }
262
263 /**
264 * Delete all columns of the specified family with a timestamp equal to
265 * the specified timestamp.
266 * @param family family name
267 * @param timestamp version timestamp
268 * @return this for invocation chaining
269 */
270 public Delete addFamilyVersion(final byte [] family, final long timestamp) {
271 List<Cell> list = familyMap.get(family);
272 if(list == null) {
273 list = new ArrayList<Cell>();
274 }
275 list.add(new KeyValue(row, family, null, timestamp,
276 KeyValue.Type.DeleteFamilyVersion));
277 familyMap.put(family, list);
278 return this;
279 }
280
281 /**
282 * Delete all versions of the specified column.
283 * @param family family name
284 * @param qualifier column qualifier
285 * @return this for invocation chaining
286 * @deprecated Since hbase-1.0.0. Use {@link #addColumns(byte[], byte[])}
287 */
288 @Deprecated
289 public Delete deleteColumns(byte [] family, byte [] qualifier) {
290 return addColumns(family, qualifier);
291 }
292
293 /**
294 * Delete all versions of the specified column.
295 * @param family family name
296 * @param qualifier column qualifier
297 * @return this for invocation chaining
298 */
299 public Delete addColumns(final byte [] family, final byte [] qualifier) {
300 addColumns(family, qualifier, this.ts);
301 return this;
302 }
303
304 /**
305 * Delete all versions of the specified column with a timestamp less than
306 * or equal to the specified timestamp.
307 * @param family family name
308 * @param qualifier column qualifier
309 * @param timestamp maximum version timestamp
310 * @return this for invocation chaining
311 * @deprecated Since hbase-1.0.0. Use {@link #addColumns(byte[], byte[], long)}
312 */
313 @Deprecated
314 public Delete deleteColumns(byte [] family, byte [] qualifier, long timestamp) {
315 return addColumns(family, qualifier, timestamp);
316 }
317
318 /**
319 * Delete all versions of the specified column with a timestamp less than
320 * or equal to the specified timestamp.
321 * @param family family name
322 * @param qualifier column qualifier
323 * @param timestamp maximum version timestamp
324 * @return this for invocation chaining
325 */
326 public Delete addColumns(final byte [] family, final byte [] qualifier, final long timestamp) {
327 if (timestamp < 0) {
328 throw new IllegalArgumentException("Timestamp cannot be negative. ts=" + timestamp);
329 }
330 List<Cell> list = familyMap.get(family);
331 if (list == null) {
332 list = new ArrayList<Cell>();
333 }
334 list.add(new KeyValue(this.row, family, qualifier, timestamp,
335 KeyValue.Type.DeleteColumn));
336 familyMap.put(family, list);
337 return this;
338 }
339
340 /**
341 * Delete the latest version of the specified column.
342 * This is an expensive call in that on the server-side, it first does a
343 * get to find the latest versions timestamp. Then it adds a delete using
344 * the fetched cells timestamp.
345 * @param family family name
346 * @param qualifier column qualifier
347 * @return this for invocation chaining
348 * @deprecated Since hbase-1.0.0. Use {@link #addColumn(byte[], byte[])}
349 */
350 @Deprecated
351 public Delete deleteColumn(byte [] family, byte [] qualifier) {
352 return addColumn(family, qualifier);
353 }
354
355 /**
356 * Delete the latest version of the specified column.
357 * This is an expensive call in that on the server-side, it first does a
358 * get to find the latest versions timestamp. Then it adds a delete using
359 * the fetched cells timestamp.
360 * @param family family name
361 * @param qualifier column qualifier
362 * @return this for invocation chaining
363 */
364 public Delete addColumn(final byte [] family, final byte [] qualifier) {
365 this.deleteColumn(family, qualifier, this.ts);
366 return this;
367 }
368
369 /**
370 * Delete the specified version of the specified column.
371 * @param family family name
372 * @param qualifier column qualifier
373 * @param timestamp version timestamp
374 * @return this for invocation chaining
375 * @deprecated Since hbase-1.0.0. Use {@link #addColumn(byte[], byte[], long)}
376 */
377 @Deprecated
378 public Delete deleteColumn(byte [] family, byte [] qualifier, long timestamp) {
379 return addColumn(family, qualifier, timestamp);
380 }
381
382 /**
383 * Delete the specified version of the specified column.
384 * @param family family name
385 * @param qualifier column qualifier
386 * @param timestamp version timestamp
387 * @return this for invocation chaining
388 */
389 public Delete addColumn(byte [] family, byte [] qualifier, long timestamp) {
390 if (timestamp < 0) {
391 throw new IllegalArgumentException("Timestamp cannot be negative. ts=" + timestamp);
392 }
393 List<Cell> list = familyMap.get(family);
394 if(list == null) {
395 list = new ArrayList<Cell>();
396 }
397 KeyValue kv = new KeyValue(this.row, family, qualifier, timestamp, KeyValue.Type.Delete);
398 list.add(kv);
399 familyMap.put(family, list);
400 return this;
401 }
402
403 /**
404 * Set the timestamp of the delete.
405 *
406 * @param timestamp
407 */
408 public Delete setTimestamp(long timestamp) {
409 if (timestamp < 0) {
410 throw new IllegalArgumentException("Timestamp cannot be negative. ts=" + timestamp);
411 }
412 this.ts = timestamp;
413 return this;
414 }
415
416 @Override
417 public Map<String, Object> toMap(int maxCols) {
418 // we start with the fingerprint map and build on top of it.
419 Map<String, Object> map = super.toMap(maxCols);
420 // why is put not doing this?
421 map.put("ts", this.ts);
422 return map;
423 }
424
425 @Override
426 public Delete setAttribute(String name, byte[] value) {
427 return (Delete) super.setAttribute(name, value);
428 }
429
430 @Override
431 public Delete setId(String id) {
432 return (Delete) super.setId(id);
433 }
434
435 @Override
436 @Deprecated
437 public Delete setWriteToWAL(boolean write) {
438 return (Delete) super.setWriteToWAL(write);
439 }
440
441 @Override
442 public Delete setDurability(Durability d) {
443 return (Delete) super.setDurability(d);
444 }
445
446 @Override
447 public Delete setFamilyCellMap(NavigableMap<byte[], List<Cell>> map) {
448 return (Delete) super.setFamilyCellMap(map);
449 }
450
451 @Override
452 @Deprecated
453 public Delete setFamilyMap(NavigableMap<byte[], List<KeyValue>> map) {
454 return (Delete) super.setFamilyMap(map);
455 }
456
457 @Override
458 public Delete setClusterIds(List<UUID> clusterIds) {
459 return (Delete) super.setClusterIds(clusterIds);
460 }
461
462 @Override
463 public Delete setCellVisibility(CellVisibility expression) {
464 return (Delete) super.setCellVisibility(expression);
465 }
466
467 @Override
468 public Delete setACL(String user, Permission perms) {
469 return (Delete) super.setACL(user, perms);
470 }
471
472 @Override
473 public Delete setACL(Map<String, Permission> perms) {
474 return (Delete) super.setACL(perms);
475 }
476
477 @Override
478 public Delete setTTL(long ttl) {
479 throw new UnsupportedOperationException("Setting TTLs on Deletes is not supported");
480 }
481 }