I find this function useful and I'm tired of retyping it on
every project.
Sometimes I need to preserve the order from an ORDER BY or GROUP
BY clause, but I want to use selectall_arrayref for convenience.
Only then, I have to know the order of the field names.
This routine returns an arrayref of each row as returned by
fetchrow_hashref(). So each item in the array is a hash.
Makes it easy to do transformations like:
my $sql = q{ SELECT * FROM sites WHERE url like '%.org' };
my $dot_orgs = $dbh->selectall_arrayref_hashrefs( $sql );
if ($want_to_download_excel) {
my $uri = generate_chart( $dot_orgs );
forward_browser_to( $uri );
}
else {
# ***
print_autotable([
map { $_->{url} = make_link( $_->{url} ) } @{$dot_orgs}
]);
}
# make_link wraps the url in an <a href...>
Well, no one's under any obligation of course, just thought I'd see
what people think.
Mark Hedges
Index: DBI.pm
===================================================================
--- DBI.pm (revision 2322)
+++ DBI.pm (working copy)
@@ -31,6 +31,7 @@
$rv = $dbh->do($statement, \%attr, @bind_values);
$ary_ref = $dbh->selectall_arrayref($statement);
+ $ary_ref = $dbh->selectall_arrayref_hashrefs($statement);
$hash_ref = $dbh->selectall_hashref($statement, $key_field);
$ary_ref = $dbh->selectcol_arrayref($statement);
@@ -405,6 +406,7 @@
selectrow_arrayref=>{U =>[2,0,'$statement [, \%attr [, @bind_params ]
]'], O=>0x2000 },
selectrow_hashref=>{ U =>[2,0,'$statement [, \%attr [, @bind_params ]
]'], O=>0x2000 },
selectall_arrayref=>{U =>[2,0,'$statement [, \%attr [, @bind_params ]
]'], O=>0x2000 },
+ selectall_arrayref_hashrefs=>{U =>[2,0,'$statement [, \%attr [,
@bind_params ] ]'], O=>0x2000 },
selectall_hashref=>{ U =>[3,0,'$statement, $keyfield [, \%attr [,
@bind_params ] ]'], O=>0x2000 },
selectcol_arrayref=>{U =>[2,0,'$statement [, \%attr [, @bind_params ]
]'], O=>0x2000 },
ping => { U =>[1,1], O=>0x0404 },
@@ -1594,6 +1596,33 @@
return $rows;
}
+ # select an arrayref, but each row is hashref returned by fetchrow_hashref
+ sub selectall_arrayref_hashrefs {
+ my ($dbh, $stmt, $attr, @bind) = @_;
+ my $max_rows = delete $attr->{MaxRows};
+ my $sth = (ref $stmt) ? $stmt : $dbh->prepare($stmt, $attr);
+ return unless $sth;
+ $sth->execute(@bind) || return;
+ my @rows = undef;
+ if (defined $max_rows) {
+ @rows = (undef)x$max_rows;
+ ROW:
+ for (my $i = 0; $i <= $max_rows; $i++) {
+ $rows[$i] = $sth->fetchrow_hashref();
+ }
+ $sth->finish();
+ }
+ else {
+ @rows = ( );
+ while ( my $row = $sth->fetchrow_hashref() ) {
+ push @rows, $row;
+ }
+ }
+
+ return [EMAIL PROTECTED];
+ }
+
+
sub selectall_hashref {
my ($dbh, $stmt, $key_field, $attr, @bind) = @_;
my $sth = (ref $stmt) ? $stmt : $dbh->prepare($stmt, $attr);
@@ -4014,7 +4043,26 @@
In which case the array is copied and each value decremented before
passing to C</fetchall_arrayref>.
+=item C<selectall_arrayref_hashrefs>
+ $ary_ref = $dbh->selectall_arrayref_hashref($statement);
+ $ary_ref = $dbh->selectall_arrayref_hashref($statement, \%attr);
+ $ary_ref = $dbh->selectall_arrayref_hashref($statement, \%attr, @bind_vals);
+
+This utility method does L</prepare>, L</execute> and then returns
+an arrayref of each row of data fetched, but the contents of each array
+element is the result of L</fetchrow_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
+statement is going to be executed many times.
+
+L</selectall_arrayref_hashrefs>
+supports a $max_rows parameter. You can specify a value for $max_rows
+by including a 'C<MaxRows>' attribute in \%attr. In which case finish()
+is called for you.
+
+
=item C<selectall_hashref>
$hash_ref = $dbh->selectall_hashref($statement, $key_field);