The assumption that the spec makes about the prepared statement being compiled are not valid for PostgreSQL. The metadata comes from the result set, not from the statement. You could in fact not call getMetaData on a statement which was not executed.
That being said, do you know if this behaviour is consistent with previous versions of the JDBC driver ?
I ran into troubles fetching metadata on a PreparedStatement. After some time, I isolated a simple test case that shows the issue (see the code snippet below). On a brand new PreparedStatement, I call the getMetaData() method without any problem. However, if I execute the query (executeQuery()) on this same statement, close the ResultSet and then calls again getMetaData() (still on the same PreparedStatement), getMetaData() throws a RuntimeException saying "This ResultSet is closed". I would expect to be able to get the metadata. Is that a bug in the JDBC driver ?
I tested this behavior on several flavours of the 9.3 driver version, including 9.3-1100-jdbc4 .
/** * Test on the PostgreSql JDBC driver. */ public class JdbcTest { /** * This test shows a driver issue on the PreparedStatement management. * * @throws ClassNotFoundException On driver initialization failure. * @throws SQLException On datbase operation failure. */ @Test public void test2() throws SQLException, ClassNotFoundException { Class.forName("org.postgresql.Driver"); final Connection connection = DriverManager.getConnection("jdbc:postgresql://server/db_name", "username", "password");
final String query = "SELECT 1 AS toto, 2 AS titi";
final PreparedStatement pstmt = connection.prepareStatement(query); final ResultSetMetaData rsMetadata = pstmt.getMetaData(); Assert.assertNotNull(rsMetadata);
final ResultSetMetaData rsMetadata2 = pstmt.getMetaData(); Assert.assertNotNull(rsMetadata2);
final ResultSet rs = pstmt.executeQuery(); Assert.assertNotNull(rs); rs.close();
Assert.assertFalse(pstmt.isClosed()); try { // Guess what ? The next line throws an exception ! final ResultSetMetaData rsMetadata3 = pstmt.getMetaData(); Assert.assertNotNull(rsMetadata3); } catch (final RuntimeException exception) { Assert.fail(exception.getMessage()); } pstmt.close();
connection.close(); } }
Emmanuel GUITON Ingénieur Développement Fixe : +33170928416 lStandard : +33141917777 215, avenue Georges Clemenceau l 92024 Nanterre