KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > smallsql > database > Database


1 /* =============================================================
2  * SmallSQL : a free Java DBMS library for the Java(tm) platform
3  * =============================================================
4  *
5  * (C) Copyright 2004-2006, by Volker Berlin.
6  *
7  * Project Info: http://www.smallsql.de/
8  *
9  * This library is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU Lesser General Public License as published by
11  * the Free Software Foundation; either version 2.1 of the License, or
12  * (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17  * License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
22  * USA.
23  *
24  * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
25  * in the United States and other countries.]
26  *
27  * ---------------
28  * Database.java
29  * ---------------
30  * Author: Volker Berlin
31  *
32  */

33 package smallsql.database;
34
35 import java.util.*;
36 import java.io.*;
37 import java.sql.*;
38
39
40 final class Database {
41
42     /*
43     Es gibt nur eine Instance dieser Klasse pro Datenbank. Sie wird geschert zwischen
44     allen Connections zu dieser Datenbank und allen Threads. Deshalb muß der Zugriff
45     auf diese Klasse Thread sicher sein.
46
47     Hier werden vor allem Table Definitionen und Locks gespeichert.
48     */

49
50     static private HashMap databases = new HashMap();
51
52     final private HashMap tableViews = new HashMap();
53     private String JavaDoc name;
54     private File directory;
55     private RandomAccessFile master;
56     final private WeakHashMap connections = new WeakHashMap();
57
58
59     /**
60      * Get a instance of the Database Class. If the Datbase with the given name is not open
61      * then it will be open.
62      */

63     static Database getDatabase( String JavaDoc name, SSConnection con, boolean create ) throws SQLException{
64         if(name == null) return null;
65         if(name.startsWith("file:"))
66             name = name.substring(5);
67         if(File.separatorChar == '\\')
68             name = name.replace( '/', File.separatorChar);
69         else
70             name = name.replace( '\\', File.separatorChar);
71         synchronized(databases){
72             Database db = (Database)databases.get(name);
73             if(db == null){
74                 if(create && !new File(name).isDirectory()){
75                     CommandCreateDatabase command = new CommandCreateDatabase(con.log,name);
76                     command.execute(con,null);
77                 }
78                 db = new Database(name);
79                 databases.put( name, db);
80             }
81             db.connections.put(con, null);
82             return db;
83         }
84     }
85     
86     
87     private static Database getDatabase(SSConnection con, String JavaDoc name) throws SQLException{
88         return name == null ?
89                     con.getDatabase(false) :
90                     getDatabase( name, con, false );
91     }
92     
93
94     private Database(String JavaDoc name ) throws SQLException{
95         try{
96             this.name = name;
97             directory = new File(name);
98             if(!directory.isDirectory()){
99                 throw Utils.createSQLException("Database '" + name + "' does not exists.");
100             }
101             directory = directory.getAbsoluteFile();
102             File file = new File( directory, Utils.MASTER_FILENAME);
103             if(!file.exists())
104                 throw Utils.createSQLException("Directory '" + name + "' is not a SmallSQL database.");
105             master = new RandomAccessFile( file, "rw");
106         }catch(Exception JavaDoc e){
107             throw Utils.createSQLException(e);
108         }
109     }
110
111     String JavaDoc getName(){
112         return name;
113     }
114     
115     
116     
117
118     /**
119      * Remove a connection from this database.
120      */

121     static final void closeConnection(SSConnection con) throws SQLException{
122         synchronized(databases){
123             Iterator iterator = databases.values().iterator();
124             while(iterator.hasNext()){
125                 Database database = (Database)iterator.next();
126                 WeakHashMap connections = database.connections;
127                 connections.remove(con);
128                 if(connections.size() == 0){
129                     try {
130                         iterator.remove();
131                         database.close();
132                     } catch (Exception JavaDoc e) {
133                         throw Utils.createSQLException(e);
134                     }
135                 }
136             }
137         }
138     }
139     
140
141     /**
142      * Close all tables and views of this Database.
143      */

144     private final void close() throws Exception JavaDoc{
145         synchronized(tableViews){
146             Iterator iterator = tableViews.values().iterator();
147             while(iterator.hasNext()){
148                 TableView tableView = (TableView)iterator.next();
149                 tableView.close();
150                 iterator.remove();
151             }
152         }
153         master.close();
154     }
155     
156     static TableView getTableView(SSConnection con, String JavaDoc catalog, String JavaDoc tableName) throws SQLException{
157         return getDatabase( con, catalog).getTableView( con, tableName);
158     }
159
160     
161     /**
162      * Return a TableView object. If the TableView object is not loaded then it load it.
163      * @param con
164      * @param tableName
165      * @return ever a valid TableView object and never null.
166      * @throws SQLException if the table or view does not exists
167      */

168     TableView getTableView(SSConnection con, String JavaDoc tableName) throws SQLException{
169         synchronized(tableViews){
170             TableView tableView = (TableView)tableViews.get(tableName);
171             if(tableView == null){
172                 // FIXME hier sollt nur die eine Tabelle gelockt sein und nicht alle Tabellen, Tabelle lesen sollte auserhalb des globalen syn sein.
173
tableView = TableView.load(con, this, tableName);
174                 tableViews.put( tableName, tableView);
175             }
176             return tableView;
177         }
178     }
179     
180
181     static void dropTable(SSConnection con, String JavaDoc catalog, String JavaDoc tableName) throws Exception JavaDoc{
182         getDatabase( con, catalog).dropTable( con, tableName);
183     }
184     
185
186     void dropTable(SSConnection con, String JavaDoc tableName) throws Exception JavaDoc{
187         synchronized(tableViews){
188             Table table = (Table)tableViews.get( tableName );
189             if(table != null){
190                 tableViews.remove( tableName );
191                 table.drop(con);
192             }else{
193                 Table.drop( this, tableName );
194             }
195         }
196     }
197     
198
199     static void dropView(SSConnection con, String JavaDoc catalog, String JavaDoc tableName) throws Exception JavaDoc{
200         getDatabase( con, catalog).dropView(tableName);
201     }
202     
203
204     void dropView(String JavaDoc viewName) throws Exception JavaDoc{
205         synchronized(tableViews){
206             Object JavaDoc view = tableViews.remove( viewName );
207             if(view != null && !(view instanceof View))
208                 throw Utils.createSQLException("Cannot use DROP VIEW with '" + viewName + "' because it does not is a view.");
209             
210             View.drop( this, viewName );
211         }
212     }
213     
214
215     /**
216      * @param con current Connections
217      * @param name the name of the new Table
218      * @param columns the column descriptions of the table
219      * @param indexes the indexes of the new table
220      * @param foreignKeys
221      * @throws Exception
222      */

223     void createTable(SSConnection con, String JavaDoc name, Columns columns, IndexDescriptions indexes, ForeignKeys foreignKeys) throws Exception JavaDoc{
224         // createFile() can run only one Thread success (it is atomic)
225
// Thats the create of the Table does not need in the Synchronized.
226
for(int i=0; i<foreignKeys.size(); i++){
227             ForeignKey foreignKey = foreignKeys.get(i);
228             TableView pkTable = getTableView(con, foreignKey.pkTable);
229             if(!(pkTable instanceof Table)){
230                 throw Utils.createSQLException("'" + foreignKey.pkTable +"' is not a table.");
231             }
232         }
233         Table table = new Table( this, con, name, columns, indexes, foreignKeys);
234         synchronized(tableViews){
235             tableViews.put( name, table);
236         }
237     }
238
239
240     void createView(String JavaDoc name, String JavaDoc sql) throws Exception JavaDoc{
241         // createFile() can run only one Thread success (it is atomic)
242
// Thats the create of the View does not need in the Synchronized.
243
new View( this, name, sql);
244     }
245
246
247     /**
248      * Create a list of all available Databases from the point of the current
249      * Database or current working directory
250      * @param database - current database
251      * @return
252      */

253     static Object JavaDoc[][] getCatalogs(Database database){
254         List catalogs = new ArrayList();
255         File baseDir = (database != null) ?
256                         database.directory.getParentFile() :
257                         new File(".");
258         File dirs[] = baseDir.listFiles();
259         if(dirs != null)
260             for(int i=0; i<dirs.length; i++){
261                 if(dirs[i].isDirectory()){
262                     if(new File(dirs[i], Utils.MASTER_FILENAME).exists()){
263                         Object JavaDoc[] catalog = new Object JavaDoc[1];
264                         catalog[0] = dirs[i].getPath();
265                         catalogs.add(catalog);
266                     }
267                 }
268             }
269         Object JavaDoc[][] result = new Object JavaDoc[catalogs.size()][];
270         catalogs.toArray(result);
271         return result;
272     }
273     
274     
275     Strings getTables(String JavaDoc tablePattern){
276         Strings list = new Strings();
277         File dirs[] = directory.listFiles();
278         if(dirs != null)
279             if(tablePattern == null) tablePattern = "%";
280             tablePattern += Utils.TABLE_VIEW_EXTENTION;
281             for(int i=0; i<dirs.length; i++){
282                 String JavaDoc name = dirs[i].getName();
283                 if(Utils.like(name, tablePattern)){
284                     list.add(name.substring( 0, name.length()-Utils.TABLE_VIEW_EXTENTION.length() ));
285                 }
286             }
287         return list;
288     }
289     
290     
291     Object JavaDoc[][] getColumns( SSConnection con, String JavaDoc tablePattern, String JavaDoc colPattern) throws Exception JavaDoc{
292         List rows = new ArrayList();
293         Strings tables = getTables(tablePattern);
294         for(int i=0; i<tables.size(); i++){
295             String JavaDoc tableName = tables.get(i);
296             try{
297                 TableView tab = getTableView( con, tableName);
298                 Columns cols = tab.columns;
299                 for(int c=0; c<cols.size(); c++){
300                     Column col = cols.get(c);
301                     Object JavaDoc[] row = new Object JavaDoc[18];
302                     row[0] = getName(); //TABLE_CAT
303
//TABLE_SCHEM
304
row[2] = tableName; //TABLE_NAME
305
row[3] = col.getName(); //COLUMN_NAME
306
row[4] = Utils.getShort( SQLTokenizer.getSQLDataType( col.getDataType() )); //DATA_TYPE
307
row[5] = SQLTokenizer.getKeyWord( col.getDataType() ); //TYPE_NAME
308
row[6] = Utils.getInteger(col.getColumnSize());//COLUMN_SIZE
309
//BUFFER_LENGTH
310
row[8] = Utils.getInteger(col.getScale());//DECIMAL_DIGITS
311
row[9] = Utils.getInteger(10); //NUM_PREC_RADIX
312
row[10]= Utils.getInteger(col.isNullable() ? DatabaseMetaData.columnNullable : DatabaseMetaData.columnNoNulls); //NULLABLE
313
//REMARKS
314
row[12]= col.getDefaultDefinition(); //COLUMN_DEF
315
//SQL_DATA_TYPE
316
//SQL_DATETIME_SUB
317
row[15]= row[6]; //CHAR_OCTET_LENGTH
318
row[16]= Utils.getInteger(i); //ORDINAL_POSITION
319
row[17]= col.isNullable() ? "YES" : "NO"; //IS_NULLABLE
320
rows.add(row);
321                 }
322             }catch(Exception JavaDoc e){
323                 //invalid Tables and View will not show
324
}
325         }
326         Object JavaDoc[][] result = new Object JavaDoc[rows.size()][];
327         rows.toArray(result);
328         return result;
329     }
330     
331     
332     Object JavaDoc[][] getReferenceKeys(SSConnection con, String JavaDoc pkTable, String JavaDoc fkTable) throws SQLException{
333         List rows = new ArrayList();
334         Strings tables = (pkTable != null) ? getTables(pkTable) : getTables(fkTable);
335         for(int t=0; t<tables.size(); t++){
336             String JavaDoc tableName = tables.get(t);
337             TableView tab = getTableView( con, tableName);
338             if(!(tab instanceof Table)) continue;
339             ForeignKeys references = ((Table)tab).references;
340             for(int i=0; i<references.size(); i++){
341                 ForeignKey foreignKey = references.get(i);
342                 IndexDescription pk = foreignKey.pk;
343                 IndexDescription fk = foreignKey.fk;
344                 if((pkTable == null || pkTable.equals(foreignKey.pkTable)) &&
345                    (fkTable == null || fkTable.equals(foreignKey.fkTable))){
346                     Strings columnsPk = pk.getColumns();
347                     Strings columnsFk = fk.getColumns();
348                     for(int c=0; c<columnsPk.size(); c++){
349                         Object JavaDoc[] row = new Object JavaDoc[14];
350                         row[0] = getName(); //PKTABLE_CAT
351
//PKTABLE_SCHEM
352
row[2] = foreignKey.pkTable; //PKTABLE_NAME
353
row[3] = columnsPk.get(c); //PKCOLUMN_NAME
354
row[4] = getName(); //FKTABLE_CAT
355
//FKTABLE_SCHEM
356
row[6] = foreignKey.fkTable; //FKTABLE_NAME
357
row[7] = columnsFk.get(c); //FKCOLUMN_NAME
358
row[8] = Utils.getShort(c+1); //KEY_SEQ
359
row[9] = Utils.getShort(foreignKey.updateRule);//UPDATE_RULE
360
row[10]= Utils.getShort(foreignKey.deleteRule); //DELETE_RULE
361
row[11]= fk.getName(); //FK_NAME
362
row[12]= pk.getName(); //PK_NAME
363
row[13]= Utils.getShort(DatabaseMetaData.importedKeyNotDeferrable); //DEFERRABILITY
364
rows.add(row);
365                     }
366                 }
367             }
368         }
369         Object JavaDoc[][] result = new Object JavaDoc[rows.size()][];
370         rows.toArray(result);
371         return result;
372     }
373     
374     
375     Object JavaDoc[][] getBestRowIdentifier(SSConnection con, String JavaDoc table) throws SQLException{
376         List rows = new ArrayList();
377         Strings tables = getTables(table);
378         for(int t=0; t<tables.size(); t++){
379             String JavaDoc tableName = tables.get(t);
380             TableView tab = getTableView( con, tableName);
381             if(!(tab instanceof Table)) continue;
382             IndexDescriptions indexes = ((Table)tab).indexes;
383             for(int i=0; i<indexes.size(); i++){
384                 IndexDescription index = indexes.get(i);
385                 if(index.isUnique()){
386                     Strings columns = index.getColumns();
387                     for(int c=0; c<columns.size(); c++){
388                         String JavaDoc columnName = columns.get(c);
389                         Column column = tab.findColumn(columnName);
390                         Object JavaDoc[] row = new Object JavaDoc[8];
391                         row[0] = Utils.getShort(DatabaseMetaData.bestRowSession);//SCOPE
392
row[1] = columnName; //COLUMN_NAME
393
final int dataType = column.getDataType();
394                         row[2] = Utils.getInteger(dataType);//DATA_TYPE
395
row[3] = SQLTokenizer.getKeyWord(dataType);//TYPE_NAME
396
row[4] = Utils.getInteger(column.getPrecision()); //COLUMN_SIZE
397
//BUFFER_LENGTH
398
row[6] = Utils.getShort(column.getScale()); //DECIMAL_DIGITS
399
row[7] = Utils.getShort(DatabaseMetaData.bestRowNotPseudo);//PSEUDO_COLUMN
400
rows.add(row);
401                     }
402                 }
403             }
404         }
405         Object JavaDoc[][] result = new Object JavaDoc[rows.size()][];
406         rows.toArray(result);
407         return result;
408     }
409
410     
411     Object JavaDoc[][] getPrimaryKeys(SSConnection con, String JavaDoc table) throws SQLException{
412         List rows = new ArrayList();
413         Strings tables = getTables(table);
414         for(int t=0; t<tables.size(); t++){
415             String JavaDoc tableName = tables.get(t);
416             TableView tab = getTableView( con, tableName);
417             if(!(tab instanceof Table)) continue;
418             IndexDescriptions indexes = ((Table)tab).indexes;
419             for(int i=0; i<indexes.size(); i++){
420                 IndexDescription index = indexes.get(i);
421                 if(index.isPrimary()){
422                     Strings columns = index.getColumns();
423                     for(int c=0; c<columns.size(); c++){
424                         Object JavaDoc[] row = new Object JavaDoc[6];
425                         row[0] = getName(); //TABLE_CAT
426
//TABLE_SCHEM
427
row[2] = tableName; //TABLE_NAME
428
row[3] = columns.get(c); //COLUMN_NAME
429
row[4] = Utils.getShort(c+1); //KEY_SEQ
430
row[5] = index.getName(); //PK_NAME
431
rows.add(row);
432                     }
433                 }
434             }
435         }
436         Object JavaDoc[][] result = new Object JavaDoc[rows.size()][];
437         rows.toArray(result);
438         return result;
439     }
440     
441     
442     Object JavaDoc[][] getIndexInfo( SSConnection con, String JavaDoc table, boolean unique) throws SQLException {
443         List rows = new ArrayList();
444         Strings tables = getTables(table);
445         Short JavaDoc type = Utils.getShort( DatabaseMetaData.tableIndexOther );
446         for(int t=0; t<tables.size(); t++){
447             String JavaDoc tableName = tables.get(t);
448             TableView tab = getTableView( con, tableName);
449             if(!(tab instanceof Table)) continue;
450             IndexDescriptions indexes = ((Table)tab).indexes;
451             for(int i=0; i<indexes.size(); i++){
452                 IndexDescription index = indexes.get(i);
453                 Strings columns = index.getColumns();
454                 for(int c=0; c<columns.size(); c++){
455                     Object JavaDoc[] row = new Object JavaDoc[13];
456                     row[0] = getName(); //TABLE_CAT
457
//TABLE_SCHEM
458
row[2] = tableName; //TABLE_NAME
459
row[3] = Boolean.valueOf(!index.isUnique());//NON_UNIQUE
460
//INDEX_QUALIFIER
461
row[5] = index.getName(); //INDEX_NAME
462
row[6] = type; //TYPE
463
row[7] = Utils.getShort(c+1); //ORDINAL_POSITION
464
row[8] = columns.get(c); //COLUMN_NAME
465
//ASC_OR_DESC
466
//CARDINALITY
467
//PAGES
468
//FILTER_CONDITION
469
rows.add(row);
470                 }
471             }
472         }
473         Object JavaDoc[][] result = new Object JavaDoc[rows.size()][];
474         rows.toArray(result);
475         return result;
476     }
477 }
Popular Tags