if (usingDerbyNetClient())
return;
// START XA HOLDABILITY TEST
XADataSource dscsx = J2EEDataSource.getXADataSource();
XAConnection xac = dscsx.getXAConnection();
XAResource xr = xac.getXAResource();
Xid xid = new cdsXid(25, (byte) 21, (byte) 01);
Connection conn1 = xac.getConnection();
// check that autocommit is true; default for a connection
assertTrue(conn1.getAutoCommit());
// check that holdability is HOLD_CURSORS_OVER_COMMIT in a default
// CONNECTION(not in xa transaction yet)
assertEquals(
ResultSet.HOLD_CURSORS_OVER_COMMIT, conn1.getHoldability());
// start a global transaction and default holdability and
// autocommit will be switched to match Derby XA restrictions
xr.start(xid, XAResource.TMNOFLAGS);
// So, now autocommit should be false for connection because it is
// part of the global transaction
assertFalse(conn1.getAutoCommit());
// Connection's holdability is now CLOSE_CURSORS_AT_COMMIT because
// it is part of the global transaction
assertEquals(
ResultSet.CLOSE_CURSORS_AT_COMMIT, conn1.getHoldability());
xr.end(xid, XAResource.TMSUCCESS);
conn1.commit();
conn1.close();
xid = new cdsXid(27, (byte) 21, (byte) 01);
xr.start(xid, XAResource.TMNOFLAGS);
conn1 = xac.getConnection();
// CONNECTION(in xa transaction) HOLDABILITY:
assertEquals(
ResultSet.CLOSE_CURSORS_AT_COMMIT, conn1.getHoldability());
// Autocommit on Connection inside global transaction should be false
assertFalse(conn1.getAutoCommit());
xr.end(xid, XAResource.TMSUCCESS);
conn1.rollback();
Connection conn = xac.getConnection();
conn.setAutoCommit(false);
conn.setHoldability(ResultSet.CLOSE_CURSORS_AT_COMMIT);
// CONNECTION(non-xa transaction) HOLDABILITY:
assertEquals(
ResultSet.CLOSE_CURSORS_AT_COMMIT, conn.getHoldability());
Statement s = conn.createStatement();
// STATEMENT HOLDABILITY:
assertEquals(
ResultSet.CLOSE_CURSORS_AT_COMMIT, s.getResultSetHoldability());
s.executeUpdate("insert into hold_30 values " +
"(1,'init2'), (2, 'init3'), (3,'init3')");
s.executeUpdate("insert into hold_30 values " +
"(4,'init4'), (5, 'init5'), (6,'init6')");
s.executeUpdate("insert into hold_30 values " +
"(7,'init7'), (8, 'init8'), (9,'init9')");
// STATEMENT HOLDABILITY :
assertEquals(
ResultSet.CLOSE_CURSORS_AT_COMMIT, s.getResultSetHoldability());
Statement sh = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT);
PreparedStatement psh = conn.prepareStatement(
"select id from hold_30 for update", ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT);
CallableStatement csh = conn.prepareCall(
"select id from hold_30 for update", ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT);
// STATEMENT HOLDABILITY :
assertEquals(
ResultSet.HOLD_CURSORS_OVER_COMMIT, sh.getResultSetHoldability());
// PREPARED STATEMENT HOLDABILITY :
assertEquals(
ResultSet.HOLD_CURSORS_OVER_COMMIT, psh.getResultSetHoldability());
// CALLABLE STATEMENT HOLDABILITY :
assertEquals(
ResultSet.HOLD_CURSORS_OVER_COMMIT, csh.getResultSetHoldability());
ResultSet rsh = sh.executeQuery("select id from hold_30 for update");
rsh.next();
assertEquals(1, rsh.getInt(1)); // H@1 id
rsh.next();
assertEquals(2, rsh.getInt(1)); // H@2 id
conn.commit();
rsh.next();
assertEquals(3, rsh.getInt(1)); // H@3 id
conn.commit();
xid = new cdsXid(23, (byte) 21, (byte) 01);
xr.start(xid, XAResource.TMNOFLAGS);
Statement stmtInsideGlobalTransaction = conn.createStatement();
PreparedStatement prepstmtInsideGlobalTransaction =
conn.prepareStatement("select id from hold_30");
CallableStatement callablestmtInsideGlobalTransaction =
conn.prepareCall("select id from hold_30");
// CONNECTION(xa) HOLDABILITY:
assertEquals(ResultSet.CLOSE_CURSORS_AT_COMMIT, conn.getHoldability());
// STATEMENT(this one was created with holdability false, outside the
// global transaction. Check its holdability inside global transaction
assertEquals(
ResultSet.CLOSE_CURSORS_AT_COMMIT, s.getResultSetHoldability());
// STATEMENT(this one was created with holdability true,
// outside the global transaction. Check its holdability inside
// global transaction:
// DERBY-2531: network server / DerbyNetClient has a different value
// than embedded.
if (usingEmbedded())
assertEquals(ResultSet.CLOSE_CURSORS_AT_COMMIT,
sh.getResultSetHoldability());
else if (usingDerbyNetClient())
assertEquals(ResultSet.HOLD_CURSORS_OVER_COMMIT,
sh.getResultSetHoldability());
// STATEMENT(this one was created with default holdability inside this
// global transaction. Check its holdability:
assertEquals(
ResultSet.CLOSE_CURSORS_AT_COMMIT,
stmtInsideGlobalTransaction.getResultSetHoldability());
// PREPAREDSTATEMENT(this one was created with default holdability
// inside this global transaction. Check its holdability:
assertEquals(ResultSet.CLOSE_CURSORS_AT_COMMIT,
prepstmtInsideGlobalTransaction.getResultSetHoldability());
// CALLABLESTATEMENT(this one was created with default holdability
// inside this global transaction. Check its holdability:
assertEquals(ResultSet.CLOSE_CURSORS_AT_COMMIT,
callablestmtInsideGlobalTransaction.getResultSetHoldability());
ResultSet rsx = s.executeQuery("select id from hold_30 for update");
rsx.next();
assertEquals(1, rsx.getInt(1)); // X@1 id
rsx.next();
assertEquals(2, rsx.getInt(1)); // X@2 id
xr.end(xid, XAResource.TMSUCCESS);
// result set should not be useable, since it is part of a detached
// XAConnection
try {
rsx.next();
fail("rsx's connection not active id ");
} catch (SQLException sqle) {
assertSQLState("08003", sqle);
}
// result set should not be useable, it should have been closed by
// the xa start.
try {
rsh.next();
fail("rsh's connection not active id ");
} catch (SQLException sqle) {
assertSQLState("XCL16", sqle);
}
// resume XA transaction and keep using rs");
xr.start(xid, XAResource.TMJOIN);
Statement stmtAfterGlobalTransactionResume = conn.createStatement();
PreparedStatement prepstmtAfterGlobalTransactionResume =
conn.prepareStatement("select id from hold_30");
CallableStatement callablestmtAfterGlobalTransactionResume =
conn.prepareCall("select id from hold_30");
// Check holdability of various jdbc objects after resuming XA
// transaction
// CONNECTION(xa) HOLDABILITY:
assertEquals(ResultSet.CLOSE_CURSORS_AT_COMMIT,conn.getHoldability());
// STATEMENT(this one was created with holdability false, outside the
// global transaction. Check its holdability inside global transaction
assertEquals(
ResultSet.CLOSE_CURSORS_AT_COMMIT, s.getResultSetHoldability());
// STATEMENT(this one was created with holdability true, outside the
// global transaction. Check its holdability inside global transaction
if (usingEmbedded())
assertEquals(ResultSet.CLOSE_CURSORS_AT_COMMIT,
sh.getResultSetHoldability());
else if (usingDerbyNetClient())
assertEquals(ResultSet.HOLD_CURSORS_OVER_COMMIT,
sh.getResultSetHoldability());
// STATEMENT(this one was created with default holdability inside the
// global transaction when it was first started. Check its holdability
assertEquals(ResultSet.CLOSE_CURSORS_AT_COMMIT,
stmtInsideGlobalTransaction.getResultSetHoldability());
// PREPAREDSTATEMENT(this one was created with default holdability
// inside the global transaction when it was first started. Check its
// holdability)
assertEquals(ResultSet.CLOSE_CURSORS_AT_COMMIT,
prepstmtInsideGlobalTransaction.getResultSetHoldability());
// CALLABLESTATEMENT(this one was created with default holdability
// inside the global transaction when it was first started. Check its
// holdability) HOLDABILITY
assertEquals(ResultSet.CLOSE_CURSORS_AT_COMMIT,
callablestmtInsideGlobalTransaction.getResultSetHoldability());
// STATEMENT(this one was created with default holdability after the
// global transaction was resumed. Check its holdability
assertEquals(ResultSet.CLOSE_CURSORS_AT_COMMIT,
stmtAfterGlobalTransactionResume.getResultSetHoldability());
// PREPAREDSTATEMENT(this one was created with default holdability
// after the global transaction was resumed. Check its holdability
assertEquals(ResultSet.CLOSE_CURSORS_AT_COMMIT,
prepstmtAfterGlobalTransactionResume.getResultSetHoldability());
// CALLABLESTATEMENT(this one was created with default holdability
// after the global transaction was resumed. Check its holdability
assertEquals(ResultSet.CLOSE_CURSORS_AT_COMMIT,
callablestmtAfterGlobalTransactionResume.getResultSetHoldability());
// DERBY-1370
if (usingEmbedded())
{
// Network XA BUG gives result set closed
rsx.next();
assertEquals(3, rsx.getInt(1)); // X@3 id
}
xr.end(xid, XAResource.TMSUCCESS);
if (xr.prepare(xid) != XAResource.XA_RDONLY)
xr.commit(xid, false);
// try again once the xa transaction has been committed.
try {
rsx.next();
fail("rsx's connection not active id (B)");
} catch (SQLException sqle) {
assertSQLState("XCL16", sqle);
}
try {
rsh.next();
fail ("rsh's should be closed (B)");
} catch (SQLException sqle) {
assertSQLState("XCL16", sqle);
}
// Set connection to hold
conn.setHoldability(ResultSet.HOLD_CURSORS_OVER_COMMIT);
// CONNECTION(held) HOLDABILITY:
assertEquals(ResultSet.HOLD_CURSORS_OVER_COMMIT,
conn.getHoldability());
xid = new cdsXid(24, (byte) 21, (byte) 01);
xr.start(xid, XAResource.TMNOFLAGS);
// CONNECTION(xa) HOLDABILITY:
assertEquals(ResultSet.CLOSE_CURSORS_AT_COMMIT, conn.getHoldability());
try {
conn.setHoldability(ResultSet.HOLD_CURSORS_OVER_COMMIT);
fail("allowed to set hold mode in xa transaction");
} catch (SQLException sqle) {
assertSQLState("XJ05C", sqle);
}
// JDBC 4.0 (proposed final draft) section 16.1.3.1 allows Statements
// to be created with a different holdability if the driver cannot
// support it. In this case the driver does not support holdability in
// a global transaction, so a valid statement is returned with close
// cursors on commit.
Statement shxa = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT);
// HOLDABLE Statement in global xact "
assertEquals(ResultSet.CLOSE_CURSORS_AT_COMMIT,
s.getResultSetHoldability());
assertEquals(10000, conn.getWarnings().getErrorCode());
shxa.close();
shxa = conn.prepareStatement("select id from hold_30",
ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY,
ResultSet.HOLD_CURSORS_OVER_COMMIT);
// HOLDABLE PreparedStatement in global xact
assertEquals(ResultSet.CLOSE_CURSORS_AT_COMMIT,
s.getResultSetHoldability());
assertEquals(10000, conn.getWarnings().getErrorCode());
shxa.close();
shxa = conn.prepareCall("CALL SYSCS_UTIL.SYSCS_CHECKPOINT_DATABASE()",
ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY,
ResultSet.HOLD_CURSORS_OVER_COMMIT);
// HOLDABLE CallableStatement in global xact:
assertEquals(ResultSet.CLOSE_CURSORS_AT_COMMIT,
s.getResultSetHoldability());
assertEquals(10000, conn.getWarnings().getErrorCode());
shxa.close();
// check we can use a holdable statement set up in local mode.
// holdability is downgraded, tested in XATest.java
// DERBY-1370
if(usingEmbedded()) {
// STATEMENT HOLDABILITY:
assertEquals(ResultSet.CLOSE_CURSORS_AT_COMMIT,
sh.getResultSetHoldability());
sh.executeQuery("select id from hold_30").close();
sh.execute("select id from hold_30");
sh.getResultSet().close();
// PREPARED STATEMENT HOLDABILITY:
assertEquals(ResultSet.CLOSE_CURSORS_AT_COMMIT,
psh.getResultSetHoldability());
psh.executeQuery().close();
psh.execute();
psh.getResultSet().close();
// CALLABLE STATEMENT HOLDABILITY:
assertEquals(ResultSet.CLOSE_CURSORS_AT_COMMIT,
csh.getResultSetHoldability());
csh.executeQuery().close();
csh.execute();
csh.getResultSet().close();
}
// but an update works
sh.executeUpdate("insert into hold_30 values(10, 'init10')");
xr.end(xid, XAResource.TMSUCCESS);
// CONNECTION(held) HOLDABILITY:
assertEquals(
ResultSet.HOLD_CURSORS_OVER_COMMIT, conn.getHoldability());
s.close();
sh.close();
csh.close();
psh.close();
rsx.close();
stmtInsideGlobalTransaction.close();
prepstmtInsideGlobalTransaction.close();
callablestmtInsideGlobalTransaction.close();
stmtAfterGlobalTransactionResume.close();
prepstmtAfterGlobalTransactionResume.close();
callablestmtAfterGlobalTransactionResume.close();
conn.close();
xac.close();
TestConfiguration.getCurrent().shutdownDatabase();
// END XA HOLDABILITY TEST");
}