Skip Menu |

This queue is for tickets about the DBD-Pg CPAN distribution.

Report information
The Basics
Id: 110800
Status: rejected
Priority: 0/
Queue: DBD-Pg

People
Owner: Nobody in particular
Requestors: KAMELKEV [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: (no value)
Fixed in: (no value)



Subject: Queries containing intervals of format "INTERVAL 'X period'" fail when pg_server_prepare is enabled
Discovered an unusual bug with DBI after recently doing some updates. Basically a common query just completely fails. It's not immediately clear why, but it's easy to reproduce. We use Postgres (9.4.5), running under FreeBSD (9.3), with recent versions of nearly every library that is part of our stack, DBI included (1.634). The issue occurs both when a database is either in UTF8 or SQL_ASCII. The failing queries use the "INTERVAL 'X period'" format, along the lines of: "SELECT now() > now() - INTERVAL '1 day'" Upon updating our system we started receiving syntax errors like: "ERROR: syntax error at or near "$1" LINE 1: SELECT now() > now() - INTERVAL $1 ^" I found this to be very unusual, as the query executes fine from the Postgres CLI, and the alternative formats such as "::interval" and "CAST(X as INTERVAL)" both work as well. Only the format above fails. I've since rewritten our failing queries to use an alternative format, but ideally we can get this fixed. It's not clear what sort of materials are necessary to resolve a bug like this, please let me know and I can provide those details. In addition I have attached a basic script which reproduces the issue.
Subject: dbi.pl
#!/usr/bin/perl use warnings; use strict; use DBI; my $username = ''; my $password = ''; my $host = ''; my $dbname = ''; my $datasource = "dbi:Pg:dbname=$dbname;host=$host;port=5432;"; my $dbh = DBI->connect($datasource, $username, $password, { PrintError => 0 }) or die 'dbi connect failure: ' . $DBI::errstr; my $sth0 = $dbh->prepare('SELECT now() > now() - ?::interval'); $sth0->execute('1 day') or die $dbh->errstr(); print "Result of 'SELECT now() > now() - ?::interval' = " . $sth0->fetchrow() . "\n"; my $sth1 = $dbh->prepare('SELECT now() > now() - INTERVAL ?'); $sth1->execute('1 day') or die $dbh->errstr(); print "Result of 'SELECT now() > now() - ?::interval' = " . $sth1->fetchrow() . "\n";
Thanks for the report. I've moved to the DBD::Pg queue.
I simplified the test a bit, see the following attachment. I didn't realize an interval can exist standalone, so I've updated them to only query the interval without any associated operations.
Subject: dbi2.pl
#!/usr/bin/perl use warnings; use strict; use DBI; my $username = ''; my $password = ''; my $host = ''; my $dbname = ''; my $datasource = "dbi:Pg:dbname=$dbname;host=$host;port=5432;"; my $dbh = DBI->connect($datasource, $username, $password, { PrintError => 0 }) or die 'dbi connect failure: ' . $DBI::errstr; print "Result of 'SELECT ?::interval' = \n"; my $sth0 = $dbh->prepare('SELECT ?::interval'); $sth0->execute('1 day') or die $dbh->errstr(); print $sth0->fetchrow() . "\n"; print "Result of 'SELECT INTERVAL ?' = \n"; my $sth1 = $dbh->prepare('SELECT INTERVAL ?'); $sth1->execute('1 day') or die $dbh->errstr(); print $sth1->fetchrow() . "\n";
It was suggested by a coworker that this might actually be a bug with Postgres having a bug, or possibly correcting an earlier bug relating to sql syntax. To that end I experimented a bit. For the '::interval' case: vkmlm=> PREPARE test (text) AS SELECT ($1::interval); PREPARE vkmlm=> EXECUTE test('1 day'); ?column? ---------- 1 day (1 row) For the 'INTERVAL X' case: vkmlm=> PREPARE test2 (text) AS SELECT (INTERVAL $1); ERROR: syntax error at or near "$1" Note that the above is literally what my test is providing to DBI/DBD::Pg. The following prepares correctly, but generates the wrong result, which jives with what the Postgres documentation indicates for a query formatted this way: vkmlm=> PREPARE test3 (text) AS SELECT (INTERVAL '$1'); PREPARE vkmlm=> EXECUTE test3('1 day'); interval ---------- 00:00:01 (1 row) Finally there is this format, which works, but is not really what I was looking to do: vkmlm=> prepare test4 (text) as select (INTERVAL '$1' DAY); PREPARE vkmlm=> execute test4('1'); interval ---------- 1 day (1 row) So in this particular case I think that the suggestion that Postgres has fixed a bug is the most likely explanation why this query, which has literally worked for years in production, suddenly stopped working. If so then we can close this ticket out as invalid. I'd love to hear some other opinions here though.
Considering this issue resolved. The query is simply not compatible with server side prepared transactions. The only explanation is user error on my side, which I accept. On Wed Jan 06 18:30:29 2016, KAMELKEV wrote: Show quoted text
> It was suggested by a coworker that this might actually be a bug with > Postgres having a bug, or possibly correcting an earlier bug relating > to sql syntax. > > To that end I experimented a bit. For the '::interval' case: > > vkmlm=> PREPARE test (text) AS SELECT ($1::interval); > PREPARE > vkmlm=> EXECUTE test('1 day'); > ?column? > ---------- > 1 day > (1 row) > > For the 'INTERVAL X' case: > > vkmlm=> PREPARE test2 (text) AS SELECT (INTERVAL $1); > ERROR: syntax error at or near "$1" > > Note that the above is literally what my test is providing to > DBI/DBD::Pg. > > The following prepares correctly, but generates the wrong result, > which jives with what the Postgres documentation indicates for a query > formatted this way: > > vkmlm=> PREPARE test3 (text) AS SELECT (INTERVAL '$1'); > PREPARE > vkmlm=> EXECUTE test3('1 day'); > interval > ---------- > 00:00:01 > (1 row) > > > Finally there is this format, which works, but is not really what I > was looking to do: > > vkmlm=> prepare test4 (text) as select (INTERVAL '$1' DAY); > PREPARE > vkmlm=> execute test4('1'); > interval > ---------- > 1 day > (1 row) > > So in this particular case I think that the suggestion that Postgres > has fixed a bug is the most likely explanation why this query, which > has literally worked for years in production, suddenly stopped > working. > > If so then we can close this ticket out as invalid. I'd love to hear > some other opinions here though.