Re: Bug with PreparedStatements using EXTRACT function

From: Maciek Sakrejda <msakrejda(at)truviso(dot)com>
To: Matthias Böhm <fliegenblues(at)gmx(dot)net>
Cc: pgsql-jdbc(at)postgresql(dot)org
Subject: Re: Bug with PreparedStatements using EXTRACT function
Date: 2012-03-30 19:38:14
Message-ID: CAH_hXRYdBdizWFZOpDNrsMyyRdsca+bxWBEz625AgPGgkDVddw@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-jdbc

I see--that attempt to be clever by the driver is actually the crux of
your problem. It's there to avoid issues like this (I'm in US/Pacific,
setting the time zone to US/Eastern for the test):

maciek(at)anemone:~/aux-git/pgjdbc$ cat no-tz.sql
set TimeZone to 'US/Eastern';
prepare s1(timestamp) as select extract(hour from $1);
execute s1('2012-01-01 12:00:00 +1:00');
maciek(at)anemone:~/aux-git/pgjdbc$ psql -f no-tz.sql
SET
PREPARE
date_part
-----------
12
(1 row)

maciek(at)anemone:~/aux-git/pgjdbc$ cat with-tz.sql
set TimeZone to 'US/Eastern';
prepare s1(timestamptz) as select extract(hour from $1);
execute s1('2012-01-01 12:00:00 +1:00');
maciek(at)anemone:~/aux-git/pgjdbc$ psql -f with-tz.sql
SET
PREPARE
date_part
-----------
6
(1 row)

>On the contrary, trying to prepare a statement with "SELECT EXTRACT (YEAR
>FROM DATE ?)" results, after calling toString on the prepared statement, in
>the following, seemingly correct query:
>
>SELECT EXTRACT (YEAR FROM DATE '1991-09-07 +02:00:00')
>
>But when I try to execute the query I get a "syntax error at $1".

Well, the toString() method is entirely client-side and it just
interpolates the stringified parameter values into the prepared
statement for display. Many drivers send that resulting string to the
server directly (the server doesn't see any parameters, just
literals), but the Postgres driver sends the original string with
parameter markers (well, munged to substitute JDBC-specific '?' with
Postgres-specific '$1', '$2', etc.) along with the actual parameter
values out of band. In theory, this is safer and faster (allowing
re-use of prepared plans). In practice it's great until it breaks down
in a case like yours ;)

That is, "date '2012-01-01'" is not a date literal by itself: again,
I'm not clear on the details of the grammar, but it's more like a
literal with a cast (e.g., you can do something like "select integer
'1'"). Because of that, you can't send that whole thing to the server
as a parameter value, because it's *only* expecting the value.

I'm not sure if there's a good solution to what you're seeing. If we
were starting from scratch, I'd push for ignoring timestamp entirely
in favor of the generally more sane timestamptz, but if we make that
change now, all sorts of subtle bugs will pop up (or rather, seep into
application interfaces unnoticed) for other users.

---
Maciek Sakrejda | System Architect | Truviso

1065 E. Hillsdale Blvd., Suite 215
Foster City, CA 94404
(650) 242-3500 Main
www.truviso.com

In response to

Browse pgsql-jdbc by date

  From Date Subject
Next Message Kevin Grittner 2012-04-02 16:16:44 Re: CVE DISPUTE notification: postgresql-jdbc: SQL injection due improper escaping of JDBC statement parameters
Previous Message Jan Lieskovsky 2012-03-30 12:28:02 CVE DISPUTE notification: postgresql-jdbc: SQL injection due improper escaping of JDBC statement parameters