1 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 49 50 static private HashMap databases = new HashMap(); 51 52 final private HashMap tableViews = new HashMap(); 53 private String name; 54 private File directory; 55 private RandomAccessFile master; 56 final private WeakHashMap connections = new WeakHashMap(); 57 58 59 63 static Database getDatabase( String 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 name) throws SQLException{ 88 return name == null ? 89 con.getDatabase(false) : 90 getDatabase( name, con, false ); 91 } 92 93 94 private Database(String 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 e){ 107 throw Utils.createSQLException(e); 108 } 109 } 110 111 String getName(){ 112 return name; 113 } 114 115 116 117 118 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 e) { 133 throw Utils.createSQLException(e); 134 } 135 } 136 } 137 } 138 } 139 140 141 144 private final void close() throws Exception { 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 catalog, String tableName) throws SQLException{ 157 return getDatabase( con, catalog).getTableView( con, tableName); 158 } 159 160 161 168 TableView getTableView(SSConnection con, String tableName) throws SQLException{ 169 synchronized(tableViews){ 170 TableView tableView = (TableView)tableViews.get(tableName); 171 if(tableView == null){ 172 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 catalog, String tableName) throws Exception { 182 getDatabase( con, catalog).dropTable( con, tableName); 183 } 184 185 186 void dropTable(SSConnection con, String tableName) throws Exception { 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 catalog, String tableName) throws Exception { 200 getDatabase( con, catalog).dropView(tableName); 201 } 202 203 204 void dropView(String viewName) throws Exception { 205 synchronized(tableViews){ 206 Object 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 223 void createTable(SSConnection con, String name, Columns columns, IndexDescriptions indexes, ForeignKeys foreignKeys) throws Exception { 224 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 name, String sql) throws Exception { 241 new View( this, name, sql); 244 } 245 246 247 253 static Object [][] 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 [] catalog = new Object [1]; 264 catalog[0] = dirs[i].getPath(); 265 catalogs.add(catalog); 266 } 267 } 268 } 269 Object [][] result = new Object [catalogs.size()][]; 270 catalogs.toArray(result); 271 return result; 272 } 273 274 275 Strings getTables(String 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 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 [][] getColumns( SSConnection con, String tablePattern, String colPattern) throws Exception { 292 List rows = new ArrayList(); 293 Strings tables = getTables(tablePattern); 294 for(int i=0; i<tables.size(); i++){ 295 String 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 [] row = new Object [18]; 302 row[0] = getName(); row[2] = tableName; row[3] = col.getName(); row[4] = Utils.getShort( SQLTokenizer.getSQLDataType( col.getDataType() )); row[5] = SQLTokenizer.getKeyWord( col.getDataType() ); row[6] = Utils.getInteger(col.getColumnSize()); row[8] = Utils.getInteger(col.getScale()); row[9] = Utils.getInteger(10); row[10]= Utils.getInteger(col.isNullable() ? DatabaseMetaData.columnNullable : DatabaseMetaData.columnNoNulls); row[12]= col.getDefaultDefinition(); row[15]= row[6]; row[16]= Utils.getInteger(i); row[17]= col.isNullable() ? "YES" : "NO"; rows.add(row); 321 } 322 }catch(Exception e){ 323 } 325 } 326 Object [][] result = new Object [rows.size()][]; 327 rows.toArray(result); 328 return result; 329 } 330 331 332 Object [][] getReferenceKeys(SSConnection con, String pkTable, String 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 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 [] row = new Object [14]; 350 row[0] = getName(); row[2] = foreignKey.pkTable; row[3] = columnsPk.get(c); row[4] = getName(); row[6] = foreignKey.fkTable; row[7] = columnsFk.get(c); row[8] = Utils.getShort(c+1); row[9] = Utils.getShort(foreignKey.updateRule); row[10]= Utils.getShort(foreignKey.deleteRule); row[11]= fk.getName(); row[12]= pk.getName(); row[13]= Utils.getShort(DatabaseMetaData.importedKeyNotDeferrable); rows.add(row); 365 } 366 } 367 } 368 } 369 Object [][] result = new Object [rows.size()][]; 370 rows.toArray(result); 371 return result; 372 } 373 374 375 Object [][] getBestRowIdentifier(SSConnection con, String table) throws SQLException{ 376 List rows = new ArrayList(); 377 Strings tables = getTables(table); 378 for(int t=0; t<tables.size(); t++){ 379 String 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 columnName = columns.get(c); 389 Column column = tab.findColumn(columnName); 390 Object [] row = new Object [8]; 391 row[0] = Utils.getShort(DatabaseMetaData.bestRowSession); row[1] = columnName; final int dataType = column.getDataType(); 394 row[2] = Utils.getInteger(dataType); row[3] = SQLTokenizer.getKeyWord(dataType); row[4] = Utils.getInteger(column.getPrecision()); row[6] = Utils.getShort(column.getScale()); row[7] = Utils.getShort(DatabaseMetaData.bestRowNotPseudo); rows.add(row); 401 } 402 } 403 } 404 } 405 Object [][] result = new Object [rows.size()][]; 406 rows.toArray(result); 407 return result; 408 } 409 410 411 Object [][] getPrimaryKeys(SSConnection con, String table) throws SQLException{ 412 List rows = new ArrayList(); 413 Strings tables = getTables(table); 414 for(int t=0; t<tables.size(); t++){ 415 String 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 [] row = new Object [6]; 425 row[0] = getName(); row[2] = tableName; row[3] = columns.get(c); row[4] = Utils.getShort(c+1); row[5] = index.getName(); rows.add(row); 432 } 433 } 434 } 435 } 436 Object [][] result = new Object [rows.size()][]; 437 rows.toArray(result); 438 return result; 439 } 440 441 442 Object [][] getIndexInfo( SSConnection con, String table, boolean unique) throws SQLException { 443 List rows = new ArrayList(); 444 Strings tables = getTables(table); 445 Short type = Utils.getShort( DatabaseMetaData.tableIndexOther ); 446 for(int t=0; t<tables.size(); t++){ 447 String 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 [] row = new Object [13]; 456 row[0] = getName(); row[2] = tableName; row[3] = Boolean.valueOf(!index.isUnique()); row[5] = index.getName(); row[6] = type; row[7] = Utils.getShort(c+1); row[8] = columns.get(c); rows.add(row); 470 } 471 } 472 } 473 Object [][] result = new Object [rows.size()][]; 474 rows.toArray(result); 475 return result; 476 } 477 } | Popular Tags |