db-derby-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From kahat...@apache.org
Subject svn commit: r383394 - in /db/derby/code/trunk/java: client/org/apache/derby/client/am/ResultSet.java engine/org/apache/derby/impl/jdbc/EmbedResultSet.java testing/org/apache/derbyTesting/functionTests/tests/jdbc4/TestResultSetMethods.java
Date Sun, 05 Mar 2006 20:34:23 GMT
Author: kahatlen
Date: Sun Mar  5 12:34:20 2006
New Revision: 383394

URL: http://svn.apache.org/viewcvs?rev=383394&view=rev
Log:
DERBY-1060: ResultSet methods should throw exception when the
ResultSet is closed

The patch adds calls to checkIfClosed (embeddded) or
checkForClosedResultSet (network client) in the ResultSet methods
which don't check whether the ResultSet is closed. It also adds a test
case to jdbc4/TestResultSetMethods.java.

Modified:
    db/derby/code/trunk/java/client/org/apache/derby/client/am/ResultSet.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedResultSet.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/TestResultSetMethods.java

Modified: db/derby/code/trunk/java/client/org/apache/derby/client/am/ResultSet.java
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/client/org/apache/derby/client/am/ResultSet.java?rev=383394&r1=383393&r2=383394&view=diff
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/am/ResultSet.java (original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/am/ResultSet.java Sun Mar  5 12:34:20
2006
@@ -1817,19 +1817,48 @@
 
     // ----------------Advanced features -----------------------------------------
 
-    public final java.sql.SQLWarning getWarnings() {
+    /**
+     * Returns the first <code>SQLWarning</code> reported on this
+     * <code>ResultSet</code> object, or <code>null</code> if there
+     * are no warnings. Subsequent warnings are chained on the
+     * returned object.
+     *
+     * @return the first <code>SQLWarning</code> in the chain, or
+     * <code>null</code> if no warnings are reported
+     * @exception SQLException if a database error occurs or the
+     * result set is closed
+     */
+    public final java.sql.SQLWarning getWarnings() throws SQLException {
+        try {
+            checkForClosedResultSet();
+        } catch (SqlException se) {
+            throw se.getSQLException();
+        }
         if (agent_.loggingEnabled()) {
             agent_.logWriter_.traceExit(this, "getWarnings", warnings_);
         }
         return warnings_ == null ? null : warnings_.getSQLWarning();
     }
 
+    /**
+     * Clear all warnings on this <code>ResultSet</code> and make
+     * subsequent calls to <code>getWarnings()</code> return
+     * <code>null</code> until a new warning is reported.
+     *
+     * @exception SQLException if a database error occurs or the
+     * result set is closed
+     */
     public final void clearWarnings() throws SQLException {
         synchronized (connection_) {
             if (agent_.loggingEnabled()) {
                 agent_.logWriter_.traceEntry(this, "clearWarnings");
             }
-            warnings_ = null;
+            try {
+                checkForClosedResultSet();
+            } catch (SqlException se) {
+                throw se.getSQLException();
+            }
+            clearWarningsX();
         }
     }
 
@@ -3676,7 +3705,22 @@
         }
     }
 
-    public java.sql.Statement getStatement() {
+    /**
+     * Retrieves the <code>Statement</code> object that produced this
+     * object, or <code>null</code> if the <code>ResultSet</code>
was
+     * not produced by a <code>Statement</code> object.
+     *
+     * @return the <code>Statement</code> that produced this object or
+     * <code>null</code>
+     * @exception SQLException if a database error occurs or the
+     * result set is closed
+     */
+    public java.sql.Statement getStatement() throws SQLException {
+        try {
+            checkForClosedResultSet();
+        } catch (SqlException se) {
+            throw se.getSQLException();
+        }
         if (agent_.loggingEnabled()) {
             agent_.logWriter_.traceExit(this, "getStatement", statement_);
         }

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedResultSet.java
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedResultSet.java?rev=383394&r1=383393&r2=383394&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedResultSet.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedResultSet.java Sun Mar
 5 12:34:20 2006
@@ -1676,9 +1676,12 @@
 	 * 
 	 * @return the Statment that produced the result set, or null if the result
 	 *         was produced some other way.
+	 * @exception SQLException if a database error occurs or the
+	 * result set is closed
 	 */
-	public final Statement getStatement()
+	public final Statement getStatement() throws SQLException
     {
+            checkIfClosed("getStatement");
             return applicationStmt;
     }
     
@@ -1837,6 +1840,8 @@
 	 *                if a database-access error occurs.
 	 */
 	public int getRow() throws SQLException {
+		checkIfClosed("getRow");
+
 		// getRow() is only allowed on scroll cursors
 		checkScrollCursor("getRow()");
 
@@ -1946,6 +1951,7 @@
 	 *                is TYPE_FORWARD_ONLY and direction is not FETCH_FORWARD.
 	 */
 	public void setFetchDirection(int direction) throws SQLException {
+		checkIfClosed("setFetchDirection");
 		checkScrollCursor("setFetchDirection()");
 		/*
 		 * FetchDirection is meaningless to us. We just save it off and return
@@ -1963,6 +1969,7 @@
 	 *                if a database-access error occurs
 	 */
 	public int getFetchDirection() throws SQLException {
+		checkIfClosed("getFetchDirection");
 		if (fetchDirection == 0) {
 			// value is not set at the result set level
 			// get it from the statement level
@@ -1988,6 +1995,7 @@
 	 *                rows <= this.getMaxRows() is not satisfied.
 	 */
 	public void setFetchSize(int rows) throws SQLException {
+		checkIfClosed("setFetchSize");
 		if (rows < 0 || (stmt.getMaxRows() != 0 && rows > stmt.getMaxRows())) {
 			throw Util.generateCsSQLException(SQLState.INVALID_FETCH_SIZE,
 					new Integer(rows));
@@ -2006,6 +2014,7 @@
 	 *                if a database-access error occurs
 	 */
 	public int getFetchSize() throws SQLException {
+		checkIfClosed("getFetchSize");
 		if (fetchSize == 0) {
 			// value is not set at the result set level
 			//  get the default value from the statement
@@ -2026,6 +2035,7 @@
 	 *                if a database-access error occurs
 	 */
 	public int getType() throws SQLException {
+		checkIfClosed("getType");
 		return stmt.getResultSetType();
 	}
 
@@ -2047,6 +2057,7 @@
 	 *                if a database-access error occurs
 	 */
 	public int getConcurrency() throws SQLException {
+		checkIfClosed("getConcurrency");
 		return concurrencyOfThisResultSet;
 	}
 
@@ -2068,6 +2079,7 @@
 	 * @see EmbedDatabaseMetaData#updatesAreDetected
 	 */
 	public boolean rowUpdated() throws SQLException {
+		checkIfClosed("rowUpdated");
 		return false;
 	}
 
@@ -2084,6 +2096,7 @@
 	 * @see EmbedDatabaseMetaData#insertsAreDetected
 	 */
 	public boolean rowInserted() throws SQLException {
+		checkIfClosed("rowInserted");
 		return false;
 	}
 
@@ -2102,6 +2115,7 @@
 	 * @see EmbedDatabaseMetaData#deletesAreDetected
 	 */
 	public boolean rowDeleted() throws SQLException {
+		checkIfClosed("rowDeleted");
 		return false;
 	}
 
@@ -2128,18 +2142,18 @@
 	}
 
 	//do following few checks before accepting updateRow or deleteRow
-	//1)Make sure this is an updatable ResultSet
-	//2)Make sure JDBC ResultSet is not closed
+	//1)Make sure JDBC ResultSet is not closed
+	//2)Make sure this is an updatable ResultSet
 	//3)Make sure JDBC ResultSet is positioned on a row
 	//4)Make sure underneath language resultset is not closed
 	protected void checksBeforeUpdateOrDelete(String methodName, int columnIndex) throws SQLException
{
 
-      //1)Make sure this is an updatable ResultSet
-      checkUpdatableCursor(methodName);
-
-      //2)Make sure JDBC ResultSet is not closed
+      //1)Make sure JDBC ResultSet is not closed
       checkIfClosed(methodName);
 
+      //2)Make sure this is an updatable ResultSet
+      checkUpdatableCursor(methodName);
+
       //3)Make sure JDBC ResultSet is positioned on a row
       checkOnRow(); // first make sure there's a current row
       //in case of autocommit on, if there was an exception which caused runtime rollback
in this transaction prior to this call,
@@ -2165,19 +2179,19 @@
 	}
 
     /* do following few checks before accepting insertRow
-     * 1) Make sure this is an updatable ResultSet
-     * 2) Make sure JDBC ResultSet is not closed
+     * 1) Make sure JDBC ResultSet is not closed
+     * 2) Make sure this is an updatable ResultSet
      * 3) Make sure JDBC ResultSet is positioned on insertRow
      * 4) Make sure underneath language resultset is not closed
      */
     protected void checksBeforeInsert() throws SQLException {
-        // 1)Make sure this is an updatable ResultSet
+        // 1)Make sure JDBC ResultSet is not closed
+        checkIfClosed("insertRow");
+
+        // 2)Make sure this is an updatable ResultSet
         // if not updatable resultset, then throw exception
         checkUpdatableCursor("insertRow");
 
-        // 2)Make sure JDBC ResultSet is not closed
-        checkIfClosed("insertRow");
-
         // 3)Make sure JDBC ResultSet is positioned on insertRow
         if (!isOnInsertRow) {
             throw newSQLException(SQLState.NOT_POSITIONED_ON_INSERT_ROW);
@@ -3568,11 +3582,11 @@
 	 *                not updatable
 	 */
 	public void moveToInsertRow() throws SQLException {
+		checkExecIfClosed("moveToInsertRow");
+
 		// if not updatable resultset, then throw exception
 		checkUpdatableCursor("moveToInsertRow");
 
-		checkExecIfClosed("moveToInsertRow");
-
 		synchronized (getConnectionSynchronization()) {
 			try {
 				// initialize state corresponding to insertRow/updateRow impl.
@@ -3617,10 +3631,10 @@
 	 *                not updatable
 	 */
 	public void moveToCurrentRow() throws SQLException {
+		checkExecIfClosed("moveToCurrentRow");
+
 		// if not updatable resultset, then throw exception
 		checkUpdatableCursor("moveToCurrentRow");
-
-		checkExecIfClosed("moveToCurrentRow");
 
 		synchronized (getConnectionSynchronization()) {
 			try {

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/TestResultSetMethods.java
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/TestResultSetMethods.java?rev=383394&r1=383393&r2=383394&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/TestResultSetMethods.java
(original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/TestResultSetMethods.java
Sun Mar  5 12:34:20 2006
@@ -32,6 +32,10 @@
 import java.sql.Statement;
 import org.apache.derby.shared.common.reference.SQLState;
 
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+
 /**
  * This class is used to test the implementations of the JDBC 4.0 methods
  * in the ResultSet interface
@@ -342,6 +346,78 @@
     
     void t_updateSQLXML2() {
     }
+
+    /**
+     * Test that an exception is thrown when methods are called
+     * on a closed result set (DERBY-1060).
+     */
+    private void testExceptionWhenClosed() {
+        try {
+            // create a result set and close it
+            Statement stmt = conn.createStatement();
+            ResultSet rs = stmt.executeQuery("values(1)");
+            rs.close();
+
+            // maps method name to parameter list
+            HashMap<String, Class[]> params = new HashMap<String, Class[]>();
+            // maps method name to argument list
+            HashMap<String, Object[]> args = new HashMap<String, Object[]>();
+
+            // methods with no parameters
+            String[] zeroArgMethods = {
+                "getWarnings", "clearWarnings", "getStatement",
+                "getMetaData", "getConcurrency", "getHoldability",
+                "getRow", "getType", "rowDeleted", "rowInserted",
+                "rowUpdated", "getFetchDirection", "getFetchSize",
+            };
+            for (String name : zeroArgMethods) {
+                params.put(name, null);
+                args.put(name, null);
+            }
+
+            // methods with a single int parameter
+            for (String name : new String[] { "setFetchDirection",
+                                              "setFetchSize" }) {
+                params.put(name, new Class[] { Integer.TYPE });
+                args.put(name, new Integer[] { 0 });
+            }
+
+            // invoke the methods
+            for (String name : params.keySet()) {
+                try {
+                    Method method =
+                        rs.getClass().getMethod(name, params.get(name));
+                    try {
+                        method.invoke(rs, args.get(name));
+                    } catch (InvocationTargetException ite) {
+                        Throwable cause = ite.getCause();
+                        if (cause instanceof SQLException) {
+                            SQLException sqle = (SQLException) cause;
+                            String state = sqle.getSQLState();
+                            // Should get SQL state XCL16 when the
+                            // result set is closed, but client driver
+                            // sends null.
+                            if (state == null ||
+                                state.equals("XCL16")) {
+                                continue;
+                            }
+                        }
+                        throw cause;
+                    }
+                    System.out.println("no exception thrown for " + name +
+                                       "() when ResultSet is closed");
+                } catch (Throwable t) {
+                    System.out.println("Unexpected exception when " +
+                                       "invoking " + name + "():");
+                    t.printStackTrace(System.out);
+                }
+            }
+            stmt.close();
+        } catch (SQLException e) {
+            System.out.println("Unexpected exception caught:");
+            e.printStackTrace(System.out);
+        }
+    }
     
     void startTestResultSetMethods(Connection conn_in,PreparedStatement ps_in,ResultSet rs_in)
{
         conn = conn_in;
@@ -371,6 +447,8 @@
         
         t_updateSQLXML1();
         t_updateSQLXML2();
+
+        testExceptionWhenClosed();
     }
     
     /**



Mime
View raw message