Committed by Greg Sabino Mullane <[email protected]>
Subject: [DBD::Pg 3/6] Per report, fix problem with undefined elements in an
array being passed as arguments.
Lesson here: av_fetch cannot be trusted, always test it first!
Also added a failing (but now passing) test.
---
dbdimp.c | 56 +++++++++++++++++++++++++++++++++++---------------------
t/03dbmethod.t | 18 ++++++++++++++++--
2 files changed, 51 insertions(+), 23 deletions(-)
diff --git a/dbdimp.c b/dbdimp.c
index 1931f25..175ed97 100644
--- a/dbdimp.c
+++ b/dbdimp.c
@@ -2463,7 +2463,16 @@ SV * pg_stringify_array(SV *input, const char *
array_delim, int server_version)
done = 0;
currarr = lastarr = toparr;
+
+ /* We want to walk through to find out the depth */
while (!done) {
+
+ /* If we come across a null, we are done */
+ if (! av_exists(currarr, 0)) {
+ done = 1;
+ break;
+ }
+
/* Grab the first item of the current array */
svitem = *av_fetch(currarr, 0, 0);
@@ -2509,30 +2518,35 @@ SV * pg_stringify_array(SV *input, const char *
array_delim, int server_version)
sv_catpv(value, "{");
}
for (yz=0; yz < array_items; yz++) {
- svitem = *av_fetch(currarr, yz, 0);
-
- if (SvROK(svitem))
- croak("Arrays must contain only scalars and
other arrays");
-
- if (!SvOK(svitem)) { /* Insert NULL if we can */
- /* Only version 8.2 and up can handle NULLs in
arrays */
- if (server_version < 80200)
- croak("Cannot use NULLs in arrays until
version 8.2");
- sv_catpv(value, "NULL"); /* Beware of
array_nulls config param! */
+ if (! av_exists(currarr, yz)) {
+ sv_catpv(value, "NULL");
}
else {
- sv_catpv(value, "\"");
- if (SvUTF8(svitem))
- SvUTF8_on(value);
- string = SvPV(svitem, stringlength);
- while (stringlength--) {
- /* Escape backslashes and
double-quotes. */
- if ('\"' == *string || '\\' == *string)
- sv_catpvn(value, "\\", 1);
- sv_catpvn(value, string, 1);
- string++;
+ svitem = *av_fetch(currarr, yz, 0);
+
+ if (SvROK(svitem))
+ croak("Arrays must contain only scalars
and other arrays");
+
+ if (!SvOK(svitem)) { /* Insert NULL if we can */
+ /* Only version 8.2 and up can handle
NULLs in arrays */
+ if (server_version < 80200)
+ croak("Cannot use NULLs in
arrays until version 8.2");
+ sv_catpv(value, "NULL"); /* Beware of
array_nulls config param! */
+ }
+ else {
+ sv_catpv(value, "\"");
+ if (SvUTF8(svitem))
+ SvUTF8_on(value);
+ string = SvPV(svitem, stringlength);
+ while (stringlength--) {
+ /* Escape backslashes and
double-quotes. */
+ if ('\"' == *string || '\\' ==
*string)
+ sv_catpvn(value, "\\",
1);
+ sv_catpvn(value, string, 1);
+ string++;
+ }
+ sv_catpv(value, "\"");
}
- sv_catpv(value, "\"");
}
if (yz < array_items-1)
diff --git a/t/03dbmethod.t b/t/03dbmethod.t
index 6f35e1b..9bcb2ba 100644
--- a/t/03dbmethod.t
+++ b/t/03dbmethod.t
@@ -26,7 +26,7 @@ my $dbh = connect_database();
if (! $dbh) {
plan skip_all => 'Connection to database failed, cannot continue
testing';
}
-plan tests => 532;
+plan tests => 534;
isnt ($dbh, undef, 'Connect to database for database handle method testing');
@@ -103,12 +103,26 @@ eval {
};
like ($@, qr{last_insert_id}, $t);
-$t='DB handle method "do()" returns correct count with CREATE AS SELECT';
+$t='DB handle method "do" returns correct count with CREATE AS SELECT';
$dbh->rollback();
$result = $dbh->do('CREATE TEMP TABLE foobar AS SELECT * FROM pg_class LIMIT
3');
$expected = $pgversion >= 90000 ? 3 : '0E0';
is ($result, $expected, $t);
+$t='DB handle method "do" works properly with passed-in array with undefined
entries';
+$dbh->rollback();
+$dbh->do('CREATE TEMP TABLE foobar (id INT, p TEXT[])');
+my @aa;
+$aa[2] = 'asasa';
+eval {
+ $dbh->do('INSERT INTO foobar (p) VALUES (?)', undef, \@aa);
+};
+is ($@, q{}, $t);
+
+$SQL = 'SELECT * FROM foobar';
+$result = $dbh->selectall_arrayref($SQL)->[0];
+is_deeply ($result, [undef,[undef,undef,'asasa']], $t);
+
$t='DB handle method "last_insert_id" works when given a valid sequence and an
invalid table';
$dbh->rollback();
eval {
--
1.7.1