Re: JDBC - PreparedStatement reuse oddity when using setObject() with nulls and setTimestamp()

From: Dave Cramer <pg(at)fastcrypt(dot)com>
To: Alastair Burr <alastair(dot)burr(at)bluestar-software(dot)co(dot)uk>
Cc: List <pgsql-jdbc(at)postgresql(dot)org>
Subject: Re: JDBC - PreparedStatement reuse oddity when using setObject() with nulls and setTimestamp()
Date: 2013-02-20 14:16:42
Message-ID: CADK3HH+BS38R9WN8hD_9PL5y36b4M4oKyRVoxTpiMpTbpte=pA@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-jdbc

Alastair,

I just tried to replicate this in the current driver and can't.

This in the current driver passes fine

public void testSetNullDateWOTZ() throws SQLException
{
Statement stmt = con.createStatement();
PreparedStatement pstmt =
con.prepareStatement(TestUtil.insertSQL(TSWOTZ_TABLE, "?"));

pstmt.setTimestamp(1, TS1WOTZ);
assertEquals(1, pstmt.executeUpdate());

pstmt.setObject(1, null, Types.DATE);
assertEquals(1, pstmt.executeUpdate());

Timestamp now = new Timestamp(System.currentTimeMillis());

pstmt.setTimestamp(1, now);
assertEquals(1, pstmt.executeUpdate());

// Fall through helper
timestampTestSetNullDate(now);

assertEquals(3, stmt.executeUpdate("DELETE FROM " + TSWOTZ_TABLE));

pstmt.close();
stmt.close();
}

private void timestampTestSetNullDate(Timestamp now) throws SQLException
{
Statement stmt = con.createStatement();
ResultSet rs;
java.sql.Timestamp t;

rs = stmt.executeQuery("select ts from " + TSWOTZ_TABLE); //removed
the order by ts
assertNotNull(rs);

assertTrue(rs.next());
t = rs.getTimestamp(1);
assertNotNull(t);
assertEquals(TS1WOTZ, t);

assertTrue(rs.next());
t = rs.getTimestamp(1);

assertNull(t);

assertTrue(rs.next());
t = rs.getTimestamp(1);
assertNotNull(t);
assertEquals(now, t);

assertTrue(! rs.next()); // end of table. Fail if more entries
exist.

rs.close();
stmt.close();

}

Dave Cramer

dave.cramer(at)credativ(dot)ca
http://www.credativ.ca

On Tue, Feb 19, 2013 at 1:15 PM, Dave Cramer <pg(at)fastcrypt(dot)com> wrote:

> Alastair,
>
> that certainly looks like a bug. Thanks for reporting.
>
> Dave Cramer
>
> dave.cramer(at)credativ(dot)ca
> http://www.credativ.ca
>
>
> On Tue, Feb 19, 2013 at 12:32 PM, Alastair Burr <
> alastair(dot)burr(at)bluestar-software(dot)co(dot)uk> wrote:
>
>> Hello,
>>
>> As a company we've just been adopting PostgreSQL, and we noticed this
>> oddity with the PostgreSQL JDBC driver, not sure if it classifies as a bug,
>> but it caught us out recently, so am just sharing in case it catches anyone
>> else out.
>>
>> Essentially if reusing a PreparedStatement and clearing the parameters
>> between executes, if you use setObject() with a null object on a TIMESTAMP
>> field and specify Types.DATE then all subsequent updates using
>> setTimestamp() will miss out the time component and just add in the date
>> with time set to midnight.
>>
>> Below is a snippet (this is just handwritten to demonstrate so apologies
>> if I've made any typos and not demonstrating error checking etc). Of course
>> this was easy to workaround, as we should've been using setObject passing
>> in Types.TIMESTAMP and not Types.DATE (or just using setNull) but I
>> wouldn't have expected the below behaviour!!
>>
>> I thought I would share with you anyway to see whether you just classify
>> this as "misuse" or whether it is a genuine oddity that may need to be
>> addressed. (versions of PostgreSQL mentioned in comments below). Thanks,
>>
>> "
>> // assuming a simple table with one timestamp field such as "CREATE TABLE
>> test ( dt TIMESTAMP )"
>>
>> // prepare a statement on a postgresql connection
>> PreparedStatement tStmt = tCon.prepareStatement("INSERT INTO test ( dt )
>> VALUES ( ? )");
>>
>> // clear parameters, set timestamp to now and execute
>> tStmt.clearParameters();
>> tStmt.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
>> tStmt.executeUpdate();
>>
>> // clear parameters, set using a null object and execute
>> tStmt.clearParameters();
>> tStmt.setObject(1, null, Types.DATE);
>> tStmt.executeUpdate();
>>
>> // clear parameters, set timestamp to now and execute
>> tStmt.clearParameters();
>> tStmt.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
>> tStmt.executeUpdate();
>>
>> // this will output 3 rows assuming current date / time is 12/02/2013
>> 17:08:01
>> // 1st row = 12/02/2013 17:08:01
>> // 2nd row = null
>> // 3rd row = 12/02/2013 00:00:00
>>
>> // as you can see the 3rd row has had its time wiped out and set to
>> midnight
>> // tested against various versions, last test against PostgreSQL 9.1.3 on
>> linux 64 bit
>> // and using JDBC PostgreSQL 9.2devel JDBC4 (build 1000)
>> "
>>
>>
>> P.S - Apologies if anyone has mentioned this before, didn't spot anything
>> similar on the brief searches I did!
>>
>> --
>> Alastair Burr
>> Senior Engineer & Project Coordinator, Bluestar Software
>> Telephone: +44 (0)1256 882695
>> Web site: www.bluestar-software.co.uk
>> Email: alastair(dot)burr(at)bluestar-software(dot)co(dot)uk
>>
>>
>> ------------------------------
>>
>> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>> DISCLAIMER: This email message and any attachments is for the sole
>> use of the intended recipient(s) and may contain confidential and
>> privileged information. Any unauthorised review, use, disclosure
>> or distribution is prohibited. If you are not the intended recipient,
>> please contact the sender by reply email and destroy all copies of
>> the original message.
>>
>> The views expressed in this message may not necessarily reflect the
>> views of Bluestar Software Ltd.
>>
>> Bluestar Software Ltd, Registered in England
>> Company Registration No. 03537860, VAT No. 709 2751 29
>> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>
>>
>

In response to

Responses

Browse pgsql-jdbc by date

  From Date Subject
Next Message Alastair Burr 2013-02-20 16:20:23 Re: JDBC - PreparedStatement reuse oddity when using setObject() with nulls and setTimestamp()
Previous Message News Subsystem 2013-02-20 14:01:23