Author: timbo
Date: Mon Mar 14 07:09:19 2005
New Revision: 926

Modified:
   dbi/trunk/DBI.pm
   dbi/trunk/t/11fetch.t
Log:
Initial commit of enhanced fetchall_hashref


Modified: dbi/trunk/DBI.pm
==============================================================================
--- dbi/trunk/DBI.pm    (original)
+++ dbi/trunk/DBI.pm    Mon Mar 14 07:09:19 2005
@@ -1942,23 +1942,32 @@
        return [EMAIL PROTECTED];
     }
 
-    sub fetchall_hashref {     # XXX may be better to fetchall_arrayref then 
convert to hashes
+    sub fetchall_hashref {
        my ($sth, $key_field) = @_;
 
-       my $hash_key_name = $sth->{FetchHashKeyName};
-       my $names_hash = $sth->FETCH("${hash_key_name}_hash");
-       my $index = $names_hash->{$key_field};  # perl index not column number
-       ++$index if defined $index;             # convert to column number
-       $index ||= $key_field if DBI::looks_like_number($key_field) && 
$key_field>=1;
-       return $sth->set_err(1, "Field '$key_field' does not exist (not one of 
@{[keys %$names_hash]})")
-               unless defined $index;
-       my $key_value;
-       $sth->bind_col($index, \$key_value) or return;
-       my %rows;
-       while (my $row = $sth->fetchrow_hashref($hash_key_name)) {
-           $rows{ $key_value } = $row;
-       }
-       return \%rows;
+        my $hash_key_name = $sth->{FetchHashKeyName} || 'NAME';
+        my $names_hash = $sth->FETCH("${hash_key_name}_hash");
+        my @key_fields = (ref $key_field) ? @$key_field : ($key_field);
+        my @key_indexes;
+        my $num_of_fields = $sth->FETCH('NUM_OF_FIELDS');
+        foreach (@key_fields) {
+           my $index = $names_hash->{$_};  # perl index not column
+           $index = $_ - 1 if !defined $index && DBI::looks_like_number($_) && 
$_>=1 && $_ <= $num_of_fields;
+           return $sth->set_err(1, "Field '$_' does not exist (not one of 
@{[keys %$names_hash]})")
+                unless defined $index;
+           push @key_indexes, $index;
+        }
+        my $rows = {};
+        my $NAME = $sth->FETCH($hash_key_name);
+        my @row;
+        push @row, undef for (1..$num_of_fields);
+        $sth->bind_columns(\(@row));
+        while ($sth->fetch) {
+            my $ref = $rows;
+            $ref = $ref->{$row[$_]} ||= {} for @key_indexes;
+            @[EMAIL PROTECTED] = @row;
+        }
+        return $rows;
     }
 
     *dump_results = \&DBI::dump_results;
@@ -3948,9 +3957,11 @@
 
 This utility method combines L</prepare>, L</execute> and
 L</fetchall_hashref> into a single call. It returns a reference to a
-hash containing one entry for each row. The key for each row entry is
-specified by $key_field. The value is a reference to a hash returned by
-C<fetchrow_hashref>.
+hash containing one entry, at most, for each row.  
+The C<$key_field> parameter can be the name of the key field for tables
+with a single column primary key, otherwise an array reference to the primary 
+key columns can be given. The value is a reference to a hash returned by
+C<fetchall_hashref>.
 
 The C<$statement> parameter can be a previously prepared statement handle,
 in which case the C<prepare> is skipped. This is recommended if the
@@ -5667,6 +5678,13 @@
 row is unique.  If multiple rows are returned with the same value for
 the key field then later rows overwrite earlier ones.
 
+For tables with a multiple columns primary key, an array reference 
+can be specified:
+
+  $sth = $dbh->prepare("SELECT date, account, revenue, profit FROM TABLE");
+  $sth->execute;
+  $hash_ref = $sth->fetchall_hashref([qw(date account)]);
+  print "Revenue for account 42 on 2005-02-18 is 
$hash_ref->{'2005-02-18'}{42}{revenue}\n";
 
 =item C<finish>
 

Modified: dbi/trunk/t/11fetch.t
==============================================================================
--- dbi/trunk/t/11fetch.t       (original)
+++ dbi/trunk/t/11fetch.t       Mon Mar 14 07:09:19 2005
@@ -41,7 +41,7 @@
 # etc etc
 
 # --- fetchall_hashref
-my @fetchall_hashref_results = (
+my @fetchall_hashref_results = (       # single keys
   C1 => {
     41  => { C1 => 41, C2 => 'BBB', C3 => 9 },
     42  => { C1 => 42, C2 => 'BBB', C3 => undef },
@@ -54,9 +54,29 @@
     DDD => { C1 => 44, C2 => 'DDD', C3 => 6 },
     ccc => { C1 => 43, C2 => 'ccc', C3 => 7 }
   },
-#  [ 'C1' ] => undef,
-#  [ 'C2' ] => undef,
-#  [ 'C1', 'C2' ] => undef,
+  [ 'C2' ] => {                                # single key within arrayref
+    AAA => { C1 => 41, C2 => 'AAA', C3 => 9 },
+    BBB => { C1 => 42, C2 => 'BBB', C3 => undef },
+    DDD => { C1 => 44, C2 => 'DDD', C3 => 6 },
+    ccc => { C1 => 43, C2 => 'ccc', C3 => 7 }
+  },
+);
+push @fetchall_hashref_results, (      # multiple keys
+  [ 'C1', 'C2' ] => {
+    '41' => {
+      AAA => { C1 => '41', C2 => 'AAA', C3 => 9 },
+      BBB => { C1 => '41', C2 => 'BBB', C3 => 9 }
+    },
+    '42' => {
+      BBB => { C1 => '42', C2 => 'BBB', C3 => undef }
+    },
+    '43' => {
+      ccc => { C1 => '43', C2 => 'ccc', C3 => 7 }
+    },
+    '44' => {
+      DDD => { C1 => '44', C2 => 'DDD', C3 => 6 }
+    }
+  },
 );
 
 while (my $keyfield = shift @fetchall_hashref_results) {

Reply via email to