This patch fixes the fact that DBD::mysql doesn't clear out the
sth attribute cache when switching between result sets, and doesn't
adjust NUM_OF_FIELDS.
Other driver authors please note the new 'official way' to adjust
NUM_OF_FIELDS, as per this patch. DBI >= 1.54 will now automatically
adjust the row buffer width when you adjust NUM_OF_FIELDS in this way.
(And it does it in a way that preserves column bindings.)
The patch also adds some tests to the test suite.
Tim.
diff -ru DBD-mysql-4.001/dbdimp.c DBD-mysql-4.001.gofer1/dbdimp.c
--- DBD-mysql-4.001/dbdimp.c 2007-01-08 00:39:05.000000000 +0000
+++ DBD-mysql-4.001.gofer1/dbdimp.c 2007-02-23 15:14:40.000000000 +0000
@@ -2785,6 +2785,7 @@
}
else
{
+ AV *av;
/* We have a new rowset */
imp_sth->currow=0;
@@ -2806,8 +2807,32 @@
mysql_affected_rows(svsock));
}
- /* Store the result in the current statement handle */
- DBIc_NUM_FIELDS(imp_sth)= mysql_num_fields(imp_sth->result);
+ /* delete cached handle attributes */
+ /* XXX should be driven by a list to ease maintenance */
+ hv_delete((HV*)SvRV(sth), "NAME", 4, G_DISCARD);
+ hv_delete((HV*)SvRV(sth), "NULLABLE", 8, G_DISCARD);
+ hv_delete((HV*)SvRV(sth), "NUM_OF_FIELDS", 13, G_DISCARD);
+ hv_delete((HV*)SvRV(sth), "PRECISION", 9, G_DISCARD);
+ hv_delete((HV*)SvRV(sth), "SCALE", 5, G_DISCARD);
+ hv_delete((HV*)SvRV(sth), "TYPE", 4, G_DISCARD);
+ hv_delete((HV*)SvRV(sth), "mysql_insertid", 14, G_DISCARD);
+ hv_delete((HV*)SvRV(sth), "mysql_is_auto_increment", 23, G_DISCARD);
+ hv_delete((HV*)SvRV(sth), "mysql_is_blob", 13, G_DISCARD);
+ hv_delete((HV*)SvRV(sth), "mysql_is_key", 12, G_DISCARD);
+ hv_delete((HV*)SvRV(sth), "mysql_is_num", 12, G_DISCARD);
+ hv_delete((HV*)SvRV(sth), "mysql_is_pri_key", 16, G_DISCARD);
+ hv_delete((HV*)SvRV(sth), "mysql_length", 12, G_DISCARD);
+ hv_delete((HV*)SvRV(sth), "mysql_max_length", 16, G_DISCARD);
+ hv_delete((HV*)SvRV(sth), "mysql_table", 11, G_DISCARD);
+ hv_delete((HV*)SvRV(sth), "mysql_type", 10, G_DISCARD);
+ hv_delete((HV*)SvRV(sth), "mysql_type_name", 15, G_DISCARD);
+
+ /* Adjust NUM_OF_FIELDS - which also adjusts the row buffer size */
+ DBIc_NUM_FIELDS(imp_sth)= 0; /* for DBI <= 1.53 */
+ DBIS->set_attr_k(sth, sv_2mortal(newSVpvn("NUM_OF_FIELDS",13)), 0,
+ sv_2mortal(newSViv(mysql_num_fields(imp_sth->result)))
+ );
+
DBIc_ACTIVE_on(imp_sth);
if (dbis->debug >= 5)
diff -ru DBD-mysql-4.001/t/80procs.t DBD-mysql-4.001.gofer1/t/80procs.t
--- DBD-mysql-4.001/t/80procs.t 2006-12-24 13:35:46.000000000 +0000
+++ DBD-mysql-4.001.gofer1/t/80procs.t 2007-02-23 15:10:14.000000000 +0000
@@ -113,6 +113,8 @@
Test($state or $sth->execute()) or
DbiError($dbh->err, $dbh->errstr);
+ $sth->finish;
+
my $proc_select = 'SELECT @a';
Test($state or $sth = $dbh->prepare($proc_select)) or
DbiError($dbh->err, $dbh->errstr);
@@ -120,6 +122,8 @@
Test($state or $sth->execute()) or
DbiError($dbh->err, $dbh->errstr);
+ $sth->finish;
+
Test($state or ($sth=$dbh->prepare("DROP PROCEDURE testproc"))) or
DbiError($dbh->err, $dbh->errstr);
@@ -148,6 +152,9 @@
my $dataset;
+ Test($state or ($sth->{NUM_OF_FIELDS} == 1)) or
+ DbiError($dbh->err, $dbh->errstr);
+
Test($state or $dataset = $sth->fetchrow_arrayref()) or
DbiError($dbh->err, $dbh->errstr);
@@ -159,6 +166,9 @@
Test($state or $more_results = $sth->more_results()) or
DbiError($dbh->err, $dbh->errstr);
+ Test($state or ($sth->{NUM_OF_FIELDS} == 2)) or
+ DbiError($dbh->err, $dbh->errstr);
+
Test($state or $dataset = $sth->fetchrow_arrayref()) or
DbiError($dbh->err, $dbh->errstr);
@@ -168,6 +178,9 @@
Test($state or $more_results = $sth->more_results()) or
DbiError($dbh->err, $dbh->errstr);
+ Test($state or ($sth->{NUM_OF_FIELDS} == 3)) or
+ DbiError($dbh->err, $dbh->errstr);
+
Test($state or $dataset = $sth->fetchrow_arrayref()) or
DbiError($dbh->err, $dbh->errstr);
@@ -177,7 +190,7 @@
Test($state or !($more_results = $sth->more_results())) or
DbiError($dbh->err, $dbh->errstr);
- $SIG{__WARN__} = sub { die @_ };
+ local $SIG{__WARN__} = sub { die @_ };
Test($state or $dbh->disconnect()) or
DbiError($dbh->err, $dbh->errstr);
diff -ru DBD-mysql-4.001/t/lib.pl DBD-mysql-4.001.gofer1/t/lib.pl
--- DBD-mysql-4.001/t/lib.pl 2006-12-23 18:03:30.000000000 +0000
+++ DBD-mysql-4.001.gofer1/t/lib.pl 2007-02-23 15:06:52.000000000 +0000
@@ -11,6 +11,7 @@
use strict;
use vars qw($mdriver $dbdriver $childPid $test_dsn $test_user $test_password);
+$| = 1; # flush stdout asap to keep in sync with stderr
#
# Driver names; EDIT THIS!
@@ -166,7 +167,8 @@
print "ok $::numTests\n";
return 1;
} else {
- printf("not ok $::numTests%s\n",
+ my ($pack, $file, $line) = caller();
+ printf("not ok $::numTests%s at line $line\n",
(defined($error) ? " $error" : ""));
return 0;
}
Only in DBD-mysql-4.001.gofer1: x
Only in DBD-mysql-4.001.gofer1: {mysql_errno}