Description:
Due to a bug in DatabaseMetaData (dbmd) 3.1.11 breaks JBoss AS (tested with 4.0.3*).
The problem is, that Jboss needs to find out, whether a table exists. For this it asks the dbdm, how it stores identifiers. 3.1.11 returns true for lower case and thus jboss converts the table name in question to lower case and ask for its definitions. But 3.1.11 does not return a definition, if the real table name in the db is e.g. UPPER case. So jboss thinks, the table does not exit and tries to re-create it. The result is an SQLException (saying, that the table already exists) and thus the service in question gets not started.
This has probably also an impact to other OR-Mappers like Hibernate.
How to repeat:
slightly modified snippet from Jboss source code:
private static boolean tablenameExits(String tableName)
{
try {
// (a j2ee spec compatible jdbc driver has to fully
// implement the DatabaseMetaData)
DatabaseMetaData dmd = con.getMetaData();
String catalog = con.getCatalog();
String schema = null;
String quote = dmd.getIdentifierQuoteString();
if (tableName.startsWith(quote)) {
if (tableName.endsWith(quote) == false) {
throw new IllegalArgumentException(
"Mismatched quote in table name: " + tableName);
}
int quoteLength = quote.length();
tableName = tableName.substring(quoteLength, tableName.length()
- quoteLength);
if (dmd.storesLowerCaseQuotedIdentifiers())
tableName = tableName.toLowerCase();
else if (dmd.storesUpperCaseQuotedIdentifiers())
tableName = tableName.toUpperCase();
} else {
if (dmd.storesLowerCaseIdentifiers())
tableName = tableName.toLowerCase();
else if (dmd.storesUpperCaseIdentifiers())
tableName = tableName.toUpperCase();
}
// Patch #927759: Split tablename into "schema" and "table"
// separated by '.'
int dotIndex;
if ( (dotIndex = tableName.indexOf('.')) != -1) {
// Yank out schema name ...
schema = tableName.substring(0, dotIndex);
tableName = tableName.substring(dotIndex + 1);
}
rs = dmd.getTables(catalog, schema, tableName, null);
return rs.next();
} catch (SQLException e) {
// This should not happen. A J2EE compatiable JDBC driver is
// required fully support metadata.
throw new IllegalArgumentException(
"Error while checking if table aleady exists " + tableName, e);
} finally {
safeClose(rs);
safeClose(con);
}
}
Create a table in the db named 'TIMERS' and call tablenameExits('TIMERS').
3.1.10 returns true, 3.1.11 returns false.
Suggested fix:
Switch back to the behavior of the 3.1.10.