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/10/02 00:07:49 UTC
svn commit: r700948 - in /db/derby/code/trunk/java:
client/org/apache/derby/client/am/ drda/org/apache/derby/impl/drda/
engine/org/apache/derby/iapi/services/i18n/
testing/org/apache/derbyTesting/functionTests/master/
testing/org/apache/derbyTesting/fu...
Author: myrnavl
Date: Wed Oct 1 15:07:48 2008
New Revision: 700948
URL: http://svn.apache.org/viewvc?rev=700948&view=rev
Log:
DERBY-3390; preventing ClassCastException and disconnect on SQLException thrown from a user function
Modified:
db/derby/code/trunk/java/client/org/apache/derby/client/am/Sqlca.java
db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DRDAConnThread.java
db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/i18n/MessageService.java
db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/GetPropertyInfoTest.out
db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/derbynet/SqlExceptionTest.java
Modified: db/derby/code/trunk/java/client/org/apache/derby/client/am/Sqlca.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/am/Sqlca.java?rev=700948&r1=700947&r2=700948&view=diff
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/am/Sqlca.java (original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/am/Sqlca.java Wed Oct 1 15:07:48 2008
@@ -390,8 +390,9 @@
// (five characters) and a colon. Extract the SQL state and
// clean up the token. See
// DRDAConnThread.buildTokenizedSqlerrmc() for more details.
- states[i] = tokens[i].substring(0, 5);
- tokens[i] = tokens[i].substring(6);
+ int colonpos = tokens[i].indexOf(":");
+ states[i] = tokens[i].substring(0, colonpos);
+ tokens[i] = tokens[i].substring(colonpos + 1);
}
sqlStates_ = states;
sqlErrmcMessages_ = tokens;
Modified: db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DRDAConnThread.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DRDAConnThread.java?rev=700948&r1=700947&r2=700948&view=diff
==============================================================================
--- db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DRDAConnThread.java (original)
+++ db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DRDAConnThread.java Wed Oct 1 15:07:48 2008
@@ -6005,7 +6005,7 @@
se = Util.getExceptionFactory().getArgumentFerry( se );
if (se instanceof EmbedSQLException && ! severe)
- sqlerrmc = buildTokenizedSqlerrmc((EmbedSQLException) se);
+ sqlerrmc = buildTokenizedSqlerrmc(se);
else {
// If this is not an EmbedSQLException or is a severe excecption where
// we have no hope of succussfully calling the SYSIBM.SQLCAMESSAGE send
@@ -6057,17 +6057,32 @@
* @param se SQLException to print
*
*/
- private String buildTokenizedSqlerrmc(EmbedSQLException se) {
+ private String buildTokenizedSqlerrmc(SQLException se) {
String sqlerrmc = "";
do {
- String messageId = se.getMessageId();
- // arguments are variable part of a message
- Object[] args = se.getArguments();
- for (int i = 0; args != null && i < args.length; i++)
- sqlerrmc += args[i] + SQLERRMC_TOKEN_DELIMITER;
- sqlerrmc += messageId;
- se = (EmbedSQLException) se.getNextException();
+ if ( se instanceof EmbedSQLException)
+ {
+ String messageId = ((EmbedSQLException)se).getMessageId();
+ // arguments are variable part of a message
+ Object[] args = ((EmbedSQLException)se).getArguments();
+ for (int i = 0; args != null && i < args.length; i++)
+ sqlerrmc += args[i] + SQLERRMC_TOKEN_DELIMITER;
+ sqlerrmc += messageId;
+ se = se.getNextException();
+ }
+ else
+ {
+ // this could happen for instance if an SQLException was thrown
+ // from a stored procedure.
+ StringBuffer sb = new StringBuffer();
+ sb.append(se.getLocalizedMessage());
+ se = se.getNextException();
+ if (se != null)
+ sb.append(SQLERRMC_TOKEN_DELIMITER +
+ "SQLSTATE: " + se.getSQLState());
+ sqlerrmc += sb.toString();
+ }
if (se != null)
{
sqlerrmc += SystemProcedures.SQLERRMC_MESSAGE_DELIMITER + se.getSQLState() + ":";
Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/i18n/MessageService.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/i18n/MessageService.java?rev=700948&r1=700947&r2=700948&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/i18n/MessageService.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/i18n/MessageService.java Wed Oct 1 15:07:48 2008
@@ -270,8 +270,9 @@
StringBuffer sb = new StringBuffer(messageId);
- sb.append(" : ");
int len = arguments.length;
+ if (len > 0)
+ sb.append(" : ");
for (int i=0; i < len; i++) {
// prepend a comma to all but the first
Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/GetPropertyInfoTest.out
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/GetPropertyInfoTest.out?rev=700948&r1=700947&r2=700948&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/GetPropertyInfoTest.out (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/GetPropertyInfoTest.out Wed Oct 1 15:07:48 2008
@@ -9,8 +9,8 @@
user - value: null - description: user name - required false - choices null
logDevice - value: null - description: log directory path - required false - choices null
rollForwardRecoveryFrom - value: null - description: backup path for rollforward recovery - required false - choices null
-createFrom - value: null - description: J029 : - required false - choices null
-restoreFrom - value: null - description: J030 : - required false - choices null
+createFrom - value: null - description: J029 - required false - choices null
+restoreFrom - value: null - description: J030 - required false - choices null
bootPassword - value: - description: secret cryptographic key - required false - choices null
password - value: - description: user password - required false - choices null
shutdown - value: false - description: shut down Derby - required false - choices [0] : false - choices [1] : true
@@ -27,8 +27,8 @@
user - value: null - description: user name - required false - choices null
logDevice - value: null - description: log directory path - required false - choices null
rollForwardRecoveryFrom - value: null - description: backup path for rollforward recovery - required false - choices null
-createFrom - value: null - description: J029 : - required false - choices null
-restoreFrom - value: null - description: J030 : - required false - choices null
+createFrom - value: null - description: J029 - required false - choices null
+restoreFrom - value: null - description: J030 - required false - choices null
bootPassword - value: **** - description: secret cryptographic key - required false - choices null
password - value: - description: user password - required false - choices null
shutdown - value: false - description: shut down Derby - required false - choices [0] : false - choices [1] : true
Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/derbynet/SqlExceptionTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/derbynet/SqlExceptionTest.java?rev=700948&r1=700947&r2=700948&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/derbynet/SqlExceptionTest.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/derbynet/SqlExceptionTest.java Wed Oct 1 15:07:48 2008
@@ -143,6 +143,87 @@
assertSQLExceptionEquals(se, se_ser);
}
}
+
+ /**
+ * Verify that an SQLException thrown by a function can be returned
+ * (DERBY-790).
+ */
+ public void testDerby3390() throws Exception {
+ setAutoCommit(false);
+ Statement stmt = createStatement();
+
+ // with client/server we prefetch, so the error comes earlier
+ try {
+ if (usingDerbyNetClient())
+ {
+ stmt.execute("values badFunction1()");
+ fail("expected an error");
+ }
+ else
+ {
+ stmt.execute("values badFunction1()");
+ ResultSet rs = stmt.getResultSet();
+ rs.next();
+ fail("expected an error");
+ }
+ } catch (SQLException e) {
+ setAutoCommit(true);
+ // if DERBY-3390 occurs, at this point, with networkserver/client,
+ // we'd get a 08006. In the server's derby.log you'd see a
+ // ClassCastException
+ assertSQLState("38000", e);
+ assertTrue(e.getMessage().indexOf("I refuse to return an int") > 1);
+ }
+
+ // as above, but this time the function uses the constructor for
+ // SQLException with SQLState.
+ try {
+ if (usingDerbyNetClient())
+ {
+ stmt.execute("values badFunction2()");
+ fail("expected an error");
+ }
+ else
+ {
+ stmt.execute("values badFunction2()");
+ ResultSet rs = stmt.getResultSet();
+ rs.next();
+ fail("expected an error");
+ }
+ } catch (SQLException e) {
+ setAutoCommit(true);
+ // if DERBY-3390 occurs, at this point, with networkserver/client,
+ // we'd get a 08006. In the server's derby.log you'd see a
+ // ClassCastException
+ assertSQLState("38000", e);
+ assertSQLState("50000", e);
+ assertTrue(e.getMessage().indexOf("I refuse to return an int") > 1);
+ }
+
+ // test an Exception gets thrown for good measure
+ try {
+ if (usingDerbyNetClient())
+ {
+ stmt.execute("values badFunction3()");
+ fail("expected an error");
+ }
+ else
+ {
+ stmt.execute("values badFunction3()");
+ ResultSet rs = stmt.getResultSet();
+ rs.next();
+ fail("expected an error");
+ }
+ } catch (SQLException e) {
+ setAutoCommit(true);
+ assertSQLState("38000", e);
+ assertTrue(e.getMessage().indexOf("The exception 'java.lang.Exception: I refuse to return an int!'")==0);
+ }
+
+ stmt.close();
+ rollback();
+ setAutoCommit(true);
+ }
/**
* Set up the connection to the database.
@@ -154,6 +235,15 @@
"c2 int)";
Statement stmt = conn.createStatement();
stmt.execute(createTableWithPK);
+ stmt.execute("create function badFunction1() returns int language java"
+ + " parameter style java no sql external name '" +
+ SqlExceptionTest.class.getName() + ".badFunction1'");
+ stmt.execute("create function badFunction2() returns int language java"
+ + " parameter style java no sql external name '" +
+ SqlExceptionTest.class.getName() + ".badFunction2'");
+ stmt.execute("create function badFunction3() returns int language java"
+ + " parameter style java no sql external name '" +
+ SqlExceptionTest.class.getName() + ".badFunction3'");
stmt.close();
conn.close();
}
@@ -165,6 +255,9 @@
Connection conn = getConnection();
Statement stmt = conn.createStatement();
stmt.executeUpdate("DROP TABLE tableWithPK");
+ stmt.executeUpdate("drop function badfunction1");
+ stmt.executeUpdate("drop function badfunction2");
+ stmt.executeUpdate("drop function badfunction3");
stmt.close();
conn.close();
super.tearDown();
@@ -204,4 +297,38 @@
return test;
}
}
+
+ /* <p>
+ * For testing DERBY-3390
+ * This function just throws a SQLException, without SQLState
+ * </p>
+ */
+ public static int badFunction1()
+ throws SQLException
+ {
+ throw new SQLException( "I refuse to return an int!" );
+ }
+
+ /* <p>
+ * For testing DERBY-3390
+ * This function just throws a SQLException, with SQLState
+ * </p>
+ */
+ public static int badFunction2()
+ throws SQLException
+ {
+ throw new SQLException( "I refuse to return an int!", "50000" );
+ }
+
+ /* <p>
+ * For testing DERBY-3390
+ * This function just throws an Exception
+ * </p>
+ */
+ public static int badFunction3()
+ throws Exception
+ {
+ throw new Exception( "I refuse to return an int!" );
+ }
+
}