Author: timbo
Date: Wed May 9 13:18:11 2007
New Revision: 9537
Modified:
dbi/trunk/DBI.pm
dbi/trunk/lib/DBI/Gofer/Execute.pm
dbi/trunk/t/06attrs.t
Log:
Add FETCH_many method (currently undocumented)
Use it to simplify Gofer/Execute internals.
Now return all sth attribs even if undef - fixes potential bug with multi
resultsets
Modified: dbi/trunk/DBI.pm
==============================================================================
--- dbi/trunk/DBI.pm (original)
+++ dbi/trunk/DBI.pm Wed May 9 13:18:11 2007
@@ -373,6 +373,7 @@
'CLEAR' => $keeperr,
'EXISTS' => $keeperr,
'FETCH' => { O=>0x0404 },
+ 'FETCH_many' => { O=>0x0404 },
'FIRSTKEY' => $keeperr,
'NEXTKEY' => $keeperr,
'STORE' => { O=>0x0418 | 0x4 },
@@ -1322,6 +1323,11 @@
sub EXISTS { defined($_[0]->FETCH($_[1])) } # XXX undef?
sub CLEAR { Carp::carp "Can't CLEAR $_[0] (DBI)" }
+ sub FETCH_many { # should move to C one day
+ my $h = shift;
+ return map { $h->FETCH($_) } @_;
+ }
+
*dump_handle = \&DBI::dump_handle;
sub install_method {
Modified: dbi/trunk/lib/DBI/Gofer/Execute.pm
==============================================================================
--- dbi/trunk/lib/DBI/Gofer/Execute.pm (original)
+++ dbi/trunk/lib/DBI/Gofer/Execute.pm Wed May 9 13:18:11 2007
@@ -341,8 +341,7 @@
push @req_attr_names, @{ $self->_std_response_attribute_names($dbh) };
}
my %dbh_attr_values;
- # XXX a FETCH_many() method implemented in C would help here
- $dbh_attr_values{$_} = $dbh->FETCH($_) for @req_attr_names;
+ @[EMAIL PROTECTED] = $dbh->FETCH_many(@req_attr_names);
# XXX piggyback installed_methods onto dbh_attributes for now
$dbh_attr_values{dbi_installed_methods} = { DBI->installed_methods };
@@ -454,7 +453,7 @@
}
# XXX needs to be integrated with private_attribute_info() etc
if (my $dbh_attr = $extra_attr{$dbh->{Driver}{Name}}{dbh_after_sth}) {
- $dbh_attr_set->{$_} = $dbh->FETCH($_) for @$dbh_attr;
+ @[EMAIL PROTECTED] = $dbh->FETCH_many(@$dbh_attr);
}
$response->dbh_attributes($dbh_attr_set) if $dbh_attr_set &&
%$dbh_attr_set;
@@ -477,11 +476,12 @@
$sth_attr->{$_} = $sth_result_attr->{$_}
for keys %$sth_result_attr;
}
+ my @sth_attr = grep { $sth_attr->{$_} } keys %$sth_attr;
my $row_count = 0;
my $rs_list = [];
while (1) {
- my $rs = $self->fetch_result_set($sth, $sth_attr);
+ my $rs = $self->fetch_result_set($sth, [EMAIL PROTECTED]);
push @$rs_list, $rs;
if (my $rows = $rs->{rowset}) {
$row_count += @$rows;
@@ -503,24 +503,23 @@
sub fetch_result_set {
- my ($self, $sth, $extra_sth_attr) = @_;
+ my ($self, $sth, $sth_attr) = @_;
my %meta;
- while ( my ($attr,$use) = each %$extra_sth_attr ) {
- next unless $use;
- my $v = eval { $sth->FETCH($attr) };
- if (defined $v) {
- $meta{ $attr } = $v;
- }
- else {
- warn $@ if $@;
- }
- }
- my $NUM_OF_FIELDS = $meta{NUM_OF_FIELDS};
- $NUM_OF_FIELDS = $sth->FETCH('NUM_OF_FIELDS') unless defined
$NUM_OF_FIELDS;
- if ($NUM_OF_FIELDS) { # is a select
- $meta{rowset} = eval { $sth->fetchall_arrayref() };
- $meta{err} = $DBI::err;
- $meta{errstr} = $DBI::errstr;
+ eval {
+ @meta{ @$sth_attr } = $sth->FETCH_many(@$sth_attr);
+ # we assume @$sth_attr contains NUM_OF_FIELDS
+ $meta{rowset} = $sth->fetchall_arrayref()
+ if (($meta{NUM_OF_FIELDS}||0) > 0); # is SELECT
+ # the fetchall_arrayref may fail with a 'not executed' kind of error
+ # because gather_sth_resultsets/fetch_result_set are called even if
+ # execute() failed, or even if there was no execute() call at all.
+ # The corresponding error goes into the resultset err, not the
top-level
+ # response err, so in most cases this resultset err is never noticed.
+ };
+ if ($@) {
+ chomp $@;
+ $meta{err} = $DBI::err || 1;
+ $meta{errstr} = $DBI::errstr || $@;
$meta{state} = $DBI::state;
}
return \%meta;
Modified: dbi/trunk/t/06attrs.t
==============================================================================
--- dbi/trunk/t/06attrs.t (original)
+++ dbi/trunk/t/06attrs.t Wed May 9 13:18:11 2007
@@ -2,7 +2,7 @@
use strict;
-use Test::More tests => 144;
+use Test::More tests => 145;
## ----------------------------------------------------------------------------
## 06attrs.t - ...
@@ -74,6 +74,9 @@
cmp_ok($dbh->{TraceLevel}, '==', $DBI::dbi_debug & 0xF, '... checking
TraceLevel attribute for dbh');
cmp_ok($dbh->{LongReadLen}, '==', 80, '... checking
LongReadLen attribute for dbh');
+is_deeply [ $dbh->FETCH_many(qw(HandleError FetchHashKeyName LongReadLen
ErrCount)) ],
+ [ undef, qw(NAME 80 0) ], 'should be able to FETCH_many';
+
is $dbh->{examplep_private_dbh_attrib}, 42, 'should see driver-private dbh
attribute value';
# Raise an error.