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 da...@apache.org on 2006/03/23 20:06:08 UTC

svn commit: r388234 - in /db/derby/code/trunk/java: client/org/apache/derby/client/am/ engine/org/apache/derby/impl/jdbc/ testing/org/apache/derbyTesting/functionTests/suites/ testing/org/apache/derbyTesting/functionTests/tests/jdbc4/

Author: davidvc
Date: Thu Mar 23 11:06:05 2006
New Revision: 388234

URL: http://svn.apache.org/viewcvs?rev=388234&view=rev
Log:
DERBY-953: Add Statement.isClosed() JDBC4 method
DERBY-1097: Add tests for Statement.isClosed() JDBC4 method

Contributed by Kristian Waagan.  

I modified his patch for DERBY-953 to match
Dan's suggested approach.  I also added StatementTest.junit to the jdbc40
test suite, which passes.  Since this is a JDBC40-specific feature, and
only new code has been added (no existing code has been modified) I did
not run derbyall


Added:
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/StatementTest.java   (with props)
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/StatementTestSetup.java   (with props)
Modified:
    db/derby/code/trunk/java/client/org/apache/derby/client/am/Statement.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedStatement.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/jdbc40.runall

Modified: db/derby/code/trunk/java/client/org/apache/derby/client/am/Statement.java
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/client/org/apache/derby/client/am/Statement.java?rev=388234&r1=388233&r2=388234&view=diff
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/am/Statement.java (original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/am/Statement.java Thu Mar 23 11:06:05 2006
@@ -463,6 +463,24 @@
         }
     }
 
+    /**
+     * Tell whether the statement has been closed or not.
+     *
+     * @return <code>true</code> if closed, <code>false</code> otherwise.
+     * @exception SQLException if a database access error occurs (according to
+     *                         spec). Never thrown by this implementation. 
+     */
+    public boolean isClosed()
+        throws SQLException {
+        if (agent_.loggingEnabled()) {
+            agent_.logWriter_.traceEntry(this, "isClosed", !openOnClient_);
+        }
+        if (agent_.loggingEnabled()) {
+            agent_.logWriter_.traceExit(this, "isClosed", !openOnClient_);
+        }
+        return !openOnClient_;
+    }
+    
     // The server holds statement resources until transaction end.
     public void close() throws SQLException {
         try

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedStatement.java
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedStatement.java?rev=388234&r1=388233&r2=388234&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedStatement.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedStatement.java Thu Mar 23 11:06:05 2006
@@ -234,6 +234,23 @@
 	}
 
     /**
+     * Tell whether this statment has been closed or not.
+     *
+     * @return <code>true</code> is closed, <code>false</code> otherwise.
+     * @exception SQLException if a database access error occurs.
+     */
+    public boolean isClosed() throws SQLException {
+        // If active, verify state by consulting parent connection.
+        if (active) {
+            try {
+                checkExecStatus();
+            } catch (SQLException sqle) {
+            }
+        }
+        return !active;
+    }
+
+    /**
      * In many cases, it is desirable to immediately release a
      * Statements's database and JDBC resources instead of waiting for
      * this to happen when it is automatically closed; the close

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/jdbc40.runall
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/jdbc40.runall?rev=388234&r1=388233&r2=388234&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/jdbc40.runall (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/jdbc40.runall Thu Mar 23 11:06:05 2006
@@ -5,3 +5,4 @@
 jdbc4/TestQueryObject.java
 jdbc4/TestDbMetaData.java
 jdbc4/TestJDBC40Exception.java
+jdbc4/StatementTest.junit

Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/StatementTest.java
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/StatementTest.java?rev=388234&view=auto
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/StatementTest.java (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/StatementTest.java Thu Mar 23 11:06:05 2006
@@ -0,0 +1,242 @@
+/*
+ *
+ * Derby - Class StatementTest
+ *
+ * Copyright 2006 The Apache Software Foundation or its 
+ * licensors, as applicable.
+ *
+ * Licensed 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.jdbc4;
+
+import org.apache.derby.shared.common.reference.SQLState;
+import org.apache.derbyTesting.functionTests.util.BaseJDBCTestCase;
+
+import junit.framework.*;
+
+import java.sql.*;
+
+/**
+ * Tests for new methods added for Statement in JDBC4.
+ */
+public class StatementTest
+    extends BaseJDBCTestCase {
+
+    /** Default connection used by the tests. */
+    private Connection con = null;
+    /** Default statement used by the tests. */
+    private Statement stmt = null;
+    
+    /**
+     * Create a new test with the given name.
+     *
+     * @param name name of the test.
+     */
+    public StatementTest(String name) {
+        super(name);
+    }
+
+    /**
+     * Create default connection and statement.
+     *
+     * @throws SQLException if setAutoCommit, createStatement or 
+     *                      BaseJDBCTestCase.getConnection fails.
+     */
+    public void setUp() 
+        throws SQLException {
+        con = getConnection();
+        assertFalse("Connection must be open initially", con.isClosed());
+        con.setAutoCommit(false);
+        // Create a default statement.
+        stmt = con.createStatement();
+        assertFalse("First statement must be open initially", 
+                stmt.isClosed());
+    }
+
+    /**
+     * Close default connection and statement if necessary.
+     *
+     * @throws SQLException if a database access exception occurs.
+     */
+    public void tearDown() 
+        throws SQLException {
+        // Close default statement
+        if (stmt != null) {
+            stmt.close();
+        }
+        // Close default connection
+        // Check if connection is open to avoid exception on rollback.
+        if (con != null && !con.isClosed()) {
+            // Abort changes that may have been done in the test.
+            // The test-method may however commit these itself.
+            con.rollback();
+            con.close();
+        }
+    }
+
+    /**
+     * Check that <code>isClosed</code> returns <code>true</code> after
+     * the statement has been explicitly closed.
+     */
+    public void testIsClosedBasic()
+        throws SQLException {
+        ResultSet rs = stmt.executeQuery("select count(*) from stmtTable");
+        assertFalse("Statement should still be open", stmt.isClosed());
+        rs.close();
+        assertFalse("Statement should be open after ResultSet has been " +
+                "closed", stmt.isClosed());
+        stmt.close();
+        assertTrue("Statement should be closed, close() has been called", 
+                stmt.isClosed());
+    }
+    
+    /**
+     * Test that creating two statements on the same connection does not
+     * cause side effects on the statements.
+     */
+    public void testIsClosedWithTwoStatementsOnSameConnection()
+        throws SQLException {
+        // Create a second statement on the default connection.
+        Statement stmt2 = con.createStatement();
+        assertFalse("Second statement must be open initially", 
+                stmt2.isClosed());
+        assertFalse("First statement should not be closed when " +
+                "creating a second statement", stmt.isClosed());
+        ResultSet rs = stmt2.executeQuery("select count(*) from stmtTable");
+        assertFalse("Second statement should be open after call to " +
+                "execute()", stmt2.isClosed());
+        assertFalse("First statement should be open after call to " +
+                "second statment's execute()", stmt.isClosed());
+        stmt2.close();
+        assertTrue("Second statement should be closed, close() has " +
+                "been called!", stmt2.isClosed());
+        assertFalse("First statement should be open after call to " +
+                "second statment's close()", stmt.isClosed());
+    }
+
+    /**
+     * Test that the two statements created on the connection are closed
+     * when the connection itself is closed.
+     */
+    public void testIsClosedWhenClosingConnection()
+        throws SQLException {
+        // Create an extra statement for good measure.
+        Statement stmt2 = con.createStatement();
+        assertFalse("Second statement must be open initially",
+                stmt2.isClosed());
+        // Exeute something on it, as opposed to the default statement.
+        stmt2.execute("select count(*) from stmtTable");
+        assertFalse("Second statement should be open after call to " +
+                "execute()", stmt2.isClosed());
+        // Close the connection. We must commit/rollback first, or else a
+        // "Invalid transaction state" exception is raised.
+        con.rollback();
+        con.close();
+        assertTrue("Connection should be closed after close()", 
+                con.isClosed());
+        assertTrue("First statement should be closed, as parent " +
+                "connection has been closed", stmt.isClosed());
+        assertTrue("Second statement should be closed, as parent " +
+                "connection has been closed", stmt2.isClosed());
+    }
+    
+    /**
+     * Check the state of the statement when the connection is first attempted
+     * closed when in an invalid transaction state, then closed after a
+     * commit. According to the JDBC 4 API documentation: </i>"It is strongly 
+     * recommended that an application explictly commits or rolls back an 
+     * active transaction prior to calling the close method. If the close 
+     * method is called and there is an active transaction, 
+     * the results are implementation-defined."</i>
+     * Derby throws an exception and keeps the connection open.
+     */
+    public void testIsClosedWhenClosingConnectionInInvalidState()
+        throws SQLException {
+        stmt.executeQuery("select count(*) from stmtTable");
+        // Connection should now be in an invalid transaction state.
+        try {
+            con.close();
+            fail("Invalid transaction state exception was not thrown");
+        } catch (SQLException sqle) {
+            if (usingEmbedded()) {
+                assertEquals("Unexpected exception thrown: " + sqle.getMessage(),
+                        SQLState.LANG_INVALID_TRANSACTION_STATE,
+                        sqle.getSQLState());
+            } else {
+                // TODO: Compare with SQLState when implemented on the client side.
+                assertEquals("Unexpected exception thrown: " + sqle.getMessage(),
+                        "java.sql.Connection.close() requested while a " +
+                        "transaction is in progress on the connection.The " +
+                        "transaction remains active, and the connection " +
+                        "cannot be closed.",
+                        sqle.getMessage());
+            }
+        }
+        assertFalse("Statement should still be open, because " +
+                "Connection.close() failed", stmt.isClosed());
+        assertFalse("Connection should still be open", con.isClosed());
+        // Do a commit here, since we do a rollback in another test.
+        con.commit();
+        con.close();
+        assertTrue("Connection should be closed after close()", 
+                con.isClosed());
+        assertTrue("Statement should be closed, because " +
+                "the connection has been closed", stmt.isClosed()); 
+        stmt.close();
+        assertTrue("Statement should still be closed", stmt.isClosed()); 
+    }
+        
+    /**
+     * Execute a query on a statement after the parent connection has been
+     * closed.
+     */
+    public void testStatementExecuteAfterConnectionClose() 
+        throws SQLException {
+        con.close();
+        assertTrue("Connection should be closed after close()", 
+                con.isClosed());
+        try {
+            stmt.executeQuery("select count(*) from stmtTable");
+        } catch (SQLException sqle) {
+            // Different error messages are returned for embedded and client.
+            if (usingEmbedded()) {
+                assertEquals("Unexpected SQL state for performing " +
+                        "operations on a closed statement.",
+                        SQLState.NO_CURRENT_CONNECTION,
+                        sqle.getSQLState());
+            } else {
+                // TODO: Compare with SQLState when implemented on client side.
+                assertEquals("Unexpected SQL state for performing " +
+                        "operations on a closed statement.",
+                        "Invalid operation: statement closed",
+                        sqle.getMessage());
+            }
+        }
+        assertTrue("Statement should be closed, because " +
+                "the connection has been closed", stmt.isClosed()); 
+    }
+    
+    /**
+     * Create test suite for StatementTest.
+     */
+    public static Test suite() {
+        TestSuite suite = new TestSuite("StatementTest suite");
+        // Decorate test suite with a TestSetup class.
+        suite.addTest(new StatementTestSetup(
+                        new TestSuite(StatementTest.class)));
+
+        return suite;
+    }
+    
+} // End class StatementTest

Propchange: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/StatementTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/StatementTestSetup.java
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/StatementTestSetup.java?rev=388234&view=auto
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/StatementTestSetup.java (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/StatementTestSetup.java Thu Mar 23 11:06:05 2006
@@ -0,0 +1,101 @@
+/*
+ *
+ * Derby - Class StatementTestSetup
+ *
+ * Copyright 2006 The Apache Software Foundation or its 
+ * licensors, as applicable.
+ *
+ * Licensed 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.jdbc4;
+
+import org.apache.derbyTesting.functionTests.util.BaseJDBCTestCase;
+
+import junit.framework.Test;
+import junit.extensions.TestSetup;
+
+import java.sql.*;
+
+/**
+ *  Create the table necessary for running {@link StatementTest}.
+ *
+ *  @see StatementTest
+ */
+public class StatementTestSetup 
+    extends TestSetup {
+
+    /**
+     * Initialize database schema.
+     * Uses the framework specified by the test harness.
+     *
+     * @see StatementTest
+     */
+    public StatementTestSetup(Test test) {
+        super(test);
+    }
+
+    /**
+     * Create the table and data needed for the test.
+     *
+     * @throws SQLException if database operations fail.
+     *
+     * @see StatementTest
+     */
+    public void setUp()
+        throws SQLException {
+        Connection con = BaseJDBCTestCase.getConnection();
+        // Create tables used by the test.
+        Statement stmt = con.createStatement();
+        // See if the table is already there, and if so, delete it.
+        try {
+            stmt.execute("select count(*) from stmtTable");
+            // Only get here is the table already exists.
+            stmt.execute("drop table stmtTable");
+        } catch (SQLException sqle) {
+            // Table does not exist, so we can go ahead and create it.
+            assertEquals("Unexpected error when accessing non-existing table.",
+                    "42X05",
+                    sqle.getSQLState());
+        }
+        stmt.execute("create table stmtTable (id int, val varchar(10))");
+        stmt.execute("insert into stmtTable values (1, 'one'),(2,'two')");
+        // Check just to be sure, and to notify developers if the database
+        // contents are changed at a later time.
+        ResultSet rs = stmt.executeQuery("select count(*) from stmtTable");
+        rs.next();
+        assertEquals("Number of rows are not as expected", 
+                2, rs.getInt(1));
+        rs.close();
+        stmt.close();
+        con.commit();
+        con.close();
+    }
+
+    /**
+     * Clean up after the tests.
+     * Deletes the table that was created for the tests.
+     *
+     * @throws SQLException if database operations fail.
+     */
+    public void tearDown() 
+        throws SQLException {
+        Connection con = BaseJDBCTestCase.getConnection();
+        Statement stmt = con.createStatement();
+        stmt.execute("drop table stmtTable");
+        stmt.close();
+        con.commit();
+        con.close();
+    }
+   
+} // End class StatementTestSetup

Propchange: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/StatementTestSetup.java
------------------------------------------------------------------------------
    svn:eol-style = native