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 ab...@apache.org on 2007/05/15 19:28:19 UTC

svn commit: r538260 - in /db/derby/code/trunk/java: engine/org/apache/derby/impl/jdbc/ engine/org/apache/derby/impl/sql/execute/ engine/org/apache/derby/loc/ shared/org/apache/derby/shared/common/reference/ testing/org/apache/derbyTesting/functionTests...

Author: abrown
Date: Tue May 15 10:28:17 2007
New Revision: 538260

URL: http://svn.apache.org/viewvc?view=rev&rev=538260
Log:
DERBY-2631: Expose existing auto-generated key functionality through more JDBC
APIs in embedded mode. 

 1. Updates the following JDBC methods so that they no longer throw a "Feature
     not implemented" error in embedded mode. Instead they make calls to an
     already existing internal method and pass in the appropriate arguments:

      Connection.prepareStatement(String sql, String[] columnNames);
      Connection.prepareStatement(String sql, int[] columnIndexes);

      Statement.execute(String sql, String[] columNames);
      Statement.execute(String sql, int[] columIndexes);

      Statement.executeUpdate(String sql, String[] columnNames);
      Statement.executeUpdate(String sql, int[] columnIndexes);

  2. Changes the (already existing but not currently used) code in
     sql/execute/InsertResultSet that handles autogen column indexes/names
     to throw an error for any target column that is not an auto-increment
     column. This is because Derby's implementation of getGeneratedKeys()
     internally maps to the IDENTITY_VAL_LOCAL() function, which only returns
     keys for identity (autoincrement) columns. So if the user specifies
     something else, we'll throw an error.

  3. Changes the names of two existing (but unused) errors to more accurately
     reflect their intended use (they are now called by the changes for #2).
     Also changes the text for those errors as the old text seemed a tad
     awkward. No regression impact here because the two errors in question
     were never exposed to users before now.

  4. Makes a slight change to jdbcapi/statementJdbc30.java (a test) to
     reflect the new behavior (we no longer throw "Feature not implemented"
     errors).

  5. Adds test cases for the newly supported APIs to the JUnit test
     lang/AutoGenJDBC30Test.java. This involved adding two more utility
     methods to junit/BaseJDBCTestCase.java, as well. 


Modified:
    db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedConnection.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedStatement.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/InsertResultSet.java
    db/derby/code/trunk/java/engine/org/apache/derby/loc/messages.xml
    db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/AutoGenJDBC30Test.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/statementJdbc30.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/junit/BaseJDBCTestCase.java

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedConnection.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedConnection.java?view=diff&rev=538260&r1=538259&r2=538260
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedConnection.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedConnection.java Tue May 15 10:28:17 2007
@@ -817,14 +817,22 @@
 	 *  SQL statement, that will have the capability of returning auto-generated keys
 	 *  designated by the given array of column indexes
 	 *
-	 * @exception SQLException  Feature not implemented for now.
+	 * @exception SQLException  Thrown on error.
 	 */
 	public final PreparedStatement prepareStatement(
 			String sql,
 			int[] columnIndexes)
     throws SQLException
 	{
- 		throw Util.notImplemented("prepareStatement(String, int[])");
+  		return prepareStatement(sql,
+			JDBC20Translation.TYPE_FORWARD_ONLY,
+			JDBC20Translation.CONCUR_READ_ONLY,
+			connectionHoldAbility,
+			columnIndexes == null
+				? JDBC30Translation.NO_GENERATED_KEYS
+				: JDBC30Translation.RETURN_GENERATED_KEYS,
+			columnIndexes,
+			null);
 	}
 
 	/**
@@ -844,14 +852,22 @@
 	 *  SQL statement, that will have the capability of returning auto-generated keys
 	 *  designated by the given array of column names
 	 *
-	 * @exception SQLException  Feature not implemented for now.
+	 * @exception SQLException Thrown on error.
 	 */
 	public final PreparedStatement prepareStatement(
 			String sql,
 			String[] columnNames)
     throws SQLException
 	{
- 		throw Util.notImplemented("prepareStatement(String, String[])");
+  		return prepareStatement(sql,
+			JDBC20Translation.TYPE_FORWARD_ONLY,
+			JDBC20Translation.CONCUR_READ_ONLY,
+			connectionHoldAbility,
+			columnNames == null
+				? JDBC30Translation.NO_GENERATED_KEYS
+				: JDBC30Translation.RETURN_GENERATED_KEYS,
+			null,
+			columnNames);
 	}
 
 	/**

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedStatement.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedStatement.java?view=diff&rev=538260&r1=538259&r2=538260
==============================================================================
--- 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 Tue May 15 10:28:17 2007
@@ -217,7 +217,13 @@
      */
 	public int executeUpdate(String sql, int[] columnIndexes) throws SQLException
 	{
- 		throw Util.notImplemented("executeUpdate(String, int[])");
+		execute(sql, false, true,
+			((columnIndexes == null) || (columnIndexes.length == 0))
+				? JDBC30Translation.NO_GENERATED_KEYS
+				: JDBC30Translation.RETURN_GENERATED_KEYS,
+			columnIndexes,
+			null);
+		return updateCount;
 	}
 
     /**
@@ -238,7 +244,13 @@
      */
 	public int executeUpdate(String sql, String[] columnNames) throws SQLException
 	{
- 		throw Util.notImplemented("executeUpdate(String, String[])");
+		execute(sql, false, true,
+			((columnNames == null) || (columnNames.length == 0))
+				? JDBC30Translation.NO_GENERATED_KEYS
+				: JDBC30Translation.RETURN_GENERATED_KEYS,
+			null,
+			columnNames);
+		return updateCount;
 	}
 
 	final void checkIfInMiddleOfBatch() throws SQLException {
@@ -631,7 +643,12 @@
      */
 	public boolean execute(String sql, int[] columnIndexes) throws SQLException
 	{
- 		throw Util.notImplemented("execute(String, int[])");
+		return execute(sql, false, true,
+			((columnIndexes == null) || (columnIndexes.length == 0))
+				? JDBC30Translation.NO_GENERATED_KEYS
+				: JDBC30Translation.RETURN_GENERATED_KEYS,
+			columnIndexes,
+			null);
 	}
 
     /**
@@ -655,7 +672,12 @@
      */
 	public boolean execute(String sql, String[] columnNames) throws SQLException
 	{
- 		throw Util.notImplemented("execute(String, String[])");
+		return execute(sql, false, true,
+			((columnNames == null) || (columnNames.length == 0))
+				? JDBC30Translation.NO_GENERATED_KEYS
+				: JDBC30Translation.RETURN_GENERATED_KEYS,
+			null,
+			columnNames);
 	}
 
     /**

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/InsertResultSet.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/InsertResultSet.java?view=diff&rev=538260&r1=538259&r2=538260
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/InsertResultSet.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/InsertResultSet.java Tue May 15 10:28:17 2007
@@ -563,8 +563,13 @@
 		// all 1-based column ids.
 		for (int i = 0; i < size; i++)
 		{
-			if (td.getColumnDescriptor(columnIndexes[i]) == null)
-				throw StandardException.newException(SQLState.LANG_COLUMN_POSITION_NOT_FOUND, new Integer(columnIndexes[i]));
+			ColumnDescriptor cd = td.getColumnDescriptor(columnIndexes[i]);
+			if (!verifyAutoGenColumn(cd))
+			{
+				throw StandardException.newException(
+					SQLState.LANG_INVALID_AUTOGEN_COLUMN_POSITION,
+					new Integer(columnIndexes[i]), td.getName());
+			}
 		}
 	}
 
@@ -664,14 +669,39 @@
 		for (int i = 0; i < size; i++)
 		{
 			if (columnNames[i] == null)
-				throw StandardException.newException(SQLState.LANG_COLUMN_NAME_NOT_FOUND, columnNames[i]);
+			{
+				throw StandardException.newException(
+					SQLState.LANG_INVALID_AUTOGEN_COLUMN_NAME,
+					columnNames[i], td.getName());
+			}
+
 			cd = td.getColumnDescriptor(columnNames[i]);
-			if (cd == null)
-				throw StandardException.newException(SQLState.LANG_COLUMN_NAME_NOT_FOUND, columnNames[i]);
-			else
-				columnPositions[i] = cd.getPosition();
+			if (!verifyAutoGenColumn(cd))
+			{
+				throw StandardException.newException(
+					SQLState.LANG_INVALID_AUTOGEN_COLUMN_NAME,
+					columnNames[i], td.getName());
+			}
+
+			columnPositions[i] = cd.getPosition();
 		}
 		activation.setAutoGeneratedKeysResultsetInfo(columnPositions, null);
+	}
+
+	/**
+	 * Check that the received ColumnDescriptor corresponds to a column
+	 * for which it is possible to fetch auto-generated keys.
+	 */
+	private boolean verifyAutoGenColumn(ColumnDescriptor cd)
+	{
+		/* Derby currently gets generated keys by calling the
+		 * IDENTITY_VAL_LOCAL() function (see "getGeneratedKeys()"
+		 * as defined on EmbedStatement).  That function only
+		 * considers autoincrement columns.  So if the column
+		 * specified by the user is not autoincrement, we return
+		 * false.
+		 */
+		return ((cd != null) && cd.isAutoincrement());
 	}
 
 	/**

Modified: db/derby/code/trunk/java/engine/org/apache/derby/loc/messages.xml
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/loc/messages.xml?view=diff&rev=538260&r1=538259&r2=538260
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/loc/messages.xml (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/loc/messages.xml Tue May 15 10:28:17 2007
@@ -2657,14 +2657,16 @@
 
             <msg>
                 <name>X0X0E.S</name>
-                <text>The column position '{0}' listed in the auto-generated column selection array was not found in the insert table. </text>
+                <text>Table '{1}' does not have an auto-generated column at column position '{0}'.</text>
                 <arg>columnPosition</arg>
+                <arg>tableName</arg>
             </msg>
 
             <msg>
                 <name>X0X0F.S</name>
-                <text>Column name '{0}' listed in auto-generated column selection array not found in the insert table.</text>
+                <text>Table '{1}' does not have an auto-generated column named '{0}'.</text>
                 <arg>columnName</arg>
+                <arg>tableName</arg>
             </msg>
 
             <msg>

Modified: db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java?view=diff&rev=538260&r1=538259&r2=538260
==============================================================================
--- db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java (original)
+++ db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java Tue May 15 10:28:17 2007
@@ -1248,8 +1248,8 @@
 	String LANG_CANT_INVALIDATE_OPEN_RESULT_SET                        = "X0X95.S";
 	String LANG_CANT_CHANGE_ISOLATION_HOLD_CURSOR                      = "X0X03.S";
 	//following three for auto-generated keys feature in JDBC3.0
-	String LANG_COLUMN_POSITION_NOT_FOUND                              = "X0X0E.S";
-	String LANG_COLUMN_NAME_NOT_FOUND                                  = "X0X0F.S";
+	String LANG_INVALID_AUTOGEN_COLUMN_POSITION                        = "X0X0E.S";
+	String LANG_INVALID_AUTOGEN_COLUMN_NAME                            = "X0X0F.S";
 
 	String LANG_INDEX_NOT_FOUND_DURING_EXECUTION                       = "X0X99.S";
 

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/AutoGenJDBC30Test.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/AutoGenJDBC30Test.java?view=diff&rev=538260&r1=538259&r2=538260
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/AutoGenJDBC30Test.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/AutoGenJDBC30Test.java Tue May 15 10:28:17 2007
@@ -955,8 +955,15 @@
      * Expected result: Exception 0A000 should occur.
      * @throws SQLException 
      */
-    public void testColumnIndexesError() throws SQLException
+    public void testColumnIndexesNotImpl() throws SQLException
     {
+        /* As of DERBY-2631 we support this with embedded.  So do nothing
+         * for this test fixture; we'll test the functionality as part
+         * of a separate fixture.
+         */
+        if (usingEmbedded())
+            return;
+
         Statement s = createStatement();
         int colPositions[] = new int[1];
         colPositions[0] = 1;
@@ -1000,8 +1007,15 @@
      * Expected result: Exception 0A000 should occur.
      * @throws SQLException 
      */
-    public void testColumnNamesError() throws SQLException
+    public void testColumnNamesNotImpl() throws SQLException
     {
+        /* As of DERBY-2631 we support this with embedded.  So do nothing
+         * for this test fixture; we'll test the functionality as part
+         * of a separate fixture.
+         */
+        if (usingEmbedded())
+            return;
+
         Statement s = createStatement();
         String colNames[] = new String[1];
         colNames[0] = "C11";
@@ -1036,7 +1050,348 @@
         }
     }
 
+    /**
+     * Test that use of columnIndexes to indicate which keys should be
+     * made available works as expected.
+     *
+     * @throws SQLException 
+     */
+    public void testColumnIndexes() throws SQLException
+    {
+        /* Not supported for Derby client.  We check the "not supported"
+         * error message as part of a different fixture.
+         */
+        if (usingDerbyNetClient())
+            return;
+
+        // Valid (typical) usage.
+
+        int [] colIndexes = new int [] { 2 };
+        testUserGivenColumns(colIndexes, null, 1);
+
+        // Non-existent column index.
+
+        colIndexes[0] = 100;
+        testUserGivenColumnsError(colIndexes, null);
+
+        // Valid column index but not an auto-gen column.
+
+        colIndexes[0] = 1;
+        testUserGivenColumnsError(colIndexes, null);
+
+        /* If user specifies the same column index multiple times,
+         * things should still work.  We effectively just take the
+         * one and ignore the rest.
+         */
+
+        colIndexes = new int [] { 2, 2, 2 };
+        testUserGivenColumns(colIndexes, null, 5);
+
+        // Multiple col indexes, one of which is invalid.
+
+        colIndexes[1] = 100;
+        testUserGivenColumnsError(colIndexes, null);
+
+        // Multiple col indexes, one of which is not an auto-gen column.
+
+        colIndexes[1] = 1;
+        testUserGivenColumnsError(colIndexes, null);
+
+        /* Multiple col indexes, one of which is invalid and another
+         * of which is not an auto-gen column.
+         */
+
+        colIndexes[2] = 100;
+        testUserGivenColumnsError(colIndexes, null);
+
+        // Same as previous but with "bad" indexes switched.
+
+        colIndexes[1] = 100;
+        colIndexes[2] = 1;
+        testUserGivenColumnsError(colIndexes, null);
+    }
+
+    /**
+     * Test that use of columnNames to indicate which keys should be
+     * made available works as expected.
+     *
+     * @throws SQLException 
+     */
+    public void testColumnNames() throws SQLException
+    {
+        /* Not supported for Derby client.  We check the "not supported"
+         * error message as part of a different fixture.
+         */
+        if (usingDerbyNetClient())
+            return;
+
+        // Valid (typical) usage.
+
+        String [] colNames = new String [] { "C12" };
+        testUserGivenColumns(null, colNames, 1);
+
+        // Non-existent column name.
+
+        colNames[0] = "NOTTHERE";
+        testUserGivenColumnsError(null, colNames);
+
+        // Valid column name but not an auto-gen column.
+
+        colNames[0] = "C11";
+        testUserGivenColumnsError(null, colNames);
+
+        // "null" column name.
+
+        colNames[0] = null;
+        testUserGivenColumnsError(null, colNames);
+
+        /* If user specifies the same column name multiple times,
+         * things should still work.  We effectively just take the
+         * one and ignore the rest.
+         */
+
+        colNames = new String [] { "C12", "C12", "C12" };
+        testUserGivenColumns(null, colNames, 5);
+
+        // Multiple col names, one of which is invalid.
+
+        colNames[1] = "NOTTHERE";
+        testUserGivenColumnsError(null, colNames);
+
+        // Multiple col names, one of which is not an auto-gen column.
+
+        colNames[1] = "C11";
+        testUserGivenColumnsError(null, colNames);
+
+        // Multiple col names, one of which is null.
+
+        colNames[1] = null;
+        testUserGivenColumnsError(null, colNames);
+
+        /* Multiple col names, one of which is invalid and another
+         * of which is not an auto-gen column.
+         */
+
+        colNames[1] = "C11";
+        colNames[2] = "NOTTHERE";
+        testUserGivenColumnsError(null, colNames);
+
+        // Same as previous but with "bad" names switched.
+
+        colNames[1] = "NOTTHERE";
+        colNames[2] = "C11";
+        testUserGivenColumnsError(null, colNames);
+    }
+
+    /**
+     * Verify that if a user specifies a *NULL* column index or column
+     * name array to indicate which keys should be made available, Derby will
+     * effectively disable autogenerated keys (i.e. same as if user passed
+     * NO_GENERATED_KEYS).
+     *
+     * Expected result: a NULL result set.
+     * @throws SQLException 
+     */
+    public void testUserGivenColumnsNull() throws SQLException
+    {
+        /* Not supported for Derby client.  We check the "not supported"
+         * error message as part of a different fixture.
+         */
+        if (usingDerbyNetClient())
+            return;
+
+        Statement s = createStatement();
+
+        String sql="insert into t11_AutoGen(c11) values (99)";
+
+        s.execute(sql, (int[]) null);
+        assertNull("Expected NULL ResultSet after s.execute()", 
+            s.getGeneratedKeys());
+
+        s.executeUpdate(sql, (int[]) null);
+        assertNull("Expected NULL ResultSet after s.executeUpdate()", 
+            s.getGeneratedKeys());
+
+        s.execute(sql, (String[]) null);
+        assertNull("Expected NULL ResultSet after s.execute()", 
+            s.getGeneratedKeys());
+
+        s.executeUpdate(sql, (String[]) null);
+        assertNull("Expected NULL ResultSet after s.executeUpdate()", 
+            s.getGeneratedKeys());
+
+        s.close();
+
+        PreparedStatement ps = prepareStatement(sql, (int[]) null);
+        ps.execute();
+        assertNull("Expected NULL ResultSet after ps.execute()", 
+            ps.getGeneratedKeys());
+
+        ps = prepareStatement(sql, (int[]) null);
+        ps.executeUpdate();
+        assertNull("Expected NULL ResultSet after ps.executeUpdate()", 
+            ps.getGeneratedKeys());
+
+        ps = prepareStatement(sql, (String[]) null);
+        ps.execute();
+        assertNull("Expected NULL ResultSet after ps.execute()", 
+            ps.getGeneratedKeys());
+
+        ps = prepareStatement(sql, (String[]) null);
+        ps.executeUpdate();
+        assertNull("Expected NULL ResultSet after ps.executeUpdate()", 
+            ps.getGeneratedKeys());
+
+        ps.close();
+    }
+
     // Local utility methods.
+
+    /**
+     * Verify that if user specifies *valid* column indexes or column
+     * names to indicate which keys should be made available, Derby will
+     * return the correct results.
+     *
+     * Expected result: one row with a non-NULL key.
+     *
+     * @param colIndexes Array of column indexes indicating which keys
+     *  should be made available.  Must be null if colNames is non-null.
+     * @param colNames Array of column names indicating which keys should
+     *  be made available.  Must be null if colIndexes is non-null.
+     * @param expectedVal First expected autogenerated key; will be
+     *  incremented for each successful INSERT statement.
+     *
+     * @throws SQLException
+     */
+    private void testUserGivenColumns(int [] colIndexes, String [] colNames,
+        int expectedVal) throws SQLException
+    {
+        assertTrue("Exactly one of colIndexes or colNames should be null",
+            ((colIndexes != null) ^ (colNames != null)));
+
+        boolean useIndexes = (colIndexes != null);
+        Statement s = createStatement();
+
+        String sql="insert into t11_AutoGen(c11) values (99)";
+
+        if (useIndexes)
+            s.execute(sql, colIndexes);
+        else
+            s.execute(sql, colNames);
+
+        int keyval = getKeyValue (s.getGeneratedKeys());
+        assertEquals("Key value after s.execute()", expectedVal++, keyval);
+
+        if (useIndexes)
+            s.executeUpdate(sql, colIndexes);
+        else
+            s.executeUpdate(sql, colNames);
+
+        keyval = getKeyValue (s.getGeneratedKeys());
+        assertEquals("Key value after s.executeUpdate()",
+            expectedVal++, keyval);
+
+        s.close();
+
+        PreparedStatement ps = null;
+        if (useIndexes)
+            ps = prepareStatement(sql, colIndexes);
+        else
+            ps = prepareStatement(sql, colNames);
+
+        ps.execute();
+        keyval = getKeyValue (ps.getGeneratedKeys());
+        assertEquals("Key value after ps.execute()", expectedVal++, keyval);
+
+        if (useIndexes)
+            ps = prepareStatement(sql, colIndexes);
+        else
+            ps = prepareStatement(sql, colNames);
+
+        ps.executeUpdate();
+        keyval = getKeyValue (ps.getGeneratedKeys());
+        assertEquals("Key value after ps.executeUpdate()",
+            expectedVal++, keyval);
+
+        ps.close();
+    }
+
+    /**
+     * Verify that if user specifies *INvalid* column indexes or column
+     * names to indicate which keys should be made available, Derby will
+     * throw an appropriate error.
+     *
+     * Expected result: Execution-time error: X0X0E or X0X0F.
+     *
+     * @param colIndexes Array of column indexes indicating which keys
+     *  should be made available.  Must be null if colNames is non-null.
+     * @param colNames Array of column names indicating which keys should
+     *  be made available.  Must be null if colIndexes is non-null.
+     *
+     * @throws SQLException 
+     */
+    private void testUserGivenColumnsError(int [] colIndexes,
+        String [] colNames) throws SQLException
+    {
+        assertTrue("Exactly one of colIndexes or colNames should be null.",
+            ((colIndexes != null) ^ (colNames != null)));
+
+        boolean useIndexes = (colIndexes != null);
+        String expectedSQLState = (useIndexes ? "X0X0E" : "X0X0F");
+
+        Statement s = createStatement();
+        String sql="insert into t11_AutoGen(c11) values (99)";
+
+        try {
+
+            if (useIndexes)
+                s.execute(sql, colIndexes);
+            else
+                s.execute(sql, colNames);
+
+            fail("Expected s.execute() to fail, but it did not.");
+
+        } catch (SQLException se) {
+            assertSQLState(expectedSQLState, se.getSQLState(), se);
+        }
+
+        try {
+
+            if (useIndexes)
+                s.executeUpdate(sql, colIndexes);
+            else
+                s.executeUpdate(sql, colNames);
+
+            fail("Expected s.executeUpdate() to fail, but it did not.");
+
+        } catch (SQLException se) {
+            assertSQLState(expectedSQLState, se.getSQLState(), se);
+        }
+
+        s.close();
+
+        PreparedStatement ps = null;
+        if (useIndexes)
+               ps = prepareStatement(sql, colIndexes);
+        else
+               ps = prepareStatement(sql, colNames);
+
+        try {
+            ps.execute();
+            fail("Expected ps.execute() to fail, but it did not.");
+        } catch (SQLException se) {
+            assertSQLState(expectedSQLState, se.getSQLState(), se);
+        }
+
+        try {
+            ps.executeUpdate();
+            fail("Expected ps.executeUpdate() to fail, but it did not.");
+        } catch (SQLException se) {
+            assertSQLState(expectedSQLState, se.getSQLState(), se);
+        }
+
+        ps.close();
+    }
 
     /**
      * Runs the same SQL INSERT statement four ways: 

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/statementJdbc30.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/statementJdbc30.java?view=diff&rev=538260&r1=538259&r2=538260
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/statementJdbc30.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/statementJdbc30.java Tue May 15 10:28:17 2007
@@ -68,6 +68,11 @@
 			System.out.println("trying stmt.executeUpdate(String, int) :");
 			stmt.executeUpdate("insert into tab1 values(2, 3, 4.1)", JDBC30Translation.NO_GENERATED_KEYS);
 
+			/* Next two stmts will fail because there's no auto-generated
+			 * column.  These forms of "executeUpdate()" are tested more
+			 * in the JUnit test, jdbcapi/AutoGenJDBC30Test.java.
+			 */
+
 			System.out.println("trying stmt.executeUpdate(String, int[]) :");
 			int[] columnIndexes = new int[2];
 			columnIndexes[0] = 1;
@@ -75,7 +80,7 @@
 			try {
 				stmt.executeUpdate("insert into tab1 values(2, 3, 4.1)", columnIndexes);
 			} catch (SQLException ex) {
-                BaseJDBCTestCase.assertSQLState("0A000", ex);
+				BaseJDBCTestCase.assertSQLState("X0X0E", ex);
 			}
 
 			System.out.println("trying stmt.executeUpdate(String, String[]) :");
@@ -85,24 +90,29 @@
 			try {
 				stmt.executeUpdate("insert into tab1 values(2, 3, 4.1)", columnNames);
 			} catch (SQLException ex) {
-                BaseJDBCTestCase.assertSQLState("0A000", ex);
+				BaseJDBCTestCase.assertSQLState("X0X0F", ex);
 			}
 
 			System.out.println("trying stmt.execute(String, int) :");
 			stmt.execute("select * from tab1", JDBC30Translation.NO_GENERATED_KEYS);
 
+			/* Next two stmts will fail because there's no auto-generated
+			 * column.  These forms of "execute()" are tested more in the
+			 * JUnit test, jdbcapi/AutoGenJDBC30Test.java.
+			 */
+
 			System.out.println("trying stmt.execute(String, int[]) :");
 			try {
 				stmt.execute("insert into tab1 values(2, 3, 4.1)", columnIndexes);
 			} catch (SQLException ex) {
-                BaseJDBCTestCase.assertSQLState("0A000", ex);
+				BaseJDBCTestCase.assertSQLState("X0X0E", ex);
 			}
 
 			System.out.println("trying stmt.execute(String, String[]) :");
 			try {
 				stmt.execute("insert into tab1 values(2, 3, 4.1)", columnNames);
 			} catch (SQLException ex) {
-                BaseJDBCTestCase.assertSQLState("0A000", ex);
+				BaseJDBCTestCase.assertSQLState("X0X0F", ex);
 			}
 
 			System.out.println("trying stmt.getResultSetHoldability() :");

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/junit/BaseJDBCTestCase.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/junit/BaseJDBCTestCase.java?view=diff&rev=538260&r1=538259&r2=538260
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/junit/BaseJDBCTestCase.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/junit/BaseJDBCTestCase.java Tue May 15 10:28:17 2007
@@ -161,6 +161,40 @@
     }    
 
     /**
+     * Utility method to create a PreparedStatement using the connection
+     * returned by getConnection and an array of column indexes that
+     * indicates which auto-generated keys produced by this Statement
+     * object should be made available for retrieval.
+     *
+     * @return Statement object from:
+     *     prepareStatement(sql, columnIndexes)
+     *
+     * @throws SQLException
+     */
+    public PreparedStatement prepareStatement(String sql,
+        int [] columnIndexes) throws SQLException
+    {
+        return getConnection().prepareStatement(sql, columnIndexes);
+    }
+
+    /**
+     * Utility method to create a PreparedStatement using the connection
+     * returned by getConnection and an array of column names that
+     * indicates which auto-generated keys produced by this Statement
+     * object should be made available for retrieval.
+     *
+     * @return Statement object from:
+     *     prepareStatement(sql, columnNames)
+     *
+     * @throws SQLException
+     */
+    public PreparedStatement prepareStatement(String sql,
+        String [] columnNames) throws SQLException
+    {
+        return getConnection().prepareStatement(sql, columnNames);
+    }
+
+    /**
      * Utility method to create a CallableStatement using the connection
      * returned by getConnection.
      * @return Statement object from