Skip Menu |

This queue is for tickets about the DBI CPAN distribution.

Report information
The Basics
Id: 76520
Status: resolved
Priority: 0/
Queue: DBI

People
Owner: Nobody in particular
Requestors: ilmari [...] ilmari.org
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: (no value)
Fixed in: 1.619



Subject: [PATCH] Optimize fetchall_arrayref with hash slice
Date: Thu, 12 Apr 2012 23:16:22 +0100
To: bug-DBI [...] rt.cpan.org
From: Dagfinn Ilmari Mannsåker <ilmari [...] ilmari.org>
Bind the sliced columns to an existing hash and copy that into the return array, rather than calling fetchrow_hashref and building a new hash each time. --- DBI.pm | 25 ++++++++----------------- 1 files changed, 8 insertions(+), 17 deletions(-) diff --git a/DBI.pm b/DBI.pm index 035087a..9b5fc0b 100644 --- a/DBI.pm +++ b/DBI.pm @@ -2031,29 +2031,20 @@ sub _new_sth { # called by DBD::<drivername>::db::prepare) } elsif ($mode eq 'HASH') { $max_rows = -1 unless defined $max_rows; - # XXX both these could be made faster (and unified) by pre-binding - # a local hash using bind_columns and then copying it per row, so - # we'd be able to replace the expensive fetchrow_hashref with - # fetchrow_arrayref. So the main loop would end up being like: - # push @rows, { %bound_hash } - # while ($max_rows-- and $sth->fetchrow_arrayref); - # XXX Also, it would be very helpful for DBIx::Class and others + # XXX It would be very helpful for DBIx::Class and others # if a slice could 'rename' columns. Some kind of 'renaming slice' # could be incorporated here. + my %row; if (keys %$slice) { - my @o_keys = keys %$slice; - my @i_keys = map { lc } keys %$slice; - while ($max_rows-- and $row = $sth->fetchrow_hashref('NAME_lc')) { - my %hash; - @hash{@o_keys} = @{$row}{@i_keys}; - push @rows, \%hash; - } + my %map = map { lc($_) => $_ } keys %$slice; + $sth->bind_columns( map { exists $map{$_} ? \$row{$map{$_}} : \do { my $dummy } } @{$sth->FETCH('NAME_lc')} ); } else { - # XXX assumes new ref each fetchhash - push @rows, $row - while ($max_rows-- and $row = $sth->fetchrow_hashref()); + $sth->bind_columns( \( @row{ @{$sth->FETCH($sth->FETCH('FetchHashKeyName')) } } ) ); } + push @rows, { %row } + while ($max_rows-- and $sth->fetch); + } else { Carp::croak("fetchall_arrayref($mode) invalid") } return \@rows; -- 1.7.5.4
Subject: [[rt.cpan.org #76520]] Don't mention fetchrow_hashref in fetchall_arrayref docs
Date: Sun, 15 Apr 2012 14:55:47 +0100
To: bug-DBI [...] rt.cpan.org
From: Dagfinn Ilmari Mannsåker <ilmari [...] ilmari.org>
It's a implementation detail, and is no longer correct. --- DBI.pm | 17 ++++++++--------- 1 files changed, 8 insertions(+), 9 deletions(-) diff --git a/DBI.pm b/DBI.pm index 9b5fc0b..c0325ae 100644 --- a/DBI.pm +++ b/DBI.pm @@ -6394,15 +6394,14 @@ start at 1). With no parameters, or if $slice is undefined, C<fetchall_arrayref> acts as if passed an empty array ref. -If $slice is a hash reference, C<fetchall_arrayref> uses L</fetchrow_hashref> -to fetch each row as a hash reference. If the $slice hash is empty then -fetchrow_hashref() is simply called in a tight loop and the keys in the hashes -have whatever name lettercase is returned by default from fetchrow_hashref. -(See L</FetchHashKeyName> attribute.) If the $slice hash is not -empty, then it is used as a slice to select individual columns by -name. The values of the hash should be set to 1. The key names -of the returned hashes match the letter case of the names in the -parameter hash, regardless of the L</FetchHashKeyName> attribute. +If $slice is a hash reference, C<fetchall_arrayref> fetches each row as +a hash reference. If the $slice hash is empty then the keys in the +hashes have whatever name lettercase is returned by default. (See +L</FetchHashKeyName> attribute.) If the $slice hash is not empty, then +it is used as a slice to select individual columns by name. The values +of the hash should be set to 1. The key names of the returned hashes +match the letter case of the names in the parameter hash, regardless of +the L</FetchHashKeyName> attribute. For example, to fetch just the first column of every row: -- 1.7.5.4
Wonderful. Many thanks! Will be applied soon for the next release.
Patch applied to subversion trunk. Please check you credit (name) in the Change file and your other patch is to follow so you might want to hold off until I apply that too. Thanks Martin -- Martin J. Evans Wetherby, UK