To make a long story short, row_description, a field of
DBD::PgPP::Protocol (the internal connection handle)
really needs to live on DBD::PgPP::ProtocolStatement,
(the internal statement handle) instead.
Basically, whenever you have multiple select handles on the same
connection and you're fetching from both at the same time, the one
executed latest has its row_description applied to the earlier one
and data gets corrupted. But it's actually worse than that because the
row_description is also being applied to things that aren't even select
statements -- often harmlessly but sometimes not:
DB<1> $stmt=$dbh->prepare('SELECT * FROM EightColumnTable');
DB<2> p $stmt->execute
0E0
DB<3> p $stmt->{NUM_OF_FIELDS}
8
DB<4> $istmt=$dbh->prepare('INSERT into Whatever values(?,?,?)')
DB<5> p $istmt->execute(1,2,3);
1
DB<6> p $istmt->{NUM_OF_FIELDS}
8
## oops. but so far this is harmless, since nothing cares about
## the number of fields on INSERT statements. However, we continue...
DB<7> $stmt=$dbh->prepare('SELECT * FROM FourColumnTable');
DB<8> p $stmt->execute
1
DB<9> p $stmt->{NUM_OF_FIELDS}
4
DB<10> p $istmt->execute(1,3,2);
DBD::PgPP::st execute failed: NUM_OF_FIELDS already set to 8 at
C:/prgfiles/perl/site/lib/DBD/PgPP.pm line 454.
at (eval 63)[C:/prgfiles/perl/lib/perl5db.pl:628] line 2
eval '($@, $!, $^E, $,, $/, $\\, $^W) = @saved;package main; $^D = $^D
| $DB::db_stop;
print {$DB::OUT} $istmt->execute(1,3,2);;
;' called at C:/prgfiles/perl/lib/perl5db.pl line 628
DB::eval called at C:/prgfiles/perl/lib/perl5db.pl line 3410
DB::DB called at -e line 1
The error arises because it's trying to (pointlessly) set
NUM_OF_FIELDS on $istmt to 4
Here's an example of data corruption:
DB<1> $stmt=$dbh->prepare('SELECT varchar_column FROM t0');
DB<2> p $stmt->execute;
1
DB<3> x $stmt->fetch;
0 ARRAY(0x22c674c)
0 'T'
DB<4> $stmt1=$dbh->prepare('SELECT boolean_column FROM t1');
DB<5> p $stmt1->execute;
1
DB<6> x $stmt1->fetch;
0 ARRAY(0x22c6530)
0 1
DB<7> x $stmt->fetch;
0 ARRAY(0x22c674c)
0 1
In all fetches from $stmt from now on, any string not eq to 'f' will
gets converted to 1 while 'f' becomes 0, which is proper for a boolean
column, but the t0 column isn't boolean.
I've attached a patch that appears to fix things
Examples above were run on v5.8.7 MSWin32-x86-multi-thread (Active Perl
build 815), but I'm pretty sure that doesn't matter a whole lot.
Subject: | ppat.txt |
Message body not shown because it is not plain text.