File D:\maven-qcr-plugin-testsunitaires\qcr4java\h2-1.3.170-sources\target\site\qc\lecode\command\Prepared.java.html

1 /*
2 * Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
3 * Version 1.0, and under the Eclipse Public License, Version 1.0
4 * (http://h2database.com/html/license.html).
5 * Initial Developer: H2 Group
6 */
7 package org.h2.command;
8
9 import java.util.ArrayList;
10 import org.h2.api.DatabaseEventListener;
11 import org.h2.constant.ErrorCode;
12 import org.h2.engine.Database;
13 import org.h2.engine.Session;
14 import org.h2.expression.Expression;
15 import org.h2.expression.Parameter;
16 import org.h2.message.DbException;
17 import org.h2.message.Trace;
18 import org.h2.result.ResultInterface;
19 import org.h2.util.StatementBuilder;
20 import org.h2.value.Value;
21
22 /**
23 * A prepared statement.
24 */
25 public abstract class Prepared {
26
27 /**
28 * The session.
29 */
30 protected Session session;
31
32 /**
33 * The SQL string.
34 */
35 protected String sqlStatement;
36
37 /**
38 * Whether to create a new object (for indexes).
39 */
40 protected boolean create = true;
41
42 /**
43 * The list of parameters.
44 */
45 protected ArrayList<Parameter> parameters;
46
47 /**
48 * If the query should be prepared before each execution. This is set for
49 * queries with LIKE ?, because the query plan depends on the parameter
50 * value.
51 */
52 protected boolean prepareAlways;
53
54 private long modificationMetaId;
55 private Command command;
56 private int objectId;
57 private int currentRowNumber;
58 private int rowScanCount;
59
60 /**
61 * Create a new object.
62 *
63 * @param session the session
64 */
65 public Prepared(Session session) {
66 this.session = session;
67 modificationMetaId = session.getDatabase().getModificationMetaId();
68 }
69
70 /**
71 * Check if this command is transactional.
72 * If it is not, then it forces the current transaction to commit.
73 *
74 * @return true if it is
75 */
76 public abstract boolean isTransactional();
77
78 /**
79 * Get an empty result set containing the meta data.
80 *
81 * @return the result set
82 */
83 public abstract ResultInterface queryMeta();
84
85
86 /**
87 * Get the command type as defined in CommandInterface
88 *
89 * @return the statement type
90 */
91 public abstract int getType();
92
93 /**
94 * Check if this command is read only.
95 *
96 * @return true if it is
97 */
98 public boolean isReadOnly() {
99 return false;
100 }
101
102 /**
103 * Check if the statement needs to be re-compiled.
104 *
105 * @return true if it must
106 */
107 public boolean needRecompile() {
108 Database db = session.getDatabase();
109 if (db == null) {
110 throw DbException.get(ErrorCode.CONNECTION_BROKEN_1, "database closed");
111 }
112 // parser: currently, compiling every create/drop/... twice
113 // because needRecompile return true even for the first execution
114 return prepareAlways || modificationMetaId < db.getModificationMetaId() || db.getSettings().recompileAlways;
115 }
116
117 /**
118 * Get the meta data modification id of the database when this statement was
119 * compiled.
120 *
121 * @return the meta data modification id
122 */
123 long getModificationMetaId() {
124 return modificationMetaId;
125 }
126
127 /**
128 * Set the meta data modification id of this statement.
129 *
130 * @param id the new id
131 */
132 void setModificationMetaId(long id) {
133 this.modificationMetaId = id;
134 }
135
136 /**
137 * Set the parameter list of this statement.
138 *
139 * @param parameters the parameter list
140 */
141 public void setParameterList(ArrayList<Parameter> parameters) {
142 this.parameters = parameters;
143 }
144
145 /**
146 * Get the parameter list.
147 *
148 * @return the parameter list
149 */
150 public ArrayList<Parameter> getParameters() {
151 return parameters;
152 }
153
154 /**
155 * Check if all parameters have been set.
156 *
157 * @throws DbException if any parameter has not been set
158 */
159 protected void checkParameters() {
160 if (parameters != null) {
161 for (int i = 0, size = parameters.size(); i < size; i++) {
162 Parameter param = parameters.get(i);
163 param.checkSet();
164 }
165 }
166 }
167
168 /**
169 * Set the command.
170 *
171 * @param command the new command
172 */
173 public void setCommand(Command command) {
174 this.command = command;
175 }
176
177 /**
178 * Check if this object is a query.
179 *
180 * @return true if it is
181 */
182 public boolean isQuery() {
183 return false;
184 }
185
186 /**
187 * Prepare this statement.
188 */
189 public void prepare() {
190 // nothing to do
191 }
192
193 /**
194 * Execute the statement.
195 *
196 * @return the update count
197 * @throws DbException if it is a query
198 */
199 public int update() {
200 throw DbException.get(ErrorCode.METHOD_NOT_ALLOWED_FOR_QUERY);
201 }
202
203 /**
204 * Execute the query.
205 *
206 * @param maxrows the maximum number of rows to return
207 * @return the result set
208 * @throws DbException if it is not a query
209 */
210 public ResultInterface query(int maxrows) {
211 throw DbException.get(ErrorCode.METHOD_ONLY_ALLOWED_FOR_QUERY);
212 }
213
214 /**
215 * Set the SQL statement.
216 *
217 * @param sql the SQL statement
218 */
219 public void setSQL(String sql) {
220 this.sqlStatement = sql;
221 }
222
223 /**
224 * Get the SQL statement.
225 *
226 * @return the SQL statement
227 */
228 public String getSQL() {
229 return sqlStatement;
230 }
231
232 /**
233 * Get the object id to use for the database object that is created in this
234 * statement. This id is only set when the object is persistent.
235 * If not set, this method returns 0.
236 *
237 * @return the object id or 0 if not set
238 */
239 protected int getCurrentObjectId() {
240 return objectId;
241 }
242
243 /**
244 * Get the current object id, or get a new id from the database. The object
245 * id is used when creating new database object (CREATE statement).
246 *
247 * @return the object id
248 */
249 protected int getObjectId() {
250 int id = objectId;
251 if (id == 0) {
252 id = session.getDatabase().allocateObjectId();
253 } else {
254 objectId = 0;
255 }
256 return id;
257 }
258
259 /**
260 * Get the SQL statement with the execution plan.
261 *
262 * @return the execution plan
263 */
264 public String getPlanSQL() {
265 return null;
266 }
267
268 /**
269 * Check if this statement was canceled.
270 *
271 * @throws DbException if it was canceled
272 */
273 public void checkCanceled() {
274 session.checkCanceled();
275 Command c = command != null ? command : session.getCurrentCommand();
276 if (c != null) {
277 c.checkCanceled();
278 }
279 }
280
281 /**
282 * Set the object id for this statement.
283 *
284 * @param i the object id
285 */
286 public void setObjectId(int i) {
287 this.objectId = i;
288 this.create = false;
289 }
290
291 /**
292 * Set the session for this statement.
293 *
294 * @param currentSession the new session
295 */
296 public void setSession(Session currentSession) {
297 this.session = currentSession;
298 }
299
300 /**
301 * Print information about the statement executed if info trace level is
302 * enabled.
303 *
304 * @param startTime when the statement was started
305 * @param count the update count
306 */
307 void trace(long startTime, int count) {
308 if (session.getTrace().isInfoEnabled() && startTime > 0) {
309 long time = System.currentTimeMillis() - startTime;
310 String params = Trace.formatParams(parameters);
311 session.getTrace().infoSQL(sqlStatement, params, count, time);
312 }
313 }
314
315 /**
316 * Set the prepare always flag.
317 * If set, the statement is re-compiled whenever it is executed.
318 *
319 * @param prepareAlways the new value
320 */
321 public void setPrepareAlways(boolean prepareAlways) {
322 this.prepareAlways = prepareAlways;
323 }
324
325 /**
326 * Set the current row number.
327 *
328 * @param rowNumber the row number
329 */
330 protected void setCurrentRowNumber(int rowNumber) {
331 if ((++rowScanCount & 127) == 0) {
332 checkCanceled();
333 }
334 this.currentRowNumber = rowNumber;
335 setProgress();
336 }
337
338 /**
339 * Get the current row number.
340 *
341 * @return the row number
342 */
343 public int getCurrentRowNumber() {
344 return currentRowNumber;
345 }
346
347 /**
348 * Notifies query progress via the DatabaseEventListener
349 */
350 private void setProgress() {
351 if ((currentRowNumber & 127) == 0) {
352 session.getDatabase().setProgress(DatabaseEventListener.STATE_STATEMENT_PROGRESS, sqlStatement, currentRowNumber, 0);
353 }
354 }
355
356 /**
357 * Convert the statement to a String.
358 *
359 * @return the SQL statement
360 */
361 public String toString() {
362 return sqlStatement;
363 }
364
365 /**
366 * Get the SQL snippet of the value list.
367 *
368 * @param values the value list
369 * @return the SQL snippet
370 */
371 protected static String getSQL(Value[] values) {
372 StatementBuilder buff = new StatementBuilder();
373 for (Value v : values) {
374 buff.appendExceptFirst(", ");
375 if (v != null) {
376 buff.append(v.getSQL());
377 }
378 }
379 return buff.toString();
380 }
381
382 /**
383 * Get the SQL snippet of the expression list.
384 *
385 * @param list the expression list
386 * @return the SQL snippet
387 */
388 protected static String getSQL(Expression[] list) {
389 StatementBuilder buff = new StatementBuilder();
390 for (Expression e : list) {
391 buff.appendExceptFirst(", ");
392 if (e != null) {
393 buff.append(e.getSQL());
394 }
395 }
396 return buff.toString();
397 }
398
399 /**
400 * Set the SQL statement of the exception to the given row.
401 *
402 * @param e the exception
403 * @param rowId the row number
404 * @param values the values of the row
405 * @return the exception
406 */
407 protected DbException setRow(DbException e, int rowId, String values) {
408 StringBuilder buff = new StringBuilder();
409 if (sqlStatement != null) {
410 buff.append(sqlStatement);
411 }
412 buff.append(" -- ");
413 if (rowId > 0) {
414 buff.append("row #").append(rowId + 1).append(' ');
415 }
416 buff.append('(').append(values).append(')');
417 return e.addSQL(buff.toString());
418 }
419
420 public boolean isCacheable() {
421 return false;
422 }
423
424 }
425