Author: mjevans
Date: Wed Apr 18 10:53:08 2012
New Revision: 15272

Modified:
   dbi/trunk/Changes
   dbi/trunk/DBI.pm

Log:
rt76520 - Optimize fetchall_arrayref with hash slice


Modified: dbi/trunk/Changes
==============================================================================
--- dbi/trunk/Changes   (original)
+++ dbi/trunk/Changes   Wed Apr 18 10:53:08 2012
@@ -6,6 +6,11 @@
 
 =cut
 
+CHANGES SINCE LAST RELEASE (not sure if they will go in 1.619):
+
+  RT76520 - Optimize fetchall_arrayref with hash slice thanks
+    to Dagfinn Ilmari Manns�ker
+
 =head2 Changes in DBI 1.619-TRIAL (svn r15271) 18th April 2012
 
   Further method dispatch optimizations thanks to Dave Mitchell.

Modified: dbi/trunk/DBI.pm
==============================================================================
--- dbi/trunk/DBI.pm    (original)
+++ dbi/trunk/DBI.pm    Wed Apr 18 10:53:08 2012
@@ -2029,29 +2029,20 @@
        }
        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;
@@ -6401,15 +6392,14 @@
 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:
 

Reply via email to