Re: Recent backward compatibility break in PreparedStatement.setObject() - Mailing list pgsql-jdbc

From Dave Cramer
Subject Re: Recent backward compatibility break in PreparedStatement.setObject()
Date
Msg-id CADK3HH+kA8JvUvPAVTKcguvh67LoDc-R_021Xd4Qggq=pYY4pA@mail.gmail.com
Whole thread Raw
In response to Recent backward compatibility break in PreparedStatement.setObject()  (Adam Rauch <adam@labkey.com>)
Responses Re: Recent backward compatibility break in PreparedStatement.setObject()  ("Markus KARG" <markus@headcrashing.eu>)
List pgsql-jdbc
No, this was not intentional.

Thanks for the report!


On 30 December 2015 at 16:45, Adam Rauch <adam@labkey.com> wrote:
The PostgreSQL JDBC driver recently changed PreparedStatement behavior with calls such as setObject(index, value, Types.VARCHAR). Previously, the driver would call value.toString() before binding all VARCHAR values... meaning any object could be passed as "value." In recent updates (e.g., 9.4.1207), most non-String values now result in an exception:

    Exception in thread "main" org.postgresql.util.PSQLException: Cannot convert an instance of XXX to type String
        at org.postgresql.jdbc.PgStatement.cannotCastException(PgStatement.java:1813)
        at org.postgresql.jdbc.PgStatement.cannotCastException(PgStatement.java:1809)
        at org.postgresql.jdbc.PgStatement.castToString(PgStatement.java:1805)
        at org.postgresql.jdbc.PgStatement.setObject(PgStatement.java:1540)
        at org.postgresql.jdbc.PgStatement.setObject(PgStatement.java:1818)
        at PGTest.main(PGTest.java:25)


This seems to have broken during the refactor to support binary transfer for setObject(), https://github.com/pgjdbc/pgjdbc/issues/328. Was the behavior change intentional? If so, it should probably be documented (e.g., I didn't see any mention in the change log). If not, I'd suggest going back to calling value.toString() for all types. I'm sure ours is not the only application that relies on this long-standing (>10 years) PostgreSQL JDBC behavior. FWIW, other JDBC drivers call toString() in this situation.

Here's a contrived example that demonstrates the behavior change. This code snippet runs fine in 1201 but fails with the exception above in 1207.

    Object param = new Object() {public String toString() {return "tables";}};

    try (PreparedStatement stmt = conn.prepareStatement("SELECT * FROM information_schema.tables WHERE table_name = ?"))   {       stmt.setObject(1, param, Types.VARCHAR);
       try (ResultSet rs = stmt.executeQuery())       {           while (rs.next())               System.out.println(rs.getString(1));       }   }

Thanks,
Adam

pgsql-jdbc by date:

Previous
From: Adam Rauch
Date:
Subject: Recent backward compatibility break in PreparedStatement.setObject()
Next
From: John Harvey
Date:
Subject: Re: Are pgrpm changes for JDBC discussed here before submission?