rlucas.net: The Next Generation Rotating Header Image

[FIX] Perl DBI / DBD::Pg bind values rely on Perl's automatic numeric/string scalar conversion

Scenario: you are using DBD::Pg to interface with your database (perhaps directly through DBI, or through an abstraction layer like Class::DBI or DBIx::ContextualFetch) when you get an odd result:

DBD::Pg::st execute failed: ERROR: parser: parse error at or near [your string, or the part of your string that doesn't begin with leading digits] at …

or

DBD::Pg::db selectrow_array failed: ERROR: Attribute “yourstring” not found at …

If you look at the PostgreSQL query log, you'll see that “yourstring” was not properly quoted as a literal in the SQL delivered to the parser.

Since you've either been relying upon your abstraction layer or personally doing the Right Thing and binding your values with the “WHERE thing=? AND otherthing=?” syntax, you're quite confused — this should all be quoted.

The problem is that Perl has flagged that scalar as a numeric value, possibly because you used a numeric operator on it (like > or == instead of gt or eq). The solution is to upgrade to DBD::Pg 1.32 or to explicitly stringify your string as “$yourstring”.

Below is the bug filed with CPAN.

Mac OS X 10.2, Perl 5.6.0, DBD::Pg 1.22, DBI 1.45

Bind values appear to rely upon Perl's automatic numeric/string scalar conversion in order to determine whether or not to quote.

This bug was discussed on
http://aspn.activestate.com/ASPN/Mail/Message/perl-DBI-dev/1607287

my $dbh = DBI->connect(…); #connect to Postgres; no errors with SQLite
my $scalar = “abc”;
warn “scalar is greater than zero (and now considered numeric)” if $scalar > 0;
warn “dbh->quote(scalar) works ok: ” . $dbh->quote($scalar);
warn “but bind values do not:” . $dbh->selectrow_array(
“SELECT 1 WHERE 1=?”,
undef,
($scalar)
);

Using a numeric operator on the scalar makes Perl auto-convert it to a number; this is interpreted by the magic in Pg.xs as rendering the scalar ineligible for quoting.

One solution is to bind those variables that must be text but might have been numberified with “$varname”, thereby stringifying them in the eyes of Perl.

Leave a Reply

Your email address will not be published. Required fields are marked *