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 super.setPriority(d.getPriority());
151 }
152
153 /**
154 * Advanced use only.
155 * Add an existing delete marker to this Delete object.
156 * @param kv An existing KeyValue of type "delete".
157 * @return this for invocation chaining
158 * @throws IOException
159 */
160 @SuppressWarnings("unchecked")
161 public Delete addDeleteMarker(Cell kv) throws IOException {
162 // TODO: Deprecate and rename 'add' so it matches how we add KVs to Puts.
163 if (!CellUtil.isDelete(kv)) {
164 throw new IOException("The recently added KeyValue is not of type "
165 + "delete. Rowkey: " + Bytes.toStringBinary(this.row));
166 }
167 if (Bytes.compareTo(this.row, 0, row.length, kv.getRowArray(),
168 kv.getRowOffset(), kv.getRowLength()) != 0) {
169 throw new WrongRowIOException("The row in " + kv.toString() +
170 " doesn't match the original one " + Bytes.toStringBinary(this.row));
171 }
172 byte [] family = CellUtil.cloneFamily(kv);
173 List<Cell> list = getCellList(family);
174 list.add(kv);
175 return this;
176 }
177
178 /**
179 * Delete all versions of all columns of the specified family.
180 * <p>
181 * Overrides previous calls to deleteColumn and deleteColumns for the
182 * specified family.
183 * @param family family name
184 * @return this for invocation chaining
185 * @deprecated Since 1.0.0. Use {@link #addFamily(byte[])}
186 */
187 @Deprecated
188 public Delete deleteFamily(byte [] family) {
189 return addFamily(family);
190 }
191
192 /**
193 * Delete all versions of all columns of the specified family.
194 * <p>
195 * Overrides previous calls to deleteColumn and deleteColumns for the
196 * specified family.
197 * @param family family name
198 * @return this for invocation chaining
199 */
200 public Delete addFamily(final byte [] family) {
201 this.deleteFamily(family, this.ts);
202 return this;
203 }
204
205 /**
206 * Delete all columns of the specified family with a timestamp less than
207 * or equal to the specified timestamp.
208 * <p>
209 * Overrides previous calls to deleteColumn and deleteColumns for the
210 * specified family.
211 * @param family family name
212 * @param timestamp maximum version timestamp
213 * @return this for invocation chaining
214 * @deprecated Since 1.0.0. Use {@link #addFamily(byte[], long)}
215 */
216 @Deprecated
217 public Delete deleteFamily(byte [] family, long timestamp) {
218 return addFamily(family, timestamp);
219 }
220
221 /**
222 * Delete all columns of the specified family with a timestamp less than
223 * or equal to the specified timestamp.
224 * <p>
225 * Overrides previous calls to deleteColumn and deleteColumns for the
226 * specified family.
227 * @param family family name
228 * @param timestamp maximum version timestamp
229 * @return this for invocation chaining
230 */
231 public Delete addFamily(final byte [] family, final long timestamp) {
232 if (timestamp < 0) {
233 throw new IllegalArgumentException("Timestamp cannot be negative. ts=" + timestamp);
234 }
235 List<Cell> list = getCellList(family);
236 if(!list.isEmpty()) {
237 list.clear();
238 }
239 KeyValue kv = new KeyValue(row, family, null, timestamp, KeyValue.Type.DeleteFamily);
240 list.add(kv);
241 return this;
242 }
243
244 /**
245 * Delete all columns of the specified family with a timestamp equal to
246 * the specified timestamp.
247 * @param family family name
248 * @param timestamp version timestamp
249 * @return this for invocation chaining
250 * @deprecated Since hbase-1.0.0. Use {@link #addFamilyVersion(byte[], long)}
251 */
252 @Deprecated
253 public Delete deleteFamilyVersion(byte [] family, long timestamp) {
254 return addFamilyVersion(family, timestamp);
255 }
256
257 /**
258 * Delete all columns of the specified family with a timestamp equal to
259 * the specified timestamp.
260 * @param family family name
261 * @param timestamp version timestamp
262 * @return this for invocation chaining
263 */
264 public Delete addFamilyVersion(final byte [] family, final long timestamp) {
265 List<Cell> list = getCellList(family);
266 list.add(new KeyValue(row, family, null, timestamp,
267 KeyValue.Type.DeleteFamilyVersion));
268 return this;
269 }
270
271 /**
272 * Delete all versions of the specified column.
273 * @param family family name
274 * @param qualifier column qualifier
275 * @return this for invocation chaining
276 * @deprecated Since hbase-1.0.0. Use {@link #addColumns(byte[], byte[])}
277 */
278 @Deprecated
279 public Delete deleteColumns(byte [] family, byte [] qualifier) {
280 return addColumns(family, qualifier);
281 }
282
283 /**
284 * Delete all versions of the specified column.
285 * @param family family name
286 * @param qualifier column qualifier
287 * @return this for invocation chaining
288 */
289 public Delete addColumns(final byte [] family, final byte [] qualifier) {
290 addColumns(family, qualifier, this.ts);
291 return this;
292 }
293
294 /**
295 * Delete all versions of the specified column with a timestamp less than
296 * or equal to the specified timestamp.
297 * @param family family name
298 * @param qualifier column qualifier
299 * @param timestamp maximum version timestamp
300 * @return this for invocation chaining
301 * @deprecated Since hbase-1.0.0. Use {@link #addColumns(byte[], byte[], long)}
302 */
303 @Deprecated
304 public Delete deleteColumns(byte [] family, byte [] qualifier, long timestamp) {
305 return addColumns(family, qualifier, timestamp);
306 }
307
308 /**
309 * Delete all versions of the specified column with a timestamp less than
310 * or equal to the specified timestamp.
311 * @param family family name
312 * @param qualifier column qualifier
313 * @param timestamp maximum version timestamp
314 * @return this for invocation chaining
315 */
316 public Delete addColumns(final byte [] family, final byte [] qualifier, final long timestamp) {
317 if (timestamp < 0) {
318 throw new IllegalArgumentException("Timestamp cannot be negative. ts=" + timestamp);
319 }
320 List<Cell> list = getCellList(family);
321 list.add(new KeyValue(this.row, family, qualifier, timestamp,
322 KeyValue.Type.DeleteColumn));
323 return this;
324 }
325
326 /**
327 * Delete the latest version of the specified column.
328 * This is an expensive call in that on the server-side, it first does a
329 * get to find the latest versions timestamp. Then it adds a delete using
330 * the fetched cells timestamp.
331 * @param family family name
332 * @param qualifier column qualifier
333 * @return this for invocation chaining
334 * @deprecated Since hbase-1.0.0. Use {@link #addColumn(byte[], byte[])}
335 */
336 @Deprecated
337 public Delete deleteColumn(byte [] family, byte [] qualifier) {
338 return addColumn(family, qualifier);
339 }
340
341 /**
342 * Delete the latest version of the specified column.
343 * This is an expensive call in that on the server-side, it first does a
344 * get to find the latest versions timestamp. Then it adds a delete using
345 * the fetched cells timestamp.
346 * @param family family name
347 * @param qualifier column qualifier
348 * @return this for invocation chaining
349 */
350 public Delete addColumn(final byte [] family, final byte [] qualifier) {
351 this.deleteColumn(family, qualifier, this.ts);
352 return this;
353 }
354
355 /**
356 * Delete the specified version of the specified column.
357 * @param family family name
358 * @param qualifier column qualifier
359 * @param timestamp version timestamp
360 * @return this for invocation chaining
361 * @deprecated Since hbase-1.0.0. Use {@link #addColumn(byte[], byte[], long)}
362 */
363 @Deprecated
364 public Delete deleteColumn(byte [] family, byte [] qualifier, long timestamp) {
365 return addColumn(family, qualifier, timestamp);
366 }
367
368 /**
369 * Delete the specified version of the specified column.
370 * @param family family name
371 * @param qualifier column qualifier
372 * @param timestamp version timestamp
373 * @return this for invocation chaining
374 */
375 public Delete addColumn(byte [] family, byte [] qualifier, long timestamp) {
376 if (timestamp < 0) {
377 throw new IllegalArgumentException("Timestamp cannot be negative. ts=" + timestamp);
378 }
379 List<Cell> list = getCellList(family);
380 KeyValue kv = new KeyValue(this.row, family, qualifier, timestamp, KeyValue.Type.Delete);
381 list.add(kv);
382 return this;
383 }
384
385 /**
386 * Set the timestamp of the delete.
387 *
388 * @param timestamp
389 */
390 public Delete setTimestamp(long timestamp) {
391 if (timestamp < 0) {
392 throw new IllegalArgumentException("Timestamp cannot be negative. ts=" + timestamp);
393 }
394 this.ts = timestamp;
395 return this;
396 }
397
398 @Override
399 public Map<String, Object> toMap(int maxCols) {
400 // we start with the fingerprint map and build on top of it.
401 Map<String, Object> map = super.toMap(maxCols);
402 // why is put not doing this?
403 map.put("ts", this.ts);
404 return map;
405 }
406
407 @Override
408 public Delete setAttribute(String name, byte[] value) {
409 return (Delete) super.setAttribute(name, value);
410 }
411
412 @Override
413 public Delete setId(String id) {
414 return (Delete) super.setId(id);
415 }
416
417 @Override
418 @Deprecated
419 public Delete setWriteToWAL(boolean write) {
420 return (Delete) super.setWriteToWAL(write);
421 }
422
423 @Override
424 public Delete setDurability(Durability d) {
425 return (Delete) super.setDurability(d);
426 }
427
428 @Override
429 public Delete setFamilyCellMap(NavigableMap<byte[], List<Cell>> map) {
430 return (Delete) super.setFamilyCellMap(map);
431 }
432
433 @Override
434 @Deprecated
435 public Delete setFamilyMap(NavigableMap<byte[], List<KeyValue>> map) {
436 return (Delete) super.setFamilyMap(map);
437 }
438
439 @Override
440 public Delete setClusterIds(List<UUID> clusterIds) {
441 return (Delete) super.setClusterIds(clusterIds);
442 }
443
444 @Override
445 public Delete setCellVisibility(CellVisibility expression) {
446 return (Delete) super.setCellVisibility(expression);
447 }
448
449 @Override
450 public Delete setACL(String user, Permission perms) {
451 return (Delete) super.setACL(user, perms);
452 }
453
454 @Override
455 public Delete setACL(Map<String, Permission> perms) {
456 return (Delete) super.setACL(perms);
457 }
458
459 @Override
460 public Delete setTTL(long ttl) {
461 throw new UnsupportedOperationException("Setting TTLs on Deletes is not supported");
462 }
463
464 @Override
465 public Delete setPriority(int priority) {
466 return (Delete) super.setPriority(priority);
467 }
468
469 }