Index: java/build/org/apache/derbyBuild/splitmessages.java
===================================================================
--- java/build/org/apache/derbyBuild/splitmessages.java (revision 628487)
+++ java/build/org/apache/derbyBuild/splitmessages.java (working copy)
@@ -117,6 +117,7 @@
clientMessageIds.add(SQLState.NET_PGNAMCSN_INVALID_AT_SQLAM);
clientMessageIds.add(SQLState.NET_VCM_VCS_LENGTHS_INVALID);
clientMessageIds.add(SQLState.LANG_STRING_TOO_LONG);
+ clientMessageIds.add(SQLState.INVALID_COLUMN_ARRAY_LENGTH);
}
public static void main(String[] args) throws Exception {
Index: java/engine/org/apache/derby/loc/messages.xml
===================================================================
--- java/engine/org/apache/derby/loc/messages.xml (revision 628487)
+++ java/engine/org/apache/derby/loc/messages.xml (working copy)
@@ -2775,6 +2775,12 @@
+ X0X0D.S
+ Invalid column array length '{0}'. Column array must be of length 1 and contain only the identity column.
+ columnArrayLength
+
+
+
X0X0E.S
Table '{1}' does not have an auto-generated column at column position '{0}'.
columnPosition
Index: java/shared/org/apache/derby/shared/common/reference/SQLState.java
===================================================================
--- java/shared/org/apache/derby/shared/common/reference/SQLState.java (revision 628487)
+++ java/shared/org/apache/derby/shared/common/reference/SQLState.java (working copy)
@@ -1273,6 +1273,7 @@
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 INVALID_COLUMN_ARRAY_LENGTH = "X0X0D.S";
String LANG_INVALID_AUTOGEN_COLUMN_POSITION = "X0X0E.S";
String LANG_INVALID_AUTOGEN_COLUMN_NAME = "X0X0F.S";
Index: java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/StatementJdbc30Test.java
===================================================================
--- java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/StatementJdbc30Test.java (revision 628487)
+++ java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/StatementJdbc30Test.java (working copy)
@@ -255,13 +255,10 @@
* @param ex
*/
private void assertFailedExecuteUpdateForColumnName(SQLException ex) {
- /*
- * DERBY-2943 -- execute() and executeUpdate() return different
- * SQLState in embedded and network client
- *
- */
+ // Derby client complains that the array is too long.
+ // Embedded is smart enough to know which column caused the problem.
if (usingDerbyNetClient()) {
- assertSQLState("0A000", ex);
+ assertSQLState("X0X0D", ex);
} else {
assertSQLState("X0X0F", ex);
}
Index: java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/AutoGenJDBC30Test.java
===================================================================
--- java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/AutoGenJDBC30Test.java (revision 628487)
+++ java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/AutoGenJDBC30Test.java (working copy)
@@ -1011,58 +1011,6 @@
}
/**
- * Verifies that an exception is raised if a columnNames array is passed,
- * which signals the driver that the auto-generated keys indicated in the
- * given array should be made available for retrieval (feature not
- * supported).
- * Old master Test22, Test22ps
- * Expected result: Exception 0A000 should occur.
- * @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";
-
- String sql="insert into t11_AutoGen(c11) " +
- "select c21 from t21_noAutoGen";
-
- try {
- s.execute(sql, colNames);
- fail("Expected s.execute to fail");
- } catch (SQLException se) {
- assertSQLState("0A000", se.getSQLState(), se);
- }
-
- try {
- s.executeUpdate(sql, colNames);
- fail("Expected s.executeUpdate to fail");
- } catch (SQLException se) {
- assertSQLState("0A000", se.getSQLState(), se);
- }
-
- try {
- /* Deliberately not adding this prepareStatement wrapper to
- * BaseJDBCTestCase.java because Derby doesn't support passing
- * the array.
- */
- Connection conn = getConnection();
- PreparedStatement ps=conn.prepareStatement(sql, colNames);
- fail("Expected prepareStatement to fail");
- } catch (SQLException se) {
- assertSQLState("0A000", se.getSQLState(), se);
- }
- }
-
- /**
* Test that use of columnIndexes to indicate which keys should be
* made available works as expected.
*
@@ -1131,22 +1079,24 @@
*/
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);
+ // column name array is of length > 1
+ colNames = new String[] {"C12","C13"};
+ testUserGivenColumnsError(null, colNames);
+
+ if (usingDerbyNetClient())
+ return;
+
// Non-existent column name.
- colNames[0] = "NOTTHERE";
+ colNames= new String[] {"NOTTHERE"};
testUserGivenColumnsError(null, colNames);
-
+
// Valid column name but not an auto-gen column.
colNames[0] = "C11";
@@ -1206,24 +1156,12 @@
*/
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());
@@ -1232,29 +1170,43 @@
assertNull("Expected NULL ResultSet after s.executeUpdate()",
s.getGeneratedKeys());
- s.close();
- PreparedStatement ps = prepareStatement(sql, (int[]) null);
+ PreparedStatement ps;
+ ps = prepareStatement(sql, (String[]) null);
ps.execute();
assertNull("Expected NULL ResultSet after ps.execute()",
ps.getGeneratedKeys());
- ps = prepareStatement(sql, (int[]) null);
+ ps = prepareStatement(sql, (String[]) null);
ps.executeUpdate();
assertNull("Expected NULL ResultSet after ps.executeUpdate()",
ps.getGeneratedKeys());
+
+ // No columnIndexes yet for derby client.
+ if (usingDerbyNetClient())
+ return;
+
+ s.execute(sql, (int[]) null);
+ assertNull("Expected NULL ResultSet after s.execute()",
+ s.getGeneratedKeys());
- ps = prepareStatement(sql, (String[]) null);
+ s.executeUpdate(sql, (int[]) null);
+ assertNull("Expected NULL ResultSet after s.executeUpdate()",
+ s.getGeneratedKeys());
+
+ ps = prepareStatement(sql, (int[]) null);
ps.execute();
assertNull("Expected NULL ResultSet after ps.execute()",
ps.getGeneratedKeys());
- ps = prepareStatement(sql, (String[]) null);
+ ps = prepareStatement(sql, (int[]) null);
ps.executeUpdate();
assertNull("Expected NULL ResultSet after ps.executeUpdate()",
ps.getGeneratedKeys());
+
ps.close();
+
}
// Local utility methods.
@@ -1350,7 +1302,11 @@
boolean useIndexes = (colIndexes != null);
String expectedSQLState = (useIndexes ? "X0X0E" : "X0X0F");
-
+ // Derby client will only give an error if colNames array is not of length 1.
+ if (usingDerbyNetClient() && colNames != null &&
+ colNames.length != 1)
+ expectedSQLState = "X0X0D";
+
Statement s = createStatement();
String sql="insert into t11_AutoGen(c11) values (99)";
Index: java/client/org/apache/derby/client/am/Connection.java
===================================================================
--- java/client/org/apache/derby/client/am/Connection.java (revision 628487)
+++ java/client/org/apache/derby/client/am/Connection.java (working copy)
@@ -1635,7 +1635,6 @@
int autoGeneratedKeys,
String[] columnNames) throws SqlException {
checkForClosedConnection();
- checkAutoGeneratedKeysParameters(autoGeneratedKeys, columnNames);
resultSetType = downgradeResultSetType(resultSetType);
PreparedStatement ps = newPreparedStatement_(sql, resultSetType, resultSetConcurrency, resultSetHoldability, autoGeneratedKeys, columnNames);
ps.cursorAttributesToSendOnPrepare_ = ps.cacheCursorAttributesToSendOnPrepare();
@@ -1741,11 +1740,13 @@
if (agent_.loggingEnabled()) {
agent_.logWriter_.traceEntry(this, "prepareStatement", sql, columnNames);
}
+ int genKeys = (columnNames == null ? Statement.NO_GENERATED_KEYS:
+ Statement.RETURN_GENERATED_KEYS);
PreparedStatement ps = prepareStatementX(sql,
java.sql.ResultSet.TYPE_FORWARD_ONLY,
java.sql.ResultSet.CONCUR_READ_ONLY,
holdability(),
- java.sql.Statement.RETURN_GENERATED_KEYS,
+ genKeys,
columnNames);
if (agent_.loggingEnabled()) {
agent_.logWriter_.traceExit(this, "prepareStatement", ps);
@@ -2070,22 +2071,6 @@
}
}
- void checkAutoGeneratedKeysParameters(int autoGeneratedKeys, String[] columnNames) throws SqlException {
- if (autoGeneratedKeys != java.sql.Statement.NO_GENERATED_KEYS &&
- autoGeneratedKeys != java.sql.Statement.RETURN_GENERATED_KEYS) {
- throw new SqlException(agent_.logWriter_,
- new ClientMessageId(SQLState.BAD_AUTO_GEN_KEY_VALUE),
- new Integer (autoGeneratedKeys));
- }
-
- if (columnNames != null) {
- throw new SqlException(agent_.logWriter_,
- new ClientMessageId (SQLState.NOT_IMPLEMENTED),
- "getAutoGeneratedKeys(columnNames == null)");
- }
-
- }
-
public boolean isXAConnection() {
return isXAConnection_;
}
Index: java/client/org/apache/derby/client/am/Statement.java
===================================================================
--- java/client/org/apache/derby/client/am/Statement.java (revision 628780)
+++ java/client/org/apache/derby/client/am/Statement.java (working copy)
@@ -1211,6 +1211,8 @@
if (agent_.loggingEnabled()) {
agent_.logWriter_.traceEntry(this, "executeUpdate", sql, columnNames);
}
+ if (columnNames != null)
+ autoGeneratedKeys_ = Statement.RETURN_GENERATED_KEYS;
generatedKeysColumnNames_ = columnNames;
int updateValue = executeUpdateX(sql);
if (agent_.loggingEnabled()) {
@@ -1270,6 +1272,8 @@
if (agent_.loggingEnabled()) {
agent_.logWriter_.traceEntry(this, "execute", sql, columnNames);
}
+ if (columnNames != null)
+ autoGeneratedKeys_ = Statement.RETURN_GENERATED_KEYS;
generatedKeysColumnNames_ = columnNames;
boolean b = executeX(sql);
if (agent_.loggingEnabled()) {
@@ -1854,12 +1858,11 @@
}
private void flowExecute(int executeType, String sql) throws SqlException {
- checkForClosedStatement(); // Per jdbc spec (see java.sql.Statement.close() javadoc)
- checkAutoGeneratedKeysParameters();
+ checkForClosedStatement(); // Per jdbc spec (see java.sql.Statement.close() javadoc)
clearWarningsX(); // Per jdbc spec 0.7, and getWarnings() javadoc
-
sql = escape(sql);
parseSqlAndSetSqlModes(sql);
+ checkAutoGeneratedKeysParameters();
if (sqlMode_ == isUpdate__) {
updateCount_ = 0;
} else {
@@ -2688,11 +2691,15 @@
"Statement.execute()/executeQuery()");
}
- if (generatedKeysColumnNames_ != null) {
- throw new SqlException(agent_.logWriter_,
- new ClientMessageId(SQLState.NOT_IMPLEMENTED),
- "Connection.prepareStatement(String sql, String[] columnNames)");
- }
+
+ if (sqlUpdateMode_ == isInsertSql__ &&
+ generatedKeysColumnNames_ != null &&
+ generatedKeysColumnNames_.length !=1) {
+ throw new SqlException(agent_.logWriter_,
+ new ClientMessageId(SQLState.INVALID_COLUMN_ARRAY_LENGTH),
+ new Integer(generatedKeysColumnNames_.length));
+ }
+
}
public ColumnMetaData getGuessedResultSetMetaData() {
Index: java/client/org/apache/derby/client/am/PreparedStatement.java
===================================================================
--- java/client/org/apache/derby/client/am/PreparedStatement.java (revision 628780)
+++ java/client/org/apache/derby/client/am/PreparedStatement.java (working copy)
@@ -1943,6 +1943,7 @@
private void flowExecute(int executeType) throws SqlException {
checkForClosedStatement();
+ checkAutoGeneratedKeysParameters();
clearWarningsX();
checkForAppropriateSqlMode(executeType, sqlMode_);
checkThatAllParametersAreSet();