Just an update, applying the patch to the 10.1 stream gave a clean
bill of health except for 2 failures:
1) A failure with lang/errorStream.java
I'm confident this stems from DERBY-459
(http://issues.apache.org/jira/browse/DERBY-459).
2) A intermittent failure with lang/logStream.java
Less sure where this one comes from but I am confident that the
problem isn't from my changes.
Thus I'm ready to go ahead with the 10.1 port if I can convince anyone
to do the commit..
Philip
------------------------------------------------------------------------
Index:
java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/copyfiles.ant
===================================================================
---
java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/copyfiles.ant
(revision 265703)
+++
java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/copyfiles.ant
(working copy)
@@ -32,6 +32,7 @@
resultsetStream_app.properties
resultsetJdbc30_sed.properties
resultset_app.properties
+resultset_derby.properties
savepointJdbc30_app.properties
savepointJdbc30_derby.properties
secureUsers.sql
Index:
java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/resultset_derby.properties
===================================================================
---
java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/resultset_derby.properties
(revision 0)
+++
java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/resultset_derby.properties
(revision 0)
@@ -0,0 +1 @@
+derby.locks.waitTimeout=1
\ No newline at end of file
Index:
java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/resultset.java
===================================================================
---
java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/resultset.java
(revision 265703)
+++
java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/resultset.java
(working copy)
@@ -20,6 +20,7 @@
package org.apache.derbyTesting.functionTests.tests.jdbcapi;
+import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSetMetaData;
@@ -35,6 +36,7 @@
import org.apache.derbyTesting.functionTests.util.TestUtil;
import org.apache.derbyTesting.functionTests.util.JDBCTestDisplayUtil;
import org.apache.derby.iapi.reference.JDBC30Translation;
+import org.apache.derby.iapi.reference.SQLState;
/**
* Test of JDBC result set and result set meta-data.
@@ -526,6 +528,12 @@
testMutableValues(con);
testCorrelationNamesAndMetaDataCalls(con);
+
+ //We know that JCC behavior does not match
+ //DerbyNetClient or embedded
+ if (!TestUtil.isJCCFramework()) {
+ runAutoCommitTests(con);
+ }
con.close();
}
@@ -772,5 +780,289 @@
list.add(value);
}
+
+ /**
+ * Helper method to set up and run the auto-commit tests.
+ *
+ * @param conn The Connection
+ * @throws SQLException
+ */
+ private static void runAutoCommitTests(Connection conn) throws
SQLException {
+ Statement s = conn.createStatement();
+ ResultSet rs = s.executeQuery("select tablename from sys.systables " +
+ "where tablename = 'AUTOCOMMITTABLE'");
+ if (rs.next()) {
+ rs.close();
+ s.executeUpdate("delete from AutoCommitTable");
+ } else {
+ rs.close();
+ s.executeUpdate("create table AutoCommitTable (num int)");
+ }
+ s.executeUpdate("insert into AutoCommitTable values (1)");
+ s.executeUpdate("insert into AutoCommitTable values (2)");
+ int isolation = conn.getTransactionIsolation();
+ conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
+ testSingleRSAutoCommit(conn);
+ testSingleRSCloseCursorsAtCommit(conn);
+ multipleRSTests(conn);
+ conn.setTransactionIsolation(isolation);
+ s.executeUpdate("drop table AutoCommitTable");
+ s.close();
+ }
+
+ /**
+ * Tests for two things:
+ *
+ * 1) The ResultSet does not close implicitly when the ResultSet completes
+ * and holdability == HOLD_CURSORS_OVER_COMMIT
+ *
+ * 2) The ResultSet auto-commits when it completes and auto-commit is on.
+ *
+ * @param conn The Connection
+ * @param tableName
+ * @throws SQLException
+ */
+ private static void testSingleRSAutoCommit(Connection conn) throws
SQLException {
+ setHoldability(conn, JDBC30Translation.HOLD_CURSORS_OVER_COMMIT);
+ System.out.print("Single RS auto-commit test: ");
+ Statement s = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_READ_ONLY);
+ ResultSet rs = s.executeQuery("select * from AutoCommitTable");
+ while (rs.next());
+ if (!checkLocks()) {
+ System.out.println("FAIL. Auto-commit unsuccessful.");
+ rs.close();
+ return;
+ }
+ try {
+ if (!rs.next()) {
+ System.out.println("PASS.");
+ } else {
+ System.out.println("FAIL. Final call of the ResultSet should return
false");
+ }
+ rs.close();
+ } catch (SQLException e) {
+ System.out.println("FAIL. Final call to ResultSet.next() threw an
Exception: ");
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Check to see that ResultSet closes implicitly when holdability is set to
+ * CLOSE_CURORS_AT_COMMIT.
+ *
+ * @param conn The Connection
+ * @throws SQLException
+ */
+ private static void testSingleRSCloseCursorsAtCommit(Connection conn)
throws SQLException {
+ setHoldability(conn, JDBC30Translation.CLOSE_CURSORS_AT_COMMIT);
+ conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
+ System.out.print("SingleRSCloseCursorsAtCommit: ");
+ Statement s = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_READ_ONLY);
+ ResultSet rs = s.executeQuery("select * from AutoCommitTable");
+ while (rs.next());
+ if (!checkLocks()) {
+ System.out.println("FAIL. Auto-commit unsuccessful.");
+ rs.close();
+ return;
+ }
+ try {
+ rs.next();
+ System.out.println("FAIL. ResultSet not closed implicitly");
+ rs.close();
+ } catch (SQLException e) {
+ System.out.println("PASS.");
+ }
+ }
+
+ /**
+ * Sets up and runs two tests with multiple ResultSets
+ *
+ * @param conn The Connection
+ * @throws SQLException
+ */
+ private static void multipleRSTests(Connection conn) throws SQLException {
+ setHoldability(conn, JDBC30Translation.HOLD_CURSORS_OVER_COMMIT);
+
+ //Installing Procedure
+ Statement stmt = conn.createStatement();
+ ResultSet mdrs = conn.getMetaData().getProcedures(
+ null, null, "MULTIRESULT");
+ if (mdrs != null || !mdrs.next()) {
+ stmt.executeUpdate("create procedure multiResult(p1 int, " +
+ "p2 int) parameter style JAVA READS SQL DATA dynamic " +
+ "result sets 2 language java external name " +
+ "'org.apache.derbyTesting.functionTests." +
+ "tests.jdbcapi.resultset.multiResult'");
+ }
+ mdrs.close();
+ multipleRSAutoCommit(conn);
+ multipleRSNoCommit(conn);
+ stmt.executeUpdate("drop procedure multiResult");
+ stmt.close();
+ }
+
+ /**
+ * Test to see that an auto commit occurs for multiple ResultSets if all
+ * ResultSets but one are closed and the final ResultSet has completed.
+ *
+ * @param conn The Connection
+ * @throws SQLException
+ */
+ private static void multipleRSAutoCommit(Connection conn) throws
SQLException {
+ System.out.print("MultipleRSAutoCommit: ");
+ CallableStatement cs = conn.prepareCall("call multiResult(?, ?)");
+ cs.setInt(1, 1);
+ cs.setInt(2, 2);
+ cs.execute();
+ ResultSet rs = null;
+ do {
+ if (rs != null)
+ rs.close();
+ rs = cs.getResultSet();
+ while (rs.next());
+
+ if (rs.next()) {
+ System.out.println("FAIL. Final call to ResultSet should return
false.");
+ }
+ } while (getMoreResults(cs));
+
+ if (!checkLocks()) {
+ return;
+ }
+
+ System.out.println("PASS. ");
+
+ if (rs != null)
+ rs.close();
+ cs.close();
+ }
+
+ /**
+ * Used to insure that there is no auto-commit in the event that there is
+ * more then one ResultSet open.
+ *
+ * @param conn The Connection
+ * @throws SQLException
+ */
+ private static void multipleRSNoCommit(Connection conn) throws
SQLException {
+ System.out.print("MultipleRSNoCommit: ");
+ CallableStatement cs = conn.prepareCall("call multiResult(?, ?)");
+ cs.setInt(1, 1);
+ cs.setInt(2, 2);
+ cs.execute();
+ ResultSet rs = null;
+ do {
+ rs = cs.getResultSet();
+ while (rs.next());
+
+ if (rs.next()) {
+ System.out.println("FAIL. Final call to ResultSet should return
false.");
+ }
+ } while (getMoreResults(cs));
+
+ if (checkLocks()) {
+ System.out.println("FAIL. Connection incorrectly auto-committed.");
+ }
+
+ System.out.println("PASS. ");
+
+ if (rs != null)
+ rs.close();
+ cs.close();
+ }
+
+ /**
+ * Checks to see if there is a lock on a table by attempting to modify the
+ * same table. If the first connection was serializable then it will
+ * continue to hold a lock and the second Connection will time out.
+ *
+ * @return false if the a lock could not be established, true if a lock
+ * can be established.
+ * @throws SQLException
+ */
+ private static boolean checkLocks() throws SQLException {
+ Connection conn = null;
+ try {
+ conn = ij.startJBMS();
+ } catch (Exception e) {
+ System.out.println("FAIL. Unable to establish connection in
checkLocks");
+ return false;
+ }
+ Statement stmt = conn.createStatement();
+ try {
+ stmt.executeUpdate("update AutoCommitTable "
+ + "set num = 3 where num = 2");
+ stmt.executeUpdate("update AutoCommitTable "
+ + "set num = 2 where num = 3");
+ } catch (SQLException e) {
+ if (e.getSQLState().equals(SQLState.LOCK_TIMEOUT)) {
+ return false;
+ } else {
+ throw e;
+ }
+ }
+ stmt.close();
+ conn.close();
+ return true;
+ }
+
+ /**
+ * Sets the holdability of a Connection using reflection so it is
+ * JDBC2.0 compatible.
+ *
+ * @param conn The Connection
+ * @param hold The new holdability.
+ * @throws SQLException
+ */
+ public static void setHoldability(Connection conn, int hold) throws
SQLException {
+ try {
+ Object[] holdArray = {new Integer(hold)};
+ Method sh = conn.getClass().getMethod("setHoldability",
CONN_PARAM);
+ sh.invoke(conn, holdArray);
+ } catch (Exception e) {System.out.println("shouldn't get that error "
+ e.getMessage());}//for jdks prior to jdk14
+ }
+
+ /**
+ * Uses reflection to call
CallableStatement.getMoreResults(KEEP_CURRENT_RESULT)
+ * for JDBC2.0 compatibilty
+ * @param cs The Callable statement
+ * @return boolean value indicating if there are more results
+ * @throws SQLException
+ */
+ public static boolean getMoreResults(CallableStatement cs) throws
SQLException {
+ try {
+ Object[] holdArray = {new
Integer(JDBC30Translation.KEEP_CURRENT_RESULT)};
+ Method sh = cs.getClass().getMethod("getMoreResults", CONN_PARAM);
+ Boolean temp = (Boolean)sh.invoke(cs, holdArray);
+ return temp.booleanValue();
+ } catch (Exception e) {return cs.getMoreResults();}//for jdks prior to jdk14
+ }
+
+ /**
+ * Procedure installed by the multipleResultSet method and used by the
+ * multiRSHelper. Designed to return two ResultSets from a specified table
+ * where the num column equals p1 and p2 respectively.
+ *
+ * @param p1 Number parameter for the first ResultSet
+ * @param p2 Number parameter for the second ResultSet
+ * @param data1 The first ResultSet to be returned.
+ * @param data2 The Second ResultSet to be returned
+ * @throws SQLException
+ */
+ public static void multiResult(int p1, int p2, ResultSet[] data1, ResultSet[] data2)
+ throws SQLException {
+
+ Connection conn =
DriverManager.getConnection("jdbc:default:connection");
+ PreparedStatement ps = conn.prepareStatement("select * from AutoCommitTable
where num = ?");
+ ps.setInt(1, p1);
+ data1[0] = ps.executeQuery();
+
+ ps = conn.prepareStatement("select * from AutoCommitTable where num =
?");
+ ps.setInt(1, p2);
+ data2[0] = ps.executeQuery();
+
+ conn.close();
+ }
+
}
Index:
java/testing/org/apache/derbyTesting/functionTests/harness/SpecialFlags.java
===================================================================
---
java/testing/org/apache/derbyTesting/functionTests/harness/SpecialFlags.java
(revision 265703)
+++
java/testing/org/apache/derbyTesting/functionTests/harness/SpecialFlags.java
(working copy)
@@ -105,6 +105,8 @@
{
// flags is a list of key-value pairs separated by a ^;
// to be parsed and added to either ijProps or srvProps
+ if (flags == null)
+ flags = "";
StringTokenizer st = new StringTokenizer(flags, "^");
String str = "";
String key = "";
Index:
java/testing/org/apache/derbyTesting/functionTests/master/DerbyNetClient/holdCursorJDBC30.out
===================================================================
---
java/testing/org/apache/derbyTesting/functionTests/master/DerbyNetClient/holdCursorJDBC30.out
(revision 265703)
+++
java/testing/org/apache/derbyTesting/functionTests/master/DerbyNetClient/holdCursorJDBC30.out
(working copy)
@@ -58,7 +58,7 @@
No current row
ij> commit;
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> close test1;
ij> -- should fail
next test1;
@@ -68,7 +68,7 @@
No current row
ij> commit;
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> commit;
ij> close test1;
ij> -- should fail
@@ -79,14 +79,14 @@
No current row
ij> commit;
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> commit;
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> commit;
ij> close test1;
ij> -- should fail
@@ -97,16 +97,16 @@
No current row
ij> commit;
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> commit;
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> commit;
ij> close test1;
ij> -- should fail
@@ -117,16 +117,16 @@
No current row
ij> commit;
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> commit;
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> close test1;
ij> commit;
ij> -- should fail
@@ -337,7 +337,7 @@
No current row
ij> commit;
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> close test1;
ij> -- should fail
next test1;
@@ -348,7 +348,7 @@
No current row
ij> commit;
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> commit;
ij> close test1;
ij> -- should fail
@@ -360,14 +360,14 @@
No current row
ij> commit;
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> commit;
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> commit;
ij> close test1;
ij> -- should fail
@@ -379,16 +379,16 @@
No current row
ij> commit;
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> commit;
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> commit;
ij> close test1;
ij> -- should fail
@@ -400,16 +400,16 @@
No current row
ij> commit;
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> commit;
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> close test1;
ij> commit;
ij> -- should fail
@@ -678,7 +678,7 @@
ij> next test1;
No current row
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> close test1;
ij> commit;
ij> -- should fail
@@ -732,7 +732,7 @@
No current row
ij> commit;
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> close test1;
ij> -- should fail
next test1;
@@ -743,7 +743,7 @@
No current row
ij> commit;
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> commit;
ij> close test1;
ij> -- should fail
@@ -755,14 +755,14 @@
No current row
ij> commit;
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> commit;
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> commit;
ij> close test1;
ij> -- should fail
@@ -774,16 +774,16 @@
No current row
ij> commit;
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> commit;
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> commit;
ij> close test1;
ij> -- should fail
@@ -795,16 +795,16 @@
No current row
ij> commit;
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> commit;
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> close test1;
ij> commit;
ij> -- should fail
@@ -1026,7 +1026,7 @@
No current row
ij> commit;
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> close test1;
ij> -- should fail
next test1;
@@ -1037,7 +1037,7 @@
No current row
ij> commit;
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> commit;
ij> close test1;
ij> -- should fail
@@ -1049,14 +1049,14 @@
No current row
ij> commit;
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> commit;
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> commit;
ij> close test1;
ij> -- should fail
@@ -1068,16 +1068,16 @@
No current row
ij> commit;
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> commit;
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> commit;
ij> close test1;
ij> -- should fail
@@ -1089,16 +1089,16 @@
No current row
ij> commit;
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> commit;
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> next test1;
-ERROR (no SQLState): Invalid operation: result set closed
+No current row
ij> close test1;
ij> commit;
ij> -- should fail
Index:
java/testing/org/apache/derbyTesting/functionTests/master/DerbyNetClient/forupdate.out
===================================================================
---
java/testing/org/apache/derbyTesting/functionTests/master/DerbyNetClient/forupdate.out
(revision 265703)
+++
java/testing/org/apache/derbyTesting/functionTests/master/DerbyNetClient/forupdate.out
(working copy)
@@ -56,7 +56,7 @@
ij> -- the delete will get a 'cursor not updatable' execution error, but won't
get
----- a compile time error
delete from t1 where current of c1;
-ERROR (no SQLState): Invalid cursor name "C1" in the Update/Delete statement.
+ERROR 42X23: Cursor SQL_CURLH000C1 is not updatable.
ij> close c1;
ij> -- . read only for read only cursor spec
----- we know because the delete is refused with a 'cursor not updatable'
message
@@ -129,10 +129,10 @@
No current row
ij> -- this will get a target table mismatch error, it uses the correlation
name:
delete from s1 where current of c4;
-ERROR (no SQLState): Invalid cursor name "C4" in the Update/Delete statement.
+ERROR 42X28: Delete table 'S1' is not target of cursor 'SQL_CURLH000C1'.
ij> -- this will compile and get a 'no current row' error, it uses the table
name:
delete from t1 where current of c4;
-ERROR (no SQLState): Invalid cursor name "C4" in the Update/Delete statement.
+ERROR XCL08: Cursor 'SQL_CURLH000C1' is not on a row.
ij> close c4;
ij> -- . list columns in order same/different from appearance in table
----- the columns are 'found' regardless of their order.
Index:
java/testing/org/apache/derbyTesting/functionTests/master/DerbyNetClient/resultset.out
===================================================================
---
java/testing/org/apache/derbyTesting/functionTests/master/DerbyNetClient/resultset.out
(revision 265703)
+++
java/testing/org/apache/derbyTesting/functionTests/master/DerbyNetClient/resultset.out
(working copy)
@@ -1035,4 +1035,8 @@
Schema name of first column is APP1
Table name of second column is T1
Schema name of second column is APP2
+Single RS auto-commit test: PASS.
+SingleRSCloseCursorsAtCommit: PASS.
+MultipleRSAutoCommit: PASS.
+MultipleRSNoCommit: PASS.
Test resultset finished
Index:
java/testing/org/apache/derbyTesting/functionTests/master/DerbyNetClient/jdk14/updatableResultSet.out
===================================================================
---
java/testing/org/apache/derbyTesting/functionTests/master/DerbyNetClient/jdk14/updatableResultSet.out
(revision 265703)
+++
java/testing/org/apache/derbyTesting/functionTests/master/DerbyNetClient/jdk14/updatableResultSet.out
(working copy)
@@ -70,11 +70,11 @@
SQL State : null
Got expected exception Invalid operation to update at current cursor position
ResultSet is positioned after the last row. attempt to deleteRow at this point
should fail!
-SQL State : null
-Got expected exception Invalid operation: result set closed
+SQL State : XCL08
+Got expected exception Cursor '<xxx-cursor-name-xxx>' is not on a row.
ResultSet is positioned after the last row. attempt to updateRow at this point
should fail!
SQL State : null
-Got expected exception Invalid operation: result set closed
+Got expected exception Invalid operation to update at current cursor position
Negative Test8 - attempt deleteRow & updateRow on updatable resultset after
closing the resultset
Make sure that we got CONCUR_UPDATABLE? true
SQL State : null
@@ -374,8 +374,8 @@
Positive Test13a - Another test case for delete trigger
column 1 on this row is 1
this delete row will fire the delete trigger which will delete all the rows
from the table and from the resultset
-SQL State : null
-Got expected exception Invalid operation: result set closed
+SQL State : XCL08
+Got expected exception Cursor '<xxx-cursor-name-xxx>' is not on a row.
Verify that delete trigger got fired by verifying the row count to be 0 in
table1WithTriggers
1
-
@@ -391,7 +391,7 @@
column 1 on this row is 2
this update row will fire the update trigger which will update all the rows in
the table to have c1=1 and hence no more rows will qualify for the resultset
SQL State : null
-Got expected exception Invalid operation: result set closed
+Got expected exception Invalid operation to update at current cursor position
Verify that update trigger got fired by verifying that all column c1s have
value 1 in table2WithTriggers
C1,C2
-- --
@@ -408,8 +408,8 @@
{e4,e3}
column 1 on this row is e1
this delete row will cause the delete cascade constraint to delete all the rows
from the table and from the resultset
-SQL State : null
-Got expected exception Invalid operation: result set closed
+SQL State : XCL08
+Got expected exception Cursor '<xxx-cursor-name-xxx>' is not on a row.
Verify that delete trigger got fired by verifying the row count to be 0 in
selfReferencingT1
1
-
Index: java/testing/org/apache/derbyTesting/functionTests/master/resultset.out
===================================================================
--- java/testing/org/apache/derbyTesting/functionTests/master/resultset.out
(revision 265703)
+++ java/testing/org/apache/derbyTesting/functionTests/master/resultset.out
(working copy)
@@ -1035,4 +1035,8 @@
Schema name of first column is APP1
Table name of second column is T1
Schema name of second column is APP2
+Single RS auto-commit test: PASS.
+SingleRSCloseCursorsAtCommit: PASS.
+MultipleRSAutoCommit: PASS.
+MultipleRSNoCommit: PASS.
Test resultset finished
Index: java/client/org/apache/derby/client/am/Connection.java
===================================================================
--- java/client/org/apache/derby/client/am/Connection.java (revision
265703)
+++ java/client/org/apache/derby/client/am/Connection.java (working copy)
@@ -520,10 +520,12 @@
}
// precondition: autoCommit_ is true
- public void flowAutoCommit() throws SqlException {
+ public boolean flowAutoCommit() throws SqlException {
if (willAutoCommitGenerateFlow()) {
flowCommit();
+ return true;
}
+ return false;
}
public boolean willAutoCommitGenerateFlow() throws
org.apache.derby.client.am.SqlException {
Index: java/client/org/apache/derby/client/am/Statement.java
===================================================================
--- java/client/org/apache/derby/client/am/Statement.java (revision
265703)
+++ java/client/org/apache/derby/client/am/Statement.java (working copy)
@@ -2108,4 +2108,74 @@
cursorName_ = null;
}
}
+
+ /**
+ * Convenience method for resultSetCommitting(ResultSet, boolean)
+ *
+ * @see Statement#resultSetCommitting(ResultSet, boolean)
+ * @param closingRS The ResultSet to be closed
+ * @throws SqlException
+ */
+ public void resultSetCommitting(ResultSet closingRS) throws SqlException {
+ resultSetCommitting(closingRS, false);
+ }
+
+ /**
+ * Method that checks to see if any other ResultSets are open. If not
+ * proceeds with the autocommit.
+ *
+ * @param closingRS The ResultSet to be closed
+ * @param writeChain A Boolean indicating whether this method
+ * is part of a chain of write from client to Server
+ * @throws SqlException
+ */
+ public boolean resultSetCommitting(ResultSet closingRS, boolean
writeChain) throws SqlException {
+
+ // If the Connection is not in auto commit then this statement
completion
+ // cannot cause a commit.
+ if (!connection_.autoCommit_ || closingRS.autoCommitted_)
+ return false;
+
+ // If we have multiple results, see if there is another result set
open.
+ // If so, then no commit. The last result set to close will close the
statement.
+ if (resultSetList_ != null) {
+ for (int i = 0; i < resultSetList_.length; i++) {
+ ResultSet crs = resultSetList_[i];
+ if (crs == null)
+ continue;
+ if (!crs.openOnClient_)
+ continue;
+ if (crs == closingRS)
+ continue;
+
+ // at least one still open so no commit now.
+ return false;
+ }
+ }
+
+ if (writeChain) {
+ connection_.writeAutoCommit();
+ return true;
+ } else {
+ if (connection_.flowAutoCommit()) {
+ markAutoCommitted();
+ return true;
+ }
+ return false;
+ }
+ }
+
+ /**
+ * Mark all ResultSets associated with this statement as auto-committed.
+ */
+ public void markAutoCommitted() {
+ if (resultSetList_ != null) {
+ for (int i = 0; i < resultSetList_.length; i++)
+ if (resultSetList_[i] != null) {
+ resultSetList_[i].markAutoCommitted();
+ }
+ } else if (resultSet_ != null) {
+ resultSet_.markAutoCommitted();
+ }
+ }
}
Index: java/client/org/apache/derby/client/am/ResultSet.java
===================================================================
--- java/client/org/apache/derby/client/am/ResultSet.java (revision
265703)
+++ java/client/org/apache/derby/client/am/ResultSet.java (working copy)
@@ -281,6 +281,9 @@
// In these cases, the commit occurs when all results and output
parameter values have been retrieved.
// we will check to see if the forward only result set has gone
past the end,
// we will close the result set, the autocommit logic is in the
closeX() method
+ //
+ //Aug 24, 2005: Auto-commit logic is no longer in the closeX() method. Insted it has been
+ //moved to Statement and is handled in a manner similar to the embedded driver.
// if (!isValidCursorPosition_ && // We've gone past the end (+100)
// cursor_ != null) {
if ((!isValidCursorPosition_ && cursor_ != null) ||
@@ -291,10 +294,6 @@
// check for an error which may have caused the cursor to
terminate.
// if there were no more rows because of an error, then this
method
// should throw an SqlException rather than just returning
false.
- // note: closeX is still called and this will cause the
- // result set to be closed on the client. any additional calls
to
- // next() will fail checkForClosedResultSet(), the query
terminating exception is
- // only thrown once.
// depending on how this works with scrollable cursors, there
may be
// a better way/more common place for this logic.
SqlException sqlException = null;
@@ -304,16 +303,17 @@
accumulateWarning(new SqlWarning(agent_.logWriter_,
queryTerminatingSqlca_));
} else if (sqlcode < 0) {
sqlException = new SqlException(agent_.logWriter_,
queryTerminatingSqlca_);
- }
+ }
}
+
try {
- closeX(); // the auto commit logic is in closeX()
+ statement_.resultSetCommitting(this);
} catch (SqlException sqle) {
sqlException = Utils.accumulateSQLException(sqle,
sqlException);
}
- if (sqlException != null) {
+
+ if (sqlException != null)
throw sqlException;
- }
}
}
@@ -385,14 +385,13 @@
if (openOnServer_) {
flowCloseAndAutoCommitIfNotAutoCommitted();
} else {
- flowAutoCommitIfNotAutoCommitted(); // in case of early close
+ statement_.resultSetCommitting(this);
}
} finally {
markClosed();
connection_.CommitAndRollbackListeners_.remove(this);
}
- flowAutoCommitIfLastOpenMultipleResultSetWasJustClosed();
if (statement_.openOnClient_ && statement_.isCatalogQuery_) {
statement_.closeX();
}
@@ -413,31 +412,28 @@
void flowCloseAndAutoCommitIfNotAutoCommitted() throws SqlException {
agent_.beginWriteChain(statement_);
- writeCloseAndAutoCommitIfNotAutoCommitted();
+ boolean performedAutoCommit = writeCloseAndAutoCommit();
agent_.flow(statement_);
- readCloseAndAutoCommitIfNotAutoCommitted();
+ readCloseAndAutoCommit(performedAutoCommit);
agent_.endReadChain();
}
- private void writeCloseAndAutoCommitIfNotAutoCommitted() throws
SqlException {
+ private boolean writeCloseAndAutoCommit() throws SqlException {
// set autoCommitted_ to false so commit will flow following
// close cursor if autoCommit is true.
autoCommitted_ = false;
if (generatedSection_ == null) { // none call statement result set case
writeCursorClose_(statement_.section_);
- writeAutoCommitIfNotAutoCommitted();
} else { // call statement result set(s) case
writeCursorClose_(generatedSection_);
}
+ return statement_.resultSetCommitting(this, true);
}
- private void readCloseAndAutoCommitIfNotAutoCommitted() throws
SqlException {
- if (generatedSection_ == null) { // none call statement result set case
- readCursorClose_();
+ private void readCloseAndAutoCommit(boolean readAutoCommit) throws
SqlException {
+ readCursorClose_();
+ if (readAutoCommit)
readAutoCommitIfNotAutoCommitted();
- } else { // call statement result set(s) case
- readCursorClose_();
- }
}
void writeClose() throws SqlException {
@@ -463,13 +459,6 @@
}
}
- void flowAutoCommitIfNotAutoCommitted() throws SqlException {
- if (generatedSection_ == null && connection_.autoCommit_ &&
!autoCommitted_) {
- connection_.flowAutoCommit();
- markAutoCommitted();
- }
- }
-
// precondition: transaction state allows for auto commit to generate flow
private void writeAutoCommitIfNotAutoCommitted() throws SqlException {
if (connection_.autoCommit_ && !autoCommitted_) {
@@ -484,25 +473,6 @@
}
}
- private void flowAutoCommitIfLastOpenMultipleResultSetWasJustClosed()
throws SqlException {
- // After this call, the generatedSection_ is reset to null to avoid
repeating the commit.
- if (generatedSection_ != null && statement_ != null &&
statement_.resultSetList_ != null) {
- int count = 0;
- for (int i = 0; i < statement_.resultSetList_.length; i++) {
- if (statement_.resultSetList_[i] == null) {
- count++;
- }
- }
- if (count == statement_.resultSetList_.length) {
- if (connection_.autoCommit_ && !autoCommitted_) {
- connection_.flowAutoCommit();
- markAutoCommitted();
- }
- }
- }
- generatedSection_ = null; // this is prevent a subsequent close() call
from doing another autocommit.
- }
-
public boolean wasNull() throws SqlException {
if (agent_.loggingEnabled()) {
@@ -3005,6 +2975,11 @@
if (statement_.resultSet_ == this) {
statement_.resultSet_ = null;
}
+ /*
+ * Aug 10, 2005: Do we really only want to only null out the one resultSet?
+ * The only time this method is called is from completeLocalCommit or
+ * completeLocalRollback, both of which affect *all* ResultSets
+ */
if (statement_.resultSetList_ != null) {
for (int i = 0; i < statement_.resultSetList_.length; i++) {
if (statement_.resultSetList_[i] == this) {
@@ -3890,17 +3865,3 @@
}
}
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-