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;
22
23 import org.apache.expreval.client.NullColumnValueException;
24 import org.apache.expreval.client.ResultMissingColumnException;
25 import org.apache.expreval.expr.ExpressionTree;
26 import org.apache.hadoop.hbase.client.Delete;
27 import org.apache.hadoop.hbase.client.HTableInterface;
28 import org.apache.hadoop.hbase.client.Result;
29 import org.apache.hadoop.hbase.client.ResultScanner;
30 import org.apache.hadoop.hbase.hbql.client.ExecutionResults;
31 import org.apache.hadoop.hbase.hbql.client.HBqlException;
32 import org.apache.hadoop.hbase.hbql.impl.HConnectionImpl;
33 import org.apache.hadoop.hbase.hbql.impl.HTableWrapper;
34 import org.apache.hadoop.hbase.hbql.mapping.ColumnAttrib;
35 import org.apache.hadoop.hbase.hbql.mapping.TableMapping;
36 import org.apache.hadoop.hbase.hbql.statement.args.WithArgs;
37 import org.apache.hadoop.hbase.hbql.statement.select.RowRequest;
38 import org.apache.hadoop.hbase.hbql.util.Lists;
39
40 import java.io.IOException;
41 import java.util.List;
42 import java.util.Set;
43
44 public class DeleteStatement extends StatementWithParameters implements ConnectionStatement {
45
46 private final List<String> deleteItemList = Lists.newArrayList();
47 private final List<String> originaltemList;
48 private final WithArgs withArgs;
49
50 private HConnectionImpl connection = null;
51 private boolean validated = false;
52
53 public DeleteStatement(final StatementPredicate predicate,
54 final List<String> originaltemList,
55 final String mappingName,
56 final WithArgs withArgs) {
57 super(predicate, mappingName);
58
59 this.withArgs = (withArgs == null) ? new WithArgs() : withArgs;
60
61 if (originaltemList == null)
62 this.originaltemList = Lists.newArrayList();
63 else
64 this.originaltemList = originaltemList;
65 }
66
67 private WithArgs getWithArgs() {
68 return this.withArgs;
69 }
70
71 private List<String> getDeleteItemList() {
72 return this.deleteItemList;
73 }
74
75 private HConnectionImpl getConnection() {
76 return this.connection;
77 }
78
79 private boolean isValidated() {
80 return this.validated;
81 }
82
83 public void validate(final HConnectionImpl conn) throws HBqlException {
84
85 if (this.isValidated())
86 return;
87
88 this.validated = true;
89 this.connection = conn;
90
91 this.getMappingContext().validateMappingName(conn);
92
93 this.getWithArgs().setMappingContext(this.getMappingContext());
94 this.getWithArgs().validate(conn, this.getMappingContext().getTableMapping());
95
96 this.collectParameters();
97
98
99
100 for (final String deleteItem : this.originaltemList) {
101 if (deleteItem.contains(":")) {
102 this.getDeleteItemList().add(deleteItem);
103 }
104 else {
105 final TableMapping mapping = this.getMappingContext().getTableMapping();
106 final ColumnAttrib attrib = mapping.getAttribByVariableName(deleteItem);
107 if (attrib == null)
108 throw new HBqlException("Invalid variable: " + deleteItem);
109
110 this.getDeleteItemList().add(attrib.getFamilyQualifiedName());
111 }
112 }
113 }
114
115 public void validateTypes() throws HBqlException {
116 this.getWithArgs().validateArgTypes();
117 }
118
119 protected ExecutionResults execute(final HConnectionImpl conn) throws HBqlException {
120
121 this.validate(conn);
122
123 this.validateTypes();
124
125 final WithArgs withArgs = this.getWithArgs();
126 final Set<ColumnAttrib> allWhereAttribs = withArgs.getColumnsUsedInAllWhereExprs();
127
128 HTableWrapper tableWrapper = null;
129
130 try {
131 tableWrapper = conn.newHTableWrapper(withArgs, this.getMappingContext().getMapping().getTableName());
132
133 final List<RowRequest> rowRequests = withArgs.getRowRequestList(conn,
134 this.getMappingContext().getMapping(),
135 allWhereAttribs);
136
137 int cnt = 0;
138
139 for (final RowRequest rowRequest : rowRequests)
140 cnt += this.delete(tableWrapper, withArgs, rowRequest);
141
142 try {
143 tableWrapper.getHTable().flushCommits();
144 tableWrapper.getHTable().close();
145 }
146 catch (IOException e) {
147 throw new HBqlException(e);
148 }
149
150 final ExecutionResults results = new ExecutionResults("Delete count: " + cnt);
151 results.setCount(cnt);
152 return results;
153 }
154 finally {
155
156 if (tableWrapper != null)
157 tableWrapper.releaseHTable();
158 }
159 }
160
161 private int delete(final HTableWrapper tableWrapper,
162 final WithArgs withArgs,
163 final RowRequest rowRequest) throws HBqlException {
164
165 final HTableInterface table = tableWrapper.getHTable();
166 final ExpressionTree clientExpressionTree = withArgs.getClientExpressionTree();
167 final ResultScanner resultScanner = rowRequest.getResultScanner(this.getMappingContext().getMapping(),
168 withArgs,
169 table);
170
171 int cnt = 0;
172
173 try {
174 for (final Result result : resultScanner) {
175 try {
176 if (clientExpressionTree == null || clientExpressionTree.evaluate(this.getConnection(), result)) {
177
178 final Delete rowDelete = new Delete(result.getRow());
179
180 for (final String deleteItem : this.getDeleteItemList()) {
181 if (deleteItem.endsWith(":*")) {
182 final String familyName = deleteItem.substring(0, deleteItem.length() - 2);
183 rowDelete.deleteFamily(familyName.getBytes());
184 }
185 else {
186 final int delim = deleteItem.indexOf(":");
187 String family = deleteItem.substring(0, delim);
188 String qualifier = deleteItem.substring(delim + 1, deleteItem.length());
189 rowDelete.deleteColumns(family.getBytes(), qualifier.getBytes());
190 }
191 }
192
193 table.delete(rowDelete);
194 cnt++;
195 }
196 }
197 catch (ResultMissingColumnException e) {
198
199 }
200 catch (NullColumnValueException e) {
201
202 }
203 }
204 if (cnt > 0)
205 table.flushCommits();
206 return cnt;
207 }
208 catch (IOException e) {
209 throw new HBqlException(e);
210 }
211 }
212
213 public void resetParameters() {
214 this.getWithArgs().reset();
215 }
216
217 private void collectParameters() {
218 this.getNamedParameters().addParameters(this.getWithArgs().getParameterList());
219 }
220
221 public int setStatementParameter(final String name, final Object val) throws HBqlException {
222 final int cnt = this.getWithArgs().setParameter(name, val);
223 if (cnt == 0)
224 throw new HBqlException("Parameter name " + name + " does not exist in " + this.asString());
225 return cnt;
226 }
227
228 public String asString() {
229
230 final StringBuilder sbuf = new StringBuilder();
231
232 sbuf.append("DELETE ");
233
234 boolean firsttime = true;
235 for (final String familyName : this.originaltemList) {
236 if (!firsttime)
237 sbuf.append(", ");
238 sbuf.append(familyName);
239 firsttime = false;
240 }
241
242 sbuf.append(" FROM ");
243 sbuf.append(this.getMappingContext().getMappingName());
244 sbuf.append(" ");
245 sbuf.append(this.getWithArgs().asString());
246 return sbuf.toString();
247 }
248
249 public static String usage() {
250 return "DELETE delete_item_list FROM [MAPPING] mapping_name with_clause [IF bool_expr]";
251 }
252 }