in reply to DBD::Pg placeholder problem

This really has nothing to do with Pg, and everything to do with SQL (and maybe DBI). I would avoid using the funky INSERT ... VALUES construct. Instead, you should name the columns that are to receive values, and associate the values you want to bind with the columns, via the insert into foo (a, b, c) values ('var_a', 'var_b) syntax. Something like:

my $sql1 = <<SQL_END; insert into t ( tstamp, message ) values ( current_timestamp, ? ) SQL_END

Creative use of whitespace lets you see at a glance which columns are bound to placeholders.

Secondly, as soon as placeholders come into play, don't use the do method. If it's a one-off, just interpolate the value of $var into the string, do that, and move on. (Just remember to quote $var beforehand ).

<update>I should elaborate on the above a bit more. Yes, using do+bind is useful, because it quotes (or defangs) the inputted values and thus guards you from SQL injection attacks. But you can always perform it yourself with the quote method. So you could execute the statement with:

$db->do( 'insert into t values ( current_timestamp, ' . $db->quote( $var1 ) . ' )' ) or die "SQL go boom " . $db->errstr;

This is much less make-work code. Tip 'o the hat to Corion for nudging me to clarify this point.</update>

If you've gone to the trouble of setting up a placeholder, it's because you want to run the statement more than once. In that case, prepare the statement up front, and then execute it as necessary.

my $sth = $db->prepare( $sql1 ) or die(...); ... $sth->execute( $var );

Finally, if you do wish to continue with the do/bind approach, you should note that the third parameter of do should be a reference to a hash. That's what both the docs and the error message are telling you. (Insert obligatory MJD maxim here).

update: Oops, no, I misread the docs. The third param is an array... but your error message talks about a hashref, which led me astray. Nevertheless, something weird is going on, so use the other INSERT form as suggested.

- another intruder with the mooring of the heat of the Perl

Replies are listed 'Best First'.
Re^2: DBD::Pg placeholder problem
by runrig (Abbot) on Aug 31, 2004 at 16:37 UTC
    ...as soon as placeholders come into play, don't use the do method.

    I would disagree with this, in some cases. First, I think the syntax is less ugly when using placeholders (just looking at your example), and second, for databases that support query caches (and cached query plans), using placeholders makes it more likely that your query will be found in the cache (though this second point does not apply to PostgreSQL, yet).

    But I'm also still curious as to why the OP's original code has a problem, and IMHO it would be worthwhile debugging it to make DBD::Pg a better module, if indeed it is a bug with that module. I tried to reproduce the problem myself (see above), but I couldn't see any problem, which makes me think it might be the version of DBD::Pg (in which case forget debugging, just upgrade).

    Oh, and the second argument to "do" is a hash reference, but it is rarely used, and so it is usually set to undef.

Re^2: DBD::Pg placeholder problem
by McMahon (Chaplain) on Aug 31, 2004 at 14:20 UTC
    Thanks grinder! (and Corion!)

    The elaboration makes good sense, the db->do and db->quote snippet above is working properly for me.

    Something weird was going on, but this snippet seems to skirt the problem nicely (whatever it was).

    This is my first experience with PostgreSQL and my first non-trivial use of DBI, so I'm feeling my way a bit.