Обсуждение: ResultSet.getObject(..., LocalTime.class) not working with Postgrestimetz type

Поиск
Список
Период
Сортировка

ResultSet.getObject(..., LocalTime.class) not working with Postgrestimetz type

От
Thomas Kellerer
Дата:
Retrieving the value of a timetz column fails when using getObject(, LocalTime.class)

Consider the following code:

   Connection con = DriverManager.getConnection(...);
   Statement stmt = con.createStatement();
   ResultSet rs = stmt.executeQuery("select current_time");
   rs.next();
   LocalTime lt = rs.getObject(1, LocalTime.class);

The above fails with:

org.postgresql.util.PSQLException: Bad value for type timestamp/date/time: {1}
    at org.postgresql.jdbc.TimestampUtils.toLocalTime(TimestampUtils.java:433)
    at org.postgresql.jdbc.PgResultSet.getLocalTime(PgResultSet.java:563)
    at org.postgresql.jdbc.PgResultSet.getObject(PgResultSet.java:3391)
    at TestLocalTime.main(TestLocalTime.java:23)
Caused by: java.time.format.DateTimeParseException: Text '09:48:19.747249+02' could not be parsed, unparsed text found
atindex 15
 
    at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1952)
    at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1851)
    at java.time.LocalTime.parse(LocalTime.java:441)
    at java.time.LocalTime.parse(LocalTime.java:426)
    at org.postgresql.jdbc.TimestampUtils.toLocalTime(TimestampUtils.java:430)

getObject(1, OffsetTime.class) fails with "conversion to class java.time.OffsetTime from 92 not supported"

I am not sure if this is the same as: https://github.com/pgjdbc/pgjdbc/issues/1048
If it's not the same root cause, should I create an issue?

Using "select localtime" instead, works just fine


Regards
Thomas
  




Re: ResultSet.getObject(..., LocalTime.class) not working withPostgres timetz type

От
Mark Rotteveel
Дата:
For reference, the JDBC specification does not specify support 
java.time.LocalXXX types on WITH TIME ZONE types.

Especially because it is rather ambiguous what local would mean: would 
it mean local in the default JVM time zone, local at the original zone 
or local at UTC?

Mark

On 6-4-2019 09:59, Thomas Kellerer wrote:
> Retrieving the value of a timetz column fails when using getObject(, 
> LocalTime.class)
> 
> Consider the following code:
> 
>    Connection con = DriverManager.getConnection(...);
>    Statement stmt = con.createStatement();
>    ResultSet rs = stmt.executeQuery("select current_time");
>    rs.next();
>    LocalTime lt = rs.getObject(1, LocalTime.class);
> 
> The above fails with:
> 
> org.postgresql.util.PSQLException: Bad value for type 
> timestamp/date/time: {1}
>      at 
> org.postgresql.jdbc.TimestampUtils.toLocalTime(TimestampUtils.java:433)
>      at org.postgresql.jdbc.PgResultSet.getLocalTime(PgResultSet.java:563)
>      at org.postgresql.jdbc.PgResultSet.getObject(PgResultSet.java:3391)
>      at TestLocalTime.main(TestLocalTime.java:23)
> Caused by: java.time.format.DateTimeParseException: Text 
> '09:48:19.747249+02' could not be parsed, unparsed text found at index 15
>      at 
> java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1952) 
> 
>      at 
> java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1851)
>      at java.time.LocalTime.parse(LocalTime.java:441)
>      at java.time.LocalTime.parse(LocalTime.java:426)
>      at 
> org.postgresql.jdbc.TimestampUtils.toLocalTime(TimestampUtils.java:430)
> 
> getObject(1, OffsetTime.class) fails with "conversion to class 
> java.time.OffsetTime from 92 not supported"
> 
> I am not sure if this is the same as: 
> https://github.com/pgjdbc/pgjdbc/issues/1048
> If it's not the same root cause, should I create an issue?
> 
> Using "select localtime" instead, works just fine
> 
> 
> Regards
> Thomas
> 
> 
> 
> 
> 


-- 
Mark Rotteveel



Re: ResultSet.getObject(..., LocalTime.class) not working withPostgres timetz type

От
Thomas Kellerer
Дата:
Mark Rotteveel schrieb am 06.04.2019 um 10:15:
>> Retrieving the value of a timetz column fails when using getObject(, LocalTime.class)
>>
>> I am not sure if this is the same as: https://github.com/pgjdbc/pgjdbc/issues/1048
>> If it's not the same root cause, should I create an issue?
>>
>> Using "select localtime" instead, works just fine

> For reference, the JDBC specification does not specify support java.time.LocalXXX types on WITH TIME ZONE types.
>
> Especially because it is rather ambiguous what local would mean: would it mean local in the default JVM time zone,
localat the original zone or local at UTC? 

Makes sense.

However, the column is reported as Types.TIME and not Types.TIME_WITH_TIMEZONE, that's why I stumbled over it.

I think the driver should then support getObject(1, OffsetTime.class), shouldn't it?

Thomas






Re: ResultSet.getObject(..., LocalTime.class) not working withPostgres timetz type

От
pm@netcetera.ch
Дата:
On 06.04.19 19:40, Thomas Kellerer wrote:
> Mark Rotteveel schrieb am 06.04.2019 um 10:15:
>>> Retrieving the value of a timetz column fails when using getObject(, 
>>> LocalTime.class)
>>>
>>> I am not sure if this is the same as: 
>>> https://github.com/pgjdbc/pgjdbc/issues/1048
>>> If it's not the same root cause, should I create an issue?
>>>
>>> Using "select localtime" instead, works just fine
> 
>> For reference, the JDBC specification does not specify support 
>> java.time.LocalXXX types on WITH TIME ZONE types.
>>
>> Especially because it is rather ambiguous what local would mean: would 
>> it mean local in the default JVM time zone, local at the original zone 
>> or local at UTC?
> 
> Makes sense.
> 
> However, the column is reported as Types.TIME and not 
> Types.TIME_WITH_TIMEZONE, that's why I stumbled over it.
> 
> I think the driver should then support getObject(1, OffsetTime.class), 
> shouldn't it?

It was originally not implemented out of laziness, somewhat justified by 
the fact that the documentation recommends against using the type saying 
it's only present because of legacy and standards compliance reasons. 
 From a functional point of view there is nothing wrong with 
implementing it. Again, in practice it's hard to find a use for the type.

Yes the type should be Types.TIME_WITH_TIMEZONE. However in #695 [2] it 
was decided that following the JDBC specification would break frameworks 
and it would be better to instead go against the JDBC specification and 
instead having each framework implement driver specific hacks.

  [1] 
https://www.postgresql.org/docs/current/datatype-datetime.html#DATATYPE-TIMEZONES 

  [2] https://github.com/pgjdbc/pgjdbc/pull/695

Cheers
Philippe



Re: ResultSet.getObject(..., LocalTime.class) not working withPostgres timetz type

От
Mark Rotteveel
Дата:
On 9-4-2019 13:20, pm@netcetera.ch wrote:
> On 06.04.19 19:40, Thomas Kellerer wrote:
>> I think the driver should then support getObject(1, OffsetTime.class), 
>> shouldn't it?
> 
> It was originally not implemented out of laziness, somewhat justified by 
> the fact that the documentation recommends against using the type saying 
> it's only present because of legacy and standards compliance reasons. 
>  From a functional point of view there is nothing wrong with 
> implementing it. Again, in practice it's hard to find a use for the type.
> 
> Yes the type should be Types.TIME_WITH_TIMEZONE. However in #695 [2] it 
> was decided that following the JDBC specification would break frameworks 
> and it would be better to instead go against the JDBC specification and 
> instead having each framework implement driver specific hacks.

This decision will still mean that frameworks will have to implement 
driver-specific hacks though: That is those tools or frameworks that do 
follow the guidance of the JDBC 4.2 or higher specification and expect 
to be able to obtain the LocalXXX types here.

If you declare that a column is Types.TIME(STAMP), then you should also 
be able to return java.time.LocalTime, java.time.LocalDateTime (and of 
course java.sql.Time/java.sql.Timestamp).

Declaring Types.TIME(STAMP), but not supporting java.time.LocalXXX is in 
my opinion a worse 'violation' of the JDBC specification compared to 
declaring Types.TIME(STAMP) instead of Types.TIME(STAMP)_WITH_TIMEZONE. 
By saying you are Types.TIMESTAMP, you implicitly promise to deliver the 
type conversions defined in Appendix B of JDBC 4.3 (B.4/B.5). Supporting 
java.time.OffsetDateTime / java.time.OffsetTime on Types.TIME(STAMP) is 
then just a non-standard extension.

That of course leaves the problem of ambiguity what local means in the 
context of a type with time zone information.

Mark
-- 
Mark Rotteveel



Re: ResultSet.getObject(..., LocalTime.class) not working withPostgres timetz type

От
Dave Cramer
Дата:


On Wed, 10 Apr 2019 at 08:43, Mark Rotteveel <mark@lawinegevaar.nl> wrote:
On 9-4-2019 13:20, pm@netcetera.ch wrote:
> On 06.04.19 19:40, Thomas Kellerer wrote:
>> I think the driver should then support getObject(1, OffsetTime.class),
>> shouldn't it?
>
> It was originally not implemented out of laziness, somewhat justified by
> the fact that the documentation recommends against using the type saying
> it's only present because of legacy and standards compliance reasons.
>  From a functional point of view there is nothing wrong with
> implementing it. Again, in practice it's hard to find a use for the type.
>
> Yes the type should be Types.TIME_WITH_TIMEZONE. However in #695 [2] it
> was decided that following the JDBC specification would break frameworks
> and it would be better to instead go against the JDBC specification and
> instead having each framework implement driver specific hacks.

This decision will still mean that frameworks will have to implement
driver-specific hacks though: That is those tools or frameworks that do
follow the guidance of the JDBC 4.2 or higher specification and expect
to be able to obtain the LocalXXX types here.

If you declare that a column is Types.TIME(STAMP), then you should also
be able to return java.time.LocalTime, java.time.LocalDateTime (and of
course java.sql.Time/java.sql.Timestamp).

Declaring Types.TIME(STAMP), but not supporting java.time.LocalXXX is in
my opinion a worse 'violation' of the JDBC specification compared to
declaring Types.TIME(STAMP) instead of Types.TIME(STAMP)_WITH_TIMEZONE.
By saying you are Types.TIMESTAMP, you implicitly promise to deliver the
type conversions defined in Appendix B of JDBC 4.3 (B.4/B.5). Supporting
java.time.OffsetDateTime / java.time.OffsetTime on Types.TIME(STAMP) is
then just a non-standard extension.

That of course leaves the problem of ambiguity what local means in the
context of a type with time zone information.

Mark
--
Mark Rotteveel

The whole time, timestamp, timezone thing was not well thought out and is the bane of all driver implementers existence...


 

Re: ResultSet.getObject(..., LocalTime.class) not working withPostgres timetz type

От
Mark Rotteveel
Дата:
On 2019-04-16 02:20, Dave Cramer wrote:
> The whole time, timestamp, timezone thing was not well thought out and
> is the bane of all driver implementers existence...

With timezone support coming in Firebird 4 and having implemented it 
just recently in Jaybird 4, I look forward with a bit of trepidation to 
those releases...

Mark



Re: ResultSet.getObject(..., LocalTime.class) not working withPostgres timetz type

От
Philippe Marschall
Дата:
On 16.04.19 02:20, Dave Cramer wrote:
> 
> 
> The whole time, timestamp, timezone thing was not well thought out and 
> is the bane of all driver implementers existence...


Pre JDBC 4.2 and java.sql types I agree.

JDBC 4.2+ and java.time types I disagree. Issues with JDBC 4.2 and 
java.time types start when:

- people want backwards compatibility with bugs in java.sql
- support is implemented in terms of java.sql
- people want to support other java.time types and the direct 1:1 mappings

If you stay away from these then everything is really easy.

Cheers
Philippe




Re: ResultSet.getObject(..., LocalTime.class) not working withPostgres timetz type

От
Philippe Marschall
Дата:
On 16.04.19 02:20, Dave Cramer wrote:
> 
> 
> The whole time, timestamp, timezone thing was not well thought out and 
> is the bane of all driver implementers existence...


Pre JDBC 4.2 and java.sql types I agree.

JDBC 4.2+ and java.time types I disagree. Issues with JDBC 4.2+ and 
java.time types start when:

- people want backwards compatibility with bugs in java.sql
- support is implemented in terms of java.sql
- people want to support other java.time types besides the direct 1:1 
mappings

If you stay away from these then everything is really easy.

Cheers
Philippe




Re: ResultSet.getObject(..., LocalTime.class) not working withPostgres timetz type

От
Philippe Marschall
Дата:
On 10.04.19 14:43, Mark Rotteveel wrote:
> On 9-4-2019 13:20, pm@netcetera.ch wrote:
>> On 06.04.19 19:40, Thomas Kellerer wrote:
>>> I think the driver should then support getObject(1, 
>>> OffsetTime.class), shouldn't it?
>>
>> It was originally not implemented out of laziness, somewhat justified 
>> by the fact that the documentation recommends against using the type 
>> saying it's only present because of legacy and standards compliance 
>> reasons.  From a functional point of view there is nothing wrong with 
>> implementing it. Again, in practice it's hard to find a use for the type.
>>
>> Yes the type should be Types.TIME_WITH_TIMEZONE. However in #695 [2] 
>> it was decided that following the JDBC specification would break 
>> frameworks and it would be better to instead go against the JDBC 
>> specification and instead having each framework implement driver 
>> specific hacks.
> 
> This decision will still mean that frameworks will have to implement 
> driver-specific hacks though: That is those tools or frameworks that do 
> follow the guidance of the JDBC 4.2 or higher specification and expect 
> to be able to obtain the LocalXXX types here.
> 
> If you declare that a column is Types.TIME(STAMP), then you should also 
> be able to return java.time.LocalTime, java.time.LocalDateTime (and of 
> course java.sql.Time/java.sql.Timestamp).
> 
> Declaring Types.TIME(STAMP), but not supporting java.time.LocalXXX is in 
> my opinion a worse 'violation' of the JDBC specification compared to 
> declaring Types.TIME(STAMP) instead of Types.TIME(STAMP)_WITH_TIMEZONE. 
> By saying you are Types.TIMESTAMP, you implicitly promise to deliver the 
> type conversions defined in Appendix B of JDBC 4.3 (B.4/B.5). Supporting 
> java.time.OffsetDateTime / java.time.OffsetTime on Types.TIME(STAMP) is 
> then just a non-standard extension.
> 
> That of course leaves the problem of ambiguity what local means in the 
> context of a type with time zone information.

I agree with you. We should report _WITH_TIMEZONE as the type and 
support Offset* types for the tz database types. For the non tz types we 
support the Local* types and report Types accordingly.

This is a case were deviating from the standard with well defined 
semantics just leads to more and more issues down the road.

Cheers
Philippe



Re: ResultSet.getObject(..., LocalTime.class) not working withPostgres timetz type

От
Dave Cramer
Дата:
Not everyone agrees with WITH TIMEZONE qnd it doesn't help that the server does not store the timezone 

On Wed, Apr 17, 2019, 8:35 AM Philippe Marschall, <pm@netcetera.ch> wrote:
On 10.04.19 14:43, Mark Rotteveel wrote:
> On 9-4-2019 13:20, pm@netcetera.ch wrote:
>> On 06.04.19 19:40, Thomas Kellerer wrote:
>>> I think the driver should then support getObject(1,
>>> OffsetTime.class), shouldn't it?
>>
>> It was originally not implemented out of laziness, somewhat justified
>> by the fact that the documentation recommends against using the type
>> saying it's only present because of legacy and standards compliance
>> reasons.  From a functional point of view there is nothing wrong with
>> implementing it. Again, in practice it's hard to find a use for the type.
>>
>> Yes the type should be Types.TIME_WITH_TIMEZONE. However in #695 [2]
>> it was decided that following the JDBC specification would break
>> frameworks and it would be better to instead go against the JDBC
>> specification and instead having each framework implement driver
>> specific hacks.
>
> This decision will still mean that frameworks will have to implement
> driver-specific hacks though: That is those tools or frameworks that do
> follow the guidance of the JDBC 4.2 or higher specification and expect
> to be able to obtain the LocalXXX types here.
>
> If you declare that a column is Types.TIME(STAMP), then you should also
> be able to return java.time.LocalTime, java.time.LocalDateTime (and of
> course java.sql.Time/java.sql.Timestamp).
>
> Declaring Types.TIME(STAMP), but not supporting java.time.LocalXXX is in
> my opinion a worse 'violation' of the JDBC specification compared to
> declaring Types.TIME(STAMP) instead of Types.TIME(STAMP)_WITH_TIMEZONE.
> By saying you are Types.TIMESTAMP, you implicitly promise to deliver the
> type conversions defined in Appendix B of JDBC 4.3 (B.4/B.5). Supporting
> java.time.OffsetDateTime / java.time.OffsetTime on Types.TIME(STAMP) is
> then just a non-standard extension.
>
> That of course leaves the problem of ambiguity what local means in the
> context of a type with time zone information.

I agree with you. We should report _WITH_TIMEZONE as the type and
support Offset* types for the tz database types. For the non tz types we
support the Local* types and report Types accordingly.

This is a case were deviating from the standard with well defined
semantics just leads to more and more issues down the road.

Cheers
Philippe


Re: ResultSet.getObject(..., LocalTime.class) not working withPostgres timetz type

От
Philippe Marschall
Дата:
On 17.04.19 19:10, Dave Cramer wrote:
> Not everyone agrees with WITH TIMEZONE qnd it doesn't help that the 
> server does not store the timezone

It is my understanding the server converts to UTC when storing and 
returns UTC.

Cheers
Philippe



Re: ResultSet.getObject(..., LocalTime.class) not working withPostgres timetz type

От
Philippe Marschall
Дата:
On 17.04.19 19:10, Dave Cramer wrote:
> Not everyone agrees with WITH TIMEZONE qnd it doesn't help that the 
> server does not store the timezone

It is my understanding the server converts to UTC when storing and 
returns UTC.

Cheers
Philippe



Re: ResultSet.getObject(..., LocalTime.class) not working withPostgres timetz type

От
Dave Cramer
Дата:


On Thu, 18 Apr 2019 at 13:19, Philippe Marschall <pm@netcetera.ch> wrote:
On 17.04.19 19:10, Dave Cramer wrote:
> Not everyone agrees with WITH TIMEZONE qnd it doesn't help that the
> server does not store the timezone

It is my understanding the server converts to UTC when storing and
returns UTC.

Yes, so the problem becomes what Timezone should we convert it to ? The server timezone, or the client timezone?

There are some that say only use without timezone, others say with. Depends on your application

Dave Cramer

Re: ResultSet.getObject(..., LocalTime.class) not working withPostgres timetz type

От
Philippe Marschall
Дата:
On 19.04.19 15:36, Dave Cramer wrote:
> 
> 
> On Thu, 18 Apr 2019 at 13:19, Philippe Marschall <pm@netcetera.ch 
> <mailto:pm@netcetera.ch>> wrote:
> 
>     On 17.04.19 19:10, Dave Cramer wrote:
>      > Not everyone agrees with WITH TIMEZONE qnd it doesn't help that the
>      > server does not store the timezone
> 
>     It is my understanding the server converts to UTC when storing and
>     returns UTC.
> 
> 
> Yes, so the problem becomes what Timezone should we convert it to ? The 
> server timezone, or the client timezone?

I don't think we should do conversion. To me JDBC in an interface to the 
database, it exposes the database functionality, behavior and semantics. 
I personally expect JDBC to return what the database returns. If I want 
to have it converted to something else then I have to do that with the 
semantics I want.
Java 8 Date Time types allow us to do exactly this.

Cheers
Philippe