Skip to content

Commit

Permalink
Support binding native boolean false on 5.36 and newer
Browse files Browse the repository at this point in the history
Fixes #125
  • Loading branch information
ilmari committed Sep 27, 2024
1 parent 4504771 commit 58fa82b
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 8 deletions.
3 changes: 3 additions & 0 deletions Changes
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ Changes for the DBD::Pg module

RT refers to rt.cpan.org

- Support binding native boolean false on Perl 5.36 and newer
[Dagfinn Ilmari Mannsåker]

Version 3.18.0 (released December 6, 2023)

- Support new PQclosePrepared function, added in Postgres 17
Expand Down
7 changes: 7 additions & 0 deletions Pg.pm
Original file line number Diff line number Diff line change
Expand Up @@ -4455,6 +4455,13 @@ set the L<pg_bool_tf|/pg_bool_tf (boolean)> attribute to a true value to change
Boolean values can be passed to PostgreSQL as TRUE, 't', 'true', 'y', 'yes' or
'1' for true and FALSE, 'f', 'false', 'n', 'no' or '0' for false.
On Perl 5.36 and newer, distinguished boolean values (see
L<builtin/is_bool>) can be used as placeholder values. On older
versions of Perl, false values returned by built-in operators (such
as C<!!0>) must be converted to one of the above false values, or
bound with C<pg_type => PG_BOOL>, since they stringify to the empty
string.
=head2 Schema support
The PostgreSQL schema concept may differ from those of other databases. In a nutshell,
Expand Down
17 changes: 14 additions & 3 deletions dbdimp.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
#define atoll(X) _atoi64(X)
#endif

#ifndef SvIsBOOL
#define SvIsBOOL(sv) DBDPG_FALSE
#endif

#define DEBUG_LAST_RESULT 0

#if PGLIBVERSION < 80300
Expand Down Expand Up @@ -2625,9 +2629,16 @@ int dbd_bind_ph (SV * sth, imp_sth_t * imp_sth, SV * ph_name, SV * newvalue, IV
(void)SvUPGRADE(newvalue, SVt_PV);

if (SvOK(newvalue)) {
/* get the right encoding, without modifying the caller's copy */
newvalue = pg_rightgraded_sv(aTHX_ newvalue, imp_dbh->pg_utf8_flag && PG_BYTEA!=currph->bind_type->type_id);
value_string = SvPV(newvalue, currph->valuelen);
if (SvIsBOOL(newvalue)) {
/* bind native booleans as 1/0 */
value_string = SvTRUE(newvalue) ? "1" : "0";
currph->valuelen = 1;
}
else {
/* get the right encoding, without modifying the caller's copy */
newvalue = pg_rightgraded_sv(aTHX_ newvalue, imp_dbh->pg_utf8_flag && PG_BYTEA!=currph->bind_type->type_id);
value_string = SvPV(newvalue, currph->valuelen);
}
Renew(currph->value, currph->valuelen+1, char); /* freed in dbd_st_destroy */
Copy(value_string, currph->value, currph->valuelen+1, char);
currph->value[currph->valuelen] = '\0';
Expand Down
22 changes: 17 additions & 5 deletions t/12placeholders.t
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ my $dbh = connect_database();
if (! $dbh) {
plan skip_all => 'Connection to database failed, cannot continue testing';
}
plan tests => 261;
plan tests => 264;

my $t='Connect to database for placeholder testing';
isnt ($dbh, undef, $t);
Expand Down Expand Up @@ -819,6 +819,7 @@ undef => 'NULL',
'0e0' => 'TRUE',
'0 but true' => 'TRUE',
'0 BUT TRUE' => 'TRUE',
'real true' => 'TRUE',
'f' => 'FALSE',
'F' => 'FALSE',
0 => 'FALSE',
Expand All @@ -827,6 +828,7 @@ undef => 'NULL',
'false' => 'FALSE',
'FALSE' => 'FALSE',
'' => 'FALSE',
'real false' => 'FALSE',
12 => 'ERROR',
'01' => 'ERROR',
'00' => 'ERROR',
Expand All @@ -839,10 +841,12 @@ undef => 'NULL',
);

while (my ($name,$res) = each %booltest) {
$name = undef if $name eq 'undef';
$t = sprintf 'Boolean quoting of %s',
defined $name ? qq{"$name"} : 'undef';
eval { $result = $dbh->quote($name, {pg_type => PG_BOOL}); };
my ($bool, $desc) =
$name eq 'undef' ? (undef, $name) :
$name =~ /\Areal/ ? (!!($name =~ / true\z/), $name) :
($name, qq{"$name"});
$t = "Boolean quoting of $desc",
eval { $result = $dbh->quote($bool, {pg_type => PG_BOOL}); };
if ($@) {
if ($res eq 'ERROR' and $@ =~ /Invalid boolean/) {
pass ($t);
Expand Down Expand Up @@ -889,6 +893,14 @@ $dbh->{pg_bool_tf} = 1;
is_deeply ($sth->fetch, [104,'f'], $t);
$dbh->{pg_bool_tf} = 0;

SKIP: {
skip 'Cannot test native false without builtin::is_bool', 1 unless defined &builtin::is_bool;
$t = q{Inserting into a boolean column with native false works};
$sth = $dbh->prepare($SQL);
$sth->execute(105, !!0, 'Boolean native false');
is_deeply ($sth->fetch, [105, 0], $t);
}

## Test of placeholder escaping. Enabled by default, so let's jump right in
$t = q{Basic placeholder escaping works via backslash-question mark for \?};

Expand Down

0 comments on commit 58fa82b

Please sign in to comment.