Re: PreparedStatement parameters and mutable objects - Mailing list pgsql-jdbc

From Oliver Jowett
Subject Re: PreparedStatement parameters and mutable objects
Date
Msg-id 4001D0D9.8020507@opencloud.com
Whole thread Raw
In response to Re: PreparedStatement parameters and mutable objects  (Dave Cramer <pg@fastcrypt.com>)
Responses Re: PreparedStatement parameters and mutable objects  (Kris Jurka <books@ejurka.com>)
Re: PreparedStatement parameters and mutable objects  (Paul Thomas <paul@tmsl.demon.co.uk>)
List pgsql-jdbc
Dave Cramer wrote:
> Well there is some hint that this is incorrect:
>
>
> pstmnt = con.prepareStatment("insert into foo values(?,?)");
>
> pstmnt.setString(1,"abcd");
>
> for( i=0; i< 5; i++)
> {
>     Integer intx = new Integer(i);
>     pstmnt.setInt(2,intx)
>     pstmnt.executeUpdate();
> }
>
> The above code should insert ("abcd", 0 .. 4 ) into five rows
>
> The point being that the value for setXXX does not change until setXXX
> is called.

Well, this is a different case -- Integer is immutable, so when the
driver transforms it to a DB representation is irrelevant. (I assume you
mean setObject(), above, since setInt() expects a primitive int..).

Even if the implication of the above code is that a parameter doesn't
change from what you last set it to on execution, that doesn't really
help us answer the question .. so you don't set it, and have the same
mutable object reference, but that's no different to the case where you
set it to a new mutable object reference .. it could still mutate before
execution.

If we were using e.g. setBytes() the analogous case is something like this:

   byte[] data = new byte[10];
   // (1)
   for (int i = 0; i < 5; ++i) {
      data[0] = i;
      pstmt.setBytes(2, data);       // (2)
      pstmt.executeUpdate();
   }

If binding was guaranteed to happen at execution you could get away with
a setBytes() at (1) and remove (2). But I think the above code is the
only way to be safe under all drivers.

The above case is relatively boring as 'data' does not change between
setBytes() and executeUpdate() anyway. More interesting is this one..

   byte[] data = new byte[10];
   for (int i = 0; i < 5; ++i) {
      data[0] = i;
      pstmt.setBytes(2, data);
      pstmt.addBatch();
   }
   pstmt.executeBatch();

I think this is the case that is more likely to bite us. "set
parameters, modify mutable objects, execute" seems like an unlikely
pattern to use in real code. "reuse mutable objects, set parameters, add
to batch, loop" seems more likely.

I'm still in favour of an "undefined behaviour" interpretation here.
There's not much benefit to application code in nailing down one
behaviour or the other, and leaving it undefined gives the driver the
flexibility to do whichever is a better implementation for the DB in
question.

I might send a query to the JDBC expert group about this. Anyone have a
better contact address than the spec feedback address? (the Sun
JDBC-INTEREST list seems to be pretty useless, it seems to be the "where
can I find an oracle driver?" mailing list)

-O

pgsql-jdbc by date:

Previous
From: Kris Jurka
Date:
Subject: Re: jdbc pooling question
Next
From: "Marcus Andree S. Magalhaes"
Date:
Subject: Re: Connection Pool Timeout