1 22 23 package org.xquark.mapper.dbms; 24 25 import java.sql.*; 26 import java.util.*; 27 28 import org.apache.commons.logging.Log; 29 import org.apache.commons.logging.LogFactory; 30 import org.xquark.jdbc.typing.*; 31 import org.xquark.mapper.RepositoryException; 32 import org.xquark.mapper.metadata.Repository; 33 import org.xquark.mapper.metadata.RepositoryConstants; 34 import org.xquark.schema.datatypes.PrimitiveType; 35 36 42 public abstract class DefaultConnectionImpl implements AbstractConnection, RepositoryConstants { 43 private static final String RCSRevision = "$Revision: 1.5 $"; 44 private static final String RCSName = "$Name: $"; 45 46 private static Log log = LogFactory.getLog(DefaultConnectionImpl.class); 47 48 protected Connection connection; 49 protected String schemaName; 50 protected short dbms; 51 protected DBMSInfo dbmsInfo; 52 53 protected DefaultConnectionImpl(Connection connection, short dbms) throws SQLException { 54 this(connection, dbms, new DBMSInfo()); 55 dbmsInfo.setTypeMap(new TypeMap()); 57 dbmsInfo.getTypeMap().load(connection); 58 } 59 60 protected DefaultConnectionImpl(Connection connection, short dbms, DBMSInfo dbmsInfo) throws SQLException { 61 this.connection = connection; 62 this.dbms = dbms; 63 this.dbmsInfo = dbmsInfo; 64 setSchemaName(); 65 } 66 67 protected void setSchemaName() throws SQLException { 71 schemaName = connection.getMetaData().getUserName(); 72 } 73 74 public String getSchemaName() { 75 return schemaName; 76 } 77 78 81 public Connection getConnection() { 82 return connection; 83 } 84 85 88 public short getDBMSType() { 89 return dbms; 90 } 91 92 public TypeMap getTypeMap() { 93 return dbmsInfo.getTypeMap(); 94 } 95 96 public int getMaxDataLength() { 97 return dbmsInfo.getMaxUserCollectionsDataLength(); 98 } 99 100 public int getSystemCollectionDataLength() { 101 return dbmsInfo.getSystemCollectionsDataLength(); 102 } 103 104 public String getRowID() { 105 return dbmsInfo.getRowId(); 106 } 107 108 public boolean useDoubleQuotes4DDLNames() { 109 return dbmsInfo.useDoubleQuotes4DDLNames(); 110 } 111 117 public void rollback() throws SQLException { 118 if (connection.getAutoCommit() == false) { 120 connection.rollback(); 121 connection.setAutoCommit(true); 122 } 123 } 124 130 public void start() throws RepositoryException { 131 try { 132 connection.setAutoCommit(false); 133 } catch (SQLException e) { 134 throw new RepositoryException(RepositoryException.DB_ERROR, "Relational database error while setting autocommit mode to false.", e); 135 } 136 } 137 138 153 public void commit() throws RepositoryException { 154 try { 155 if (connection.getAutoCommit() == false) { 157 connection.commit(); 158 connection.setAutoCommit(true); 159 } 160 } catch (SQLException e) { 161 throw new RepositoryException(RepositoryException.DB_ERROR, "Relational database error while restoring autocommit mode to initial value.", e); 162 } 163 } 164 165 public boolean checkTable(TableInfo table) throws SQLException { 169 return checkTable(table.getName()); 170 } 171 172 public boolean checkTable(String name) throws SQLException { 173 ResultSet rs = null; 174 try { 175 rs = connection.getMetaData().getTables(connection.getCatalog(), schemaName, name, null); 176 return rs.next(); 177 } finally { 178 if (rs != null) 179 rs.close(); 180 } 181 } 182 183 188 public Map getTableMetadata(String tableName) throws SQLException { 189 Iterator it = dbmsInfo.getTableMetadata(connection.getCatalog(), 190 schemaName, tableName, connection, 191 new JDBCProperties() { 192 public boolean useResultSet4ColumnMetadata() {return false;} 193 public boolean useStaticMappingFromNativeType() {return true;} 194 }).iterator(); 195 HashMap columns = new HashMap(); 196 ColumnMetaData cmeta; 197 while (it.hasNext()) { 198 cmeta = (ColumnMetaData)it.next(); 199 columns.put(cmeta.getColumnName(), cmeta); 200 } 201 return columns; 202 } 203 204 212 protected void createTable(TableInfo table) throws SQLException { 213 214 Statement stmt = connection.createStatement(); 215 try { 216 stmt.executeUpdate(table.getCreationStatement()); 217 } finally { 218 stmt.close(); 219 } 220 } 221 222 226 public String getDeleteUserTableRowsStatement(String tableName, String documentRowsSelectionClause) throws SQLException, RepositoryException { 227 StringBuffer deletionStmt = new StringBuffer (); 228 deletionStmt.append("DELETE FROM "); 229 deletionStmt.append(tableName); 230 deletionStmt.append(" WHERE "); 231 deletionStmt.append(getRowID()); 232 deletionStmt.append(" IN ("); 233 deletionStmt.append("SELECT w."); 234 deletionStmt.append(getRowID()); 235 deletionStmt.append(' '); 236 deletionStmt.append(documentRowsSelectionClause); 237 deletionStmt.append(')'); 238 239 return deletionStmt.toString(); 240 } 241 242 public void executeRangeUpdate(String statement, long first, long last) throws SQLException, RepositoryException { 243 PreparedStatement stmt = null; 244 try { 245 stmt = connection.prepareStatement(statement); 246 stmt.setLong(1, first); 247 stmt.setLong(2, last); 248 stmt.executeUpdate(); 249 } finally { 250 if (stmt != null) 251 stmt.close(); 252 } 253 } 254 255 259 268 public String getColumnStatement(int type) throws RepositoryException { 269 switch (type) { 270 case PrimitiveType.DURATION : case PrimitiveType.DATE_TIME : 273 return "to_date(?, 'YYYY-MM-DD'T'HH24:MI:SS')"; 275 case PrimitiveType.TIME : 276 return "to_date(?, 'HH24:MI:SS')"; 277 case PrimitiveType.DATE : 278 return "to_date(?, 'YYYY-MM-DD')"; 280 case PrimitiveType.GYEAR_MONTH : 281 return "to_date(?, 'YYYY-MM')"; 283 case PrimitiveType.GYEAR : 284 return "to_date(?, 'YYYY')"; 286 case PrimitiveType.GMONTH_DAY : 287 return "to_date(?, 'MM-DD')"; 288 case PrimitiveType.GMONTH : 289 return "to_date(?, 'DD')"; 290 case PrimitiveType.DECIMAL : 291 return "to_number(?, '999999999.999999999')"; case PrimitiveType.DOUBLE : 293 case PrimitiveType.FLOAT : 294 default : 295 return "?"; 296 } 297 } 298 299 302 public void onInitRepository(Repository rep) throws SQLException {} 303 304 307 public void onDeleteRepository(Repository rep) throws SQLException {} 308 309 312 public void onInitConnection() throws SQLException { 313 dropTemporaryTables(); 314 } 315 316 protected short getRandomCollectionID() { 317 return (short) (System.currentTimeMillis() % Short.MAX_VALUE); 318 } 319 320 322 public void emptyTable(String tableName) throws SQLException { 323 Statement stmt = null; 324 try { 325 stmt = connection.createStatement(); 326 stmt.execute("TRUNCATE TABLE " + tableName); 327 } finally { 328 stmt.close(); 329 } 330 } 331 332 public TableInfo createQueryTemporaryTable() throws SQLException { 333 String randomTableName = null; 334 boolean created = false; 335 TableInfo table = null; 336 while (!created) { 337 try { 338 table = getTemporaryTableInfo(); 339 executeUpdate(table.getCreationStatement()); 340 created = true; 341 } catch (SQLException e) { 342 if (getUniversalError(e) != OBJECT_ALREADY_EXISTS) 343 throw e; 344 } 345 } 346 return table; 347 } 348 349 public String createTemporaryTableAs(String subQuery) throws SQLException { 350 String randomTable = null; 351 boolean created = false; 352 Statement stmt = null; 353 while (!created) { 354 try { 355 randomTable = getTemporaryTableName(); 356 stmt = connection.createStatement(); 357 StringBuffer DDLStatement = new StringBuffer ("CREATE"); 358 DDLStatement.append(" GLOBAL TEMPORARY "); 360 DDLStatement.append("TABLE "); 361 DDLStatement.append(randomTable); 362 DDLStatement.append(" ON COMMIT PRESERVE ROWS"); 364 DDLStatement.append(" AS "); 365 DDLStatement.append(subQuery); 366 367 if (log.isDebugEnabled()) 368 log.debug("Temp table creation\n" + DDLStatement); 369 370 stmt.executeUpdate(DDLStatement.toString()); 371 created = true; 372 } catch (SQLException e) { 373 if (getUniversalError(e) != OBJECT_ALREADY_EXISTS) 374 throw e; 375 } finally { 376 if (stmt != null) 377 stmt.close(); 378 } 379 } 380 return randomTable; 381 } 382 383 public void dropTable(String tableName) throws SQLException { 384 executeUpdate("DROP TABLE " + tableName); 385 } 386 387 public void executeUpdate(String sqlStmt) throws SQLException { 388 Statement stmt = connection.createStatement(); 389 try { 390 stmt.executeUpdate(sqlStmt); 391 } finally { 392 stmt.close(); 393 } 394 } 395 396 public void dropTemporaryTable(String tableName) throws SQLException { 397 dropTable(tableName); 398 } 399 400 public void dropTemporaryTables() throws SQLException { 401 DatabaseMetaData metadata = connection.getMetaData(); 402 TableSpec tempSpecs = TableSpecLoader.getInstance().getTableSpec(TableSpec.CAT_QUERY_TMP, TableSpec.TYPE_QUERY_TMP); 403 ResultSet rs = metadata.getTables(connection.getCatalog(), schemaName, tempSpecs.getAllCollectionsWildcardTableName(), null); try { 405 while (rs.next()) { 406 try { 407 dropTable(rs.getString(3)); 408 } catch (SQLException e) { 409 } 411 } 412 } finally { 413 rs.close(); 414 } 415 } 416 417 public int getUniversalError(SQLException e) { 418 return UNKNOW_ERROR_CODE; 419 } 420 421 422 public void close() throws SQLException { 423 connection.close(); 424 } 425 426 public void updateStatistics(String tableName) throws SQLException {} 427 428 public boolean useStringDelimitor() { 429 return false; 430 } 431 432 public boolean distinguishNullAndEmptyStrings() { 433 return true; 434 } 435 436 440 public String getTemporaryTableName() { 441 return TableSpecLoader.getInstance().getTableSpec(TableSpec.CAT_QUERY_TMP, TableSpec.TYPE_QUERY_TMP).getTableName(getRandomCollectionID()); 442 } 443 444 public TableInfo getTemporaryTableInfo() { 445 return new TableInfo(TableSpecLoader.getInstance().getTableSpec(TableSpec.CAT_QUERY_TMP, TableSpec.TYPE_QUERY_TMP), getRandomCollectionID(), this); 446 } 447 448 public String getTemporaryTableCreationStatement(TableInfo table) { 449 return dbmsInfo.getTemporaryTableStatement().getTableCreationStatement(table.getName(), table.getLogicalSpecification()); 450 } 451 452 public String getIndexOrganizedTableCreationStatement(TableInfo table) { 453 return dbmsInfo.getIndexOrganizedStatement().getTableCreationStatement(table.getName(), table.getLogicalSpecification()); 454 } 455 456 public String getLockSelectStatement(TableInfo table, String filterClause) { 457 return getLockSelectStatement(table.getColumnList(), table.getName(), filterClause); 458 } 459 460 public String getLockSelectStatement(String columnList, String tableName, String filterClause) { 461 return dbmsInfo.getSelectLockStatement().getSelectStatement(columnList, tableName, filterClause); 462 } 463 464 public String getBitmapIndexClause() { 465 return null; 466 } 467 468 public String getHashIndexClause() { 469 return null; 470 } 471 472 public String getBTreeIndexClause() { 473 return null; 474 } 475 476 public void createSequence(TableInfo table, int step) throws SQLException { 477 executeUpdate(table.getCreationStatement()); 478 StringBuffer sql = new StringBuffer (); 480 sql.append("INSERT INTO "); 481 sql.append(table.getName()); 482 sql.append('('); 483 sql.append(table.getColumns()[0]); 484 sql.append(") VALUES("); 485 sql.append(RepositoryConstants.SEQUENCE_FIRST_VALUE); 486 sql.append(')'); 487 executeUpdate(sql.toString()); 488 } 489 490 public void dropSequence(String seqName) throws SQLException { 491 dropTable(seqName); 492 } 493 494 public long nextSequenceValue(TableInfo table, short step) throws RepositoryException { 495 start(); 496 Statement stmt = null; 497 ResultSet rs = null; 498 long next = 0; 499 try { 500 stmt = connection.createStatement(); 501 rs = stmt.executeQuery(getLockSelectStatement(table, "")); 502 if (rs.next()) 503 next = rs.getLong(1); 504 else 505 throw new RepositoryException(RepositoryException.CONSISTENCY_ERROR, "Table " + table.getName() + " should contain one row."); 506 } catch (SQLException e) { 507 throw new RepositoryException(RepositoryException.DB_ERROR, "JDBC error while querying the " + table.getName() + " table."); 508 } finally { 509 if (rs != null) { 510 try { 511 rs.close(); 512 stmt.close(); 513 } catch (SQLException e) { 514 } 516 } 517 } 518 StringBuffer sql = new StringBuffer (); 519 String column = table.getColumns()[0].getName(); sql.append("UPDATE "); 521 sql.append(table.getName()); 522 sql.append(" SET "); 523 sql.append(column); 524 sql.append('='); 525 sql.append(next + step); 526 sql.append(" WHERE "); 527 sql.append(column); 528 sql.append('='); 529 sql.append(next); 530 try { 531 executeUpdate(sql.toString()); 532 } catch (SQLException e) { 533 throw new RepositoryException(RepositoryException.DB_ERROR, "JDBC error while inserting new value in the " + table.getName() + " table."); 534 } 535 commit(); 536 537 return next; 538 } 539 540 public Collection createTables(Collection tables) throws SQLException { 541 Iterator it = tables.iterator(); 542 TableInfo wTable; 543 Statement stmt = null; 544 ArrayList notCreated = new ArrayList(); 545 try { 546 stmt = connection.createStatement(); 547 while (it.hasNext()) { 548 wTable = (TableInfo) it.next(); 549 if (wTable.isSequence()) 550 notCreated.add(wTable); 551 else { 552 stmt.executeUpdate(wTable.getCreationStatement()); 554 for (int i = 0; i < wTable.getIndexCreationStatements().length; i++) 555 stmt.executeUpdate(wTable.getIndexCreationStatements()[i]); 556 } 558 } 559 } finally { 561 if (stmt != null) 562 stmt = null; 563 } 564 return notCreated; 565 } 566 567 public void createIndexes(Collection tables) throws SQLException { 568 Iterator it = tables.iterator(); 569 TableInfo wTable; 570 Statement stmt = null; 571 try { 572 stmt = connection.createStatement(); 573 while (it.hasNext()) { 574 wTable = (TableInfo) it.next(); 575 if (!wTable.isSequence()) { 576 for (int i = 0; i < wTable.getIndexCreationStatements().length; i++) 577 addBatch(stmt, wTable.getIndexCreationStatements()[i]); 578 } 579 } 580 executeBatch(stmt); 581 } finally { 582 if (stmt != null) 583 stmt = null; 584 } 585 } 586 587 public void dropIndexes(Collection tables) throws SQLException { 588 Iterator it = tables.iterator(); 589 TableInfo wTable; 590 Statement stmt = null; 591 try { 592 stmt = connection.createStatement(); 593 while (it.hasNext()) { 594 wTable = (TableInfo) it.next(); 595 if (!wTable.isSequence()) { 596 for (int i = 0; i < wTable.getIndexDropStatements().length; i++) 597 addBatch(stmt, wTable.getIndexDropStatements()[i]); 598 } 599 } 600 executeBatch(stmt); 601 } finally { 602 if (stmt != null) 603 stmt = null; 604 } 605 } 606 607 public void createSequence(TableInfo table, short step) throws SQLException {} 608 609 public void setObject(PreparedStatement pStmt, int index, Object o, int javaType, DbType sqlType) 610 throws SQLException { 611 pStmt.setObject(index, o); 612 } 613 614 public List getUserTableNames(String tablePattern) throws SQLException { 615 ResultSet rs = null; 616 ArrayList tables = new ArrayList(); 617 618 try { 619 rs = connection.getMetaData().getTables(connection.getCatalog(), schemaName, tablePattern, null); 620 while (rs.next()) 621 tables.add(rs.getString(3)); 622 } finally { 623 if (rs != null) 624 rs.close(); 625 } 626 return tables; 627 } 628 629 public List getUserSequenceNames(String seqPattern) throws SQLException { 630 return Collections.EMPTY_LIST; 631 } 632 633 } 634 | Popular Tags |