1 24 25 package org.continuent.sequoia.driver; 26 27 import java.sql.BatchUpdateException ; 28 import java.sql.ResultSet ; 29 import java.sql.ResultSetMetaData ; 30 import java.sql.SQLException ; 31 import java.sql.SQLWarning ; 32 import java.util.ArrayList ; 33 import java.util.Iterator ; 34 import java.util.LinkedList ; 35 import java.util.Vector ; 36 import java.util.regex.Matcher ; 37 38 import org.continuent.sequoia.common.exceptions.NotImplementedException; 39 import org.continuent.sequoia.common.protocol.Field; 40 import org.continuent.sequoia.common.sql.Request; 41 import org.continuent.sequoia.common.sql.RequestWithResultSetParameters; 42 43 62 public class Statement implements java.sql.Statement 63 { 64 65 protected Driver driver; 66 67 68 protected Connection connection = null; 69 70 71 protected Vector batch = null; 72 73 74 SQLWarning warnings = null; 75 76 77 protected ResultSet result = null; 78 79 80 protected LinkedList resultList = null; 81 protected Iterator resultListIterator = null; 82 83 84 protected int updateCount = -1; 85 86 87 protected int timeout = 0; 88 89 90 private int fetchSize = 0; 91 92 private String cursorName; 93 94 95 private int resultSetType = ResultSet.TYPE_FORWARD_ONLY; 96 97 98 private int resultSetConcurrency = ResultSet.CONCUR_READ_ONLY; 99 100 101 private int maxFieldSize = 0; 102 103 104 private int maxRows = 0; 105 106 110 private int fetchDirection = ResultSet.FETCH_FORWARD; 111 112 115 protected boolean escapeProcessing = true; 116 117 118 protected ResultSet generatedKeys = null; 119 protected int generatedKeysFlag = java.sql.Statement.NO_GENERATED_KEYS; 120 121 127 Statement(Connection c, Driver driver) 128 { 129 connection = c; 130 this.driver = driver; 131 } 132 133 139 public synchronized void addBatch(String sql) throws SQLException 140 { 141 if (batch == null) 142 batch = new Vector (); 143 batch.addElement(sql.trim()); 144 } 145 146 152 public void cancel() throws SQLException 153 { 154 throw new NotImplementedException("cancel()"); 155 } 156 157 162 public void clearBatch() throws SQLException 163 { 164 if (batch != null) 165 batch.removeAllElements(); 166 } 167 168 174 public void clearWarnings() throws SQLException 175 { 176 warnings = null; 177 } 178 179 186 protected void addWarningTo(SQLWarning addMe, SQLWarning toThis) 187 { 188 if (toThis != null) 189 toThis.setNextWarning(warnings); 190 else 191 toThis = warnings; 192 } 193 194 204 public int[] executeBatch() throws BatchUpdateException 205 { 206 if (batch == null || batch.isEmpty()) 207 return new int[0]; 208 209 ArrayList generatedKeysData = null; 210 Field generatedKeysField = null; 211 if (connection.isAlwaysGettingGeneratedKeys()) 212 generatedKeysData = new ArrayList (); 213 214 int size = batch.size(); 215 int[] batchResult = new int[size]; 216 int i = 0; 217 SQLWarning allWarnings = null; 220 try 221 { 222 for (i = 0; i < size; i++) 223 { 224 batchResult[i] = this.executeUpdate((String ) batch.elementAt(i)); 225 if (warnings != null) 226 addWarningTo(warnings, allWarnings); 227 if (connection.isAlwaysGettingGeneratedKeys()) 228 { 229 if (generatedKeys != null) 230 { 231 while (generatedKeys.next()) 232 { 233 generatedKeysData.add(generatedKeys.getObject(1)); 234 if (generatedKeysField == null) 235 { 236 ResultSetMetaData metaData = generatedKeys.getMetaData(); 237 generatedKeysField = new Field(metaData.getTableName(1), 238 metaData.getColumnName(1), 239 metaData.getColumnDisplaySize(1), 240 metaData.getColumnType(1), metaData.getColumnTypeName(1), 241 metaData.getColumnClassName(1)); 242 } 243 } 244 } 245 } 246 } 247 warnings = allWarnings; 249 generatedKeys = new DriverResultSet(connection, generatedKeysData, 250 generatedKeysField); 251 return batchResult; 252 } 253 catch (SQLException e) 254 { 255 String message = "Batch failed for request " + i + ": " 256 + batch.elementAt(i) + " (" + e + ")"; 257 258 int[] updateCounts = new int[i]; 259 System.arraycopy(batchResult, 0, updateCounts, 0, i); 260 261 throw new BatchUpdateException (message, updateCounts); 262 } 263 finally 264 { 265 batch.removeAllElements(); 266 } 267 } 268 269 280 public void close() throws SQLException 281 { 282 if (result != null) 284 try 285 { 286 result.close(); 287 } 288 catch (SQLException ignore) 289 { 290 } 291 292 result = null; 294 connection = null; 295 } 296 297 303 private void checkIfClosedAndCleanupLastResult() throws SQLException 304 { 305 if (isClosed()) 306 throw new SQLException ("Unable to execute query on a closed statement"); 307 308 updateCount = -1; if (result != null) 310 { try 312 { 313 result.close(); 314 } 315 catch (Exception ignore) 316 { 317 } 318 result = null; 319 } 320 if (generatedKeys != null) 321 { try 323 { 324 generatedKeys.close(); 325 } 326 catch (Exception ignore) 327 { 328 } 329 generatedKeys = null; 330 } 331 resultList = null; 332 resultListIterator = null; 333 clearWarnings(); 334 } 335 336 344 private boolean sqlHasBeenMappedToJDBCCall(String sqlQuery) 345 throws SQLException 346 { 347 final JDBCRegExp jdbcRegExp = driver.getJDBCRegExp(); 348 if (jdbcRegExp.getBeginPattern().matcher(sqlQuery).matches()) 349 { 350 connection.setAutoCommit(false); 351 return true; 352 } 353 if (jdbcRegExp.getCommitPattern().matcher(sqlQuery).matches()) 354 { 355 connection.commit(); 356 return true; 357 } 358 Matcher m = jdbcRegExp.getRollbackToSavepointPattern().matcher(sqlQuery); 359 if (m.matches()) 360 { 361 connection.rollback(new Savepoint(sqlQuery.substring(m.end(), 363 sqlQuery.length()).trim())); 364 return true; 365 } 366 m = jdbcRegExp.getReleaseSavepointPattern().matcher(sqlQuery); 367 if (m.matches()) 368 { 369 connection.releaseSavepoint(new Savepoint(sqlQuery.substring(m.end(), 371 sqlQuery.length()).trim())); 372 return true; 373 } 374 if (jdbcRegExp.getRollbackPattern().matcher(sqlQuery).matches()) 375 { 376 connection.rollback(); 377 return true; 378 } 379 if (jdbcRegExp.getSetReadOnlyTransactionPattern().matcher(sqlQuery) 380 .matches()) 381 { 382 connection.setReadOnly(true); 383 return true; 384 } 385 m = jdbcRegExp.getSetSavepointPattern().matcher(sqlQuery); 386 if (m.matches()) 387 { 388 connection.setSavepoint(sqlQuery.substring(m.end(), sqlQuery.length()) 390 .trim()); 391 return true; 392 } 393 m = jdbcRegExp.getSetAutocommit1Pattern().matcher(sqlQuery); 394 if (m.matches()) 395 { 396 connection.setAutoCommit(true); 397 return true; 398 } 399 m = jdbcRegExp.getSetIsolationLevelPattern().matcher(sqlQuery); 400 if (m.matches()) 401 { 402 String isolationLevel = sqlQuery.substring(m.end(), sqlQuery.length()) 403 .toLowerCase(); 404 if (isolationLevel.startsWith("read commited")) 405 { 406 connection 407 .setTransactionIsolation(java.sql.Connection.TRANSACTION_READ_COMMITTED); 408 return true; 409 } 410 if (isolationLevel.startsWith("read uncommited")) 411 { 412 connection 413 .setTransactionIsolation(java.sql.Connection.TRANSACTION_READ_UNCOMMITTED); 414 return true; 415 } 416 if (isolationLevel.startsWith("repeatable read")) 417 { 418 connection 419 .setTransactionIsolation(java.sql.Connection.TRANSACTION_REPEATABLE_READ); 420 return true; 421 } 422 if (isolationLevel.startsWith("serializable")) 423 { 424 connection 425 .setTransactionIsolation(java.sql.Connection.TRANSACTION_SERIALIZABLE); 426 427 return true; 428 } 429 } 430 return false; 431 } 432 433 440 public boolean execute(String sql) throws SQLException 441 { 442 if (connection.isAlwaysGettingGeneratedKeys() 443 && sql.toLowerCase().trim().startsWith("insert")) 444 return execute(sql, RETURN_GENERATED_KEYS); 445 return execute(sql.trim(), (String ) null); 446 } 447 448 457 protected boolean execute(String sqlSkeleton, String parameters) 458 throws SQLException 459 { 460 checkIfClosedAndCleanupLastResult(); 461 462 if (sqlHasBeenMappedToJDBCCall(sqlSkeleton)) 463 return false; 464 465 RequestWithResultSetParameters request = new RequestWithResultSetParameters( 466 sqlSkeleton, parameters, escapeProcessing, timeout); 467 setReadRequestParameters(request); 468 ResultAndWarnings resultAndWarns = connection.statementExecute(request); 469 this.warnings = resultAndWarns.getStatementWarnings(); 470 resultList = (LinkedList ) resultAndWarns.getResultList(); 471 resultListIterator = resultList.iterator(); 472 generatedKeys = new DriverResultSet(this.connection, true); 473 return getMoreResults(); 474 } 475 476 483 public java.sql.ResultSet executeQuery(String sql) throws SQLException 484 { 485 return executeQuery(sql.trim(), null); 486 } 487 488 497 protected java.sql.ResultSet executeQuery(String sqlSkeleton, 498 String parameters) throws SQLException 499 { 500 checkIfClosedAndCleanupLastResult(); 501 502 if (sqlHasBeenMappedToJDBCCall(sqlSkeleton)) 503 return null; 508 509 RequestWithResultSetParameters request = new RequestWithResultSetParameters( 510 sqlSkeleton, parameters, escapeProcessing, timeout); 511 setReadRequestParameters(request); 512 DriverResultSet drs = connection.statementExecuteQuery(request); 513 drs.setStatement(this); 514 this.warnings = drs.getStatementWarnings(); 515 this.result = drs; 516 517 return result; 518 } 519 520 protected void setReadRequestParameters(RequestWithResultSetParameters request) 521 { 522 request.setMaxRows(maxRows); 523 request.setFetchSize(fetchSize); 524 request.setCursorName(cursorName); 525 } 526 527 535 public int executeUpdate(String sql) throws SQLException 536 { 537 if (connection.isAlwaysGettingGeneratedKeys()) 538 generatedKeysFlag = RETURN_GENERATED_KEYS; 539 return executeUpdateWithSkeleton(sql.trim(), null); 540 } 541 542 552 protected int executeUpdateWithSkeleton(String sqlSkeleton, String parameters) 553 throws SQLException 554 { 555 checkIfClosedAndCleanupLastResult(); 556 557 if (sqlHasBeenMappedToJDBCCall(sqlSkeleton)) 558 return 0; 559 560 Request request = new Request(sqlSkeleton, parameters, escapeProcessing, 561 timeout); 562 563 if (generatedKeysFlag == java.sql.Statement.RETURN_GENERATED_KEYS) 564 { DriverGeneratedKeysResult answer = connection 566 .statementExecuteUpdateWithKeys(request); 567 generatedKeys = answer.getDriverResultSet(); 568 updateCount = answer.getUpdateCount(); 569 warnings = answer.getWarnings(); 570 return answer.getUpdateCount(); 571 } 572 else 573 { ResultAndWarnings resultAndWarns = connection 575 .statementExecuteUpdate(request); 576 this.warnings = resultAndWarns.getStatementWarnings(); 577 updateCount = resultAndWarns.getUpdateCount(); 578 generatedKeys = new DriverResultSet(this.connection, true); 579 return updateCount; 580 } 581 } 582 583 589 public java.sql.Connection getConnection() throws SQLException 590 { 591 return connection; 592 } 593 594 597 public int getFetchDirection() throws SQLException 598 { 599 return fetchDirection; 600 } 601 602 605 public int getFetchSize() throws SQLException 606 { 607 return fetchSize; 608 } 609 610 622 public int getMaxFieldSize() throws SQLException 623 { 624 return maxFieldSize; 625 } 626 627 635 public int getMaxRows() throws SQLException 636 { 637 return maxRows; 638 } 639 640 650 public boolean getMoreResults() throws SQLException 651 { 652 return getMoreResults(CLOSE_CURRENT_RESULT); 653 } 654 655 663 public int getQueryTimeout() throws SQLException 664 { 665 return timeout; 666 } 667 668 674 public java.sql.ResultSet getResultSet() throws SQLException 675 { 676 return result; 677 } 678 679 685 public int getResultSetConcurrency() throws SQLException 686 { 687 return resultSetConcurrency; 688 } 689 690 697 public int getResultSetType() throws SQLException 698 { 699 return resultSetType; 700 } 701 702 710 public int getUpdateCount() throws SQLException 711 { 712 return updateCount; 713 } 714 715 731 public SQLWarning getWarnings() throws SQLException 732 { 733 if (isClosed()) 734 throw new SQLException ("Unable to get warnings on a closed statement"); 735 return warnings; 736 } 737 738 749 public void setCursorName(String name) throws SQLException 750 { 751 cursorName = name; 752 } 753 754 761 public void setEscapeProcessing(boolean enable) throws SQLException 762 { 763 escapeProcessing = enable; 764 } 765 766 769 public void setFetchDirection(int direction) throws SQLException 770 { 771 if ((direction == ResultSet.FETCH_FORWARD) 772 || (direction == ResultSet.FETCH_REVERSE) 773 || (direction == ResultSet.FETCH_UNKNOWN)) 774 this.fetchDirection = direction; 775 else 776 throw new SQLException ("Unsupported direction " + direction 777 + " in setFetchDirection"); 778 } 779 780 787 public void setFetchSize(int rows) throws SQLException 788 { 789 if (rows < 0 790 || 0 < maxRows && maxRows < rows) 792 { 793 throw new SQLException ("Invalid fetch size value: " + rows); 794 } 795 798 fetchSize = rows; 799 } 800 801 808 public void setMaxFieldSize(int max) throws SQLException 809 { 810 if (max < 0) 811 { 812 throw new SQLException ("Invalid max field size value: " + max); 813 } 814 maxFieldSize = max; 815 } 816 817 825 public void setMaxRows(int max) throws SQLException 826 { 827 if (max < 0) 828 { 829 throw new SQLException ("Invalid max rows limit: " + max); 830 } 831 maxRows = max; 833 } 834 835 843 public void setQueryTimeout(int seconds) throws SQLException 844 { 845 if (seconds < 0) 846 { 847 throw new SQLException ("Invalid query timeout value: " + seconds); 848 } 849 timeout = seconds; 850 } 851 852 856 public void setResultSetConcurrency(int value) throws SQLException 857 { 858 switch (value) 859 { 860 case ResultSet.CONCUR_READ_ONLY : 861 case ResultSet.CONCUR_UPDATABLE : 862 resultSetConcurrency = value; 863 break; 864 default : 865 throw new SQLException ("Invalid ResultSet " + "concurrency mode: " 866 + value); 867 } 868 } 869 870 874 public void setResultSetType(int value) throws SQLException 875 { 876 switch (value) 877 { 878 case ResultSet.TYPE_FORWARD_ONLY : 879 case ResultSet.TYPE_SCROLL_INSENSITIVE : 880 resultSetType = value; 881 break; 882 case ResultSet.TYPE_SCROLL_SENSITIVE : 883 throw new SQLException ( 884 "TYPE_SCROLL_SENSITIVE is not a supported ResultSet type"); 885 default : 886 throw new SQLException ("Invalid ResultSet type"); 887 } 888 } 889 890 892 914 public boolean getMoreResults(int current) throws SQLException 915 { 916 if (current != KEEP_CURRENT_RESULT) 919 { 920 if (result != null) 921 try 922 { 923 result.close(); 924 } 925 catch (SQLException ignore) 926 { 927 } 928 } 929 930 updateCount = -1; 933 result = null; 934 935 if (!resultListIterator.hasNext()) 936 { 937 return false; 939 } 940 941 Object nextResult = resultListIterator.next(); 942 if (nextResult instanceof DriverResultSet) 943 { 944 result = (ResultSet ) nextResult; 949 950 ((DriverResultSet) result).setStatement(this); 953 return true; 954 } 955 if (nextResult instanceof Integer ) 956 { 957 updateCount = ((Integer ) nextResult).intValue(); 958 return false; 959 } 960 throw new SQLException ("Unexpected result type in getMoreResults (" 961 + nextResult + ")"); 962 } 963 964 976 public java.sql.ResultSet getGeneratedKeys() throws SQLException 977 { 978 return generatedKeys; 979 } 980 981 1001 public int executeUpdate(String sql, int autoGeneratedKeys) 1002 throws SQLException 1003 { 1004 if (!connection.isAlwaysGettingGeneratedKeys()) 1005 generatedKeysFlag = autoGeneratedKeys; 1006 else 1007 generatedKeysFlag = RETURN_GENERATED_KEYS; 1008 int executeUpdateResult = executeUpdate(sql); 1009 if (!connection.isAlwaysGettingGeneratedKeys()) 1010 generatedKeysFlag = NO_GENERATED_KEYS; 1011 return executeUpdateResult; 1012 } 1013 1014 1032 public int executeUpdate(String sql, int[] columnIndexes) throws SQLException 1033 { 1034 return executeUpdate(sql, RETURN_GENERATED_KEYS); 1035 } 1036 1037 1054 public int executeUpdate(String sql, String [] columnNames) 1055 throws SQLException 1056 { 1057 return executeUpdate(sql, RETURN_GENERATED_KEYS); 1058 } 1059 1060 1093 public boolean execute(String sql, int autoGeneratedKeys) throws SQLException 1094 { 1095 if (connection.isAlwaysGettingGeneratedKeys() 1096 && sql.toLowerCase().trim().startsWith("insert")) 1097 generatedKeysFlag = RETURN_GENERATED_KEYS; 1098 else 1099 generatedKeysFlag = autoGeneratedKeys; 1100 1101 if (autoGeneratedKeys == RETURN_GENERATED_KEYS) 1102 { 1103 int executeUpdateResult = executeUpdate(sql); 1104 resultList = new LinkedList (); 1105 resultList.add(new Integer (executeUpdateResult)); 1106 resultListIterator = resultList.iterator(); 1107 if (!connection.isAlwaysGettingGeneratedKeys()) 1108 autoGeneratedKeys = NO_GENERATED_KEYS; 1109 return getMoreResults(); 1110 } 1111 return execute(sql); 1112 } 1113 1114 1147 public boolean execute(String sql, int[] columnIndexes) throws SQLException 1148 { 1149 return execute(sql, RETURN_GENERATED_KEYS); 1150 } 1151 1152 1185 public boolean execute(String sql, String [] columnNames) throws SQLException 1186 { 1187 return execute(sql, RETURN_GENERATED_KEYS); 1188 } 1189 1190 1199 public int getResultSetHoldability() throws SQLException 1200 { 1201 return connection.getHoldability(); 1202 } 1203 1204 1209 protected boolean isClosed() 1210 { 1211 return (connection == null); 1212 } 1213} | Popular Tags |