Обсуждение: 7.3 -> 8.0.4 migration timestamp problem

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

7.3 -> 8.0.4 migration timestamp problem

От
Eliézer Madeira de Campos
Дата:
Hello everyone:

I'm currently working to migrate a database from PostgreSQL 7.3 to 8.0.4.
I have found the two issues below:

 1) Timestamp before 1914.
    When I execute the query by java statement no problem occurs, but when I execute the query
    by java preparedstatement this is what happens:

      PreparedStatement pst = con.prepareStatement("insert into teste values (?, ?, ?)");
      pst.setObject(1, new Integer(1));
      pst.setObject(2, "TESTE");
      Calendar c = new GregorianCalendar(1913, 0, 1, 0, 0, 0);
      Timestamp t = new Timestamp(c.getTimeInMillis());
      pst.setTimestamp(3, t);
      pst.executeUpdate();

    The date stored in database is actually 1912-12-31 23:53:12.0 (however it should have stored 1913-01-01.

    I have already debugged the Postgres-8.0 (build 313) driver and it seems to send the correct date to database.

This problem occurs both with Windows and Linux versions of PostgreSQL 8. There is a small difference in the actual
datestored, but in both systems it is not the date I'm trying to store. 

   2)
      Another problem is with functions like date_trunc and date_part that use a timestamp parameter.
      The problem ocurrs only with the java preparedstatment.

      Calendar c = new GregorianCalendar();
      Timestamp ts = new Timestamp(c.getTimeInMillis());
      pst = con.prepareStatement("select date_trunc('day', TIMESTAMP ?)");
      pst.setObject(1, ts);
      rs = pst.executeQuery();

      below the printstacktrace:

      Exception in thread "main" java.sql.SQLException: ERROR: syntax error at or near "$1"
   at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:1471)
   at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1256)
   at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:175)
   at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:392)
   at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:330)
   at org.postgresql.jdbc2.AbstractJdbc2Statement.executeQuery(AbstractJdbc2Statement.java:240)
   at teste.Teste3.main(Teste3.java:54)

This behaviour is exactly the same both in Windows and Linux.

Any ideas?

Eliézer M de Campos/Fernando Rubbo

Re: 7.3 -> 8.0.4 migration timestamp problem

От
Eliézer Madeira de Campos
Дата:


-----Original Message-----
From: Oliver Jowett [mailto:oliver@opencloud.com]
Sent: sexta-feira, 4 de novembro de 2005 20:20
To: Eliézer Madeira de Campos
Cc: pgsql-jdbc@postgresql.org
Subject: Re: [JDBC] 7.3 -> 8.0.4 migration timestamp problem

Eliézer Madeira de Campos wrote:

>>     The date stored in database is actually 1912-12-31 23:53:12.0 (however it should have stored 1913-01-01.
>>
>>     I have already debugged the Postgres-8.0 (build 313) driver and it seems to send the correct date to database.

> What type is the target column you are inserting into?
Timestamp without timezone.

>>       Timestamp ts = new Timestamp(c.getTimeInMillis());
>>       pst = con.prepareStatement("select date_trunc('day', TIMESTAMP ?)");
>>       pst.setObject(1, ts);

> Use "CAST (? AS TIMESTAMP)" instead of "TIMESTAMP ?".
Why should I, if "TIMESTAMP ?" works when I run the insert in psql (or via unprepared statement)?
That might be valid as a workaround, but it would cost me thousands changes in the application, so it's not really a
solutionto the problem. 

Eliézer M de Campos

Re: 7.3 -> 8.0.4 migration timestamp problem

От
Oliver Jowett
Дата:
Eliézer Madeira de Campos wrote:

>>>      Timestamp ts = new Timestamp(c.getTimeInMillis());
>>>      pst = con.prepareStatement("select date_trunc('day', TIMESTAMP ?)");
>>>      pst.setObject(1, ts);
>
>

>>Use "CAST (? AS TIMESTAMP)" instead of "TIMESTAMP ?".
>
> Why should I, if "TIMESTAMP ?" works when I run the insert in psql (or via unprepared statement)?

There are lots of other places where you can't blindly use '?'
placeholders -- for example, you can't use them where a column or table
name is expected. Prepared statements aren't just textual substitution.
The 8.0 driver's implementation uses protocol-level parameter binding
that is roughly equivalent to PREPARE/EXECUTE at the SQL level. Try that
same query via PREPARE in psql and you will see that it fails in the
same way.

> That might be valid as a workaround, but it would cost me thousands changes in the application, so it's not really a
solutionto the problem. 

You need to talk to the backend developers then -- it's a limitation of
the SQL grammar used by the backend.

As a workaround, set protocolVersion=2 as a URL parameter, but you will
lose other driver functionality if you do that (e.g. parameter
metadata), and the v2 protocol path will not stay around forever.

-O

Re: 7.3 -> 8.0.4 migration timestamp problem

От
Oliver Jowett
Дата:
Eliézer Madeira de Campos wrote:

>     The date stored in database is actually 1912-12-31 23:53:12.0 (however it should have stored 1913-01-01.
>
>     I have already debugged the Postgres-8.0 (build 313) driver and it seems to send the correct date to database.

What type is the target column you are inserting into?

>       Timestamp ts = new Timestamp(c.getTimeInMillis());
>       pst = con.prepareStatement("select date_trunc('day', TIMESTAMP ?)");
>       pst.setObject(1, ts);

Use "CAST (? AS TIMESTAMP)" instead of "TIMESTAMP ?".

-O


Re: 7.3 -> 8.0.4 migration timestamp problem

От
Oliver Jowett
Дата:
Eliézer Madeira de Campos wrote:

>  1) Timestamp before 1914.
>     When I execute the query by java statement no problem occurs, but when I execute the query
>     by java preparedstatement this is what happens:
>
>       PreparedStatement pst = con.prepareStatement("insert into teste values (?, ?, ?)");
>       pst.setObject(1, new Integer(1));
>       pst.setObject(2, "TESTE");
>       Calendar c = new GregorianCalendar(1913, 0, 1, 0, 0, 0);
>       Timestamp t = new Timestamp(c.getTimeInMillis());
>       pst.setTimestamp(3, t);
>       pst.executeUpdate();
>
>     The date stored in database is actually 1912-12-31 23:53:12.0 (however it should have stored 1913-01-01.
>
>     I have already debugged the Postgres-8.0 (build 313) driver and it seems to send the correct date to database.

I could not reproduce this problem using the attached testcase against
8.0.3 and the build 313 driver. I get the expected output:

> $ java -classpath .:postgresql-8.0-313.jdbc3.jar TestTimestamp6 'jdbc:postgresql:test?user=oliver'
> 1 => 1913-01-01 00:00:00.0 (literal '1913-01-01 00:00:00')

What are you doing differently? Perhaps the JVM and server timezone
settings are important, what are you using?

-O
import java.sql.*;
import java.util.*;
import java.text.*;

public class TestTimestamp6 {
    public static void main(String[] args) throws Exception {
        Class.forName("org.postgresql.Driver");

        Connection conn = DriverManager.getConnection(args[0]);
        Statement stmt = conn.createStatement();

        try {
            stmt.executeUpdate("DROP TABLE testtimestamp6");
        } catch (SQLException e) {}

        stmt.executeUpdate("CREATE TABLE testtimestamp6(index int4, datetime timestamp without time zone)");

        PreparedStatement pst = conn.prepareStatement("insert into testtimestamp6 values (?, ?)");
        pst.setObject(1, new Integer(1));
        Calendar c = new GregorianCalendar(1913, 0, 1, 0, 0, 0);
        Timestamp t = new Timestamp(c.getTimeInMillis());
        pst.setTimestamp(2, t);
        pst.executeUpdate();

        ResultSet rs = stmt.executeQuery("select * from testtimestamp6");
        while (rs.next()) {
            int index = rs.getInt(1);
            Timestamp ts = rs.getTimestamp(2);
            String ts_text = rs.getString(2);
            System.out.println(index + " => " + ts + " (literal '" + ts_text + "')");
        }
    }
}