Source code: org/hsqldb/Session.java
1 /* Copyrights and Licenses
2 *
3 * This product includes Hypersonic SQL.
4 * Originally developed by Thomas Mueller and the Hypersonic SQL Group.
5 *
6 * Copyright (c) 1995-2000 by the Hypersonic SQL Group. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without modification, are permitted
8 * provided that the following conditions are met:
9 * - Redistributions of source code must retain the above copyright notice, this list of conditions
10 * and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright notice, this list of
12 * conditions and the following disclaimer in the documentation and/or other materials
13 * provided with the distribution.
14 * - All advertising materials mentioning features or use of this software must display the
15 * following acknowledgment: "This product includes Hypersonic SQL."
16 * - Products derived from this software may not be called "Hypersonic SQL" nor may
17 * "Hypersonic SQL" appear in their names without prior written permission of the
18 * Hypersonic SQL Group.
19 * - Redistributions of any form whatsoever must retain the following acknowledgment: "This
20 * product includes Hypersonic SQL."
21 * This software is provided "as is" and any expressed or implied warranties, including, but
22 * not limited to, the implied warranties of merchantability and fitness for a particular purpose are
23 * disclaimed. In no event shall the Hypersonic SQL Group or its contributors be liable for any
24 * direct, indirect, incidental, special, exemplary, or consequential damages (including, but
25 * not limited to, procurement of substitute goods or services; loss of use, data, or profits;
26 * or business interruption). However caused any on any theory of liability, whether in contract,
27 * strict liability, or tort (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 * This software consists of voluntary contributions made by many individuals on behalf of the
30 * Hypersonic SQL Group.
31 *
32 *
33 * For work added by the HSQL Development Group:
34 *
35 * Copyright (c) 2001-2002, The HSQL Development Group
36 * All rights reserved.
37 *
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions are met:
40 *
41 * Redistributions of source code must retain the above copyright notice, this
42 * list of conditions and the following disclaimer, including earlier
43 * license statements (above) and comply with all above license conditions.
44 *
45 * Redistributions in binary form must reproduce the above copyright notice,
46 * this list of conditions and the following disclaimer in the documentation
47 * and/or other materials provided with the distribution, including earlier
48 * license statements (above) and comply with all above license conditions.
49 *
50 * Neither the name of the HSQL Development Group nor the names of its
51 * contributors may be used to endorse or promote products derived from this
52 * software without specific prior written permission.
53 *
54 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
55 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
56 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
57 * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
58 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
59 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
60 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
61 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
62 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
63 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
64 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
65 */
66
67
68 package org.hsqldb;
69
70 import java.sql.SQLException;
71 import java.util.Hashtable;
72 import java.util.Vector;
73
74 // fredt@users 20020320 - doc 1.7.0 - update
75 // fredt@users 20020315 - patch 1.7.0 by fredt - switch for scripting
76 // fredt@users 20020130 - patch 476694 by velichko - transaction savepoints
77 // additions in different parts to support savepoint transactions
78 // fredt@users 20020910 - patch 1.7.1 by fredt - database readonly enforcement
79 // fredt@users 20020912 - patch 1.7.1 by fredt - permanent internal connection
80
81 /**
82 * Implementation of a user session with the database.
83 *
84 * @version 1.7.0
85 */
86 class Session {
87
88 private Database dDatabase;
89 private User uUser;
90 private Vector tTransaction;
91 private boolean bAutoCommit;
92 private boolean bNestedTransaction;
93 private boolean bNestedOldAutoCommit;
94 private int iNestedOldTransIndex;
95 private boolean bReadOnly;
96 private int iMaxRows;
97 private int iLastIdentity;
98 private boolean bClosed;
99 private int iId;
100 private Hashtable hSavepoints;
101 private boolean script;
102 private jdbcConnection intConnection;
103
104 /**
105 * closes the session.
106 *
107 * @throws SQLException
108 */
109 public void finalize() throws SQLException {
110 disconnect();
111 }
112
113 /**
114 * Constructor declaration
115 *
116 * @param c
117 * @param id
118 */
119 Session(Session c, int id) {
120 this(c.dDatabase, c.uUser, true, c.bReadOnly, id);
121 }
122
123 /**
124 * Constructor declaration
125 *
126 * @param db
127 * @param user
128 * @param autocommit
129 * @param readonly
130 * @param id
131 */
132 Session(Database db, User user, boolean autocommit, boolean readonly,
133 int id) {
134
135 iId = id;
136 dDatabase = db;
137 uUser = user;
138 tTransaction = new Vector();
139 bAutoCommit = autocommit;
140 bReadOnly = db.bReadOnly || readonly;
141 hSavepoints = new Hashtable();
142 }
143
144 /**
145 * Method declaration
146 *
147 * @return
148 */
149 int getId() {
150 return iId;
151 }
152
153 /**
154 * Method declaration
155 *
156 * @throws SQLException
157 */
158 void disconnect() throws SQLException {
159
160 if (bClosed) {
161 return;
162 }
163
164 rollback();
165 this.dDatabase.dropTempTables(this);
166
167 dDatabase = null;
168 uUser = null;
169 tTransaction = null;
170 hSavepoints = null;
171 intConnection = null;
172 bClosed = true;
173 }
174
175 /**
176 * Method declaration
177 *
178 * @return
179 */
180 boolean isClosed() {
181 return bClosed;
182 }
183
184 /**
185 * Method declaration
186 *
187 * @param i
188 */
189 void setLastIdentity(int i) {
190 iLastIdentity = i;
191 }
192
193 /**
194 * Method declaration
195 *
196 * @return
197 */
198 int getLastIdentity() {
199 return iLastIdentity;
200 }
201
202 /**
203 * Method declaration
204 *
205 * @return
206 */
207 Database getDatabase() {
208 return dDatabase;
209 }
210
211 /**
212 * Method declaration
213 *
214 * @return
215 */
216 String getUsername() {
217 return uUser.getName();
218 }
219
220 /**
221 * Method declaration
222 *
223 * @param user
224 */
225 void setUser(User user) {
226 uUser = user;
227 }
228
229 /**
230 * Method declaration
231 *
232 * @throws SQLException
233 */
234 void checkAdmin() throws SQLException {
235 uUser.checkAdmin();
236 }
237
238 /**
239 * Method declaration
240 *
241 * @param object
242 * @param right
243 * @throws SQLException
244 */
245 void check(String object, int right) throws SQLException {
246 uUser.check(object, right);
247 }
248
249 /**
250 * Method declaration
251 *
252 * @throws SQLException
253 */
254 void checkReadWrite() throws SQLException {
255 Trace.check(!bReadOnly, Trace.DATABASE_IS_READONLY);
256 }
257
258 /**
259 * Method declaration
260 *
261 * @param s
262 */
263 void setPassword(String s) {
264 uUser.setPassword(s);
265 }
266
267 /**
268 * Method declaration
269 *
270 * @param table
271 * @param row
272 * @throws SQLException
273 */
274 void addTransactionDelete(Table table, Object row[]) throws SQLException {
275
276 if (!bAutoCommit) {
277 Transaction t = new Transaction(true, table, row);
278
279 tTransaction.addElement(t);
280 }
281 }
282
283 /**
284 * Method declaration
285 *
286 * @param table
287 * @param row
288 * @throws SQLException
289 */
290 void addTransactionInsert(Table table, Object row[]) throws SQLException {
291
292 if (!bAutoCommit) {
293 Transaction t = new Transaction(false, table, row);
294
295 tTransaction.addElement(t);
296 }
297 }
298
299 /**
300 * Method declaration
301 *
302 * @param autocommit
303 * @throws SQLException
304 */
305 void setAutoCommit(boolean autocommit) throws SQLException {
306
307 commit();
308
309 bAutoCommit = autocommit;
310 }
311
312 /**
313 * Method declaration
314 *
315 * @throws SQLException
316 */
317 void commit() throws SQLException {
318 tTransaction.removeAllElements();
319 hSavepoints.clear();
320 }
321
322 /**
323 * Method declaration
324 *
325 * @throws SQLException
326 */
327 void rollback() throws SQLException {
328
329 for (int i = tTransaction.size() - 1; i >= 0; i--) {
330 Transaction t = (Transaction) tTransaction.elementAt(i);
331
332 t.rollback();
333 }
334
335 tTransaction.removeAllElements();
336 hSavepoints.clear();
337 }
338
339 /**
340 * Implements a transaction SAVEPOIINT. Application may do a partial
341 * rollback by calling rollbackToSavepoint()
342 *
343 * @param name Name of savepoint
344 * @throws SQLException
345 */
346 void savepoint(String name) throws SQLException {
347 hSavepoints.put(name, new Integer(tTransaction.size()));
348 }
349
350 /**
351 * Implements a partial transaction ROLLBACK.
352 *
353 * @param name Name of savepoint that was marked before by savepoint()
354 * call
355 * @throws SQLException
356 */
357 void rollbackToSavepoint(String name) throws SQLException {
358
359 Integer idx = (Integer) hSavepoints.get(name);
360
361 Trace.check(idx != null, Trace.SAVEPOINT_NOT_FOUND, name);
362
363 for (int i = tTransaction.size() - 1; i >= idx.intValue(); i--) {
364 Transaction t = (Transaction) tTransaction.elementAt(i);
365
366 t.rollback();
367 tTransaction.removeElementAt(i);
368 }
369
370 hSavepoints.remove(name);
371 }
372
373 /**
374 * Method declaration
375 *
376 * @throws SQLException
377 */
378 void beginNestedTransaction() throws SQLException {
379
380 Trace.doAssert(!bNestedTransaction, "beginNestedTransaction");
381
382 bNestedOldAutoCommit = bAutoCommit;
383
384 // now all transactions are logged
385 bAutoCommit = false;
386 iNestedOldTransIndex = tTransaction.size();
387 bNestedTransaction = true;
388 }
389
390 /**
391 * Method declaration
392 *
393 * @param rollback
394 * @throws SQLException
395 */
396 void endNestedTransaction(boolean rollback) throws SQLException {
397
398 Trace.doAssert(bNestedTransaction, "endNestedTransaction");
399
400 if (rollback) {
401 for (int i = tTransaction.size() - 1; i >= iNestedOldTransIndex;
402 i--) {
403 Transaction t = (Transaction) tTransaction.elementAt(i);
404
405 t.rollback();
406 }
407 }
408
409 bNestedTransaction = false;
410 bAutoCommit = bNestedOldAutoCommit;
411
412 if (bAutoCommit == true) {
413 tTransaction.setSize(iNestedOldTransIndex);
414 }
415 }
416
417 /**
418 * Method declaration
419 *
420 * @param readonly
421 */
422 void setReadOnly(boolean readonly) {
423 bReadOnly = readonly;
424 }
425
426 /**
427 * Method declaration
428 *
429 * @return
430 */
431 boolean isReadOnly() {
432 return bReadOnly || dDatabase.bReadOnly;
433 }
434
435 /**
436 * Method declaration
437 *
438 * @param max
439 */
440 void setMaxRows(int max) {
441 iMaxRows = max;
442 }
443
444 /**
445 * Method declaration
446 *
447 * @return
448 */
449 int getMaxRows() {
450 return iMaxRows;
451 }
452
453 /**
454 * Method declaration
455 *
456 * @return
457 */
458 boolean isNestedTransaction() {
459 return bNestedTransaction;
460 }
461
462 /**
463 * Method declaration
464 *
465 * @return
466 */
467 boolean getAutoCommit() {
468 return bAutoCommit;
469 }
470
471 /**
472 * A switch to set scripting on the basis of type of statement executed.
473 * A method in Database.jave sets this value to false before other
474 * methods are called to act on an SQL statement, which may set this to
475 * true. Afterwards the method reponsible for logging uses
476 * getScripting() to determine if logging is required for the executed
477 * statement. (fredt@users)
478 *
479 * @param script The new scripting value
480 */
481 void setScripting(boolean script) {
482 this.script = script;
483 }
484
485 /**
486 * @return scripting for the last statement.
487 */
488 boolean getScripting() {
489 return script;
490 }
491
492 /**
493 * @return scripting for the last statement.
494 */
495 jdbcConnection getInternalConnection() throws SQLException {
496
497 if (intConnection == null) {
498 intConnection = new jdbcConnection(this);
499 }
500
501 return intConnection;
502 }
503 }