KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hsqldb > CompiledStatementExecutor


1 /* Copyright (c) 2001-2005, The HSQL Development Group
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * Redistributions of source code must retain the above copyright notice, this
8  * list of conditions and the following disclaimer.
9  *
10  * Redistributions in binary form must reproduce the above copyright notice,
11  * this list of conditions and the following disclaimer in the documentation
12  * and/or other materials provided with the distribution.
13  *
14  * Neither the name of the HSQL Development Group nor the names of its
15  * contributors may be used to endorse or promote products derived from this
16  * software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
22  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */

30
31
32 package org.hsqldb;
33
34 import org.hsqldb.jdbc.jdbcResultSet;
35 import org.hsqldb.lib.HashMappedList;
36 import org.hsqldb.lib.HsqlArrayList;
37 import org.hsqldb.lib.java.JavaSystem;
38
39 // boucherb@users 200404xx - fixed broken CALL statement result set unwrapping;
40
// fixed broken support for prepared SELECT...INTO
41

42 /**
43  * Provides execution of CompiledStatement objects. <p>
44  *
45  * If multiple threads access a CompiledStatementExecutor.execute()
46  * concurrently, they must be synchronized externally, relative to both
47  * this object's Session and the Session's Database object. Internally, this
48  * is accomplished in Session.execute() by synchronizing on the Session
49  * object's Database object.
50  *
51  * @author boucherb@users
52  * @version 1.7.2
53  * @since 1.7.2
54  */

55 final class CompiledStatementExecutor {
56
57     private Session session;
58     private Result updateResult;
59     private static Result emptyZeroResult =
60         new Result(ResultConstants.UPDATECOUNT);
61     private static Result updateOneResult =
62         new Result(ResultConstants.UPDATECOUNT);
63
64     static {
65         updateOneResult.updateCount = 1;
66     }
67
68     /**
69      * Creates a new instance of CompiledStatementExecutor.
70      *
71      * @param session the context in which to perform the execution
72      */

73     CompiledStatementExecutor(Session session) {
74         this.session = session;
75         updateResult = new Result(ResultConstants.UPDATECOUNT);
76     }
77
78     /**
79      * Executes a generic CompiledStatement. Execution includes first building
80      * any subquery result dependencies and clearing them after the main result
81      * is built.
82      *
83      * @return the result of executing the statement
84      * @param cs any valid CompiledStatement
85      */

86     Result execute(CompiledStatement cs, Object JavaDoc[] paramValues) {
87
88         Result result = null;
89
90         JavaSystem.gc();
91
92         for (int i = 0; i < cs.parameters.length; i++) {
93             cs.parameters[i].bind(paramValues[i]);
94         }
95
96         try {
97             cs.materializeSubQueries(session);
98
99             result = executeImpl(cs);
100         } catch (Throwable JavaDoc t) {
101             result = new Result(t, cs.sql);
102         }
103
104         // clear redundant data
105
cs.dematerializeSubQueries(session);
106
107         if (result == null) {
108             result = emptyZeroResult;
109         }
110
111         return result;
112     }
113
114     /**
115      * Executes a generic CompiledStatement. Execution excludes building
116      * subquery result dependencies and clearing them after the main result
117      * is built.
118      *
119      * @param cs any valid CompiledStatement
120      * @throws HsqlException if a database access error occurs
121      * @return the result of executing the statement
122      */

123     private Result executeImpl(CompiledStatement cs) throws HsqlException {
124
125         switch (cs.type) {
126
127             case CompiledStatement.SELECT :
128                 return executeSelectStatement(cs);
129
130             case CompiledStatement.INSERT_SELECT :
131                 return executeInsertSelectStatement(cs);
132
133             case CompiledStatement.INSERT_VALUES :
134                 return executeInsertValuesStatement(cs);
135
136             case CompiledStatement.UPDATE :
137                 return executeUpdateStatement(cs);
138
139             case CompiledStatement.DELETE :
140                 return executeDeleteStatement(cs);
141
142             case CompiledStatement.CALL :
143                 return executeCallStatement(cs);
144
145             case CompiledStatement.DDL :
146                 return executeDDLStatement(cs);
147
148             default :
149                 throw Trace.runtimeError(
150                     Trace.UNSUPPORTED_INTERNAL_OPERATION,
151                     "CompiledStatementExecutor.executeImpl()");
152         }
153     }
154
155     /**
156      * Executes a CALL statement. It is assumed that the argument is
157      * of the correct type.
158      *
159      * @param cs a CompiledStatement of type CompiledStatement.CALL
160      * @throws HsqlException if a database access error occurs
161      * @return the result of executing the statement
162      */

163     private Result executeCallStatement(CompiledStatement cs)
164     throws HsqlException {
165
166         Expression e = cs.expression; // representing CALL
167
Object JavaDoc o = e.getValue(session); // expression return value
168
Result r;
169
170         if (o instanceof Result) {
171             return (Result) o;
172         } else if (o instanceof jdbcResultSet) {
173             return ((jdbcResultSet) o).rResult;
174         }
175
176         r = Result.newSingleColumnResult(CompiledStatement.RETURN_COLUMN_NAME,
177                                          e.getDataType());
178
179         Object JavaDoc[] row = new Object JavaDoc[1];
180
181         row[0] = o;
182         r.metaData.classNames[0] = e.getValueClassName();
183
184         r.add(row);
185
186         return r;
187     }
188
189 // fredt - currently deletes that fail due to referential constraints are caught prior to
190
// actual delete operation, so no nested transaction is required
191

192     /**
193      * Executes a DELETE statement. It is assumed that the argument is
194      * of the correct type.
195      *
196      * @param cs a CompiledStatement of type CompiledStatement.DELETE
197      * @throws HsqlException if a database access error occurs
198      * @return the result of executing the statement
199      */

200     private Result executeDeleteStatement(CompiledStatement cs)
201     throws HsqlException {
202
203         Table table = cs.targetTable;
204         TableFilter filter = cs.targetFilter;
205         int count = 0;
206
207         if (filter.findFirst(session)) {
208             Expression c = cs.condition;
209             HsqlArrayList del;
210
211             del = new HsqlArrayList();
212
213             do {
214                 if (c == null || c.testCondition(session)) {
215                     del.add(filter.currentRow);
216                 }
217             } while (filter.next(session));
218
219             count = table.delete(session, del);
220         }
221
222         updateResult.updateCount = count;
223
224         return updateResult;
225     }
226
227     /**
228      * Executes an INSERT_SELECT statement. It is assumed that the argument
229      * is of the correct type.
230      *
231      * @param cs a CompiledStatement of type CompiledStatement.INSERT_SELECT
232      * @throws HsqlException if a database access error occurs
233      * @return the result of executing the statement
234      */

235     private Result executeInsertSelectStatement(CompiledStatement cs)
236     throws HsqlException {
237
238         Table t = cs.targetTable;
239         Select s = cs.select;
240         int[] ct = t.getColumnTypes(); // column types
241
Result r = s.getResult(session, Integer.MAX_VALUE);
242         Record rc = r.rRoot;
243         int[] cm = cs.columnMap; // column map
244
boolean[] ccl = cs.checkColumns; // column check list
245
int len = cm.length;
246         Object JavaDoc[] row;
247         int count;
248         boolean success = false;
249
250         session.beginNestedTransaction();
251
252         try {
253             while (rc != null) {
254                 row = t.getNewRowData(session, ccl);
255
256                 for (int i = 0; i < len; i++) {
257                     int j = cm[i];
258
259                     if (ct[j] != r.metaData.colTypes[i]) {
260                         row[j] = Column.convertObject(rc.data[i], ct[j]);
261                     } else {
262                         row[j] = rc.data[i];
263                     }
264                 }
265
266                 rc.data = row;
267                 rc = rc.next;
268             }
269
270             count = t.insert(session, r);
271             success = true;
272         } finally {
273             session.endNestedTransaction(!success);
274         }
275
276         updateResult.updateCount = count;
277
278         return updateResult;
279     }
280
281     /**
282      * Executes an INSERT_VALUES statement. It is assumed that the argument
283      * is of the correct type.
284      *
285      * @param cs a CompiledStatement of type CompiledStatement.INSERT_VALUES
286      * @throws HsqlException if a database access error occurs
287      * @return the result of executing the statement
288      */

289     private Result executeInsertValuesStatement(CompiledStatement cs)
290     throws HsqlException {
291
292         Table t = cs.targetTable;
293         Object JavaDoc[] row = t.getNewRowData(session, cs.checkColumns);
294         int[] cm = cs.columnMap; // column map
295
Expression[] acve = cs.columnValues;
296         Expression cve;
297         int[] ct = t.getColumnTypes(); // column types
298
int ci; // column index
299
int len = acve.length;
300
301         for (int i = 0; i < len; i++) {
302             cve = acve[i];
303             ci = cm[i];
304             row[ci] = cve.getValue(session, ct[ci]);
305         }
306
307         t.insert(session, row);
308
309         return updateOneResult;
310     }
311
312     /**
313      * Executes a SELECT statement. It is assumed that the argument
314      * is of the correct type.
315      *
316      * @param cs a CompiledStatement of type CompiledStatement.SELECT
317      * @throws HsqlException if a database access error occurs
318      * @return the result of executing the statement
319      */

320     private Result executeSelectStatement(CompiledStatement cs)
321     throws HsqlException {
322
323         Select select = cs.select;
324         Result result;
325
326         if (select.sIntoTable != null) {
327
328             // session level user rights
329
session.checkDDLWrite();
330
331             boolean exists =
332                 session.database.schemaManager.findUserTable(
333                     session, select.sIntoTable.name,
334                     select.sIntoTable.schema.name) != null;
335
336             if (exists) {
337                 throw Trace.error(Trace.TABLE_ALREADY_EXISTS,
338                                   select.sIntoTable.name);
339             }
340
341             result = select.getResult(session, Integer.MAX_VALUE);
342             result = session.dbCommandInterpreter.processSelectInto(result,
343                     select.sIntoTable, select.intoType);
344
345             session.getDatabase().setMetaDirty(false);
346         } else {
347             result = select.getResult(session, session.getMaxRows());
348         }
349
350         return result;
351     }
352
353     /**
354      * Executes an UPDATE statement. It is assumed that the argument
355      * is of the correct type.
356      *
357      * @param cs a CompiledStatement of type CompiledStatement.UPDATE
358      * @throws HsqlException if a database access error occurs
359      * @return the result of executing the statement
360      */

361     private Result executeUpdateStatement(CompiledStatement cs)
362     throws HsqlException {
363
364         Table table = cs.targetTable;
365         TableFilter filter = cs.targetFilter;
366         int count = 0;
367
368         if (filter.findFirst(session)) {
369             int[] colmap = cs.columnMap; // column map
370
Expression[] colvalues = cs.columnValues;
371             Expression condition = cs.condition; // update condition
372
int len = colvalues.length;
373             HashMappedList rowset = new HashMappedList();
374             int size = table.getColumnCount();
375             int[] coltypes = table.getColumnTypes();
376             boolean success = false;
377
378             do {
379                 if (condition == null || condition.testCondition(session)) {
380                     try {
381                         Row row = filter.currentRow;
382                         Object JavaDoc[] ni = table.getEmptyRowData();
383
384                         System.arraycopy(row.getData(), 0, ni, 0, size);
385
386                         for (int i = 0; i < len; i++) {
387                             int ci = colmap[i];
388
389                             ni[ci] = colvalues[i].getValue(session,
390                                                            coltypes[ci]);
391                         }
392
393                         rowset.add(row, ni);
394                     } catch (HsqlInternalException e) {}
395                 }
396             } while (filter.next(session));
397
398             session.beginNestedTransaction();
399
400             try {
401                 count = table.update(session, rowset, colmap);
402                 success = true;
403             } finally {
404
405                 // update failed (constraint violation) or succeeded
406
session.endNestedTransaction(!success);
407             }
408         }
409
410         updateResult.updateCount = count;
411
412         return updateResult;
413     }
414
415     /**
416      * Executes a DDL statement. It is assumed that the argument
417      * is of the correct type.
418      *
419      * @param cs a CompiledStatement of type CompiledStatement.DDL
420      * @throws HsqlException if a database access error occurs
421      * @return the result of executing the statement
422      */

423     private Result executeDDLStatement(CompiledStatement cs)
424     throws HsqlException {
425         return session.sqlExecuteDirectNoPreChecks(cs.sql);
426     }
427 }
428
Popular Tags