KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hsqldb > Database


1 /* Copyright (c) 1995-2000, The Hypersonic SQL 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 Hypersonic SQL 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 THE HYPERSONIC SQL GROUP,
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  * This software consists of voluntary contributions made by many individuals
31  * on behalf of the Hypersonic SQL Group.
32  *
33  *
34  * For work added by the HSQL Development Group:
35  *
36  * Copyright (c) 2001-2005, The HSQL Development Group
37  * All rights reserved.
38  *
39  * Redistribution and use in source and binary forms, with or without
40  * modification, are permitted provided that the following conditions are met:
41  *
42  * Redistributions of source code must retain the above copyright notice, this
43  * list of conditions and the following disclaimer.
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.
48  *
49  * Neither the name of the HSQL Development Group nor the names of its
50  * contributors may be used to endorse or promote products derived from this
51  * software without specific prior written permission.
52  *
53  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
54  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56  * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
57  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
58  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
59  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
60  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
61  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
62  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
63  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
64  */

65
66
67 package org.hsqldb;
68
69 import java.lang.reflect.Constructor JavaDoc;
70
71 import org.hsqldb.lib.FileAccess;
72 import org.hsqldb.lib.FileUtil;
73 import org.hsqldb.lib.HashMap;
74 import org.hsqldb.persist.HsqlDatabaseProperties;
75 import org.hsqldb.persist.HsqlProperties;
76 import org.hsqldb.persist.Logger;
77
78 // fredt@users 20020130 - patch 476694 by velichko - transaction savepoints
79
// additions to different parts to support savepoint transactions
80
// fredt@users 20020215 - patch 1.7.0 - new HsqlProperties class
81
// support use of properties from database.properties file
82
// fredt@users 20020218 - patch 1.7.0 - DEFAULT keyword
83
// support for default values for table columns
84
// fredt@users 20020305 - patch 1.7.0 - restructuring
85
// some methods move to Table.java, some removed
86
// fredt@users 20020221 - patch 513005 by sqlbob@users (RMP) - restructuring
87
// fredt@users 20020221 - patch 513005 by sqlbob@users (RMP) - error trapping
88
// boucherb@users 20020130 - patch 1.7.0 - use lookup for speed
89
// idents listed in alpha-order for easy check of stats...
90
// fredt@users 20020420 - patch523880 by leptipre@users - VIEW support
91
// boucherb@users - doc 1.7.0 - added javadoc comments
92
// tony_lai@users 20020820 - patch 595073 - duplicated exception msg
93
// tony_lai@users 20020820 - changes to shutdown compact to save memory
94
// boucherb@users 20020828 - allow reconnect to local db that has shutdown
95
// fredt@users 20020912 - patch 1.7.1 by fredt - drop duplicate name triggers
96
// fredt@users 20021112 - patch 1.7.2 by Nitin Chauhan - use of switch
97
// rewrite of the majority of multiple if(){}else if(){} chains with switch()
98
// boucherb@users 20020310 - class loader update for JDK 1.1 compliance
99
// fredt@users 20030401 - patch 1.7.2 by akede@users - data files readonly
100
// fredt@users 20030401 - patch 1.7.2 by Brendan Ryan - data files in Jar
101
// boucherb@users 20030405 - removed 1.7.2 lint - updated JavaDocs
102
// boucherb@users 20030425 - DDL methods are moved to DatabaseCommandInterpreter.java
103
// boucherb@users - fredt@users 200305..200307 - patch 1.7.2 - DatabaseManager upgrade
104
// loosecannon1@users - patch 1.7.2 - properties on the JDBC URL
105
// oj@openoffice.org - changed to file access api
106

107 /**
108  * Database is the root class for HSQL Database Engine database. <p>
109  *
110  * It holds the data structure that form an HSQLDB database instance.
111  *
112  * Modified significantly from the Hypersonic original in successive
113  * HSQLDB versions.
114  *
115  * @author Thomas Mueller (Hypersonic SQL Group)
116  * @version 1.8.0
117  * @since Hypersonic SQL
118  */

119 public class Database {
120
121     int databaseID;
122     String JavaDoc sType;
123     String JavaDoc sName;
124
125 // loosecannon1@users 1.7.2 patch properties on the JDBC URL
126
private HsqlProperties urlProperties;
127     private String JavaDoc sPath;
128     DatabaseInformation dbInfo;
129     ClassLoader JavaDoc classLoader;
130
131     /** indicates the state of the database */
132     private int dbState;
133     public Logger logger;
134
135     /** true means that all tables are readonly. */
136     boolean databaseReadOnly;
137
138     /**
139      * true means that all CACHED and TEXT tables are readonly.
140      * MEMORY tables are updatable but updates are not persisted.
141      */

142     private boolean filesReadOnly;
143
144     /** true means filesReadOnly but CACHED and TEXT tables are disallowed */
145     private boolean filesInJar;
146     public boolean sqlEnforceStrictSize;
147     public int firstIdentity;
148     private boolean bIgnoreCase;
149     private boolean bReferentialIntegrity;
150     private HsqlDatabaseProperties databaseProperties;
151     private boolean shutdownOnNoConnection;
152
153     // schema invarient objects
154
private HashMap hAlias;
155     public UserManager userManager;
156     public GranteeManager granteeManager;
157     public HsqlNameManager nameManager;
158
159     // session related objects
160
public SessionManager sessionManager;
161     public TransactionManager txManager;
162     CompiledStatementManager compiledStatementManager;
163
164     // schema objects
165
public SchemaManager schemaManager;
166     public Collation collation;
167
168     //
169
public static final int DATABASE_ONLINE = 1;
170     public static final int DATABASE_OPENING = 4;
171     public static final int DATABASE_CLOSING = 8;
172     public static final int DATABASE_SHUTDOWN = 16;
173     public static final int CLOSEMODE_IMMEDIATELY = -1;
174     public static final int CLOSEMODE_NORMAL = 0;
175     public static final int CLOSEMODE_COMPACT = 1;
176     public static final int CLOSEMODE_SCRIPT = 2;
177
178     /**
179      * Constructs a new Database object.
180      *
181      * @param type is the type of the database: "mem", "file", "res"
182      * @param path is the fiven path to the database files
183      * @param name is the combination of type and canonical path
184      * @param props property overrides placed on the connect URL
185      * @exception HsqlException if the specified name and path
186      * combination is illegal or unavailable, or the database files the
187      * name and path resolves to are in use by another process
188      */

189     Database(String JavaDoc type, String JavaDoc path, String JavaDoc name,
190              HsqlProperties props) throws HsqlException {
191
192         urlProperties = props;
193
194         setState(Database.DATABASE_SHUTDOWN);
195
196         sName = name;
197         sType = type;
198         sPath = path;
199
200         if (sType == DatabaseURL.S_RES) {
201             filesInJar = true;
202             filesReadOnly = true;
203         }
204
205         // does not need to be done more than once
206
try {
207             classLoader = getClass().getClassLoader();
208         } catch (Exception JavaDoc e) {
209
210             // strict security policy: just use the system/boot loader
211
classLoader = null;
212         }
213
214 // oj@openoffice.org - changed to file access api
215
String JavaDoc fileaccess_class_name =
216             (String JavaDoc) urlProperties.getProperty("fileaccess_class_name");
217
218         if (fileaccess_class_name != null) {
219             String JavaDoc storagekey = urlProperties.getProperty("storage_key");
220
221             try {
222                 Class JavaDoc zclass = Class.forName(fileaccess_class_name);
223                 Constructor JavaDoc constructor = zclass.getConstructor(new Class JavaDoc[]{
224                     Object JavaDoc.class });
225
226                 fileaccess =
227                     (FileAccess) constructor.newInstance(new Object JavaDoc[]{
228                         storagekey });
229                 isStoredFileAccess = true;
230             } catch (java.lang.ClassNotFoundException JavaDoc e) {
231                 System.out.println("ClassNotFoundException");
232             } catch (java.lang.InstantiationException JavaDoc e) {
233                 System.out.println("InstantiationException");
234             } catch (java.lang.IllegalAccessException JavaDoc e) {
235                 System.out.println("IllegalAccessException");
236             } catch (Exception JavaDoc e) {
237                 System.out.println("Exception");
238             }
239         } else {
240             fileaccess = FileUtil.getDefaultInstance();
241         }
242
243         shutdownOnNoConnection = urlProperties.getProperty("shutdown",
244                 "false").equals("true");
245         logger = new Logger();
246         compiledStatementManager = new CompiledStatementManager(this);
247     }
248
249     /**
250      * Opens this database. The database should be opened after construction.
251      */

252     synchronized void open() throws HsqlException {
253
254         if (!isShutdown()) {
255             return;
256         }
257
258         reopen();
259     }
260
261     /**
262      * Opens this database. The database should be opened after construction.
263      * or reopened by the close(int closemode) method during a
264      * "shutdown compact". Closes the log if there is an error.
265      */

266     void reopen() throws HsqlException {
267
268         boolean isNew;
269
270         setState(DATABASE_OPENING);
271
272         try {
273             databaseProperties = new HsqlDatabaseProperties(this);
274             isNew = !DatabaseURL.isFileBasedDatabaseType(sType)
275                     ||!databaseProperties.checkFileExists();
276
277             if (isNew && urlProperties.isPropertyTrue("ifexists")) {
278                 throw Trace.error(Trace.DATABASE_NOT_EXISTS, sName);
279             }
280
281             databaseProperties.load();
282             databaseProperties.setURLProperties(urlProperties);
283             compiledStatementManager.reset();
284
285             nameManager = new HsqlNameManager();
286             granteeManager = new GranteeManager(this);
287             userManager = new UserManager(this);
288             hAlias = Library.getAliasMap();
289             schemaManager = new SchemaManager(this);
290             bReferentialIntegrity = true;
291             sessionManager = new SessionManager(this);
292             txManager = new TransactionManager(this);
293             collation = new Collation();
294             dbInfo = DatabaseInformation.newDatabaseInformation(this);
295
296             databaseProperties.setDatabaseVariables();
297
298             if (DatabaseURL.isFileBasedDatabaseType(sType)) {
299                 logger.openLog(this);
300             }
301
302             if (isNew) {
303                 sessionManager.getSysSession().sqlExecuteDirectNoPreChecks(
304                     "CREATE USER SA PASSWORD \"\" ADMIN");
305                 logger.synchLogForce();
306             }
307
308             dbInfo.setWithContent(true);
309         } catch (Throwable JavaDoc e) {
310             logger.closeLog(Database.CLOSEMODE_IMMEDIATELY);
311             logger.releaseLock();
312             setState(DATABASE_SHUTDOWN);
313             clearStructures();
314             DatabaseManager.removeDatabase(this);
315
316             if (!(e instanceof HsqlException)) {
317                 e = Trace.error(Trace.GENERAL_ERROR, e.toString());
318             }
319
320             throw (HsqlException) e;
321         }
322
323         setState(DATABASE_ONLINE);
324     }
325
326     /**
327      * Clears the data structuress, making them elligible for garbage collection.
328      */

329     void clearStructures() {
330
331         if (schemaManager != null) {
332             schemaManager.clearStructures();
333         }
334
335         granteeManager = null;
336         userManager = null;
337         hAlias = null;
338         nameManager = null;
339         schemaManager = null;
340         sessionManager = null;
341         dbInfo = null;
342     }
343
344     /**
345      * Returns the type of the database: "mem", "file", "res"
346      */

347     public String JavaDoc getType() {
348         return sType;
349     }
350
351     /**
352      * Returns the path of the database
353      */

354     public String JavaDoc getPath() {
355         return sPath;
356     }
357
358     /**
359      * Returns the database properties.
360      */

361     public HsqlDatabaseProperties getProperties() {
362         return databaseProperties;
363     }
364
365     /**
366      * Returns the SessionManager for the database.
367      */

368     public SessionManager getSessionManager() {
369         return sessionManager;
370     }
371
372     /**
373      * Returns true if database has been shut down, false otherwise
374      */

375     synchronized boolean isShutdown() {
376         return dbState == DATABASE_SHUTDOWN;
377     }
378
379     /**
380      * Constructs a new Session that operates within (is connected to) the
381      * context of this Database object. <p>
382      *
383      * If successful, the new Session object initially operates on behalf of
384      * the user specified by the supplied user name.
385      *
386      * Throws if username or password is invalid.
387      */

388     synchronized Session connect(String JavaDoc username,
389                                  String JavaDoc password) throws HsqlException {
390
391         User user = userManager.getUser(username, password);
392         Session session = sessionManager.newSession(this, user,
393             databaseReadOnly, false);
394
395         logger.logConnectUser(session);
396
397         return session;
398     }
399
400     /**
401      * Puts this Database object in global read-only mode. After
402      * this call, all existing and future sessions are limited to read-only
403      * transactions. Any following attempts to update the state of the
404      * database will result in throwing an HsqlException.
405      */

406     public void setReadOnly() {
407         databaseReadOnly = true;
408         filesReadOnly = true;
409     }
410
411     /**
412      * After this call all CACHED and TEXT tables will be set to read-only
413      * mode. Changes to MEMORY tables will NOT
414      * be stored or updated in the script file. This mode is intended for
415      * use with read-only media where data should not be persisted.
416      */

417     public void setFilesReadOnly() {
418         filesReadOnly = true;
419     }
420
421     /**
422      * Is this in filesReadOnly mode?
423      */

424     public boolean isFilesReadOnly() {
425         return filesReadOnly;
426     }
427
428     /**
429      * Is this in filesInJar mode?
430      */

431     public boolean isFilesInJar() {
432         return filesInJar;
433     }
434
435     /**
436      * Returns the UserManager for this Database.
437      */

438     UserManager getUserManager() {
439         return userManager;
440     }
441
442     /**
443      * Returns the GranteeManager for this Database.
444      */

445     GranteeManager getGranteeManager() {
446         return granteeManager;
447     }
448
449     /**
450      * Sets the isReferentialIntegrity attribute.
451      */

452     public void setReferentialIntegrity(boolean ref) {
453         bReferentialIntegrity = ref;
454     }
455
456     /**
457      * Is referential integrity currently enforced?
458      */

459     boolean isReferentialIntegrity() {
460         return bReferentialIntegrity;
461     }
462
463     /**
464      * Returns a map from Java method-call name aliases to the
465      * fully-qualified names of the Java methods themsleves.
466      */

467     HashMap getAliasMap() {
468         return hAlias;
469     }
470
471     /**
472      * Returns the fully qualified name for the Java method corresponding to
473      * the given method alias. If there is no Java method, then returns the
474      * alias itself.
475      */

476     String JavaDoc getJavaName(String JavaDoc s) {
477
478         String JavaDoc alias = (String JavaDoc) hAlias.get(s);
479
480         return (alias == null) ? s
481                                : alias;
482     }
483
484     /**
485      * Sets the database to treat any new VARCHAR column declarations as
486      * VARCHAR_IGNORECASE.
487      */

488     void setIgnoreCase(boolean b) {
489         bIgnoreCase = b;
490     }
491
492     /**
493      * Does the database treat any new VARCHAR column declarations as
494      * VARCHAR_IGNORECASE.
495      */

496     boolean isIgnoreCase() {
497         return bIgnoreCase;
498     }
499
500     /**
501      * Obtain default table types from database properties
502      */

503     int getDefaultTableType() {
504
505         String JavaDoc dttName = getProperties().getProperty(
506             HsqlDatabaseProperties.hsqldb_default_table_type);
507
508         return Token.T_CACHED.equalsIgnoreCase(dttName) ? Table.CACHED_TABLE
509                                                         : Table.MEMORY_TABLE;
510     }
511
512     /**
513      * Called by the garbage collector on this Databases object when garbage
514      * collection determines that there are no more references to it.
515      */

516     protected void finalize() {
517
518         if (getState() != DATABASE_ONLINE) {
519             return;
520         }
521
522         try {
523             close(CLOSEMODE_IMMEDIATELY);
524         } catch (HsqlException e) { // it's too late now
525
}
526     }
527
528     void closeIfLast() {
529
530         if (shutdownOnNoConnection && sessionManager.isEmpty()
531                 && dbState == this.DATABASE_ONLINE) {
532             try {
533                 close(CLOSEMODE_NORMAL);
534             } catch (HsqlException e) {}
535         }
536     }
537
538     /**
539      * Closes this Database using the specified mode. <p>
540      *
541      * <ol>
542      * <LI> closemode -1 performs SHUTDOWN IMMEDIATELY, equivalent
543      * to a poweroff or crash.
544      *
545      * <LI> closemode 0 performs a normal SHUTDOWN that
546      * checkpoints the database normally.
547      *
548      * <LI> closemode 1 performs a shutdown compact that scripts
549      * out the contents of any CACHED tables to the log then
550      * deletes the existing *.data file that contains the data
551      * for all CACHED table before the normal checkpoint process
552      * which in turn creates a new, compact *.data file.
553      * </ol>
554      */

555     void close(int closemode) throws HsqlException {
556
557         HsqlException he = null;
558
559         setState(DATABASE_CLOSING);
560         sessionManager.closeAllSessions();
561         sessionManager.clearAll();
562
563         if (filesReadOnly) {
564             closemode = CLOSEMODE_IMMEDIATELY;
565         }
566
567         // fredt - impact of possible error conditions in closing the log
568
// should be investigated for the CLOSEMODE_COMPACT mode
569
logger.closeLog(closemode);
570
571         try {
572             if (closemode == CLOSEMODE_COMPACT) {
573                 clearStructures();
574                 reopen();
575                 setState(DATABASE_CLOSING);
576                 logger.closeLog(CLOSEMODE_NORMAL);
577             }
578         } catch (Throwable JavaDoc t) {
579             if (t instanceof HsqlException) {
580                 he = (HsqlException) t;
581             } else {
582                 he = Trace.error(Trace.GENERAL_ERROR, t.toString());
583             }
584         }
585
586         classLoader = null;
587
588         logger.releaseLock();
589         setState(DATABASE_SHUTDOWN);
590         clearStructures();
591
592         // fredt - this could change to avoid removing a db from the
593
// DatabaseManager repository if there are pending getDatabase()
594
// calls
595
DatabaseManager.removeDatabase(this);
596
597         if (he != null) {
598             throw he;
599         }
600     }
601
602     /**
603      * Ensures system table producer's table cache, if it exists, is set dirty.
604      * After this call up-to-date versions are generated in response to
605      * system table requests. <p>
606      *
607      * Also resets all prepared statements if a change to database structure
608      * can possibly affect any existing prepared statement's validity.<p>
609      *
610      * The argument is false if the change to the database structure does not
611      * affect the prepared statement, such as when a new table is added.<p>
612      *
613      * The argument is typically true when a database object is dropped,
614      * altered or a permission was revoked.
615      *
616      * @param resetPrepared If true, reset all prepared statements.
617      */

618     public void setMetaDirty(boolean resetPrepared) {
619
620         if (dbInfo != null) {
621             dbInfo.setDirty();
622         }
623
624         if (resetPrepared) {
625             compiledStatementManager.resetStatements();
626         }
627     }
628
629     private synchronized void setState(int state) {
630         dbState = state;
631     }
632
633     synchronized int getState() {
634         return dbState;
635     }
636
637     String JavaDoc getStateString() {
638
639         int state = getState();
640
641         switch (state) {
642
643             case DATABASE_CLOSING :
644                 return "DATABASE_CLOSING";
645
646             case DATABASE_ONLINE :
647                 return "DATABASE_ONLINE";
648
649             case DATABASE_OPENING :
650                 return "DATABASE_OPENING";
651
652             case DATABASE_SHUTDOWN :
653                 return "DATABASE_SHUTDOWN";
654
655             default :
656                 return "UNKNOWN";
657         }
658     }
659
660 // boucherb@users - 200403?? - patch 1.7.2 - metadata
661
//------------------------------------------------------------------------------
662

663     /**
664      * Retrieves the uri portion of this object's in-process JDBC url.
665      *
666      * @return the uri portion of this object's in-process JDBC url
667      */

668     public String JavaDoc getURI() {
669         return sName;
670     }
671
672 // oj@openoffice.org - changed to file access api
673
public HsqlProperties getURLProperties() {
674         return urlProperties;
675     }
676
677     private FileAccess fileaccess;
678     private boolean isStoredFileAccess;
679
680     public synchronized FileAccess getFileAccess() {
681         return fileaccess;
682     }
683
684     public synchronized boolean isStoredFileAccess() {
685         return isStoredFileAccess;
686     }
687 }
688
Popular Tags