1 21 package oracle.toplink.essentials.internal.databaseaccess; 23 24 import java.util.*; 25 import java.sql.*; 26 import java.io.*; 27 import oracle.toplink.essentials.internal.helper.*; 28 import oracle.toplink.essentials.queryframework.*; 29 import oracle.toplink.essentials.exceptions.*; 30 import oracle.toplink.essentials.sessions.DatabaseLogin; 31 import oracle.toplink.essentials.internal.localization.*; 32 import oracle.toplink.essentials.logging.SessionLog; 33 import oracle.toplink.essentials.sessions.Login; 34 import oracle.toplink.essentials.sessions.SessionProfiler; 35 import oracle.toplink.essentials.sessions.DatabaseRecord; 36 import oracle.toplink.essentials.internal.sessions.AbstractRecord; 37 import oracle.toplink.essentials.internal.sessions.AbstractSession; 38 39 61 public class DatabaseAccessor extends DatasourceAccessor { 62 63 64 public static boolean shouldUseDynamicStatements = true; 65 66 67 protected Hashtable statementCache; 68 69 70 protected DatabaseMetaData metaData; 71 72 protected LOBValueWriter lobWriter; 74 75 79 protected boolean shouldUseThreadCursors; 80 81 82 protected Statement dynamicStatement; 83 protected boolean isDynamicStatementInUse; 84 85 public DatabaseAccessor() { 86 super(); 87 this.statementCache = new Hashtable(50); 88 this.lobWriter = null; 89 this.shouldUseThreadCursors = false; 90 this.isDynamicStatementInUse = false; 91 } 92 93 101 public void flushSelectCalls(AbstractSession session) { 102 if (lobWriter != null) { 103 lobWriter.buildAndExecuteSelectCalls(session); 104 } 105 } 106 107 113 public LOBValueWriter getLOBWriter() { 114 if (lobWriter == null) { 115 lobWriter = new LOBValueWriter(this); 116 } 117 return lobWriter; 118 } 119 120 125 public synchronized Statement allocateDynamicStatement() throws SQLException { 126 if (dynamicStatement == null) { 127 dynamicStatement = getConnection().createStatement(); 128 } 129 if (isDynamicStatementInUse()) { 130 return getConnection().createStatement(); 131 } 132 setIsDynamicStatementInUse(true); 133 return dynamicStatement; 134 } 135 136 141 public boolean isDynamicStatementInUse() { 142 return isDynamicStatementInUse; 143 } 144 145 149 public synchronized void setIsDynamicStatementInUse(boolean isDynamicStatementInUse) { 150 this.isDynamicStatementInUse = isDynamicStatementInUse; 151 } 152 153 156 public void basicBeginTransaction(AbstractSession session) throws DatabaseException { 157 try { 158 if (getPlatform().supportsAutoCommit()) { 159 getConnection().setAutoCommit(false); 160 } else { 161 getPlatform().beginTransaction(this); 162 } 163 } catch (SQLException exception) { 164 throw DatabaseException.sqlException(exception, this, session); 165 } 166 } 167 168 171 protected void buildConnectLog(AbstractSession session) { 172 try { 173 if (session.shouldLog(SessionLog.CONFIG, SessionLog.CONNECTION)) { DatabaseMetaData metaData = getConnectionMetaData(); 176 Object [] args = { metaData.getURL(), metaData.getUserName(), metaData.getDatabaseProductName(), metaData.getDatabaseProductVersion(), metaData.getDriverName(), metaData.getDriverVersion(), Helper.cr() + "\t" }; 177 session.log(SessionLog.CONFIG, SessionLog.CONNECTION, "connected_user_database_driver", args, this); 178 } 179 } catch (SQLException exception) { 180 session.warning("JDBC_driver_does_not_support_meta_data", SessionLog.CONNECTION); 182 } 183 } 184 185 188 public AbstractRecord buildOutputRow(CallableStatement statement, DatabaseCall call, AbstractSession session) throws DatabaseException { 189 try { 190 return call.buildOutputRow(statement); 191 } catch (SQLException exception) { 192 throw DatabaseException.sqlException(exception, call, this, session); 193 } 194 } 195 196 202 public Vector buildSortedFields(Vector fields, ResultSet resultSet, AbstractSession session) throws DatabaseException { 203 Vector sortedFields; 204 try { 205 Vector columnNames = getColumnNames(resultSet, session); 206 if (fields == null) { sortedFields = new Vector(columnNames.size()); 208 for (Enumeration columnNamesEnum = columnNames.elements(); 209 columnNamesEnum.hasMoreElements();) { 210 sortedFields.addElement(new DatabaseField((String )columnNamesEnum.nextElement())); 211 } 212 } else { 213 sortedFields = sortFields(fields, columnNames); 214 } 215 } catch (SQLException exception) { 216 throw DatabaseException.sqlException(exception, this, session); 217 } 218 return sortedFields; 219 } 220 221 226 protected void connect(Login login) throws DatabaseException { 227 super.connect(login); 228 checkTransactionIsolation(); 229 } 230 231 237 protected void checkTransactionIsolation() throws DatabaseException { 238 if ((!isInTransaction()) && (getLogin() != null) && (((DatabaseLogin)getLogin()).getTransactionIsolation() != -1)) { 239 try { 240 getConnection().setTransactionIsolation(((DatabaseLogin)getLogin()).getTransactionIsolation()); 241 } catch (java.sql.SQLException sqlEx) { 242 throw DatabaseException.sqlException(sqlEx, this, null); 243 } 244 } 245 } 246 247 251 public void clearStatementCache(AbstractSession session) { 252 if (hasStatementCache()) { 253 for (Enumeration statements = getStatementCache().elements(); 254 statements.hasMoreElements();) { 255 Statement statement = (Statement)statements.nextElement(); 256 try { 257 statement.close(); 258 } catch (SQLException exception) { 259 } 262 } 263 setStatementCache(null); 264 } 265 266 if (this.dynamicStatement != null) { 268 try { 269 this.dynamicStatement.close(); 270 } catch (SQLException exception) { 271 } 274 this.dynamicStatement = null; 275 this.setIsDynamicStatementInUse(false); 276 } 277 } 278 279 282 public void closeCursor(ResultSet resultSet) throws DatabaseException { 283 try { 284 resultSet.close(); 285 } catch (SQLException exception) { 286 throw DatabaseException.sqlException(exception, this, null); 287 } 288 } 289 290 295 public void closeStatement(Statement statement, AbstractSession session) throws SQLException { 296 if (statement == null) { 297 decrementCallCount(); 298 return; 299 } 300 301 try { 302 session.startOperationProfile(SessionProfiler.STATEMENT_EXECUTE); 303 statement.close(); 304 } finally { 305 session.endOperationProfile(SessionProfiler.STATEMENT_EXECUTE); 306 decrementCallCount(); 307 if (statement == this.dynamicStatement) { 309 this.dynamicStatement = null; 310 setIsDynamicStatementInUse(false); 312 } 313 } 314 } 315 316 319 public void commitTransaction(AbstractSession session) throws DatabaseException { 320 this.writesCompleted(session); 321 super.commitTransaction(session); 322 } 323 324 327 public void basicCommitTransaction(AbstractSession session) throws DatabaseException { 328 try { 329 if (getPlatform().supportsAutoCommit()) { 330 getConnection().commit(); 331 getConnection().setAutoCommit(true); 332 } else { 333 getPlatform().commitTransaction(this); 334 } 335 } catch (SQLException exception) { 336 throw DatabaseException.sqlException(exception, this, session); 337 } 338 } 339 340 345 public AbstractRecord cursorRetrieveNextRow(Vector fields, ResultSet resultSet, AbstractSession session) throws DatabaseException { 346 try { 347 if (resultSet.next()) { 348 return fetchRow(fields, resultSet, resultSet.getMetaData(), session); 349 } else { 350 return null; 351 } 352 } catch (SQLException exception) { 353 throw DatabaseException.sqlException(exception, this, session); 354 } 355 } 356 357 362 public AbstractRecord cursorRetrievePreviousRow(Vector fields, ResultSet resultSet, AbstractSession session) throws DatabaseException { 363 try { 364 if (resultSet.previous()) { 365 return fetchRow(fields, resultSet, resultSet.getMetaData(), session); 366 } else { 367 return null; 368 } 369 } catch (SQLException exception) { 370 throw DatabaseException.sqlException(exception, this, session); 371 } 372 } 373 374 377 public void closeDatasourceConnection() throws DatabaseException { 378 try { 379 getConnection().close(); 380 } catch (SQLException exception) { 381 throw DatabaseException.sqlException(exception, this, null); 382 } 383 } 384 385 389 public void disconnect(AbstractSession session) throws DatabaseException { 390 clearStatementCache(session); 391 super.disconnect(session); 392 } 393 394 399 public void closeConnection() { 400 clearStatementCache(null); 402 super.closeConnection(); 403 } 404 405 408 protected void executeBatchedStatement(PreparedStatement statement, AbstractSession session) throws DatabaseException { 409 try { 410 executeDirectNoSelect(statement, null, session); 411 } catch (RuntimeException exception) { 412 try { closeStatement(statement, session); 414 } catch (SQLException closeException) { 415 } 416 417 throw exception; 418 } 419 420 try { 422 closeStatement(statement, session); 423 } catch (SQLException exception) { 424 throw DatabaseException.sqlException(exception, this, session); 425 } 426 } 427 428 435 public Object executeCall(Call call, AbstractRecord translationRow, AbstractSession session) throws DatabaseException { 436 return basicExecuteCall(call, translationRow, session); 438 } 439 440 447 public Object basicExecuteCall(Call call, AbstractRecord translationRow, AbstractSession session) throws DatabaseException { 448 Statement statement = null; 449 Object result = null; 450 DatabaseCall dbCall = null; 451 ResultSet resultSet = null; try { 453 dbCall = (DatabaseCall)call; 454 } catch (ClassCastException e) { 455 throw QueryException.invalidDatabaseCall(call); 456 } 457 458 if (getLogin() == null) { 460 throw DatabaseException.databaseAccessorNotConnected(); 461 } 462 463 try { 464 incrementCallCount(session); 465 if (session.shouldLog(SessionLog.FINE, SessionLog.SQL)) { session.log(SessionLog.FINE, SessionLog.SQL, dbCall.getLogString(this), (Object [])null, this, false); 467 } 468 session.startOperationProfile(SessionProfiler.SQL_PREPARE); 469 try { 470 statement = dbCall.prepareStatement(this, translationRow, session); 471 } finally { 472 session.endOperationProfile(SessionProfiler.SQL_PREPARE); 473 } 474 475 if (dbCall.isNothingReturned()) { 477 result = executeNoSelect(dbCall, statement, session); 478 if (dbCall.isLOBLocatorNeeded()) { 479 getLOBWriter().addCall(dbCall); 482 } 483 } else if (!dbCall.getReturnsResultSet() || (dbCall.getReturnsResultSet() && dbCall.shouldBuildOutputRow())) { 484 result = session.getPlatform().executeStoredProcedure(dbCall, (PreparedStatement)statement, this, session); 485 } else { resultSet = executeSelect(dbCall, statement, session); 487 if (dbCall.getFirstResult() != 0) { 488 resultSet.absolute(dbCall.getFirstResult()); 489 } 490 ResultSetMetaData metaData = resultSet.getMetaData(); 491 dbCall.matchFieldOrder(resultSet, this, session); 492 493 if (dbCall.isCursorReturned()) { 494 dbCall.setStatement(statement); 495 dbCall.setResult(resultSet); 496 return dbCall; 497 } 498 499 session.startOperationProfile(SessionProfiler.ROW_FETCH); 500 try { 501 if (dbCall.isOneRowReturned()) { 502 if (resultSet.next()) { 503 if (dbCall.isLOBLocatorNeeded()) { 504 getLOBWriter().fetchLocatorAndWriteValue(dbCall, resultSet); 509 } else { 510 result = fetchRow(dbCall.getFields(), resultSet, metaData, session); 511 } 512 if (resultSet.next()) { 513 session.getEventManager().moreRowsDetected(dbCall); 515 } 516 } else { 517 result = null; 518 } 519 } else { 520 boolean hasNext = resultSet.next(); 521 Vector results = null; 522 523 if (hasNext) { 525 if (shouldUseThreadCursors()) { 526 return buildThreadCursoredResult(dbCall, resultSet, statement, metaData, session); 529 } else { 530 results = new Vector(20); 531 while (hasNext) { 532 results.addElement(fetchRow(dbCall.getFields(), resultSet, metaData, session)); 533 hasNext = resultSet.next(); 534 } 535 } 536 } else { 537 results = new Vector(0); 538 } 539 result = results; 540 } 541 resultSet.close(); } finally { 543 session.endOperationProfile(SessionProfiler.ROW_FETCH); 544 } 545 } 546 } catch (SQLException exception) { 547 try { closeStatement(statement, session); 549 } catch (Exception closeException) { 550 } 551 throw DatabaseException.sqlException(exception, dbCall, this, session); 552 } catch (RuntimeException exception) { 553 try { closeStatement(statement, session); 555 } catch (Exception closeException) { 556 } 557 if (exception instanceof DatabaseException) { 558 ((DatabaseException)exception).setCall(dbCall); 559 } 560 throw exception; 561 } 562 563 try { 565 releaseStatement(statement, dbCall.getSQLString(), dbCall, session); 567 } catch (SQLException exception) { 568 throw DatabaseException.sqlException(exception, this, session); 569 } 570 571 return result; 572 } 573 574 protected Vector buildThreadCursoredResult(final DatabaseCall dbCall, final ResultSet resultSet, final Statement statement, final ResultSetMetaData metaData, final AbstractSession session) { 575 final ThreadCursoredList results = new ThreadCursoredList(20); 576 Thread thread = new Thread () { 577 public void run() { 578 session.startOperationProfile(SessionProfiler.ROW_FETCH); 579 try { 580 boolean hasNext = true; 582 while (hasNext) { 583 results.addElement(fetchRow(dbCall.getFields(), resultSet, metaData, session)); 584 hasNext = resultSet.next(); 585 } 586 resultSet.close(); } catch (SQLException exception) { 588 try { closeStatement(statement, session); 590 } catch (Exception closeException) { 591 } 592 results.throwException(DatabaseException.sqlException(exception, dbCall, DatabaseAccessor.this, session)); 593 } catch (RuntimeException exception) { 594 try { closeStatement(statement, session); 596 } catch (Exception closeException) { 597 } 598 if (exception instanceof DatabaseException) { 599 ((DatabaseException)exception).setCall(dbCall); 600 } 601 results.throwException(exception); 602 } finally { 603 session.endOperationProfile(SessionProfiler.ROW_FETCH); 604 } 605 606 try { 608 DatabaseAccessor.this.releaseStatement(statement, dbCall.getSQLString(), dbCall, session); 610 } catch (SQLException exception) { 611 results.throwException(DatabaseException.sqlException(exception, DatabaseAccessor.this, session)); 612 } 613 results.setIsComplete(true); 614 } 615 }; 616 thread.start(); 617 618 return results; 619 } 620 621 624 public Integer executeDirectNoSelect(Statement statement, DatabaseCall call, AbstractSession session) throws DatabaseException { 625 int rowCount = 0; 626 627 try { 628 session.startOperationProfile(SessionProfiler.STATEMENT_EXECUTE); 629 if ((call != null) && call.isDynamicCall(session)) { 630 rowCount = statement.executeUpdate(call.getSQLString()); 631 } else { 632 rowCount = ((PreparedStatement)statement).executeUpdate(); 633 } 634 if ((!getPlatform().supportsAutoCommit()) && (!isInTransaction())) { 635 getPlatform().autoCommit(this); 636 } 637 } catch (SQLException exception) { 638 if (!getPlatform().shouldIgnoreException(exception)) { 639 throw DatabaseException.sqlException(exception, this, session); 640 } 641 } finally { 642 session.endOperationProfile(SessionProfiler.STATEMENT_EXECUTE); 643 } 644 645 return new Integer (rowCount); 646 } 647 648 651 protected void executeJDK12BatchStatement(Statement statement, DatabaseCall dbCall, AbstractSession session) throws DatabaseException { 652 try { 653 statement.executeBatch(); 654 } catch (SQLException exception) { 655 try { closeStatement(statement, session); 657 } catch (SQLException closeException) { 658 } 659 660 throw DatabaseException.sqlException(exception, this, session); 661 } catch (RuntimeException exception) { 662 try { closeStatement(statement, session); 664 } catch (SQLException closeException) { 665 } 666 667 throw exception; 668 } 669 670 try { 672 if (dbCall != null) { 675 releaseStatement((PreparedStatement)statement, dbCall.getSQLString(), dbCall, session); 676 } else { 677 closeStatement(statement, session); 678 } 679 } catch (SQLException exception) { 680 throw DatabaseException.sqlException(exception, this, session); 681 } 682 } 683 684 687 protected Integer executeNoSelect(DatabaseCall call, Statement statement, AbstractSession session) throws DatabaseException { 688 Integer rowCount = executeDirectNoSelect(statement, call, session); 689 690 if (call.shouldBuildOutputRow()) { 692 AbstractRecord outputRow = buildOutputRow((CallableStatement)statement, call, session); 693 call.getQuery().setProperty("output", outputRow); 694 session.getEventManager().outputParametersDetected(outputRow, call); 695 } 696 697 return rowCount; 698 } 699 700 703 protected ResultSet executeSelect(DatabaseCall call, Statement statement, AbstractSession session) throws SQLException { 704 ResultSet resultSet; 705 706 session.startOperationProfile(SessionProfiler.STATEMENT_EXECUTE); 707 try { 708 if (call.isDynamicCall(session)) { 709 resultSet = statement.executeQuery(call.getSQLString()); 710 } else { 711 resultSet = ((PreparedStatement)statement).executeQuery(); 712 } 713 } finally { 714 session.endOperationProfile(SessionProfiler.STATEMENT_EXECUTE); 715 } 716 717 if (call.shouldBuildOutputRow()) { 719 AbstractRecord outputRow = buildOutputRow((CallableStatement)statement, call, session); 720 call.getQuery().setProperty("output", outputRow); 721 session.getEventManager().outputParametersDetected(outputRow, call); 722 } 723 724 return resultSet; 725 } 726 727 736 protected AbstractRecord fetchRow(Vector fields, ResultSet resultSet, ResultSetMetaData metaData, AbstractSession session) throws DatabaseException { 737 Vector values = new Vector(fields.size()); 738 DatabasePlatform platform = getPlatform(); 740 boolean optimizeData = platform.shouldOptimizeDataConversion(); 741 int size = fields.size(); 742 for (int index = 0; index < size; index++) { 743 DatabaseField field = (DatabaseField)fields.elementAt(index); 744 if (field != null) { 746 values.add(getObject(resultSet, field, metaData, index + 1, platform, optimizeData, session)); 747 } else { 748 values.add(null); 749 } 750 } 751 752 return new DatabaseRecord(fields, values); 754 } 755 756 804 public Vector getColumnInfo(String catalog, String schema, String tableName, String columnName, AbstractSession session) throws DatabaseException { 805 if (session.shouldLog(SessionLog.FINEST, SessionLog.QUERY)) { Object [] args = { catalog, schema, tableName, columnName }; 807 session.log(SessionLog.FINEST, SessionLog.QUERY, "query_column_meta_data_with_column", args, this); 808 } 809 Vector result = new Vector(); 810 ResultSet resultSet = null; 811 try { 812 incrementCallCount(session); 813 resultSet = getConnectionMetaData().getColumns(catalog, schema, tableName, columnName); 814 Vector fields = buildSortedFields(null, resultSet, session); 815 ResultSetMetaData metaData = resultSet.getMetaData(); 816 817 while (resultSet.next()) { 818 result.addElement(fetchRow(fields, resultSet, metaData, session)); 819 } 820 resultSet.close(); 821 } catch (SQLException sqlException) { 822 try { 823 if (resultSet != null) { 824 resultSet.close(); 825 } 826 } catch (SQLException closeException) { 827 } 828 829 throw DatabaseException.sqlException(sqlException, this, session); 831 } finally { 832 decrementCallCount(); 833 } 834 return result; 835 } 836 837 842 protected Vector getColumnNames(ResultSet resultSet, AbstractSession session) throws SQLException { 843 ResultSetMetaData metaData = resultSet.getMetaData(); 844 Vector columnNames = new Vector(metaData.getColumnCount()); 845 846 for (int index = 0; index < metaData.getColumnCount(); index++) { 847 String columnName = metaData.getColumnLabel(index + 1); 851 if ((columnName == null) || columnName.equals("")) { 852 columnName = "C" + (index + 1); } 854 855 if (getPlatform().shouldForceFieldNamesToUpperCase()) { 857 columnName = columnName.toUpperCase(); 858 } 859 columnNames.addElement(columnName); 860 } 861 return columnNames; 862 } 863 864 869 public Connection getConnection() throws DatabaseException { 870 return (Connection)getDatasourceConnection(); 871 } 872 873 876 public DatabasePlatform getPlatform() { 877 return (DatabasePlatform)platform; 878 } 879 880 883 public DatabaseMetaData getConnectionMetaData() throws SQLException { 884 return getConnection().getMetaData(); 885 } 886 887 892 protected Object getObject(ResultSet resultSet, DatabaseField field, ResultSetMetaData metaData, int columnNumber, DatabasePlatform platform, boolean optimizeData, AbstractSession session) throws DatabaseException { 893 Object value = null; 894 try { 895 int type = field.sqlType; 897 if (type == -1) { 898 type = metaData.getColumnType(columnNumber); 899 field.setSqlType(type); 900 } 901 902 if (optimizeData) { 903 try { 904 value = getObjectThroughOptimizedDataConversion(resultSet, field, type, columnNumber, platform, session); 905 if (value == null) { 907 return null; 908 } 909 if (value == this) { 910 value = null; 911 } 912 } catch (SQLException exception) { 913 if (session.shouldLog(SessionLog.WARNING, SessionLog.SQL)) { 915 session.logThrowable(SessionLog.WARNING, SessionLog.SQL, exception); 916 } 917 } 918 } 919 if (value == null) { 920 if ((type == Types.LONGVARBINARY) && platform.usesStreamsForBinding()) { 921 InputStream tempInputStream; 923 tempInputStream = resultSet.getBinaryStream(columnNumber); 924 if (tempInputStream != null) { 925 try { 926 ByteArrayOutputStream tempOutputStream = new ByteArrayOutputStream(); 927 int tempInt = tempInputStream.read(); 928 while (tempInt != -1) { 929 tempOutputStream.write(tempInt); 930 tempInt = tempInputStream.read(); 931 } 932 value = tempOutputStream.toByteArray(); 933 } catch (IOException exception) { 934 throw DatabaseException.errorReadingBlobData(); 935 } 936 } else { 937 value = null; 938 } 939 } else { 940 value = platform.getObjectFromResultSet(resultSet, columnNumber, type); 941 if (isBlob(type)) { 944 value = platform.convertObject(value, ClassConstants.APBYTE); 945 } 946 if (isClob(type)) { 947 value = getPlatform().convertObject(value, ClassConstants.STRING); 948 } 949 } 950 } 951 if (resultSet.wasNull()) { 952 value = null; 953 } 954 } catch (SQLException exception) { 955 throw DatabaseException.sqlException(exception, this, session); 956 } 957 958 return value; 959 } 960 961 965 protected Object getObjectThroughOptimizedDataConversion(ResultSet resultSet, DatabaseField field, int type, int columnNumber, DatabasePlatform platform, AbstractSession session) throws SQLException { 966 Object value = this; Class fieldType = field.type; 968 969 if ((fieldType == ClassConstants.PLONG) || (fieldType == ClassConstants.LONG)) { 971 value = new Long (resultSet.getLong(columnNumber)); 972 } else if ((type == Types.VARCHAR) || (type == Types.CHAR)) { 973 value = resultSet.getString(columnNumber); 976 if ((type == Types.CHAR) && (value != null) && platform.shouldTrimStrings()) { 977 value = Helper.rightTrimString((String )value); 978 } 979 } else if ((fieldType == ClassConstants.INTEGER) || (fieldType == ClassConstants.PINT)) { 980 value = new Integer (resultSet.getInt(columnNumber)); 981 } else if ((fieldType == ClassConstants.FLOAT) || (fieldType == ClassConstants.PFLOAT)) { 982 value = new Float (resultSet.getFloat(columnNumber)); 983 } else if ((fieldType == ClassConstants.DOUBLE) || (fieldType == ClassConstants.PDOUBLE)) { 984 value = new Double (resultSet.getDouble(columnNumber)); 985 } else if ((fieldType == ClassConstants.SHORT) || (fieldType == ClassConstants.PSHORT)) { 986 value = new Short (resultSet.getShort(columnNumber)); 987 } else if (Helper.shouldOptimizeDates() && (fieldType != null) && ((type == Types.TIME) || (type == Types.DATE) || (type == Types.TIMESTAMP))) { 988 String dateString = resultSet.getString(columnNumber); 990 value = platform.convertObject(dateString, fieldType); 991 } else if ((fieldType != null) && ((type == Types.TIME) || (type == Types.DATE) || (type == Types.TIMESTAMP))) { 992 if (fieldType == ClassConstants.SQLDATE) { 995 value = resultSet.getDate(columnNumber); 996 } else if (fieldType == ClassConstants.TIME) { 997 value = resultSet.getTime(columnNumber); 998 } else if (fieldType == ClassConstants.TIMESTAMP) { 999 value = resultSet.getTimestamp(columnNumber); 1000 } 1001 } 1002 1003 return value; 1004 } 1005 1006 1010 protected boolean hasStatementCache() { 1011 return (statementCache != null) && (!statementCache.isEmpty()); 1012 } 1013 1014 1017 protected synchronized Hashtable getStatementCache() { 1018 if (statementCache == null) { 1019 statementCache = new Hashtable(50); 1020 } 1021 return statementCache; 1022 } 1023 1024 1053 public Vector getTableInfo(String catalog, String schema, String tableName, String [] types, AbstractSession session) throws DatabaseException { 1054 if (session.shouldLog(SessionLog.FINEST, SessionLog.QUERY)) { Object [] args = { catalog, schema, tableName }; 1056 session.log(SessionLog.FINEST, SessionLog.QUERY, "query_column_meta_data", args, this); 1057 } 1058 Vector result = new Vector(); 1059 ResultSet resultSet = null; 1060 try { 1061 incrementCallCount(session); 1062 resultSet = getConnectionMetaData().getTables(catalog, schema, tableName, types); 1063 Vector fields = buildSortedFields(null, resultSet, session); 1064 ResultSetMetaData metaData = resultSet.getMetaData(); 1065 1066 while (resultSet.next()) { 1067 result.addElement(fetchRow(fields, resultSet, metaData, session)); 1068 } 1069 resultSet.close(); 1070 } catch (SQLException sqlException) { 1071 try { 1072 if (resultSet != null) { 1073 resultSet.close(); 1074 } 1075 } catch (SQLException closeException) { 1076 } 1077 1078 throw DatabaseException.sqlException(sqlException, this, session); 1080 } finally { 1081 decrementCallCount(); 1082 } 1083 return result; 1084 } 1085 1086 1089 public boolean isDatasourceConnected() { 1090 try { 1091 return !getConnection().isClosed(); 1092 } catch (SQLException exception) { 1093 throw DatabaseException.sqlException(exception, this, null); 1094 } 1095 } 1096 1097 1101 public boolean shouldUseThreadCursors() { 1102 return shouldUseThreadCursors; 1103 } 1104 1105 1109 public void setShouldUseThreadCursors(boolean shouldUseThreadCursors) { 1110 this.shouldUseThreadCursors = shouldUseThreadCursors; 1111 } 1112 1113 1118 public Statement prepareStatement(DatabaseCall call, AbstractSession session) throws SQLException { 1119 Statement statement = null; 1120 if (call.usesBinding(session) && call.shouldCacheStatement(session)) { 1121 synchronized (getStatementCache()) { 1123 statement = (PreparedStatement)getStatementCache().get(call.getSQLString()); 1124 if (statement != null) { 1125 getStatementCache().remove(call.getSQLString()); 1127 } 1128 } 1129 } 1130 1131 if (statement == null) { 1132 if (call.isCallableStatementRequired()) { 1133 if (call.isResultSetScrollable()) { 1135 statement = getConnection().prepareCall(call.getSQLString(), call.getResultSetType(), call.getResultSetConcurrency()); 1136 } else { 1137 statement = getConnection().prepareCall(call.getSQLString()); 1138 } 1139 } else if (call.isResultSetScrollable()) { 1140 statement = getConnection().prepareStatement(call.getSQLString(), call.getResultSetType(), call.getResultSetConcurrency()); 1142 } else if (call.isDynamicCall(session)) { 1143 statement = allocateDynamicStatement(); 1145 } else { 1146 statement = getConnection().prepareStatement(call.getSQLString()); 1148 } 1149 } 1150 1151 return statement; 1152 } 1153 1154 1160 protected void reconnect(AbstractSession session) { 1161 clearStatementCache(session); 1162 super.reconnect(session); 1163 } 1164 1165 1168 protected void releaseStatement(Statement statement, String sqlString, DatabaseCall call, AbstractSession session) throws SQLException { 1169 if (call.usesBinding(session) && call.shouldCacheStatement(session)) { 1170 synchronized (getStatementCache()) { 1171 PreparedStatement preparedStatement = (PreparedStatement)statement; 1172 if (!getStatementCache().containsKey(sqlString)) { preparedStatement.clearParameters(); 1174 if (getStatementCache().size() > getPlatform().getStatementCacheSize()) { 1175 PreparedStatement removedStatement = (PreparedStatement)getStatementCache().remove(getStatementCache().keys().nextElement()); 1177 closeStatement(removedStatement, session); 1178 } else { 1179 decrementCallCount(); 1180 } 1181 getStatementCache().put(sqlString, preparedStatement); 1182 } else { 1183 closeStatement(statement, session); 1185 } 1186 } 1187 } else if (statement == this.dynamicStatement) { 1188 if (call.getMaxRows() > 0) { 1189 statement.setMaxRows(0); 1190 } 1191 setIsDynamicStatementInUse(false); 1192 decrementCallCount(); 1193 } else { 1194 closeStatement(statement, session); 1195 } 1196 } 1197 1198 1201 public void basicRollbackTransaction(AbstractSession session) throws DatabaseException { 1202 try { 1203 if (getPlatform().supportsAutoCommit()) { 1204 getConnection().rollback(); 1205 getConnection().setAutoCommit(true); 1206 } else { 1207 getPlatform().rollbackTransaction(this); 1208 } 1209 } catch (SQLException exception) { 1210 throw DatabaseException.sqlException(exception, this, session); 1211 } 1212 } 1213 1214 1217 protected void setStatementCache(Hashtable statementCache) { 1218 this.statementCache = statementCache; 1219 } 1220 1221 1225 protected Vector sortFields(Vector fields, Vector columnNames) { 1226 Vector sortedFields = new Vector(columnNames.size()); 1227 Vector eligableFields = (Vector)fields.clone(); Enumeration columnNamesEnum = columnNames.elements(); 1229 boolean valueFound = false; 1230 while (columnNamesEnum.hasMoreElements()) { 1231 String columnName = (String )columnNamesEnum.nextElement(); 1232 1233 DatabaseField field = null; 1234 Enumeration fieldEnum = eligableFields.elements(); 1235 while (fieldEnum.hasMoreElements()) { 1236 field = (DatabaseField)fieldEnum.nextElement(); 1237 if (DatabasePlatform.shouldIgnoreCaseOnFieldComparisons()) { 1238 if (field.getName().equalsIgnoreCase(columnName)) { 1239 valueFound = true; 1240 sortedFields.addElement(field); 1241 break; 1242 } 1243 } else { 1244 if (field.getName().equals(columnName)) { 1245 valueFound = true; 1246 sortedFields.addElement(field); 1247 break; 1248 } 1249 } 1250 } 1251 1252 if (valueFound) { 1253 eligableFields.removeElement(field); 1255 } else { 1256 sortedFields.addElement(new DatabaseField()); 1258 } 1259 valueFound = false; 1260 } 1261 1262 return sortedFields; 1263 } 1264 1265 public String toString() { 1266 StringWriter writer = new StringWriter(); 1267 writer.write("DatabaseAccessor("); 1268 if (isConnected()) { 1269 writer.write(ToStringLocalization.buildMessage("connected", (Object [])null)); 1270 } else { 1271 writer.write(ToStringLocalization.buildMessage("disconnected", (Object [])null)); 1272 } 1273 writer.write(")"); 1274 return writer.toString(); 1275 } 1276 1277 1280 private boolean isBlob(int type) { 1281 return (type == Types.BLOB) || (type == Types.LONGVARBINARY); 1282 } 1283 1284 1287 private boolean isClob(int type) { 1288 return (type == Types.CLOB) || (type == Types.LONGVARCHAR); 1289 } 1290 1291 1297 public void writesCompleted(AbstractSession session) { 1298 } 1300} 1301 | Popular Tags |