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 my...@apache.org on 2008/02/13 08:44:00 UTC
svn commit: r627297 [3/4] - in
/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi:
DataSourceTest.java J2EEDataSourceTest.java _Suite.java
Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/J2EEDataSourceTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/J2EEDataSourceTest.java?rev=627297&view=auto
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/J2EEDataSourceTest.java (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/J2EEDataSourceTest.java Tue Feb 12 23:43:59 2008
@@ -0,0 +1,3753 @@
+/*
+
+ Derby - Class org.apache.derbyTesting.functionTests.tests.jdbcapi.J2EEDataSourceTest
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ */
+
+package org.apache.derbyTesting.functionTests.tests.jdbcapi;
+
+import java.io.File;
+import java.io.Serializable;
+import java.security.AccessController;
+import java.sql.CallableStatement;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ParameterMetaData;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.Savepoint;
+import java.util.Hashtable;
+import java.util.Iterator;
+
+import org.apache.derbyTesting.functionTests.tests.jdbcapi.AssertEventCatcher;
+
+import javax.sql.ConnectionEvent;
+import javax.sql.ConnectionEventListener;
+import javax.sql.ConnectionPoolDataSource;
+import javax.sql.DataSource;
+import javax.sql.PooledConnection;
+import javax.sql.XAConnection;
+import javax.sql.XADataSource;
+import javax.transaction.xa.XAException;
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.apache.derby.jdbc.ClientConnectionPoolDataSource;
+import org.apache.derby.jdbc.ClientXADataSource;
+import org.apache.derby.jdbc.EmbeddedSimpleDataSource;
+import org.apache.derbyTesting.functionTests.util.SecurityCheck;
+import org.apache.derbyTesting.junit.BaseJDBCTestCase;
+import org.apache.derbyTesting.junit.CleanDatabaseTestSetup;
+import org.apache.derbyTesting.junit.DatabasePropertyTestSetup;
+import org.apache.derbyTesting.junit.J2EEDataSource;
+import org.apache.derbyTesting.junit.JDBC;
+import org.apache.derbyTesting.junit.JDBCClient;
+import org.apache.derbyTesting.junit.JDBCDataSource;
+import org.apache.derbyTesting.junit.TestConfiguration;
+
+/**
+ * Test the ConnectionPoolDataSource and XADataSource implementations of Derby.
+ * DataSource functionality common to DataSources including what is
+ * supported with JSR169 is tested in DataSourceTest.
+ *
+ * Performs SecurityCheck analysis on the JDBC objects returned.
+ * This is because this test returns to the client a number of
+ * different implementations of Connection, Statement etc.
+ *
+ * @see org.apache.derbyTesting.functionTests.util.SecurityCheck
+ *
+ */
+public class J2EEDataSourceTest extends BaseJDBCTestCase {
+
+ private static final String dbName =
+ TestConfiguration.getCurrent().getDefaultDatabaseName();
+
+ /**
+ * A hashtable of opened connections. This is used when checking to
+ * make sure connection strings are unique; we need to make sure all
+ * the connections are closed when we are done, so they are stored
+ * in this hashtable
+ */
+ protected static Hashtable conns = new Hashtable();
+
+ /** The expected format of a connection string. In English:
+ * "<classname>@<hashcode> (XID=<xid>), (SESSION = <sessionid>),
+ * (DATABASE=<dbname>), (DRDAID = <drdaid>)"
+ */
+ private static final String CONNSTRING_FORMAT =
+ "\\S+@\\-?[0-9]+.* \\(XID = .*\\), \\(SESSIONID = [0-9]+\\), " +
+ "\\(DATABASE = [A-Za-z]+\\), \\(DRDAID = .*\\) ";
+
+
+ /**
+ * Hang onto the SecurityCheck class while running the
+ * tests so that it is not garbage collected during the
+ * test and lose the information it has collected,
+ * in case it should get printed out.
+ */
+ private final Object nogc = SecurityCheck.class;
+
+ public J2EEDataSourceTest(String name) {
+ super(name);
+ }
+
+ /**
+ * Return a suite of tests that are run with a lower lock timeout.
+ *
+ * @param postfix suite name postfix
+ * @return A suite of tests being run with a lower lock timeout.
+ */
+ private static Test getTimeoutSuite(String postfix) {
+ TestSuite suite = new TestSuite("Lower lock timeout" + postfix);
+ suite.addTest(new J2EEDataSourceTest("timeoutTestDerby1144PooledDS"));
+ suite.addTest(new J2EEDataSourceTest("timeoutTestDerby1144XADS"));
+ // Reduce the timeout threshold to make the tests run faster.
+ return DatabasePropertyTestSetup.setLockTimeouts(suite, 3, 5);
+ }
+
+ /**
+ * Return a suite of tests that are run with both client and embedded
+ *
+ * @param postfix suite name postfix
+ * @return A suite of tests to be run with client and/or embedded
+ */
+ private static Test baseSuite(String postfix) {
+ TestSuite suite = new TestSuite("ClientAndEmbedded" + postfix);
+ suite.addTest(new J2EEDataSourceTest("testGlobalLocalInterleaf"));
+ suite.addTest(new J2EEDataSourceTest("testSetIsolationWithStatement"));
+ suite.addTest(new J2EEDataSourceTest("testJira95xads"));
+ suite.addTest(new J2EEDataSourceTest("testBadConnectionAttributeSyntax"));
+ suite.addTest(new J2EEDataSourceTest("testDescriptionProperty"));
+ suite.addTest(new J2EEDataSourceTest("testConnectionErrorEvent"));
+ suite.addTest(new J2EEDataSourceTest("testReadOnlyToWritableTran"));
+ suite.addTest(new J2EEDataSourceTest("testAutoCommitOnXAResourceStart"));
+ suite.addTest(new J2EEDataSourceTest("testAllDataSources"));
+ suite.addTest(new J2EEDataSourceTest("testClosedCPDSConnection"));
+ suite.addTest(new J2EEDataSourceTest("testClosedXADSConnection"));
+ suite.addTest(new J2EEDataSourceTest("testSetSchemaInXAConnection"));
+ return suite;
+ }
+
+ /**
+ * Return a suite of tests that are run with client only
+ *
+ * @return A suite of tests being run with client only
+ */
+ private static Test getClientSuite() {
+ TestSuite suite = new TestSuite("Client/Server");
+ suite.addTest(new J2EEDataSourceTest("testClientDSConnectionAttributes"));
+ suite.addTest(new J2EEDataSourceTest(
+ "testClientTraceFileDSConnectionAttribute"));
+ suite.addTest(new J2EEDataSourceTest(
+ "testClientMessageTextConnectionAttribute"));
+ return suite;
+ }
+
+ /**
+ * Return a suite of tests that are run with embedded only
+ *
+ * @param postfix suite name postfix
+ * @return A suite of tests being run with embedded only
+ */
+ private static Test getEmbeddedSuite(String postfix) {
+ TestSuite suite = new TestSuite("Embedded" + postfix);
+ suite.addTest(new J2EEDataSourceTest("testDSRequestAuthentication"));
+ // Due to a bug following cannot be run for client - DERBY-3379
+ // To run this fixture with client, add to getClientSuite(),
+ // when DERBY-3379 is fixed, remove from here (and client) and
+ // move to baseSuite.
+ suite.addTest(new J2EEDataSourceTest("testPooledReuseOnClose"));
+ // when DERBY-2498 gets fixed, move this one to baseSuite
+ suite.addTest(new J2EEDataSourceTest("testJira95pds"));
+ // Following cannot run with client because of DERBY-2533; it hangs
+ // when fixed, this can be moved to baseSuite.
+ suite.addTest(new J2EEDataSourceTest("testReuseAcrossGlobalLocal"));
+ suite.addTest(new J2EEDataSourceTest("testXAHoldability"));
+ return suite;
+ }
+
+ public static Test suite() {
+ if (JDBC.vmSupportsJSR169())
+ {
+ // test uses unsupported classes like DriverManager, XADataSource,
+ // ConnectionPoolDataSource, ConnectionEvenListenere, as well as
+ // unsupported methods, like Connection.setTypeMap()...
+ TestSuite suite =
+ new TestSuite("J2EEDatasourceTest cannot run with JSR169");
+ return suite;
+ }
+ else
+ {
+ TestSuite suite = new TestSuite("J2EEDataSourceTest suite");
+ // Add tests that will run with both embedded
+ suite.addTest(baseSuite(":embedded"));
+ // and network server/client
+ suite.addTest(TestConfiguration.clientServerDecorator(
+ baseSuite(":client")));
+ // Add the tests that only run with client
+ suite.addTest(TestConfiguration.clientServerDecorator(
+ getClientSuite()));
+ // Add the tests that only run with embedded
+ suite.addTest(getEmbeddedSuite("embedded"));
+ // Add the tests relying on getting timeouts.
+ suite.addTest(getTimeoutSuite(":embedded"));
+ suite.addTest(TestConfiguration.clientServerDecorator(
+ getTimeoutSuite(":client")));
+ // wrap all in CleanDatabaseTestSetup that creates all database
+ // objects any fixture might need.
+ // Note that not all fixtures need (all of) these.
+ return new CleanDatabaseTestSetup(suite) {
+ /**
+ * Create and populate database objects
+ *
+ * @see org.apache.derbyTesting.junit.CleanDatabaseTestSetup#decorateSQL(java.sql.Statement)
+ */
+ protected void decorateSQL(Statement s) throws SQLException {
+ s.executeUpdate("create table autocommitxastart(i int)");
+ s.executeUpdate("insert into autocommitxastart values 1,2,3,4,5");
+ s.executeUpdate("create schema SCHEMA_Patricio");
+ s.executeUpdate("create table " +
+ "SCHEMA_Patricio.Patricio (id VARCHAR(255), value INTEGER)");
+ s.executeUpdate("create table intTable(i int)");
+ s.executeUpdate("create table hold_30 " +
+ "(id int not null primary key, b char(30))");
+ s.executeUpdate(
+ "create procedure checkConn2(in dsname varchar(20)) " +
+ "parameter style java language java modifies SQL DATA " +
+ "external name " +
+ "'org.apache.derbyTesting.functionTests.tests.jdbcapi.J2EEDataSourceTest." +
+ getNestedMethodName() +
+ "'");
+ }
+ };
+ }
+ }
+
+ public void tearDown() throws Exception {
+ // attempt to get rid of any left-over trace files
+ AccessController.doPrivileged(new java.security.PrivilegedAction() {
+ public Object run() {
+ for (int i=0 ; i < 6 ; i++)
+ {
+ String traceFileName = "trace" + (i+1) + ".out";
+ File traceFile = new File(traceFileName);
+ if (traceFile.exists())
+ {
+ // if it exists, attempt to get rid of it
+ traceFile.delete();
+ }
+ }
+ return null;
+ }
+ });
+ super.tearDown();
+ }
+
+ /* comment out. leaving in, just in case it's ever relevant.
+ * when uncommented, this will run when network server tests are
+ * started, and then reflect the results of the embedded checks.
+ // perform security analysis of the public api for the embedded engine
+ public void testDataSourceAPI() throws SQLException, ClassNotFoundException
+ {
+ SecurityCheck.report();
+ }
+ */
+
+ /**
+ * Test case for DERBY-3172
+ * When the Derby engine is shutdown or Network Server is brought down, any
+ * api on JDBC Connection object should generate a Connection error event.
+ */
+ public void testConnectionErrorEvent() throws SQLException, Exception
+ {
+ AssertEventCatcher aes12 = new AssertEventCatcher(12);
+
+ ConnectionPoolDataSource ds = J2EEDataSource.getConnectionPoolDataSource();
+
+ PooledConnection pc = ds.getPooledConnection();
+ //Add a connection event listener to ConnectionPoolDataSource
+ pc.addConnectionEventListener(aes12);
+ Connection conn = pc.getConnection();
+
+ dropTable(conn, "TAB1");
+
+ //No event should have been generated at this point
+ assertFalse(aes12.didConnectionClosedEventHappen());
+ assertFalse(aes12.didConnectionErrorEventHappen());
+ aes12.resetState();
+ //Shutdown the Derby engine or Network Server depending on what
+ //mode we are running in.
+ if (usingEmbedded())
+ {
+ getTestConfiguration().shutdownDatabase();
+ } else
+ {
+ getTestConfiguration().stopNetworkServer();
+ }
+ //Now try to use various apis on the JDBC Connection object created
+ //before shutdown and they all should generate connection error event.
+ try {
+ conn.prepareStatement("CREATE TABLE TAB1(COL1 INT NOT NULL)");
+ } catch (SQLException e) {
+ //The first call on JDBC Connection object after Network Server
+ //shutdown will generate a communication error and that's why we
+ //are checking for SQL State 08006 rather than No current connection
+ //SQL State 08003. In embedded mode, we will get SQL State 08003
+ //meaning No current connection
+ if (usingEmbedded())
+ assertSQLState("08003", e);
+ else
+ assertSQLState("08006", e);
+ }
+ assertFalse(aes12.didConnectionClosedEventHappen());
+ assertTrue(aes12.didConnectionErrorEventHappen());
+ aes12.resetState();
+ try {
+ conn.prepareStatement("CREATE TABLE TAB1(COL1 INT NOT NULL)", 1);
+ } catch (SQLException e) {
+ assertSQLState("08003", e);
+ }
+ assertFalse(aes12.didConnectionClosedEventHappen());
+ assertTrue(aes12.didConnectionErrorEventHappen());
+ aes12.resetState();
+ try {
+ int[] columnIndexes = {1};
+ conn.prepareStatement("CREATE TABLE TAB1(COL1 INT NOT NULL)",
+ columnIndexes);
+ } catch (SQLException e) {
+ assertSQLState("08003", e);
+ }
+ assertFalse(aes12.didConnectionClosedEventHappen());
+ assertTrue(aes12.didConnectionErrorEventHappen());
+ aes12.resetState();
+ try {
+ String[] columnNames = {"col1"};
+ conn.prepareStatement("CREATE TABLE TAB1(COL1 INT NOT NULL)",
+ columnNames);
+ } catch (SQLException e) {
+ assertSQLState("08003", e);
+ }
+ assertFalse(aes12.didConnectionClosedEventHappen());
+ assertTrue(aes12.didConnectionErrorEventHappen());
+ aes12.resetState();
+ try {
+ conn.prepareStatement("CREATE TABLE TAB1(COL1 INT NOT NULL)",
+ ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
+ } catch (SQLException e) {
+ assertSQLState("08003", e);
+ }
+ assertFalse(aes12.didConnectionClosedEventHappen());
+ assertTrue(aes12.didConnectionErrorEventHappen());
+ aes12.resetState();
+ try {
+ conn.prepareStatement("CREATE TABLE TAB1(COL1 INT NOT NULL)",
+ ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY,
+ ResultSet.CLOSE_CURSORS_AT_COMMIT);
+ } catch (SQLException e) {
+ assertSQLState("08003", e);
+ }
+ assertFalse(aes12.didConnectionClosedEventHappen());
+ assertTrue(aes12.didConnectionErrorEventHappen());
+ aes12.resetState();
+ try {
+ conn.createStatement();
+ } catch (SQLException e) {
+ assertSQLState("08003", e);
+ }
+ assertFalse(aes12.didConnectionClosedEventHappen());
+ assertTrue(aes12.didConnectionErrorEventHappen());
+ aes12.resetState();
+ try {
+ conn.createStatement(ResultSet.TYPE_FORWARD_ONLY,
+ ResultSet.CONCUR_READ_ONLY,
+ ResultSet.CLOSE_CURSORS_AT_COMMIT);
+ } catch (SQLException e) {
+ assertSQLState("08003", e);
+ }
+ assertFalse(aes12.didConnectionClosedEventHappen());
+ assertTrue(aes12.didConnectionErrorEventHappen());
+ aes12.resetState();
+ try {
+ conn.createStatement(ResultSet.TYPE_FORWARD_ONLY,
+ ResultSet.CONCUR_READ_ONLY);
+ } catch (SQLException e) {
+ assertSQLState("08003", e);
+ }
+ assertFalse(aes12.didConnectionClosedEventHappen());
+ assertTrue(aes12.didConnectionErrorEventHappen());
+ aes12.resetState();
+ try {
+ conn.prepareCall("CREATE TABLE TAB1(COL1 INT NOT NULL)",
+ ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
+ } catch (SQLException e) {
+ assertSQLState("08003", e);
+ }
+ assertFalse(aes12.didConnectionClosedEventHappen());
+ assertTrue(aes12.didConnectionErrorEventHappen());
+ aes12.resetState();
+ try {
+ conn.prepareCall("CREATE TABLE TAB1(COL1 INT NOT NULL)");
+ } catch (SQLException e) {
+ assertSQLState("08003", e);
+ }
+ assertFalse(aes12.didConnectionClosedEventHappen());
+ assertTrue(aes12.didConnectionErrorEventHappen());
+ aes12.resetState();
+ try {
+ conn.prepareCall("CREATE TABLE TAB1(COL1 INT NOT NULL)",
+ ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY,
+ ResultSet.CLOSE_CURSORS_AT_COMMIT);
+ } catch (SQLException e) {
+ assertSQLState("08003", e);
+ }
+ assertFalse(aes12.didConnectionClosedEventHappen());
+ assertTrue(aes12.didConnectionErrorEventHappen());
+ aes12.resetState();
+ try {
+ conn.nativeSQL("CREATE TABLE TAB1(COL1 INT NOT NULL)");
+ } catch (SQLException e) {
+ assertSQLState("08003", e);
+ }
+ assertFalse(aes12.didConnectionClosedEventHappen());
+ assertTrue(aes12.didConnectionErrorEventHappen());
+ aes12.resetState();
+ try {
+ conn.getAutoCommit();
+ } catch (SQLException e) {
+ assertSQLState("08003", e);
+ }
+ assertFalse(aes12.didConnectionClosedEventHappen());
+ assertTrue(aes12.didConnectionErrorEventHappen());
+ aes12.resetState();
+ try {
+ conn.setAutoCommit(false);
+ } catch (SQLException e) {
+ assertSQLState("08003", e);
+ }
+ assertFalse(aes12.didConnectionClosedEventHappen());
+ assertTrue(aes12.didConnectionErrorEventHappen());
+ aes12.resetState();
+ try {
+ conn.getHoldability();
+ } catch (SQLException e) {
+ assertSQLState("08003", e);
+ }
+ assertFalse(aes12.didConnectionClosedEventHappen());
+ assertTrue(aes12.didConnectionErrorEventHappen());
+ aes12.resetState();
+ try {
+ conn.setHoldability(1);
+ } catch (SQLException e) {
+ assertSQLState("08003", e);
+ }
+ assertFalse(aes12.didConnectionClosedEventHappen());
+ assertTrue(aes12.didConnectionErrorEventHappen());
+ aes12.resetState();
+ try {
+ conn.commit();
+ } catch (SQLException e) {
+ assertSQLState("08003", e);
+ }
+ assertFalse(aes12.didConnectionClosedEventHappen());
+ assertTrue(aes12.didConnectionErrorEventHappen());
+ aes12.resetState();
+ try {
+ conn.rollback();
+ } catch (SQLException e) {
+ assertSQLState("08003", e);
+ }
+ assertFalse(aes12.didConnectionClosedEventHappen());
+ assertTrue(aes12.didConnectionErrorEventHappen());
+ aes12.resetState();
+ try {
+ conn.setSavepoint();
+ } catch (SQLException e) {
+ assertSQLState("08003", e);
+ }
+ assertFalse(aes12.didConnectionClosedEventHappen());
+ assertTrue(aes12.didConnectionErrorEventHappen());
+ aes12.resetState();
+ try {
+ conn.setSavepoint("savept1");
+ } catch (SQLException e) {
+ assertSQLState("08003", e);
+ }
+ assertFalse(aes12.didConnectionClosedEventHappen());
+ assertTrue(aes12.didConnectionErrorEventHappen());
+ aes12.resetState();
+ try {
+ conn.rollback((Savepoint)null);
+ } catch (SQLException e) {
+ assertSQLState("08003", e);
+ }
+ assertFalse(aes12.didConnectionClosedEventHappen());
+ assertTrue(aes12.didConnectionErrorEventHappen());
+ aes12.resetState();
+ try {
+ conn.releaseSavepoint((Savepoint)null);
+ } catch (SQLException e) {
+ assertSQLState("08003", e);
+ }
+ assertFalse(aes12.didConnectionClosedEventHappen());
+ assertTrue(aes12.didConnectionErrorEventHappen());
+ aes12.resetState();
+ try {
+ conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
+ } catch (SQLException e) {
+ assertSQLState("08003", e);
+ }
+ assertFalse(aes12.didConnectionClosedEventHappen());
+ assertTrue(aes12.didConnectionErrorEventHappen());
+ aes12.resetState();
+ try {
+ conn.getTransactionIsolation();
+ } catch (SQLException e) {
+ assertSQLState("08003", e);
+ }
+ assertFalse(aes12.didConnectionClosedEventHappen());
+ assertTrue(aes12.didConnectionErrorEventHappen());
+ aes12.resetState();
+ try {
+ conn.getWarnings();
+ } catch (SQLException e) {
+ assertSQLState("08003", e);
+ }
+ assertFalse(aes12.didConnectionClosedEventHappen());
+ assertTrue(aes12.didConnectionErrorEventHappen());
+ aes12.resetState();
+ try {
+ conn.clearWarnings();
+ } catch (SQLException e) {
+ assertSQLState("08003", e);
+ }
+ assertFalse(aes12.didConnectionClosedEventHappen());
+ assertTrue(aes12.didConnectionErrorEventHappen());
+ aes12.resetState();
+ try {
+ conn.getMetaData();
+ } catch (SQLException e) {
+ assertSQLState("08003", e);
+ }
+ assertFalse(aes12.didConnectionClosedEventHappen());
+ assertTrue(aes12.didConnectionErrorEventHappen());
+ aes12.resetState();
+ try {
+ conn.isReadOnly();
+ } catch (SQLException e) {
+ assertSQLState("08003", e);
+ }
+ assertFalse(aes12.didConnectionClosedEventHappen());
+ assertTrue(aes12.didConnectionErrorEventHappen());
+ aes12.resetState();
+ try {
+ conn.setReadOnly(true);
+ } catch (SQLException e) {
+ assertSQLState("08003", e);
+ }
+ assertFalse(aes12.didConnectionClosedEventHappen());
+ assertTrue(aes12.didConnectionErrorEventHappen());
+ aes12.resetState();
+ try {
+ conn.setCatalog(null);
+ } catch (SQLException e) {
+ assertSQLState("08003", e);
+ }
+ assertFalse(aes12.didConnectionClosedEventHappen());
+ assertTrue(aes12.didConnectionErrorEventHappen());
+ aes12.resetState();
+ try {
+ conn.getCatalog();
+ } catch (SQLException e) {
+ assertSQLState("08003", e);
+ }
+ assertFalse(aes12.didConnectionClosedEventHappen());
+ assertTrue(aes12.didConnectionErrorEventHappen());
+ aes12.resetState();
+ try {
+ conn.getTypeMap();
+ } catch (SQLException e) {
+ assertSQLState("08003", e);
+ }
+ assertFalse(aes12.didConnectionClosedEventHappen());
+ assertTrue(aes12.didConnectionErrorEventHappen());
+ aes12.resetState();
+ try {
+ conn.setTypeMap(null);
+ } catch (SQLException e) {
+ assertSQLState("08003", e);
+ }
+ assertFalse(aes12.didConnectionClosedEventHappen());
+ assertTrue(aes12.didConnectionErrorEventHappen());
+ aes12.resetState();
+ if (usingEmbedded())
+ {
+ Class.forName("org.apache.derby.jdbc.EmbeddedDriver").newInstance();
+ }else
+ {
+ getTestConfiguration().startNetworkServer();
+ }
+
+ // Get a new connection to the database
+ conn = getConnection();
+ conn.close();
+ }
+
+ /**
+ * Test that a PooledConnection can be reused and closed
+ * (separately) during the close event raised by the
+ * closing of its logical connection.
+ * DERBY-2142.
+ * @throws SQLException
+ *
+ */
+ public void testPooledReuseOnClose() throws SQLException
+ {
+ // PooledConnection from a ConnectionPoolDataSource
+ ConnectionPoolDataSource cpds =
+ J2EEDataSource.getConnectionPoolDataSource();
+ subtestPooledReuseOnClose(cpds.getPooledConnection());
+ subtestPooledCloseOnClose(cpds.getPooledConnection());
+ // DERBY-3401 - removing a callback during a close causes problems.
+ //subtestPooledRemoveListenerOnClose(cpds.getPooledConnection());
+
+ // PooledConnection from an XDataSource
+ XADataSource xads = J2EEDataSource.getXADataSource();
+ subtestPooledReuseOnClose(xads.getXAConnection());
+ subtestPooledCloseOnClose(xads.getXAConnection());
+ // DERBY-3401 - removing a callback during a close causes problems.
+ //subtestPooledRemoveListenerOnClose(xads.getXAConnection());
+ }
+
+ /**
+ * Tests that a pooled connection can successfully be reused
+ * (a new connection obtained from it) during the processing
+ * of its close event by its listener.
+ * Sections 11.2 & 12.5 of JDBC 4 specification indicate that the
+ * connection can be returned to the pool when the
+ * ConnectionEventListener.connectionClosed() is called.
+ */
+ private void subtestPooledReuseOnClose(final PooledConnection pc) throws SQLException
+ {
+ final Connection[] newConn = new Connection[1];
+ pc.addConnectionEventListener(new ConnectionEventListener() {
+
+ /**
+ * Mimic a pool handler that returns the PooledConnection
+ * to the pool and then reallocates it to a new logical connection.
+ */
+ public void connectionClosed(ConnectionEvent event) {
+ PooledConnection pce = (PooledConnection) event.getSource();
+ assertSame(pc, pce);
+ try {
+ // open a new logical connection and pass
+ // back to the fixture.
+ newConn[0] = pce.getConnection();
+ } catch (SQLException e) {
+ // Need to catch the exception here because
+ // we cannot throw an exception through
+ // the api method.
+ fail(e.getMessage());
+ }
+ }
+
+ public void connectionErrorOccurred(ConnectionEvent event) {
+ }
+
+ });
+
+ // Open a connection then close it to trigger the
+ // fetching of a new connection in the callback.
+ Connection c1 = pc.getConnection();
+ c1.close();
+
+ // Fetch the connection created in the close callback
+ Connection c2 = newConn[0];
+ assertNotNull(c2);
+
+ // Ensure the connection is useable, this hit a NPE before DERBY-2142
+ // was fixed (for embedded).
+ c2.createStatement().close();
+
+ pc.close();
+ }
+
+ /**
+ * Tests that a pooled connection can successfully be closed
+ * during the processing of its close event by its listener.
+ */
+ private void subtestPooledCloseOnClose(final PooledConnection pc) throws SQLException
+ {
+ pc.addConnectionEventListener(new ConnectionEventListener() {
+
+ /**
+ * Mimic a pool handler that closes the PooledConnection
+ * (say it no longer needs it, pool size being reduced)
+ */
+ public void connectionClosed(ConnectionEvent event) {
+ PooledConnection pce = (PooledConnection) event.getSource();
+ assertSame(pc, pce);
+ try {
+ pce.close();
+ } catch (SQLException e) {
+ // Need to catch the exception here because
+ // we cannot throw an exception through
+ // the api method.
+ fail(e.getMessage());
+ }
+ }
+
+ public void connectionErrorOccurred(ConnectionEvent event) {
+ }
+
+ });
+
+ // Open and close a connection to invoke the logic above
+ // through the callback
+ pc.getConnection().close();
+
+ // The callback closed the actual pooled connection
+ // so subsequent requests to get a logical connection
+ // should fail.
+ try {
+ pc.getConnection();
+ fail("PooledConnection should be closed");
+ } catch (SQLException sqle) {
+ assertSQLState("08003", sqle);
+ }
+ }
+
+ /**
+ * Tests that a listener of a pooled connection can successfully
+ * remove itself during the processing of its close event by its listener.
+ */
+ private void subtestPooledRemoveListenerOnClose(final PooledConnection pc) throws SQLException
+ {
+
+ final int[] count1 = new int[1];
+ pc.addConnectionEventListener(new ConnectionEventListener() {
+
+ /**
+ * Mimic a pool handler that removes the listener during
+ * a logical close.
+ */
+ public void connectionClosed(ConnectionEvent event) {
+ PooledConnection pce = (PooledConnection) event.getSource();
+ assertSame(pc, pce);
+ count1[0]++;
+ pce.removeConnectionEventListener(this);
+ }
+
+ public void connectionErrorOccurred(ConnectionEvent event) {
+ }
+
+ });
+
+ // and have another listener to ensure removing one leaves
+ // the other working and intact.
+ final int[] count2 = new int[1];
+ pc.addConnectionEventListener(new ConnectionEventListener() {
+
+ /**
+ * Mimic a pool handler that closes the PooledConnection
+ * (say it no longer needs it, pool size being reduced)
+ */
+ public void connectionClosed(ConnectionEvent event) {
+ PooledConnection pce = (PooledConnection) event.getSource();
+ assertSame(pc, pce);
+ count2[0]++;
+ }
+
+ public void connectionErrorOccurred(ConnectionEvent event) {
+ }
+
+ });
+ // no callback yet
+ assertEquals(0, count1[0]);
+ assertEquals(0, count2[0]);
+
+ // Open and close a connection to invoke the logic above
+ // through the callback
+ pc.getConnection().close();
+
+ // one callback for each
+ assertEquals(1, count1[0]);
+ assertEquals(1, count2[0]);
+
+ // the callback (count1) that was removed is not called on the
+ // second close but the second callback (count2) is called.
+ pc.getConnection().close();
+ assertEquals(1, count1[0]);
+ assertEquals(2, count2[0]);
+
+ pc.close();
+ }
+
+
+ public void testAllDataSources() throws SQLException, Exception
+ {
+ Connection dmc = getConnection();
+ CallableStatement cs = dmc.prepareCall("call checkConn2(?)");
+ cs.setString(1,"Nested");
+ try {
+ cs.execute();
+ } catch (SQLException sqle) {
+ assertSQLState("40XC0", sqle);
+ }
+ cs.setString(1,"Nested2");
+ cs.execute();
+
+ String EmptyMapValue=null;
+ // Note: currently, not supported
+ String NullMapValue=null;
+ String MapMapValue=null;
+ if (usingEmbedded())
+ {
+ EmptyMapValue="OK"; NullMapValue="XJ081"; MapMapValue="0A000";
+ }
+ else if (usingDerbyNetClient())
+ {
+ EmptyMapValue="0A000"; NullMapValue="0A000"; MapMapValue="0A000";
+ }
+ Object[] expectedValues = {
+ new Integer(ResultSet.HOLD_CURSORS_OVER_COMMIT), "XJ010",
+ new Integer(2), new Boolean(true), new Boolean(false),
+ EmptyMapValue, NullMapValue, MapMapValue};
+
+ assertConnectionOK(expectedValues, "DriverManager ", dmc);
+
+ if (usingEmbedded())
+ assertTenConnectionsUnique();
+
+ DataSource dscs = JDBCDataSource.getDataSource();
+ JDBCDataSource.setBeanProperty(dscs, "createDatabase", "false");
+ if (usingEmbedded())
+ assertToString(dscs);
+
+ DataSource ds = dscs;
+ assertConnectionOK(expectedValues, "DataSource", ds.getConnection());
+
+ DataSource dssimple = null;
+ // simple datasource is only supported with embedded
+ if (usingEmbedded())
+ {
+ EmbeddedSimpleDataSource realdssimple =
+ new EmbeddedSimpleDataSource();
+ realdssimple.setDatabaseName(dbName);
+ ds = realdssimple;
+ dssimple = (DataSource)realdssimple;
+ assertConnectionOK(
+ expectedValues, "SimpleDataSource", ds.getConnection());
+ }
+
+ ConnectionPoolDataSource dsp =
+ J2EEDataSource.getConnectionPoolDataSource();
+
+ if (usingEmbedded())
+ assertToString(dsp);
+
+ PooledConnection pc = dsp.getPooledConnection();
+ // checks currently only implemented for embedded
+ if (usingEmbedded())
+ {
+ SecurityCheck.assertSourceSecurity(
+ pc, "javax.sql.PooledConnection");
+ }
+ AssertEventCatcher aes1 = new AssertEventCatcher(1);
+ pc.addConnectionEventListener(aes1);
+
+ // DERBY-2531
+ // with Network Server / DerbyNetClient, the assertConnectionOK check
+ // returns a different connection object...
+ assertConnectionOK(
+ expectedValues, "ConnectionPoolDataSource", pc.getConnection());
+ //Check if got connection closed event but not connection error event
+ assertTrue(aes1.didConnectionClosedEventHappen());
+ assertFalse(aes1.didConnectionErrorEventHappen());
+ aes1.resetState();
+ assertConnectionOK(
+ expectedValues, "ConnectionPoolDataSource", pc.getConnection());
+ //Check if got connection closed event but not connection error event
+ assertTrue(aes1.didConnectionClosedEventHappen());
+ assertFalse(aes1.didConnectionErrorEventHappen());
+ aes1.resetState();
+
+ XADataSource dsx = J2EEDataSource.getXADataSource();
+ JDBCDataSource.setBeanProperty(dsx, "createDatabase", "false");
+
+ if (usingEmbedded())
+ assertToString(dsx);
+
+ // shutdown db and check all's still ok thereafter
+ TestConfiguration.getCurrent().shutdownDatabase();
+
+ dmc = getConnection();
+ cs = dmc.prepareCall("call checkConn2(?)");
+ // checks currently only implemented for embedded
+ if (usingEmbedded())
+ {
+ SecurityCheck.assertSourceSecurity(
+ cs, "java.sql.CallableStatement");
+ }
+ cs.setString(1,"Nested");
+ try {
+ cs.execute();
+ } catch (SQLException sqle) {
+ assertSQLState("40XC0", sqle);
+ }
+ cs.setString(1, "Nested2");
+ cs.execute();
+
+ XAConnection xac = dsx.getXAConnection();
+ // checks currently only implemented for embedded
+ if (usingEmbedded())
+ {
+ SecurityCheck.assertSourceSecurity(xac, "javax.sql.XAConnection");
+ }
+ AssertEventCatcher aes3 = new AssertEventCatcher(3);
+ xac.addConnectionEventListener(aes3);
+ assertConnectionOK(
+ expectedValues, "XADataSource", xac.getConnection());
+ //Check if got connection closed event but not connection error event
+ assertTrue(aes3.didConnectionClosedEventHappen());
+ assertFalse(aes3.didConnectionErrorEventHappen());
+ aes3.resetState();
+
+ pc = dsp.getPooledConnection();
+ AssertEventCatcher aes2 = new AssertEventCatcher(2);
+ pc.addConnectionEventListener(aes2);
+ assertConnectionOK(
+ expectedValues, "ConnectionPoolDataSource", pc.getConnection());
+ //Check if got connection closed event but not connection error event
+ assertTrue(aes2.didConnectionClosedEventHappen());
+ assertFalse(aes2.didConnectionErrorEventHappen());
+ aes2.resetState();
+
+ // test "local" XAConnections
+ xac = dsx.getXAConnection();
+ AssertEventCatcher aes4 = new AssertEventCatcher(4);
+ xac.addConnectionEventListener(aes4);
+ assertConnectionOK(
+ expectedValues, "XADataSource", xac.getConnection());
+ //Check if got connection closed event but not connection error event
+ assertTrue(aes4.didConnectionClosedEventHappen());
+ assertFalse(aes4.didConnectionErrorEventHappen());
+ aes4.resetState();
+ assertConnectionOK(
+ expectedValues, "XADataSource", xac.getConnection());
+ //Check if got connection closed event but not connection error event
+ assertTrue(aes4.didConnectionClosedEventHappen());
+ assertFalse(aes4.didConnectionErrorEventHappen());
+ aes4.resetState();
+ xac.close();
+
+ // test "global" XAConnections
+ xac = dsx.getXAConnection();
+ AssertEventCatcher aes5 = new AssertEventCatcher(5);
+ xac.addConnectionEventListener(aes5);
+ XAResource xar = xac.getXAResource();
+ // checks currently only implemented for embedded
+ if (usingEmbedded())
+ {
+ SecurityCheck.assertSourceSecurity(
+ xar, "javax.transaction.xa.XAResource");
+ }
+ Xid xid = new cdsXid(1, (byte) 35, (byte) 47);
+ xar.start(xid, XAResource.TMNOFLAGS);
+ Connection xacc = xac.getConnection();
+ xacc.close();
+ expectedValues[0] = new Integer(ResultSet.CLOSE_CURSORS_AT_COMMIT);
+ if (usingEmbedded())
+ expectedValues[1] = "XJ058";
+ expectedValues[3] = new Boolean(false);
+ assertConnectionOK(
+ expectedValues, "Global XADataSource", xac.getConnection());
+ //Check if got connection closed event but not connection error event
+ assertTrue(aes5.didConnectionClosedEventHappen());
+ assertFalse(aes5.didConnectionErrorEventHappen());
+ aes5.resetState();
+ assertConnectionOK(
+ expectedValues, "Global XADataSource", xac.getConnection());
+ //Check if got connection closed event but not connection error event
+ assertTrue(aes5.didConnectionClosedEventHappen());
+ assertFalse(aes5.didConnectionErrorEventHappen());
+ aes5.resetState();
+
+ xar.end(xid, XAResource.TMSUCCESS);
+
+ expectedValues[0] = new Integer(ResultSet.HOLD_CURSORS_OVER_COMMIT);
+ expectedValues[3] = new Boolean(true);
+ assertConnectionOK(expectedValues,
+ "Switch to local XADataSource", xac.getConnection());
+ //Check if got connection closed event but not connection error event
+ assertTrue(aes5.didConnectionClosedEventHappen());
+ assertFalse(aes5.didConnectionErrorEventHappen());
+ aes5.resetState();
+ assertConnectionOK(expectedValues,
+ "Switch to local XADataSource", xac.getConnection());
+ //Check if got connection closed event but not connection error event
+ assertTrue(aes5.didConnectionClosedEventHappen());
+ assertFalse(aes5.didConnectionErrorEventHappen());
+ aes5.resetState();
+
+ Connection backtoGlobal = xac.getConnection();
+
+ xar.start(xid, XAResource.TMJOIN);
+ expectedValues[0] = new Integer(ResultSet.CLOSE_CURSORS_AT_COMMIT);
+ expectedValues[3] = new Boolean(false);
+ assertConnectionOK(expectedValues,
+ "Switch to global XADataSource", backtoGlobal);
+ //Check if got connection closed event but not connection error event
+ assertTrue(aes5.didConnectionClosedEventHappen());
+ assertFalse(aes5.didConnectionErrorEventHappen());
+ aes5.resetState();
+ assertConnectionOK(expectedValues,
+ "Switch to global XADataSource", xac.getConnection());
+ //Check if got connection closed event but not connection error event
+ assertTrue(aes5.didConnectionClosedEventHappen());
+ assertFalse(aes5.didConnectionErrorEventHappen());
+ aes5.resetState();
+ xar.end(xid, XAResource.TMSUCCESS);
+ xar.commit(xid, true);
+
+ xac.close();
+ }
+
+ public void testClosedCPDSConnection() throws SQLException, Exception {
+ // verify that outstanding updates from a closed connection, obtained
+ // from a ConnectionPoolDataSource, are not committed, but rolled back.
+ ConnectionPoolDataSource dsp =
+ J2EEDataSource.getConnectionPoolDataSource();
+ PooledConnection pc = dsp.getPooledConnection();
+ Connection c1 = pc.getConnection();
+ Statement s = c1.createStatement();
+ // start by deleting all rows from intTable
+ s.executeUpdate("delete from intTable");
+ c1.setAutoCommit(false);
+
+ // this update should get rolled back later
+ s.executeUpdate("insert into intTable values(1)");
+ // this should automatically close the original connection
+ c1 = pc.getConnection();
+
+ ResultSet rs =
+ c1.createStatement().executeQuery("select count(*) from intTable");
+ rs.next();
+ assertEquals(0, rs.getInt(1));
+ c1.close();
+
+ // check connection objects are closed once connection is closed
+ try {
+ rs.next();
+ fail("ResultSet is open for a closed connection obtained from PooledConnection");
+ } catch (SQLException sqle) {
+ // 08003 - No current connection; XCL16 - ResultSet not open
+ if (usingEmbedded())
+ assertSQLState("08003", sqle);
+ else if (usingDerbyNetClient())
+ assertSQLState("XCL16", sqle);
+ }
+
+ try {
+ s.executeUpdate("update intTable set i = 1");
+ fail("Statement is open for a closed connection " +
+ "obtained from PooledConnection");
+ } catch (SQLException sqle) {
+ assertSQLState("08003", sqle);
+ }
+
+ pc.close();
+ pc = null;
+ PoolReset("ConnectionPoolDataSource", dsp.getPooledConnection());
+ s.close();
+ rs.close();
+ c1.close();
+ }
+
+ public void testClosedXADSConnection() throws SQLException, Exception {
+ // verify that outstanding updates from a closed connection, obtained
+ // from an XADataSource, are not committed, but rolled back.
+ XADataSource dsx = J2EEDataSource.getXADataSource();
+ XAConnection xac = dsx.getXAConnection();
+ Connection c1 = xac.getConnection();
+ Statement s = c1.createStatement();
+
+ c1.setAutoCommit(false);
+
+ // this update should be rolled back
+ s.executeUpdate("insert into intTable values(2)");
+
+ c1 = xac.getConnection();
+
+ ResultSet rs = c1.createStatement().executeQuery(
+ "select count(*) from intTable");
+ rs.next();
+
+ assertEquals(0, rs.getInt(1));
+
+ rs.close();
+ c1.close();
+ xac.close();
+ xac = null;
+
+ PoolReset("XADataSource", dsx.getXAConnection());
+ }
+
+ public void testGlobalLocalInterleaf() throws SQLException, XAException {
+ // now some explicit tests for how connection state behaves
+ // when switching between global transactions and local
+ // and setting connection state.
+ // some of this may be tested elsewhere too.
+
+ XADataSource dsx = J2EEDataSource.getXADataSource();
+ XAConnection xac = dsx.getXAConnection();
+ AssertEventCatcher aes6 = new AssertEventCatcher(6);
+ xac.addConnectionEventListener(aes6);
+ XAResource xar = xac.getXAResource();
+ Xid xid = new cdsXid(1, (byte) 93, (byte) 103);
+
+ // series 1 - Single connection object
+ Connection cs1 = xac.getConnection();
+ // initial local
+ assertConnectionState(
+ ResultSet.HOLD_CURSORS_OVER_COMMIT,
+ Connection.TRANSACTION_READ_COMMITTED,
+ true, false, cs1);
+ xar.start(xid, XAResource.TMNOFLAGS);
+ // initial X1
+ assertConnectionState(
+ ResultSet.CLOSE_CURSORS_AT_COMMIT,
+ Connection.TRANSACTION_READ_COMMITTED,
+ false, false, cs1);
+ cs1.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
+ cs1.setReadOnly(true);
+ setHoldability(cs1, false); // close cursors
+ // modified X1
+ boolean ReadOnly = false;
+ // see DERBY-911, ReadOnly state different for Embedded/DerbyNetClient
+ if (usingEmbedded())
+ ReadOnly = true;
+ assertConnectionState(
+ ResultSet.CLOSE_CURSORS_AT_COMMIT,
+ Connection.TRANSACTION_READ_UNCOMMITTED,
+ false, ReadOnly, cs1);
+ xar.end(xid, XAResource.TMSUCCESS);
+ // the underlying local transaction/connection must pick up the
+ // state of the Connection handle cs1
+ // modified local:
+ assertConnectionState(
+ ResultSet.CLOSE_CURSORS_AT_COMMIT,
+ Connection.TRANSACTION_READ_UNCOMMITTED,
+ true, ReadOnly, cs1);
+
+ cs1.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
+ cs1.setReadOnly(false);
+ setHoldability(cs1, false); // close cursors
+
+ // reset local
+ assertConnectionState(
+ ResultSet.CLOSE_CURSORS_AT_COMMIT,
+ Connection.TRANSACTION_READ_COMMITTED,
+ true, false, cs1);
+
+ // now re-join the transaction, should pick up the read-only
+ // and isolation level from the transaction,
+ // holdability remains that of this handle.
+ xar.start(xid, XAResource.TMJOIN);
+ // re-join X1
+ assertConnectionState(
+ ResultSet.CLOSE_CURSORS_AT_COMMIT,
+ Connection.TRANSACTION_READ_UNCOMMITTED,
+ false, ReadOnly, cs1);
+ xar.end(xid, XAResource.TMSUCCESS);
+
+ // back to local - should be the same as the reset local
+ assertConnectionState(
+ ResultSet.CLOSE_CURSORS_AT_COMMIT,
+ Connection.TRANSACTION_READ_COMMITTED,
+ true, false, cs1);
+
+ // test suspend/resume
+ // now re-join the transaction (X1) for the second time, should pick
+ // up the read-only and isolation level from the transaction,
+ // holdability remains that of this handle.
+ xar.start(xid, XAResource.TMJOIN);
+ assertConnectionState(
+ ResultSet.CLOSE_CURSORS_AT_COMMIT,
+ Connection.TRANSACTION_READ_UNCOMMITTED,
+ false, ReadOnly, cs1);
+
+ xar.end(xid, XAResource.TMSUSPEND);
+ // local after suspend
+ assertConnectionState(
+ ResultSet.CLOSE_CURSORS_AT_COMMIT,
+ Connection.TRANSACTION_READ_COMMITTED,
+ true, false, cs1);
+
+ xar.start(xid, XAResource.TMRESUME);
+ // resume X1
+ assertConnectionState(
+ ResultSet.CLOSE_CURSORS_AT_COMMIT,
+ Connection.TRANSACTION_READ_UNCOMMITTED,
+ false, ReadOnly, cs1);
+
+ xar.end(xid, XAResource.TMSUCCESS);
+ // back to local (second time)
+ assertConnectionState(
+ ResultSet.CLOSE_CURSORS_AT_COMMIT,
+ Connection.TRANSACTION_READ_COMMITTED,
+ true, false, cs1);
+
+ cs1.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
+ cs1.setReadOnly(true);
+ setHoldability(cs1, true); // hold
+ //Confirm - no connection closed event & connection error event
+ assertFalse(aes6.didConnectionClosedEventHappen());
+ assertFalse(aes6.didConnectionErrorEventHappen());
+ aes6.resetState();
+ cs1.close();
+ //Check if got connection closed event but not connection error event
+ assertTrue(aes6.didConnectionClosedEventHappen());
+ assertFalse(aes6.didConnectionErrorEventHappen());
+ aes6.resetState();
+
+ cs1 = xac.getConnection();
+ // new handle - local
+ assertConnectionState(
+ ResultSet.HOLD_CURSORS_OVER_COMMIT,
+ Connection.TRANSACTION_READ_COMMITTED,
+ true, false, cs1);
+ cs1.close();
+ //Check if got connection closed event but not connection error event
+ assertTrue(aes6.didConnectionClosedEventHappen());
+ assertFalse(aes6.didConnectionErrorEventHappen());
+ aes6.resetState();
+
+ xar.start(xid, XAResource.TMJOIN);
+ cs1 = xac.getConnection();
+ // re-join with new handle X1
+ assertConnectionState(
+ ResultSet.CLOSE_CURSORS_AT_COMMIT,
+ Connection.TRANSACTION_READ_UNCOMMITTED,
+ false, ReadOnly, cs1);
+ cs1.close();
+ xar.end(xid, XAResource.TMSUCCESS);
+ //Check if got connection closed event but not connection error event
+ assertTrue(aes6.didConnectionClosedEventHappen());
+ assertFalse(aes6.didConnectionErrorEventHappen());
+ aes6.resetState();
+
+ // now get a connection (attached to a local)
+ // attach to the global and commit it.
+ // state should be that of the local after the commit.
+ cs1 = xac.getConnection();
+ cs1.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);
+ // pre-X1 commit - local
+ assertConnectionState(
+ ResultSet.HOLD_CURSORS_OVER_COMMIT,
+ Connection.TRANSACTION_REPEATABLE_READ,
+ true, false, cs1);
+ xar.start(xid, XAResource.TMJOIN);
+ // pre-X1 commit - X1
+ assertConnectionState(
+ ResultSet.CLOSE_CURSORS_AT_COMMIT,
+ Connection.TRANSACTION_READ_UNCOMMITTED,
+ false, ReadOnly, cs1);
+ xar.end(xid, XAResource.TMSUCCESS);
+ // post-X1 end - local
+ assertConnectionState(
+ ResultSet.HOLD_CURSORS_OVER_COMMIT,
+ Connection.TRANSACTION_REPEATABLE_READ,
+ true, false, cs1);
+ xar.commit(xid, true);
+ // post-X1 commit - local
+ assertConnectionState(
+ ResultSet.HOLD_CURSORS_OVER_COMMIT,
+ Connection.TRANSACTION_REPEATABLE_READ,
+ true, false, cs1);
+ //Confirm - no connection closed event & connection error event
+ assertFalse(aes6.didConnectionClosedEventHappen());
+ assertFalse(aes6.didConnectionErrorEventHappen());
+ aes6.resetState();
+ cs1.close();
+ //Check if got connection closed event but not connection error event
+ assertTrue(aes6.didConnectionClosedEventHappen());
+ assertFalse(aes6.didConnectionErrorEventHappen());
+ aes6.resetState();
+ }
+
+ // really part of testGlobalLocalInterLeaf:
+ /**
+ * @throws SQLException
+ * @throws XAException
+ */
+ public void testSetIsolationWithStatement()
+ throws SQLException, XAException {
+ // DERBY-421 Setting isolation level with SQL was not getting
+ // handled correctly
+ // Some more isolation testing using SQL and JDBC api
+ XADataSource dsx = J2EEDataSource.getXADataSource();
+ XAConnection xac = dsx.getXAConnection();
+ AssertEventCatcher aes6 = new AssertEventCatcher(6);
+ xac.addConnectionEventListener(aes6);
+ XAResource xar = xac.getXAResource();
+ Connection conn = xac.getConnection();
+ Statement s = conn.createStatement();
+ // initial local
+ assertConnectionState(
+ ResultSet.HOLD_CURSORS_OVER_COMMIT,
+ Connection.TRANSACTION_READ_COMMITTED,
+ true, false, conn);
+
+ // Issue setTransactionIsolation in local transaction
+ conn.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
+ // setTransactionIsolation in local
+ assertConnectionState(
+ ResultSet.HOLD_CURSORS_OVER_COMMIT,
+ Connection.TRANSACTION_READ_UNCOMMITTED,
+ true, false, conn);
+
+ Xid xid;
+ //Issue SQL to change isolation in local transaction
+ s.executeUpdate("set current isolation = RR");
+ assertConnectionState(ResultSet.HOLD_CURSORS_OVER_COMMIT,
+ Connection.TRANSACTION_SERIALIZABLE,
+ true, false, conn);
+
+ xid = new cdsXid(1, (byte) 35, (byte) 47);
+ xar.start(xid, XAResource.TMNOFLAGS);
+ // 1st global (new)
+ assertConnectionState(ResultSet.CLOSE_CURSORS_AT_COMMIT,
+ Connection.TRANSACTION_SERIALIZABLE,
+ false, false, conn);
+ xar.end(xid, XAResource.TMSUCCESS);
+
+ // local
+ assertConnectionState(ResultSet.HOLD_CURSORS_OVER_COMMIT,
+ Connection.TRANSACTION_SERIALIZABLE,
+ true, false, conn);
+ //Issue SQL to change isolation in local transaction
+ s.executeUpdate("set current isolation = RS");
+ assertConnectionState(ResultSet.HOLD_CURSORS_OVER_COMMIT,
+ Connection.TRANSACTION_REPEATABLE_READ,
+ true, false, conn);
+
+ // DERBY-1325 - Isolation level of local connection does not get reset after ending
+ // a global transaction that was joined/resumed if the isolation level was changed
+ // using SQL
+ xar.start(xid, XAResource.TMJOIN);
+ // 1st global(existing)
+ assertConnectionState(ResultSet.CLOSE_CURSORS_AT_COMMIT,
+ Connection.TRANSACTION_SERIALIZABLE,
+ false, false, conn);
+ xar.end(xid, XAResource.TMSUCCESS);
+ // local
+ assertConnectionState(ResultSet.HOLD_CURSORS_OVER_COMMIT,
+ Connection.TRANSACTION_REPEATABLE_READ,
+ true, false, conn);
+ // DERBY-1325 end test
+
+ Xid xid2 = new cdsXid(1, (byte) 93, (byte) 103);
+ xar.start(xid2, XAResource.TMNOFLAGS);
+ // 2nd global (new)
+ assertConnectionState(ResultSet.CLOSE_CURSORS_AT_COMMIT,
+ Connection.TRANSACTION_REPEATABLE_READ,
+ false, false, conn);
+ xar.end(xid2, XAResource.TMSUCCESS);
+
+ xar.start(xid, XAResource.TMJOIN);
+ // 1st global (existing)
+ assertConnectionState(ResultSet.CLOSE_CURSORS_AT_COMMIT,
+ Connection.TRANSACTION_SERIALIZABLE,
+ false, false, conn);
+ xar.end(xid, XAResource.TMSUCCESS);
+
+ //local
+ assertConnectionState(ResultSet.HOLD_CURSORS_OVER_COMMIT,
+ Connection.TRANSACTION_REPEATABLE_READ,
+ true, false, conn);
+
+ xar.start(xid, XAResource.TMJOIN);
+
+ // 1st global (existing)
+ assertConnectionState(ResultSet.CLOSE_CURSORS_AT_COMMIT,
+ Connection.TRANSACTION_SERIALIZABLE,
+ false, false, conn);
+ // Issue SQL to change isolation in 1st global transaction
+ s.executeUpdate("set current isolation = UR");
+ assertConnectionState(ResultSet.CLOSE_CURSORS_AT_COMMIT,
+ Connection.TRANSACTION_READ_UNCOMMITTED,
+ false, false, conn);
+ xar.end(xid, XAResource.TMSUCCESS);
+
+ // local
+ assertConnectionState(ResultSet.HOLD_CURSORS_OVER_COMMIT,
+ Connection.TRANSACTION_READ_UNCOMMITTED,
+ true, false, conn);
+
+ xar.start(xid2, XAResource.TMJOIN);
+ // 2nd global (existing)
+ assertConnectionState(ResultSet.CLOSE_CURSORS_AT_COMMIT,
+ Connection.TRANSACTION_REPEATABLE_READ,
+ false, false, conn);
+ xar.end(xid2, XAResource.TMSUCCESS);
+ xar.rollback(xid2);
+ // (After 2nd global rollback ) local
+ assertConnectionState(ResultSet.HOLD_CURSORS_OVER_COMMIT,
+ Connection.TRANSACTION_READ_UNCOMMITTED,
+ true, false, conn);
+
+ xar.rollback(xid);
+ // (After 1st global rollback) local
+ assertConnectionState(ResultSet.HOLD_CURSORS_OVER_COMMIT,
+ Connection.TRANSACTION_READ_UNCOMMITTED,
+ true, false, conn);
+ //Confirm - no connection closed event & connection error event
+ assertFalse(aes6.didConnectionClosedEventHappen());
+ assertFalse(aes6.didConnectionErrorEventHappen());
+ aes6.resetState();
+ }
+
+ // This test includes some short-hand descriptions of the test cases
+ // left in for reference to the original non-junit test
+ public void testReuseAcrossGlobalLocal() throws SQLException, XAException {
+
+ // DERBY-2533 -
+ // network server cannot run this test - it hits a protocol error
+ // on tearDown. Embedded requires a database shutdown
+ if (usingDerbyNetClient())
+ return;
+
+ int[] onetwothree = {1,2,3};
+ int[] three = {3};
+ int[] pspc = {1, 4}; // expected parameter count for prepared statements
+ int[] cspc = {2, 12, 12}; // for callable statements
+
+ // statics for testReuseAcrossGlobalLocal
+ int[] StatementExpectedValues = {
+ ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY,
+ ResultSet.FETCH_REVERSE, 444, 713, 19,
+ ResultSet.HOLD_CURSORS_OVER_COMMIT};
+ //ResultSet.CLOSE_CURSORS_AT_COMMIT};
+ int[] PreparedStatementExpectedValues = {
+ ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY,
+ ResultSet.FETCH_REVERSE, 888, 317, 91,
+ ResultSet.HOLD_CURSORS_OVER_COMMIT};
+ int[] CallableStatementExpectedValues = {
+ ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY,
+ ResultSet.FETCH_REVERSE, 999, 137, 85,
+ ResultSet.HOLD_CURSORS_OVER_COMMIT};
+
+ XADataSource dsx = J2EEDataSource.getXADataSource();
+ XAConnection xac = dsx.getXAConnection();
+ AssertEventCatcher aes6 = new AssertEventCatcher(6);
+ xac.addConnectionEventListener(aes6);
+ XAResource xar = xac.getXAResource();
+ Xid xid = new cdsXid(1, (byte) 103, (byte) 119);
+
+ // now check re-use of *Statement objects across local/global
+ // connections.
+ Connection cs1 = xac.getConnection();
+
+ // ensure read locks stay around until end-of transaction
+ cs1.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);
+ cs1.setAutoCommit(false);
+ assertLocks(null, cs1);
+
+ Statement sru1 = cs1.createStatement();
+ sru1.setCursorName("SN1");
+ sru1.executeUpdate("insert into intTable values 1,2,3");
+ Statement sruBatch = cs1.createStatement();
+ sruBatch.setCursorName("sruBatch");
+ Statement sruState = createFloatStatementForStateChecking(
+ StatementExpectedValues, cs1);
+ PreparedStatement psruState = createFloatStatementForStateChecking(
+ new int[] {1, 4}, PreparedStatementExpectedValues, cs1,
+ "select i from intTable where i = ?");
+ CallableStatement csruState = createFloatCallForStateChecking(
+ new int[] {2, 12, 12}, CallableStatementExpectedValues, cs1,
+ "CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(?,?)");
+ PreparedStatement psParams =
+ cs1.prepareStatement("select * from intTable where i > ?");
+ psParams.setCursorName("params");
+ psParams.setInt(1, 2);
+ // Params-local-1
+ resultSetQuery("params", three, psParams.executeQuery());
+
+ sruBatch.addBatch("insert into intTable values 4");
+ // sru1-local-1
+ queryOnStatement("SN1", onetwothree, cs1, sru1);
+ cs1.commit(); // need to commit to switch to an global connection;
+
+ // simple case - underlying connection is re-used for global.
+ xar.start(xid, XAResource.TMNOFLAGS);
+ // Expecting downgrade because global transaction sru1-global-2 is
+ // using a statement with holdability true
+ // sru1-global-2
+ queryOnStatement("SN1", onetwothree, cs1, sru1);
+ sruBatch.addBatch("insert into intTable values 5");
+ Statement sru2 = cs1.createStatement();
+ sru2.setCursorName("OAK2");
+ //sru2-global-3
+ queryOnStatement("OAK2", onetwothree, cs1, sru2);
+ // Expecting downgrade because global transaction sru1-global-4 is
+ // using a statement with holdability true
+ // sru1-global-4
+ queryOnStatement("SN1", onetwothree, cs1, sru1);
+ // Global statement
+ StatementExpectedValues[6] = ResultSet.CLOSE_CURSORS_AT_COMMIT;
+ PreparedStatementExpectedValues[6] = ResultSet.CLOSE_CURSORS_AT_COMMIT;
+ CallableStatementExpectedValues[6] = ResultSet.CLOSE_CURSORS_AT_COMMIT;
+ assertStatementState(null, StatementExpectedValues ,sruState);
+ // Global PreparedStatement
+ assertStatementState(pspc, PreparedStatementExpectedValues, psruState);
+ // Global CallableStatement
+ assertStatementState(cspc, CallableStatementExpectedValues, csruState);
+ // Params-global-1
+ resultSetQuery("params", three, psParams.executeQuery());
+
+ xar.end(xid, XAResource.TMSUCCESS);
+ // now a new underlying connection is created
+ // sru1-local-5
+ queryOnStatement("SN1", onetwothree, cs1, sru1);
+ // sru2-local-6
+ queryOnStatement("OAK2", onetwothree, cs1, sru2);
+ sruBatch.addBatch("insert into intTable values 6,7");
+ Statement sru3 = cs1.createStatement();
+ sru3.setCursorName("SF3");
+ // sru3-local-7
+ queryOnStatement("SF3", onetwothree, cs1, sru3);
+ // Two transactions should hold locks (global and the current XA);
+ // LOCAL
+ StatementExpectedValues[6] = ResultSet.HOLD_CURSORS_OVER_COMMIT;
+ PreparedStatementExpectedValues[6] = ResultSet.HOLD_CURSORS_OVER_COMMIT;
+ CallableStatementExpectedValues[6] = ResultSet.HOLD_CURSORS_OVER_COMMIT;
+ assertStatementState(null, StatementExpectedValues, sruState);
+ assertStatementState(pspc, PreparedStatementExpectedValues, psruState);
+ assertStatementState(cspc, CallableStatementExpectedValues, csruState);
+ // Params-local-2
+ resultSetQuery("params", three, psParams.executeQuery());
+ assertLocks(new int[] {14,14}, cs1);
+ cs1.commit();
+ //Confirm - no connection closed event & connection error event
+ assertFalse(aes6.didConnectionClosedEventHappen());
+ assertFalse(aes6.didConnectionErrorEventHappen());
+ aes6.resetState();
+
+ // attach the XA transaction to another connection and see what happens
+ XAConnection xac2 = dsx.getXAConnection();
+ AssertEventCatcher aes5 = new AssertEventCatcher(5);
+ xac2.addConnectionEventListener(aes5);
+ XAResource xar2 = xac2.getXAResource();
+
+ xar2.start(xid, XAResource.TMJOIN);
+ Connection cs2 = xac2.getConnection();
+
+ // these statements were generated by cs1 and thus are still
+ // in a local connection.
+ // sru1-local-8
+ queryOnStatement("SN1", onetwothree, cs1, sru1);
+ // sru2-local-9
+ queryOnStatement("OAK2", onetwothree, cs1, sru2);
+ // sru3-local-10
+ queryOnStatement("SF3", onetwothree, cs1, sru3);
+ sruBatch.addBatch("insert into intTable values 8");
+ // LOCAL 2
+ assertStatementState(null, StatementExpectedValues, sruState);
+ assertStatementState(pspc, PreparedStatementExpectedValues, psruState);
+ assertStatementState(cspc, CallableStatementExpectedValues, csruState);
+
+ assertLocks(new int[] {14, 12}, cs1);
+
+ int[] updateCounts = sruBatch.executeBatch();
+ int[] expectedUpdateCounts = {1, 1, 2, 1};
+ // sruBatch update counts:
+ for (int i = 0; i < updateCounts.length; i++) {
+ assertEquals(expectedUpdateCounts[i], updateCounts[i]);
+ }
+ // sruBatch
+ queryOnStatement(
+ "sruBatch", new int[] {1,2,3,4,5,6,7,8}, cs1, sruBatch);
+
+ xar2.end(xid, XAResource.TMSUCCESS);
+ //Confirm - no connection closed event & connection error event
+ assertFalse(aes5.didConnectionClosedEventHappen());
+ assertFalse(aes5.didConnectionErrorEventHappen());
+ aes5.resetState();
+ xac2.close();
+
+ // allow close on already closed XAConnection
+ xac2.close();
+ xac2.addConnectionEventListener(null);
+ xac2.removeConnectionEventListener(null);
+
+ // test methods against a closed XAConnection and its resource
+ try {
+ xac2.getXAResource();
+ // DERBY-2532
+ // Network Server does not think this is worth an exception.
+ if (usingEmbedded())
+ fail("expected SQLException on " +
+ "closed XAConnection.getXAResource");
+ } catch (SQLException sqle) {
+ assertSQLState("08003", sqle);
+ }
+ try {
+ xac2.getConnection();
+ fail ("expected SQLException on XAConnection.getConnection");
+ } catch (SQLException sqle) {
+ assertSQLState("08003", sqle);
+ }
+ try {
+ xar2.start(xid, XAResource.TMJOIN);
+ fail ("expected XAException on XAResource.TMJOIN");
+ } catch (XAException xae) {
+ assertXAException("XAResource.start", xae);
+ }
+ try {
+ xar2.end(xid, XAResource.TMJOIN);
+ fail ("expected XAException on XAResource.TMJOIN");
+ } catch (XAException xae) {
+ assertXAException("XAResource.end", xae);
+ }
+ try {
+ xar2.commit(xid, true);
+ fail ("expected XAException on XAResource.commit");
+ } catch (XAException xae) {
+ assertXAException("XAResource.commit", xae);
+ }
+ try {
+ xar2.prepare(xid);
+ fail ("expected XAException on XAResource.prepare");
+ } catch (XAException xae) {
+ assertXAException("XAResource.prepare", xae);
+ }
+ try {
+ xar2.recover(0);
+ fail ("expected XAException on XAResource.recover");
+ } catch (XAException xae) {
+ assertXAException("XAResource.recover", xae);
+ }
+ try {
+ xar2.prepare(xid);
+ fail ("expected XAException on XAResource.prepare");
+ } catch (XAException xae) {
+ assertXAException("XAResource.prepare", xae);
+ }
+ try {
+ xar2.isSameRM(xar2);
+ fail ("expected XAException on XAResource.isSameRM");
+ } catch (XAException xae) {
+ assertXAException("XAResource.isSameRM", xae);
+ }
+
+ // close everything
+ cs1.rollback();
+ sruState.close();
+ psruState.close();
+ csruState.close();
+ psParams.close();
+ sruBatch.close();
+ sru1.close();
+ sru2.close();
+ sru3.close();
+ cs1.close();
+ cs2.close();
+ xac.removeConnectionEventListener(null);
+ xac.close();
+ xac2.close();
+
+ // but, still not enough.
+ // what with all the switching between global and local transactions
+ // we still have a lock open on intTable, which will interfere with
+ // our tearDown efforts. Bounce the database.
+ TestConfiguration.getCurrent().shutdownDatabase();
+ }
+
+ public void testSetSchemaInXAConnection() throws SQLException {
+ // tests that set schema works correctly in an XA connection.
+
+ XADataSource dsx = J2EEDataSource.getXADataSource();
+ XAConnection xac3 = dsx.getXAConnection();
+ Connection conn3 = xac3.getConnection();
+ Statement st3 = conn3.createStatement();
+ st3.execute("SET SCHEMA SCHEMA_Patricio");
+ st3.close();
+
+ PreparedStatement ps3 =
+ conn3.prepareStatement("INSERT INTO Patricio VALUES (?, ?)");
+ ps3.setString(1, "Patricio");
+ ps3.setInt(2, 3);
+ ps3.executeUpdate();
+
+ assertEquals(1, ps3.getUpdateCount());
+ ps3.close();
+ conn3.close();
+ xac3.close();
+ }
+
+ // test that an xastart in auto commit mode commits the existing work.
+ // test fix of a bug ('beetle 5178') wherein XAresource.start() when
+ // auto-commit is true did not implictly commit any transaction
+ // Also tests DERBY-1025, same description, but for client.
+ public void testAutoCommitOnXAResourceStart() throws SQLException, XAException {
+
+ XADataSource dsx = J2EEDataSource.getXADataSource();
+ XAConnection xac4 = dsx.getXAConnection();
+ Xid xid4a= null;
+
+ // We get an XAID_DUP error from networkserver when attempting
+ // the XAResource.start below if we use the same xid.
+ // Possibly because we're in the same jvm.
+ // When the test is run with clientserverSuite, rather than default,
+ // this wasn't needed, so just create a different id for client
+ if (usingEmbedded())
+ xid4a = new cdsXid(4, (byte) 23, (byte) 76);
+ else if (usingDerbyNetClient())
+ xid4a = new cdsXid(5, (byte) 23, (byte) 76);
+
+ Connection conn4 = xac4.getConnection();
+ assertTrue(conn4.getAutoCommit());
+
+ Statement s4 = conn4.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.CLOSE_CURSORS_AT_COMMIT);
+ ResultSet rs4 = s4.executeQuery("select i from autocommitxastart");
+ rs4.next();
+ assertEquals(1, rs4.getInt(1));
+ rs4.next();
+ assertEquals(2, rs4.getInt(1));
+
+ // XAResource().start should commit the transaction
+ xac4.getXAResource().start(xid4a, XAResource.TMNOFLAGS);
+ xac4.getXAResource().end(xid4a, XAResource.TMSUCCESS);
+
+ try {
+ rs4.next();
+ fail ("expected an exception indicating resultset is closed.");
+ } catch (SQLException sqle) {
+ // Embedded gets 08003. No current connection (DERBY-2620)
+ if (usingDerbyNetClient())
+ assertSQLState("XCL16",sqle);
+ }
+
+ conn4.setAutoCommit(false);
+ assertFalse(conn4.getAutoCommit());
+
+ rs4 = s4.executeQuery("select i from autocommitxastart");
+ rs4.next();
+ assertEquals(1, rs4.getInt(1));
+ rs4.next();
+ assertEquals(2, rs4.getInt(1));
+
+ // Get a new xid to begin another transaction.
+ if (usingEmbedded())
+ xid4a = new cdsXid(4, (byte) 93, (byte) 103);
+ else if (usingDerbyNetClient())
+ xid4a = new cdsXid(5, (byte) 93, (byte) 103);
+
+ try {
+ xac4.getXAResource().start(xid4a, XAResource.TMNOFLAGS);
+ } catch (XAException xae) {
+ if (usingEmbedded())
+ assertNull(xae.getMessage());
+ else if (usingDerbyNetClient())
+ {
+ // This should give XAER_OUTSIDE exception because
+ // the resource manager is busy in the local transaction
+ assertTrue(xae.getMessage().indexOf("XAER_OUTSIDE") >=0 );
+ }
+ assertEquals(-9, xae.errorCode);
+ }
+
+ rs4.next();
+ assertEquals(3, rs4.getInt(1));
+ rs4.close();
+
+ conn4.rollback();
+ conn4.close();
+ xac4.close();
+ }
+
+ public void testReadOnlyToWritableTran() throws SQLException, Exception
+ {
+ // This fixture will run twice, once with embedded, once with client,
+ // and insert 2 rows in addition to the 5 rows inserted during setup.
+ // The fixture tests a commit, so before running, try to remove row
+ // 6 and 7 in case this is the second run of the fixture.
+ Statement s = createStatement();
+ s.executeUpdate("delete from autocommitxastart where i = 6");
+ s.executeUpdate("delete from autocommitxastart where i = 7");
+
+ // TESTING READ_ONLY TRANSACTION FOLLOWED BY WRITABLE TRANSACTION
+ // Test following sequence of steps
+ // 1)start a read-only global transaction
+ // 2)finish that read-only transaction
+ // 3)start another global transaction
+
+ XADataSource dsx = J2EEDataSource.getXADataSource();
+ XAConnection xac5 = dsx.getXAConnection();
+ Xid xid5a = new cdsXid(5, (byte) 119, (byte) 129);
+ Connection conn5 = xac5.getConnection();
+ Statement sru5a = conn5.createStatement();
+ XAResource xar = xac5.getXAResource();
+ xar.start(xid5a, XAResource.TMNOFLAGS);
+ conn5.setReadOnly(true);
+
+ // Read-Only XA transaction;
+ // holdability: (hold, or close cursors over commit) ,
+ // transaction isolation: read-committed,
+ // auto-commit false, read-only true (with embedded)
+ if (usingEmbedded())
+ {
+ assertConnectionState(
+ ResultSet.CLOSE_CURSORS_AT_COMMIT,
+ Connection.TRANSACTION_READ_COMMITTED,
+ false, true, conn5);
+ }
+ // Note: the original test had no comments about this difference
+ // between Embedded and DerbyNetClient, this has apparently
+ // been accepted behavior.
+ else if (usingDerbyNetClient())
+ {
+ assertConnectionState(
+ ResultSet.CLOSE_CURSORS_AT_COMMIT,
+ Connection.TRANSACTION_READ_COMMITTED,
+ false, false, conn5);
+ }
+
+ ResultSet rs5 = sru5a.executeQuery(
+ "select count(*) from autocommitxastart");
+ rs5.next();
+ assertEquals(5, rs5.getInt(1));
+ rs5.close();
+ xar.end(xid5a, XAResource.TMSUCCESS);
+ xar.commit(xid5a, true);
+ conn5.close();
+
+ //now start a new transaction
+ conn5 = xac5.getConnection();
+ sru5a = conn5.createStatement();
+ xar.start(xid5a, XAResource.TMNOFLAGS);
+
+ // Writeable XA transaction
+ // holdability: (hold, or close cursors over commit) ,
+ // transaction isolation: read-committed,
+ // auto-commit false, read-only false
+ assertConnectionState(
+ ResultSet.CLOSE_CURSORS_AT_COMMIT,
+ Connection.TRANSACTION_READ_COMMITTED,
+ false, false, conn5);
+ sru5a.executeUpdate("insert into autocommitxastart values 6,7");
+ rs5 = sru5a.executeQuery("select count(*) from autocommitxastart");
+ rs5.next();
+ assertEquals(7, rs5.getInt(1));
+ xar.end(xid5a, XAResource.TMSUCCESS);
+ xar.commit(xid5a, true);
+ conn5.close();
+ xac5.close();
+ sru5a.close();
+ }
+
+ // test jira-derby 95 - a NullPointerException was returned when passing
+ // an incorrect database name, should now give error XCY00
+ // with ConnectionPoolDataSource
+ public void testJira95pds() throws SQLException {
+ try {
+ ConnectionPoolDataSource pds = J2EEDataSource.getConnectionPoolDataSource();
+ JDBCDataSource.setBeanProperty(pds, "databaseName", "jdbc:derby:boo");
+ pds.getPooledConnection();
+ fail ("expected an SQLException!");
+ } catch (SQLException sqle) {
+ // DERBY-2498 - when fixed, remove if
+ if (usingEmbedded())
+ assertSQLState("XCY00", sqle);
+ } catch (Exception e) {
+ // DERBY-2498 - when fixed, remove if
+ if (usingEmbedded())
+ fail ("unexpected exception: " + e.toString());
+ }
+ }
+
+ // test jira-derby 95 - a NullPointerException was returned when passing
+ // an incorrect database name, should now give error XCY00
+ // with XADataSource
+ public void testJira95xads() throws SQLException {
+ try {
+ XADataSource dxs = J2EEDataSource.getXADataSource();
+ JDBCDataSource.setBeanProperty(dxs, "databaseName", "jdbc:derby:boo");
+ dxs.getXAConnection().getConnection();
+ fail ("expected an SQLException!");
+ } catch (SQLException sqle) {
+ assertSQLState("XCY00", sqle);
+ } catch (Exception e) {
+ fail ("unexpected exception: " + e.toString());
+ }
+ }
+
+ // there is a corresponding fixture for datasources in DataSourceTest
+ public void testBadConnectionAttributeSyntax() throws SQLException {
+
+ // ConnectionPoolDataSource - bad connatr syntax
+ ConnectionPoolDataSource cpds = J2EEDataSource.getConnectionPoolDataSource();
+ JDBCDataSource.setBeanProperty(cpds, "ConnectionAttributes", "bad");
+ try {
+ cpds.getPooledConnection();
+ fail ("should have seen an error");
+ } catch (SQLException e) {
+ assertSQLState("XJ028", e);
+ }
+
+ // XADataSource - bad connattr syntax");
+ XADataSource xads = J2EEDataSource.getXADataSource();
+ JDBCDataSource.setBeanProperty(xads, "ConnectionAttributes", "bad");
+ try {
+ xads.getXAConnection();
+ fail ("should have seen an error");
+ } catch (SQLException e) {
+ assertSQLState("XJ028", e);
+ }
+ } // End testBadConnectionAttributeSyntax
+
+ /**
+ * Check that database name set using setConnectionAttributes is not used
+ * by ClientDataSource. This method tests DERBY-1130.
+ *
+ * @throws SQLException
+ */
+ public void testClientDSConnectionAttributes() throws SQLException {
+ if (usingEmbedded())
+ return;
+
+ // now with ConnectionPoolDataSource
+ ClientConnectionPoolDataSource cpds =
+ new ClientConnectionPoolDataSource();
+ // ConnectionPoolDataSource - EMPTY
+ dsConnectionRequests(new String[]
+ {"08001","08001","08001","08001",
+ "08001","08001","08001","08001","08001"},
+ (ConnectionPoolDataSource)cpds);
+
+ // ConnectionPoolDataSource
+ // - connectionAttributes=databaseName=<valid dbname>
+ cpds.setConnectionAttributes("databaseName=" + dbName);
+ dsConnectionRequests(new String[]
+ {"08001","08001","08001","08001",
+ "08001","08001","08001","08001","08001"},
+ (ConnectionPoolDataSource)cpds);
+ cpds.setConnectionAttributes(null);
+
+ // Test that database name specified in connection attributes is
+ // not used
+ // ConnectionPoolDataSource - databaseName=wombat and
+ // connectionAttributes=databaseName=kangaroo
+ cpds.setConnectionAttributes("databaseName=kangaroo");
+ cpds.setDatabaseName(dbName);
+ dsConnectionRequests(new String[]
+ {"OK","08001","OK","OK","08001","08001","OK","OK","OK"},
+ (ConnectionPoolDataSource)cpds);
+ cpds.setConnectionAttributes(null);
+ cpds.setDatabaseName(null);
+
+ // now with XADataSource
+ ClientXADataSource xads = new ClientXADataSource();
+ // XADataSource - EMPTY
+ dsConnectionRequests(new String[]
+ {"08001","08001","08001","08001",
+ "08001","08001","08001","08001","08001"},
+ (XADataSource) xads);
+
+ // XADataSource - connectionAttributes=databaseName=<valid dbname>
+ xads.setConnectionAttributes("databaseName=wombat");
+ dsConnectionRequests(new String[]
+ {"08001","08001","08001","08001",
+ "08001","08001","08001","08001","08001"},
+ (XADataSource) xads);
+ xads.setConnectionAttributes(null);
+
+ // Test that database name specified in connection attributes is not used
+ // XADataSource - databaseName=wombat and
+ // connectionAttributes=databaseName=kangaroo
+ xads.setConnectionAttributes("databaseName=kangaroo");
+ xads.setDatabaseName("wombat");
+ dsConnectionRequests(new String[]
+ {"OK","08001","OK","OK","08001","08001","OK","OK","OK"},
+ (XADataSource) xads);
+ xads.setConnectionAttributes(null);
+ xads.setDatabaseName(null);
+ } // End testClientDSConnectionAttributes
+
+ // Following test is similar to testClientDSConnectionAttributes, but
+ // for embedded datasources.
+ // This subtest does not run for network server, it uses
+ // setAttributesAsPassword, which isn't supported for client datasources.
+ //
+ // Note that DataSourceTest has some more basic testing of
+ // an empty DataSource in a fixture with similar name - however
+ // that fixture does not test setAttributesAsPassword
+ public void testDSRequestAuthentication() throws SQLException {
+
+// if (usingDerbyNetClient())
+// return;
+
+ JDBCClient dsclient = getTestConfiguration().getJDBCClient();
+ String dsName = dsclient.getDataSourceClassName();
+ DataSource ds = null;
+ try {
+ ds = (javax.sql.DataSource) Class.forName(dsName).newInstance();
+ } catch (Exception e) {
+ fail("unable to complete test because unable to create new instance of datasource");
+ }
+
+ // DataSource - attributesAsPassword=true");
+ JDBCDataSource.setBeanProperty(ds, "attributesAsPassword", Boolean.TRUE);
+ dsConnectionRequests(new String[] {
+ "XJ004","XJ004","XJ004","XJ028",
+ "XJ028","XJ004","XJ004","XJ004","XJ004"}, ds);
+ JDBCDataSource.setBeanProperty(ds, "attributesAsPassword", Boolean.FALSE);
+
+ // DataSource - attributesAsPassword=true,
+ // connectionAttributes=databaseName=kangaroo");
+ JDBCDataSource.setBeanProperty(ds, "attributesAsPassword", Boolean.TRUE);
+ JDBCDataSource.setBeanProperty(ds, "connectionAttributes", "databaseName=kangaroo");
+ dsConnectionRequests(new String[] {
+ "XJ004","XJ004","XJ004","XJ028",
+ "XJ028","XJ004","XJ004","XJ004","XJ004"}, ds);
+ JDBCDataSource.setBeanProperty(ds, "attributesAsPassword", Boolean.FALSE);
+ JDBCDataSource.clearStringBeanProperty(ds, "connectionAttributes");
+
+ // Enable Authentication;
+
+ setDatabaseProperty("derby.user.fred", "wilma");
+ setDatabaseProperty("derby.user.APP", "APP");
+ setDatabaseProperty("derby.authentication.provider", "BUILTIN");
+ setDatabaseProperty("derby.connection.requireAuthentication", "true");
+
+ JDBCDataSource.setBeanProperty(ds, "shutdownDatabase", "shutdown");
+ try {
+ ds.getConnection();
+ } catch (SQLException sqle) {
+ assertSQLState("XJ015", sqle);
+ }
+
+ JDBCDataSource.clearStringBeanProperty(ds, "databaseName");
+ JDBCDataSource.clearStringBeanProperty(ds, "shutdownDatabase");
+
+ // "AUTHENTICATION NOW ENABLED");
+
+ // DataSource - attributesAsPassword=true
+ JDBCDataSource.setBeanProperty(ds, "attributesAsPassword", Boolean.TRUE);
+ dsConnectionRequests(new String[] {
+ "XJ004","XJ004","XJ004","XJ028",
+ "XJ028","XJ004","XJ004","XJ004","XJ004"}, ds);
+ JDBCDataSource.setBeanProperty(ds, "attributesAsPassword", Boolean.FALSE);
+
+ // ensure the DS property password is not treated as a set of
+ // attributes.
+ // DataSource - attributesAsPassword=true, user=fred,
+ // password=databaseName=wombat;password=wilma
+ JDBCDataSource.setBeanProperty(ds, "attributesAsPassword", Boolean.TRUE);
+ JDBCDataSource.setBeanProperty(ds, "user", "fred");
+ JDBCDataSource.setBeanProperty(ds, "password", "databaseName=" + dbName + ";password=wilma");
+ dsConnectionRequests(new String[] {
+ "XJ004","XJ004","XJ004","XJ028",
+ "XJ028","XJ004","XJ004","XJ004","XJ004"}, ds);
+ JDBCDataSource.setBeanProperty(ds, "attributesAsPassword", Boolean.FALSE);
+ JDBCDataSource.clearStringBeanProperty(ds, "user");
+ JDBCDataSource.clearStringBeanProperty(ds, "password");
+ ds = null;
+
+ // now with ConnectionPoolDataSource
+ String cpdsName = dsclient.getConnectionPoolDataSourceClassName();
+ ConnectionPoolDataSource cpds = null;
+ try {
+ cpds = (javax.sql.ConnectionPoolDataSource)
+ Class.forName(cpdsName).newInstance();
+ } catch (Exception e) {
+ fail("unable to complete test because unable " +
+ "to create new instance of connection pool datasource");
+ }
+
+ // ConnectionPoolDataSource - EMPTY
+ dsConnectionRequests(new String[] {
+ "XJ004","XJ004","XJ004","XJ004",
+ "XJ004","XJ004","XJ004","XJ004","XJ004"},
+ (ConnectionPoolDataSource)cpds);
+
+ // ConnectionPoolDataSource -
+ // connectionAttributes=databaseName=wombat
+ JDBCDataSource.setBeanProperty(cpds, "connectionAttributes", "databaseName=" + dbName);
+ dsConnectionRequests(new String[] {
+ "XJ004","XJ004","XJ004","XJ004",
+ "XJ004","XJ004","XJ004","XJ004","XJ004"},
+ (ConnectionPoolDataSource)cpds);
+ JDBCDataSource.clearStringBeanProperty(cpds, "connectionAttributes");
+
+ // ConnectionPoolDataSource - attributesAsPassword=true
+ JDBCDataSource.setBeanProperty(cpds, "attributesAsPassword", Boolean.TRUE);
+ dsConnectionRequests(new String[] {
+ "XJ004","XJ004","XJ004","XJ028",
+ "XJ028","XJ004","XJ004","XJ004","XJ004"},
+ (ConnectionPoolDataSource)cpds);
+ JDBCDataSource.setBeanProperty(cpds, "attributesAsPassword", Boolean.FALSE);
+
+ // ensure the DS property password is not treated as a set of
+ // attributes.
+ // ConnectionPoolDataSource - attributesAsPassword=true,
+ // user=fred, password=databaseName=wombat;password=wilma");
+ JDBCDataSource.setBeanProperty(cpds, "attributesAsPassword", Boolean.TRUE);
+ JDBCDataSource.setBeanProperty(cpds, "user", "fred");
+ JDBCDataSource.setBeanProperty(cpds, "password", "databaseName=" + dbName + ";password=wilma");
+ dsConnectionRequests(new String[] {
+ "XJ004","XJ004","XJ004","XJ028",
+ "XJ028","XJ004","XJ004","XJ004","XJ004"},
+ (ConnectionPoolDataSource)cpds);
+ JDBCDataSource.setBeanProperty(cpds, "attributesAsPassword", Boolean.FALSE);
+ JDBCDataSource.clearStringBeanProperty(cpds, "user");
+ JDBCDataSource.clearStringBeanProperty(cpds, "password");
+ cpds = null;
+
+ // now with XADataSource
[... 1627 lines stripped ...]