You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by ba...@apache.org on 2005/11/14 16:43:04 UTC
svn commit: r344147 - in /db/derby/code/trunk/java:
client/org/apache/derby/client/am/ drda/org/apache/derby/impl/drda/
testing/org/apache/derbyTesting/functionTests/suites/
testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/
Author: bakksjo
Date: Mon Nov 14 07:42:40 2005
New Revision: 344147
URL: http://svn.apache.org/viewcvs?rev=344147&view=rev
Log:
DERBY-506
Implements Statement.setQueryTimeout in the client driver by
"piggybacking" an EXCSQLSET command on statement execution.
Modified:
db/derby/code/trunk/java/client/org/apache/derby/client/am/PreparedStatement.java
db/derby/code/trunk/java/client/org/apache/derby/client/am/Statement.java
db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DRDAConnThread.java
db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/DerbyNetClient.exclude
db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/SetQueryTimeoutTest.java
Modified: db/derby/code/trunk/java/client/org/apache/derby/client/am/PreparedStatement.java
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/client/org/apache/derby/client/am/PreparedStatement.java?rev=344147&r1=344146&r2=344147&view=diff
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/am/PreparedStatement.java (original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/am/PreparedStatement.java Mon Nov 14 07:42:40 2005
@@ -1259,15 +1259,6 @@
updateCount_ = -1;
}
- java.util.Timer queryTimer = null;
- QueryTimerTask queryTimerTask = null;
- if (timeout_ != 0) {
- queryTimer = new java.util.Timer(); // A thread that ticks the seconds
- queryTimerTask = new QueryTimerTask(this, queryTimer);
- queryTimer.schedule(queryTimerTask, 1000 * timeout_);
- }
-
- try {
agent_.beginWriteChain(this);
boolean piggybackedAutocommit = super.writeCloseResultSets(true); // true means permit auto-commits
@@ -1278,8 +1269,15 @@
boolean chainAutoCommit = false;
boolean commitSubstituted = false;
boolean repositionedCursor = false;
+ boolean timeoutSent = false;
ResultSet scrollableRS = null;
+ if (doWriteTimeout) {
+ timeoutArrayList.set(0, TIMEOUT_STATEMENT + timeout_);
+ writeSetSpecialRegister(timeoutArrayList);
+ doWriteTimeout = false;
+ timeoutSent = true;
+ }
switch (sqlMode_) {
case isUpdate__:
if (positionedUpdateCursorName_ != null) {
@@ -1369,6 +1367,10 @@
super.markResultSetsClosed(true); // true means remove from list of commit and rollback listeners
+ if (timeoutSent) {
+ readSetSpecialRegister(); // Read response to the EXCSQLSET
+ }
+
switch (sqlMode_) {
case isUpdate__:
// do not need to reposition for a rowset cursor
@@ -1450,14 +1452,6 @@
throw new SqlException(agent_.logWriter_, "Unable to open resultSet with requested " +
"holdability " + resultSetHoldability_ + ".");
}
-
- } finally {
- if (timeout_ != 0) { // query timers need to be cancelled.
- queryTimer.cancel();
- queryTimerTask.cancel();
- }
- }
-
}
public int[] executeBatchX(boolean supportsQueryBatchRequest) throws SqlException, BatchUpdateException {
@@ -1476,6 +1470,7 @@
int[] updateCounts = new int[batchSize];
int numInputColumns = parameterMetaData_ == null ? 0 : parameterMetaData_.getColumnCount();
Object[] savedInputs = null; // used to save/restore existing parameters
+ boolean timeoutSent = false;
if (batchSize == 0) {
return updateCounts;
@@ -1510,6 +1505,13 @@
agent_.beginBatchedWriteChain(this);
boolean chainAutoCommit = connection_.willAutoCommitGenerateFlow() && isAutoCommittableStatement_;
+ if (doWriteTimeout) {
+ timeoutArrayList.set(0, TIMEOUT_STATEMENT + timeout_);
+ writeSetSpecialRegister(timeoutArrayList);
+ doWriteTimeout = false;
+ timeoutSent = true;
+ }
+
for (int i = 0; i < batchSize; i++) {
parameters_ = (Object[]) batch_.get(i);
@@ -1553,6 +1555,10 @@
}
agent_.flowBatch(this, batchSize);
+
+ if (timeoutSent) {
+ readSetSpecialRegister(); // Read response to the EXCSQLSET
+ }
try {
for (int i = 0; i < batchSize; i++) {
Modified: db/derby/code/trunk/java/client/org/apache/derby/client/am/Statement.java
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/client/org/apache/derby/client/am/Statement.java?rev=344147&r1=344146&r2=344147&view=diff
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/am/Statement.java (original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/am/Statement.java Mon Nov 14 07:42:40 2005
@@ -131,7 +131,10 @@
protected int indexOfCurrentResultSet_ = -1;
ResultSet[] resultSetList_ = null; // array of ResultSet objects
- int timeout_ = 0; // for query timeout in seconds, multiplied by 1000 when passed to java.util.Timer
+ protected final static String TIMEOUT_STATEMENT = "SET STATEMENT_TIMEOUT ";
+ protected java.util.ArrayList timeoutArrayList = new java.util.ArrayList(1);
+ protected boolean doWriteTimeout = false;
+ int timeout_ = 0; // for query timeout in seconds
int maxRows_ = 0;
int maxFieldSize_ = 0; // zero means that there is no limit to the size of a column.
boolean escapedProcedureCallWithResult_ = false;
@@ -204,6 +207,9 @@
resultSetConcurrency_ = java.sql.ResultSet.CONCUR_READ_ONLY;
resultSetHoldability_ = 0;
cursorAttributesToSendOnPrepare_ = null;
+ if (timeoutArrayList.size() == 0) {
+ timeoutArrayList.add(null); // Make sure the list's length is 1
+ }
initResetStatement();
}
@@ -232,6 +238,7 @@
indexOfCurrentResultSet_ = -1;
resultSetList_ = null;
timeout_ = 0;
+ doWriteTimeout = false;
maxRows_ = 0;
maxFieldSize_ = 0;
escapedProcedureCallWithResult_ = false;
@@ -536,9 +543,14 @@
}
checkForClosedStatement(); // Per jdbc spec (see java.sql.Statement.close() javadoc)
if (seconds < 0) {
- throw new SqlException(agent_.logWriter_, "Attempt to set a negative query timeout");
+ throw new SqlException(agent_.logWriter_,
+ "Attempt to set a negative query timeout",
+ "XJ074.S");
+ }
+ if (seconds != timeout_) {
+ timeout_ = seconds;
+ doWriteTimeout = true;
}
- timeout_ = seconds; // java.util.Timer takes milliseconds
}
}
@@ -1446,17 +1458,8 @@
checkForAppropriateSqlMode(executeType, sqlMode_);
- java.util.Timer queryTimer = null;
- QueryTimerTask queryTimerTask = null;
- if (timeout_ != 0) {
- queryTimer = new java.util.Timer(); // A thread that ticks the seconds
- queryTimerTask = new QueryTimerTask(this, queryTimer);
- queryTimer.schedule(queryTimerTask, 1000 * timeout_);
- }
+ boolean timeoutSent = false;
- // enclose the processing in a try finally block in order to make sure
- // the query timeout is cancelled at the end of this method.
- try {
agent_.beginWriteChain(this);
boolean piggybackedAutoCommit = writeCloseResultSets(true); // true means permit auto-commits
@@ -1464,6 +1467,12 @@
Section newSection = null;
boolean repositionedCursor = false;
+ if (doWriteTimeout) {
+ timeoutArrayList.set(0, TIMEOUT_STATEMENT + timeout_);
+ writeSetSpecialRegister(timeoutArrayList);
+ doWriteTimeout = false;
+ timeoutSent = true;
+ }
switch (sqlMode_) {
case isQuery__:
newSection = agent_.sectionManager_.getDynamicSection(resultSetHoldability_);
@@ -1555,6 +1564,10 @@
readCloseResultSets(true); // true means permit auto-commits
+ if (timeoutSent) {
+ readSetSpecialRegister(); // Read response to the EXCSQLSET
+ }
+
// turn inUnitOfWork_ flag back on and add statement
// back on commitListeners_ list if they were off
// by an autocommit chained to a close cursor.
@@ -1634,15 +1647,6 @@
throw new SqlException(agent_.logWriter_, "Unable to open resultSet with requested " +
"holdability " + resultSetHoldability_ + ".");
}
- } finally {
- // We don't want to cancel immediately after flow since there is still incoming data on the wire and
- // so logically we have not completed a full traversal from the client to the server and back.
- // Cancelling the query timers needs to occur after endReadChain() in order to avoid deadlock conditions.
- if (timeout_ != 0) { // query timers need to be cancelled.
- queryTimer.cancel();
- queryTimerTask.cancel();
- }
- }
// In the case of executing a call to a stored procedure.
if (sqlMode_ == isCall__) {
Modified: db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DRDAConnThread.java
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DRDAConnThread.java?rev=344147&r1=344146&r2=344147&view=diff
==============================================================================
--- db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DRDAConnThread.java (original)
+++ db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DRDAConnThread.java Mon Nov 14 07:42:40 2005
@@ -139,6 +139,10 @@
private String pkgcnstknStr;
private int secnumber;
+ private final static String TIMEOUT_STATEMENT = "SET STATEMENT_TIMEOUT ";
+
+ private int pendingStatementTimeout; // < 0 means no pending timeout to set
+
// this flag is for an execute statement/procedure which actually returns a result set;
// do not commit the statement, otherwise result set is closed
@@ -171,6 +175,7 @@
this.server = server;
this.timeSlice = timeSlice;
this.logConnections = logConnections;
+ this.pendingStatementTimeout = -1;
initialize();
}
@@ -706,6 +711,10 @@
stmt = database.getDRDAStatement(pkgnamcsn);
ps = stmt.getPreparedStatement();
ps.clearWarnings();
+ if (pendingStatementTimeout >= 0) {
+ ps.setQueryTimeout(pendingStatementTimeout);
+ pendingStatementTimeout = -1;
+ }
stmt.execute();
writeOPNQRYRM(false, stmt);
checkWarning(null, ps, null, 0, false, true);
@@ -3506,6 +3515,10 @@
stmt.maxrslcnt = maxrslcnt;
stmt.outovropt = outovropt;
stmt.rslsetflg = rslsetflg;
+ if (pendingStatementTimeout >= 0) {
+ stmt.getPreparedStatement().setQueryTimeout(pendingStatementTimeout);
+ pendingStatementTimeout = -1;
+ }
// set the statement as the current statement
@@ -4323,8 +4336,13 @@
// initialize statement for reuse
drdaStmt.initialize();
String sqlStmt = parseEXECSQLIMMobjects();
- drdaStmt.getStatement().clearWarnings();
- int updCount = drdaStmt.getStatement().executeUpdate(sqlStmt);
+ Statement statement = drdaStmt.getStatement();
+ statement.clearWarnings();
+ if (pendingStatementTimeout >= 0) {
+ statement.setQueryTimeout(pendingStatementTimeout);
+ pendingStatementTimeout = -1;
+ }
+ int updCount = statement.executeUpdate(sqlStmt);
return updCount;
}
@@ -4493,6 +4511,12 @@
if (sqlStmt != null)
// then we have at least one SQL Statement.
gotSqlStt = true;
+
+ if (sqlStmt.startsWith(TIMEOUT_STATEMENT)) {
+ String timeoutString = sqlStmt.substring(TIMEOUT_STATEMENT.length());
+ pendingStatementTimeout = Integer.valueOf(timeoutString).intValue();
+ break;
+ }
if (canIgnoreStmt(sqlStmt)) {
// We _know_ Cloudscape doesn't recognize this
Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/DerbyNetClient.exclude
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/DerbyNetClient.exclude?rev=344147&r1=344146&r2=344147&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/DerbyNetClient.exclude (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/DerbyNetClient.exclude Mon Nov 14 07:42:40 2005
@@ -3,7 +3,6 @@
# excluding batchUpdate.java for it hits a problem in networkserver ('beetle' 5561)
# excluding statementJdbc20.java because this tests fetch_reverse throughout the test
# excluding jdbcapi/testRelative.java because it is a new test that requires debugging with the IBM Driver
-# excluding jdbcapi/SetQueryTimeoutTest.java because neither the JCC driver nor the ClientDriver support setQueryTimeout() yet.
# excluding jdbcapi/resultsetJdbc30.java because the features tested are not implemented by Derby Client
# excluding jdbcapi/checkDataSource30.java - Client behaves differently. Need to look into this
# excluding jdbcapi/statementJdbc30.java - Client behaves differently. Need to look into this
@@ -12,7 +11,6 @@
jdbcapi/batchUpdate.java
jdbcapi/statementJdbc20.java
jdbcapi/testRelative.java
-jdbcapi/SetQueryTimeoutTest.java
jdbcapi/resultsetJdbc30.java
jdbcapi/checkDataSource30.java
jdbcapi/statementJdbc30.java
Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/SetQueryTimeoutTest.java
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/SetQueryTimeoutTest.java?rev=344147&r1=344146&r2=344147&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/SetQueryTimeoutTest.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/SetQueryTimeoutTest.java Mon Nov 14 07:42:40 2005
@@ -70,7 +70,6 @@
* 3. Sets an invalid (negative) timeout. Verifies that the correct
* exception is thrown.
*
- * @author oyvind.bakksjo@sun.com
*/
public class SetQueryTimeoutTest
{
@@ -242,6 +241,12 @@
} catch (SQLException e) {
throw new TestFailedException("Should not happen", e);
}
+
+ try {
+ exec(conn, "DROP FUNCTION DELAY");
+ } catch (Exception e) {
+ // Ignore
+ }
exec(conn, "CREATE FUNCTION DELAY(SECONDS INTEGER, VALUE INTEGER) RETURNS INTEGER PARAMETER STYLE JAVA NO SQL LANGUAGE JAVA EXTERNAL NAME 'org.apache.derbyTesting.functionTests.tests.jdbcapi.SetQueryTimeoutTest.delay'");
@@ -427,9 +432,11 @@
// B - different stmt on the same connection; should NOT time out
// C - different stmt on different connection; should NOT time out
// D - here just to create equal contention on conn1 and conn2
-
+
+ // FIXME: Should have used conn1 for statementB below, but
+ // this is blocked by DERBY-694
PreparedStatement statementA = prepare(conn1, getFetchQuery("t"));
- PreparedStatement statementB = prepare(conn1, getFetchQuery("t"));
+ PreparedStatement statementB = prepare(conn2, getFetchQuery("t"));
PreparedStatement statementC = prepare(conn2, getFetchQuery("t"));
PreparedStatement statementD = prepare(conn2, getFetchQuery("t"));