1 10 11 package com.triactive.jdo.store; 12 13 import com.triactive.jdo.model.FieldMetaData; 14 import com.triactive.jdo.model.MetaData; 15 import java.util.ArrayList ; 16 import java.util.Iterator ; 17 import java.util.List ; 18 import java.util.ListIterator ; 19 import java.util.StringTokenizer ; 20 import java.sql.Connection ; 21 import java.sql.PreparedStatement ; 22 import java.sql.ResultSet ; 23 import java.sql.SQLException ; 24 import java.sql.Statement ; 25 import javax.jdo.JDODataStoreException; 26 import org.apache.log4j.Category; 27 28 29 class SchemaTable extends BaseTable 30 { 31 private static final Category LOG = Category.getInstance(SchemaTable.class); 32 33 private ColumnMapping tableIDMapping; 34 private ColumnMapping nextIDMapping; 35 private ColumnMapping javaIDMapping; 36 private ColumnMapping tableNameMapping; 37 private String fetchByJavaIDStmt; 38 private String getMaxTableIDStmt; 39 private String insertStmt; 40 private String fetchByTableIDStmt; 41 private String fetchByTableNameStmt; 42 private String getNextIDStmt; 43 private String incrNextIDStmt; 44 private String fetchAllStmt; 45 private int tableValidationFlags; 46 47 48 public SchemaTable(StoreManager storeMgr) 49 { 50 super(storeMgr); 51 52 name = new TableIdentifier(dba, "jdoTable"); 53 } 54 55 56 public void initialize() 57 { 58 assertIsUninitialized(); 59 60 Column tableIDColumn = newColumn(int.class, "tableID").setPrimaryKeyPart(); 61 Column nextIDColumn = newColumn(int.class, "nextID"); 62 Column javaIDColumn = newColumn(String .class, "javaName").setMaximumLength(128).setUnique(); 63 Column tableNameColumn = newColumn(String .class, "tableName").setMaximumLength(64).setUnique(); 64 65 tableIDMapping = dba.getMapping(tableIDColumn); 66 nextIDMapping = dba.getMapping(nextIDColumn); 67 javaIDMapping = dba.getMapping(javaIDColumn); 68 tableNameMapping = dba.getMapping(tableNameColumn); 69 70 fetchByJavaIDStmt = "SELECT " + tableIDColumn.getName() + "," + 71 tableNameColumn.getName() + 72 " FROM " + name + 73 " WHERE " + javaIDColumn.getName() + " = ?"; 74 75 getMaxTableIDStmt = "SELECT MAX(" + tableIDColumn.getName() + ")" + 76 " FROM " + name; 77 78 insertStmt = "INSERT INTO " + name + 79 " (" + 80 tableIDColumn.getName() + "," + 81 nextIDColumn.getName() + "," + 82 javaIDColumn.getName() + "," + 83 tableNameColumn.getName() + 84 ")" + 85 " VALUES (?,?,?,?)"; 86 87 fetchByTableIDStmt = "SELECT " + javaIDColumn.getName() + 88 " FROM " + name + 89 " WHERE " + tableIDColumn.getName() + " = ?"; 90 91 fetchByTableNameStmt = "SELECT " + tableIDColumn.getName() + 92 " FROM " + name + 93 " WHERE " + tableNameColumn.getName() + " = ?"; 94 95 getNextIDStmt = "SELECT " + nextIDColumn.getName() + 96 " FROM " + name + 97 " WHERE " + tableIDColumn.getName() + " = ?"; 98 99 incrNextIDStmt = "UPDATE " + name + 100 " SET " + nextIDColumn.getName() + " = ?" + 101 " WHERE " + tableIDColumn.getName() + " = ?"; 102 103 fetchAllStmt = "SELECT " + tableIDColumn.getName() + "," + 104 javaIDColumn.getName() + "," + 105 tableNameColumn.getName() + 106 " FROM " + name + 107 " ORDER BY " + tableIDColumn.getName(); 108 109 state = TABLE_STATE_INITIALIZED; 110 } 111 112 113 public boolean validate(int flags, Connection conn) throws SQLException 114 { 115 this.tableValidationFlags = flags; 116 117 return super.validate(flags, conn); 118 } 119 120 121 public boolean exists(Connection conn) throws SQLException 122 { 123 assertIsInitialized(); 124 125 try 126 { 127 getNextTableID(conn); 128 return true; 129 } 130 catch (SQLException e) 131 { 132 return false; 133 } 134 } 135 136 137 private SQLIdentifier generateTableName(MetaData md, Connection conn) throws SQLException 138 { 139 ArrayList nameParts = new ArrayList (); 140 141 StringTokenizer tokens = new StringTokenizer (md.getJavaName(), "."); 142 143 while (tokens.hasMoreTokens()) 144 nameParts.add(tokens.nextToken()); 145 146 ListIterator li = nameParts.listIterator(nameParts.size()); 147 148 String uniqueName = (String )li.previous(); 149 150 if (md instanceof FieldMetaData) 151 uniqueName = (String )li.previous() + '_' + uniqueName; 152 153 TableIdentifier tableName = new TableIdentifier(dba, uniqueName); 154 int n = 1; 155 156 while (tableNameInUse(tableName, conn)) 157 { 158 if (li.hasPrevious()) 159 uniqueName = (String )li.previous() + '_' + uniqueName; 160 else 161 uniqueName = uniqueName + n++; 162 163 tableName = new TableIdentifier(dba, uniqueName); 164 } 165 166 return tableName; 167 } 168 169 170 private boolean tableNameInUse(TableIdentifier tableName, Connection conn) throws SQLException 171 { 172 if (storeMgr.tableExists(tableName, conn)) 173 return true; 174 175 PreparedStatement ps = conn.prepareStatement(fetchByTableNameStmt); 176 177 try 178 { 179 ps.setString(1, tableName.getSQLIdentifier()); 180 ResultSet rs = ps.executeQuery(); 181 182 try 183 { 184 return rs.next(); 185 } 186 finally 187 { 188 rs.close(); 189 } 190 } 191 finally 192 { 193 ps.close(); 194 } 195 } 196 197 198 private TableMetadata fetchByJavaID(String javaName, Connection conn) throws SQLException 199 { 200 TableMetadata tmd = null; 201 202 PreparedStatement ps = conn.prepareStatement(fetchByJavaIDStmt); 203 204 try 205 { 206 javaIDMapping.setString(null, ps, 1, javaName); 207 208 long startTime = System.currentTimeMillis(); 209 210 ResultSet rs = ps.executeQuery(); 211 212 try 213 { 214 if (LOG.isDebugEnabled()) 215 LOG.debug("Time = " + (System.currentTimeMillis() - startTime) + " ms: " + fetchByJavaIDStmt); 216 217 storeMgr.logSQLWarnings(ps); 218 219 if (rs.next()) 220 { 221 int tableID = tableIDMapping.getInt(null, rs, 1); 222 SQLIdentifier tableName = new SQLIdentifier(dba, tableNameMapping.getString(null, rs, 2)); 223 224 storeMgr.logSQLWarnings(rs); 225 226 tmd = new TableMetadata(tableID, javaName, tableName); 227 } 228 } 229 finally 230 { 231 rs.close(); 232 } 233 } 234 finally 235 { 236 ps.close(); 237 } 238 239 return tmd; 240 } 241 242 243 private int getNextTableID(Connection conn) throws SQLException 244 { 245 int nextTableID; 246 Statement stmt = conn.createStatement(); 247 248 try 249 { 250 long startTime = System.currentTimeMillis(); 251 252 ResultSet rs = stmt.executeQuery(getMaxTableIDStmt); 253 254 try 255 { 256 if (LOG.isDebugEnabled()) 257 LOG.debug("Time = " + (System.currentTimeMillis() - startTime) + " ms: " + getMaxTableIDStmt); 258 259 storeMgr.logSQLWarnings(stmt); 260 261 if (!rs.next()) 262 throw new JDODataStoreException("Can't find max table ID in " + name + "???"); 263 264 nextTableID = rs.getInt(1) + 1; 265 storeMgr.logSQLWarnings(rs); 266 } 267 finally 268 { 269 rs.close(); 270 } 271 } 272 finally 273 { 274 stmt.close(); 275 } 276 277 return nextTableID; 278 } 279 280 281 private void insert(TableMetadata tmd, Connection conn) throws SQLException 282 { 283 PreparedStatement ps = conn.prepareStatement(insertStmt); 284 285 try 286 { 287 tableIDMapping.setInt(null, ps, 1, tmd.tableID); 288 nextIDMapping.setInt(null, ps, 2, 0); 289 javaIDMapping.setString(null, ps, 3, tmd.javaName); 290 tableNameMapping.setString(null, ps, 4, tmd.tableName.getSQLIdentifier()); 291 292 long startTime = System.currentTimeMillis(); 293 294 ps.executeUpdate(); 295 296 if (LOG.isDebugEnabled()) 297 LOG.debug("Time = " + (System.currentTimeMillis() - startTime) + " ms: " + insertStmt); 298 299 storeMgr.logSQLWarnings(ps); 300 } 301 finally 302 { 303 ps.close(); 304 } 305 } 306 307 308 324 public TableMetadata getTableMetadata(MetaData md, Connection conn) 325 throws SQLException , MissingSchemaTableEntryException 326 { 327 assertIsValidated(); 328 329 String javaName = md.getJavaName(); 330 TableMetadata tmd = fetchByJavaID(javaName, conn); 331 332 if (tmd == null) 333 { 334 if ((tableValidationFlags & AUTO_CREATE) == 0) 335 throw new MissingSchemaTableEntryException(this, javaName); 336 337 int tableID = getNextTableID(conn); 338 SQLIdentifier tableName = generateTableName(md, conn); 339 340 tmd = new TableMetadata(tableID, javaName, tableName); 341 342 insert(tmd, conn); 343 } 344 345 return tmd; 346 } 347 348 349 public String getJavaName(int tableID, Connection conn) throws SQLException 350 { 351 assertIsValidated(); 352 353 String javaName = null; 354 355 PreparedStatement ps = conn.prepareStatement(fetchByTableIDStmt); 356 357 try 358 { 359 tableIDMapping.setInt(null, ps, 1, tableID); 360 361 long startTime = System.currentTimeMillis(); 362 363 ResultSet rs = ps.executeQuery(); 364 365 try 366 { 367 if (LOG.isDebugEnabled()) 368 LOG.debug("Time = " + (System.currentTimeMillis() - startTime) + " ms: " + fetchByTableIDStmt); 369 370 storeMgr.logSQLWarnings(ps); 371 372 if (rs.next()) 373 { 374 javaName = javaIDMapping.getString(null, rs, 1); 375 376 storeMgr.logSQLWarnings(rs); 377 } 378 } 379 finally 380 { 381 rs.close(); 382 } 383 } 384 finally 385 { 386 ps.close(); 387 } 388 389 return javaName; 390 } 391 392 393 public int getNextOIDHiValue(int tableID, Connection conn) throws SQLException 394 { 395 assertIsValidated(); 396 397 int nextHiValue; 398 PreparedStatement ps = conn.prepareStatement(getNextIDStmt); 399 400 try 401 { 402 tableIDMapping.setInt(null, ps, 1, tableID); 403 404 long startTime = System.currentTimeMillis(); 405 406 ResultSet rs = ps.executeQuery(); 407 408 try 409 { 410 if (LOG.isDebugEnabled()) 411 LOG.debug("Time = " + (System.currentTimeMillis() - startTime) + " ms: " + getNextIDStmt); 412 413 storeMgr.logSQLWarnings(ps); 414 415 if (!rs.next()) 416 throw new JDODataStoreException("Can't find table ID " + tableID + " in " + getName() + "???"); 417 418 nextHiValue = nextIDMapping.getInt(null, rs, 1); 419 storeMgr.logSQLWarnings(rs); 420 } 421 finally 422 { 423 rs.close(); 424 } 425 } 426 finally 427 { 428 ps.close(); 429 } 430 431 ps = conn.prepareStatement(incrNextIDStmt); 432 433 try 434 { 435 nextIDMapping.setInt(null, ps, 1, nextHiValue + 1); 436 tableIDMapping.setInt(null, ps, 2, tableID); 437 438 long startTime = System.currentTimeMillis(); 439 440 int rowsUpdated = ps.executeUpdate(); 441 442 if (LOG.isDebugEnabled()) 443 LOG.debug("Time = " + (System.currentTimeMillis() - startTime) + " ms: " + incrNextIDStmt); 444 445 if (rowsUpdated != 1) 446 throw new JDODataStoreException("Can't update table ID " + tableID + " in " + getName() + "???"); 447 448 storeMgr.logSQLWarnings(ps); 449 } 450 finally 451 { 452 ps.close(); 453 } 454 455 return nextHiValue; 456 } 457 458 459 public List getAllTableMetadata(boolean descending, Connection conn) throws SQLException 460 { 461 assertIsValidated(); 462 463 ArrayList tmds = new ArrayList (); 464 Statement stmt = conn.createStatement(); 465 466 try 467 { 468 String stmtText = fetchAllStmt + (descending ? " DESC" : ""); 469 long startTime = System.currentTimeMillis(); 470 471 ResultSet rs = stmt.executeQuery(stmtText); 472 473 try 474 { 475 if (LOG.isDebugEnabled()) 476 LOG.debug("Time = " + (System.currentTimeMillis() - startTime) + " ms: " + stmtText); 477 478 storeMgr.logSQLWarnings(stmt); 479 480 while (rs.next()) 481 { 482 int tableID = tableIDMapping.getInt(null, rs, 1); 483 String javaID = javaIDMapping.getString(null, rs, 2); 484 SQLIdentifier tableName = new SQLIdentifier(dba, tableNameMapping.getString(null, rs, 3)); 485 486 storeMgr.logSQLWarnings(rs); 487 488 tmds.add(new TableMetadata(tableID, javaID, tableName)); 489 } 490 } 491 finally 492 { 493 rs.close(); 494 } 495 } 496 finally 497 { 498 stmt.close(); 499 } 500 501 return tmds; 502 } 503 504 505 public void dropTablesFor(Class [] classes, Connection conn) throws SQLException 506 { 507 assertIsValidated(); 508 509 String [] classNames = new String [classes.length]; 510 511 for (int i = 0; i < classes.length; ++i) 512 classNames[i] = classes[i].getName(); 513 514 ArrayList toBeRemoved = new ArrayList (); 515 Iterator i = getAllTableMetadata(true, conn).iterator(); 516 517 while (i.hasNext()) 518 { 519 TableMetadata tmd = (TableMetadata)i.next(); 520 521 for (int j = 0; j < classNames.length; ++j) 522 { 523 String name = classNames[j]; 524 525 if (tmd.javaName.equals(name) || tmd.javaName.startsWith(name + '.')) 526 { 527 toBeRemoved.add(tmd); 528 break; 529 } 530 } 531 } 532 533 dropTables(toBeRemoved, conn); 534 } 535 536 537 public void dropAllTables(Connection conn) throws SQLException 538 { 539 assertIsValidated(); 540 541 dropTables(getAllTableMetadata(true, conn), conn); 542 } 543 544 545 private void dropTables(List metadata, Connection conn) throws SQLException 546 { 547 ArrayList allBaseTables = new ArrayList (); 548 ArrayList allViews = new ArrayList (); 549 550 Iterator i = metadata.iterator(); 551 552 while (i.hasNext()) 553 { 554 TableMetadata tmd = (TableMetadata)i.next(); 555 int tableType = storeMgr.getTableType(tmd.tableName, conn); 556 557 switch (tableType) 558 { 559 case TABLE_TYPE_BASE_TABLE: 560 BaseTable t = new JDOBaseTable(tmd, storeMgr); 561 t.initialize(); 562 563 allBaseTables.add(t); 564 break; 565 566 case TABLE_TYPE_VIEW: 567 View v = new JDOView(tmd, storeMgr); 568 v.initialize(); 569 570 allViews.add(v); 571 break; 572 573 case TABLE_TYPE_MISSING: 574 case TABLE_TYPE_UNKNOWN: 575 default: 576 break; 577 } 578 } 579 580 584 i = allViews.iterator(); 585 586 while (i.hasNext()) 587 ((View)i.next()).drop(conn); 588 589 i = allBaseTables.iterator(); 590 591 while (i.hasNext()) 592 ((BaseTable)i.next()).dropConstraints(conn); 593 594 i = allBaseTables.iterator(); 595 596 while (i.hasNext()) 597 ((BaseTable)i.next()).drop(conn); 598 } 599 } 600 | Popular Tags |