Thread: JDBC problem with dates and ANYELEMENT type

JDBC problem with dates and ANYELEMENT type

From
"Peter"
Date:
We have a function that takes ANYELEMENT type. If the argument is date (set using setObject(column, datevariable,
Types.DATE))the server throws error: 

ERROR: could not determine polymorphic type because input has type "unknown"

I checked JDBC sources and seems like AbstractJdbc2Statement does this:

    public void setDate(int i, java.sql.Date d, java.util.Calendar cal) throws SQLException
    {
        checkClosed();

        if (d == null)
        {
            setNull(i, Types.DATE);
            return;
        }


        if (cal != null)
            cal = (Calendar)cal.clone();

        // We must use UNSPECIFIED here, or inserting a Date-with-timezone into a
        // timestamptz field does an unexpected rotation by the server's TimeZone:
        //
        // We want to interpret 2005/01/01 with calendar +0100 as
        // "local midnight in +0100", but if we go via date it interprets it
        // as local midnight in the server's timezone:

        // template1=# select '2005-01-01+0100'::timestamptz;
        //       timestamptz
        // ------------------------
        //  2005-01-01 02:00:00+03
        // (1 row)

        // template1=# select '2005-01-01+0100'::date::timestamptz;
        //       timestamptz
        // ------------------------
        //  2005-01-01 00:00:00+03
        // (1 row)

        bindString(i, connection.getTimestampUtils().toString(cal, d), Oid.UNSPECIFIED);
    }



So it indeed sets ‘unspecified’ type which works fine if your target datatype is defined, but fails miserably on
ANYELEMENT.

Any suggestions how to work around this so we can still use ANYELEMENT and pass in DATE?

Peter


Re: JDBC problem with dates and ANYELEMENT type

From
Kris Jurka
Date:

On Thu, 23 Apr 2009, Peter wrote:

> So it indeed sets ‘unspecified’ type which works fine if your target
> datatype is defined, but fails miserably on ANYELEMENT.
>
> Any suggestions how to work around this so we can still use ANYELEMENT
> and pass in DATE?
>

You can put a cast into the query itself "SELECT ?::date".

Kris Jurka

Re: JDBC problem with dates and ANYELEMENT type

From
"Peter"
Date:
>> Any suggestions how to work around this so we can still use ANYELEMENT
>> and pass in DATE?

> You can put a cast into the query itself "SELECT ?::date".

Nah... that's no good. The same query string is used for many different types in my app - such approach would require
meto parse the SQL string and append cast to date when argument is java.sql.Date.  I'll leave this as last-ditch
approach.

What are the potential implications if I patch setDate() method in AbstractJdbc2Statement to pass OID.Date instead of
'unspecified'?Would that break anything else? We don’t use timestamps anywhere in the app yet, so I'm not really
worriedabout timezone being potentially screwed up. 

Peter



Re: JDBC problem with dates and ANYELEMENT type

From
John Lister
Date:
> What are the potential implications if I patch setDate() method in AbstractJdbc2Statement to pass OID.Date instead of
'unspecified'?Would that break anything else? We don’t use timestamps anywhere in the app yet, so I'm not really
worriedabout timezone being potentially screwed up. 
>
Reading the comments i would guess this would break a few things :(

But i didn't think postgresql supported dates with timezones (times yes
but not dates), so is the driver being overly cautious. Isn't passing it
as unspecified with a timezone, effectively passing a timestamp instead
of a date. Having the result be in the servers timezone might be
unexpected if the calendar parameter has a timezone, but isn't it the
correct behaviour?

Similarly looking at the binary patch posted previously, there is a
comment that dates aren't transmitted in binary because the unit tests
fail as they expect millisecond accuracy, surely in SQL a date has no
time component? If you require time as well shouldn't you be using
timestamp?


Just my thoughts and i guess it probably breaks a few users apps if this
were applied...

JOHN

Re: JDBC problem with dates and ANYELEMENT type

From
Kris Jurka
Date:
Peter wrote:
>>> Any suggestions how to work around this so we can still use
>>> ANYELEMENT and pass in DATE?
>
>> You can put a cast into the query itself "SELECT ?::date".
>
> Nah... that's no good. The same query string is used for many
> different types in my app - such approach would require me to parse
> the SQL string and append cast to date when argument is
> java.sql.Date.  I'll leave this as last-ditch approach.

The other way of providing explicit type information is to create an
object that extends PGobject.  Something like:

import java.util.Date;
import java.text.SimpleDateFormat;
import org.postgresql.util.PGobject;

class MyDateWrapper extends PGobject {

     public MyDateWrapper(java.util.Date d) {
         setType("date");
    SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
         setValue(df.format(d));
     }
}

Then call PreparedStatement.setObject with an instance of MyDateWrapper.

Kris Jurka


Re: JDBC problem with dates and ANYELEMENT type

From
"Peter"
Date:
>The other way of providing explicit type information is to create an
>object that extends PGobject.  Something like:


This one is a keeper! Thanks Kris!

Peter