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.HTable;
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 HTable 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 rowDelete.deleteColumns(deleteItem.getBytes());
187 }
188 }
189
190 table.delete(rowDelete);
191 cnt++;
192 }
193 }
194 catch (ResultMissingColumnException e) {
195
196 }
197 catch (NullColumnValueException e) {
198
199 }
200 }
201 if (cnt > 0)
202 table.flushCommits();
203 return cnt;
204 }
205 catch (IOException e) {
206 throw new HBqlException(e);
207 }
208 }
209
210 public void resetParameters() {
211 this.getWithArgs().reset();
212 }
213
214 private void collectParameters() {
215 this.getNamedParameters().addParameters(this.getWithArgs().getParameterList());
216 }
217
218 public int setStatementParameter(final String name, final Object val) throws HBqlException {
219 final int cnt = this.getWithArgs().setParameter(name, val);
220 if (cnt == 0)
221 throw new HBqlException("Parameter name " + name + " does not exist in " + this.asString());
222 return cnt;
223 }
224
225 public String asString() {
226
227 final StringBuilder sbuf = new StringBuilder();
228
229 sbuf.append("DELETE ");
230
231 boolean firsttime = true;
232 for (final String familyName : this.originaltemList) {
233 if (!firsttime)
234 sbuf.append(", ");
235 sbuf.append(familyName);
236 firsttime = false;
237 }
238
239 sbuf.append(" FROM ");
240 sbuf.append(this.getMappingContext().getMappingName());
241 sbuf.append(" ");
242 sbuf.append(this.getWithArgs().asString());
243 return sbuf.toString();
244 }
245
246 public static String usage() {
247 return "DELETE delete_item_list FROM [MAPPING] mapping_name with_clause [IF bool_expr]";
248 }
249 }