home *** CD-ROM | disk | FTP | other *** search
/ PC Professionell 2004 December / PCpro_2004_12.ISO / files / webserver / xampp / xampp-perl-addon-1.4.9-installer.exe / ContextualFetch.pm < prev    next >
Encoding:
Perl POD Document  |  2004-03-15  |  5.8 KB  |  236 lines

  1. package DBIx::ContextualFetch;
  2.  
  3. $VERSION = '1.01';
  4.  
  5. use strict;
  6. use warnings;
  7.  
  8. use base 'DBI';
  9.  
  10. package DBIx::ContextualFetch::db;
  11. use base 'DBI::db';
  12.  
  13. package DBIx::ContextualFetch::st;
  14. use base 'DBI::st';
  15.  
  16. sub execute {
  17.     my ($sth) = shift;
  18.  
  19.     my $rv;
  20.  
  21.     # Allow $sth->execute(\@param, \@cols) and
  22.     # $sth->execute(undef, \@cols) syntax.
  23.     if (  @_ == 2
  24.         and (!defined $_[0] || ref $_[0] eq 'ARRAY')
  25.         and ref $_[1] eq 'ARRAY') {
  26.         my ($bind_params, $bind_cols) = @_;
  27.         $rv = $sth->_untaint_execute(@$bind_params);
  28.         $sth->SUPER::bind_columns(@$bind_cols);
  29.         } else {
  30.         $sth->_disallow_references(@_);
  31.         $rv = $sth->_untaint_execute(@_);
  32.     }
  33.     return $rv;
  34. }
  35.  
  36. sub _disallow_references {
  37.     my $self = shift;
  38.     foreach (@_) {
  39.         next unless ref $_;
  40.         next if overload::Method($_, q{""});
  41.         next if overload::Method($_, q{0+});
  42.         die "Cannot call execute with a reference ($_)\n";
  43.     }
  44. }
  45.  
  46. # local $sth->{Taint} leaks in old perls :(
  47. sub _untaint_execute {
  48.     my $sth = shift;
  49.     my $old_value = $sth->{Taint};
  50.     $sth->{Taint} = 0;
  51.     my $ret = $sth->SUPER::execute(@_);
  52.     $sth->{Taint} = $old_value;
  53.     return $ret;
  54. }
  55.  
  56. sub fetch {
  57.     my ($sth) = shift;
  58.     return wantarray
  59.         ? $sth->SUPER::fetchrow_array
  60.         : $sth->SUPER::fetchrow_arrayref;
  61. }
  62.  
  63. sub fetch_hash {
  64.     my ($sth) = shift;
  65.     my $row = $sth->SUPER::fetchrow_hashref;
  66.     return unless defined $row;
  67.     return wantarray ? %$row : $row;
  68. }
  69.  
  70. sub fetchall {
  71.     my ($sth) = shift;
  72.     my $rows = $sth->SUPER::fetchall_arrayref;
  73.     return wantarray ? @$rows : $rows;
  74. }
  75.  
  76. # There may be some code in DBI->fetchall_arrayref, but its undocumented.
  77. sub fetchall_hash {
  78.     my ($sth) = shift;
  79.     my (@rows, $row);
  80.     push @rows, $row while ($row = $sth->SUPER::fetchrow_hashref);
  81.     return wantarray ? @rows : \@rows;
  82. }
  83.  
  84. sub select_row {
  85.     my ($sth, @args) = @_;
  86.     $sth->execute(@args);
  87.     my @row = $sth->fetchrow_array;
  88.     $sth->finish;
  89.     return @row;
  90. }
  91.  
  92. sub select_col {
  93.     my ($sth, @args) = @_;
  94.     my (@row, $cur);
  95.     $sth->execute(@args);
  96.     $sth->bind_col(1, \$cur);
  97.     push @row, $cur while $sth->fetch;
  98.     $sth->finish;
  99.     return @row;
  100. }
  101.  
  102. sub select_val {
  103.     my ($sth, @args) = @_;
  104.     return ($sth->select_row(@args))[0];
  105. }
  106.  
  107. return 1;
  108.  
  109. __END__
  110.  
  111. =head1 NAME
  112.  
  113. DBIx::ContextualFetch - Add contextual fetches to DBI
  114.  
  115. =head1 SYNOPSIS
  116.  
  117.     my $dbh = DBI->connect(...., { RootClass => "DBIx::ContextualFetch" });
  118.  
  119.     # Modified statement handle methods.
  120.     my $rv = $sth->execute;
  121.     my $rv = $sth->execute(@bind_values);
  122.     my $rv = $sth->execute(\@bind_values, \@bind_cols);
  123.  
  124.     # In addition to the normal DBI sth methods...
  125.     my $row_ref = $sth->fetch;
  126.     my @row     = $sth->fetch;
  127.  
  128.     my $row_ref = $sth->fetch_hash;
  129.     my %row     = $sth->fetch_hash;
  130.  
  131.     my $rows_ref = $sth->fetchall;
  132.     my @rows     = $sth->fetchall;
  133.  
  134.     my $rows_ref = $sth->fetchall_hash;
  135.     my @tbl      = $sth->fetchall_hash;
  136.  
  137. =head1 DESCRIPTION
  138.  
  139. It always struck me odd that DBI didn't take much advantage of Perl's
  140. context sensitivity. DBIx::ContextualFetch redefines some of the various
  141. fetch methods to fix this oversight. It also adds a few new methods for
  142. convenience (though not necessarily efficiency).
  143.  
  144. =head1 SET-UP
  145.  
  146.     my $dbh = DBIx::ContextualFetch->connect(@info);
  147.     my $dbh = DBI->connect(@info, { RootClass => "DBIx::ContextualFetch" });
  148.  
  149. To use this method, you can either make sure that everywhere you normall
  150. call DBI->connect() you either call it on DBIx::ContextualFetch, or that
  151. you pass this as your RootClass. After this DBI will Do The Right Thing
  152. and pass all its calls through us.
  153.  
  154. =head1 EXTENSIONS
  155.  
  156. =head2 execute
  157.  
  158.     $rv = $sth->execute;
  159.     $rv = $sth->execute(@bind_values);
  160.     $rv = $sth->execute(\@bind_values, \@bind_cols);
  161.  
  162. execute() is enhanced slightly:
  163.  
  164. If called with no arguments, or with a simple list, execute() operates
  165. normally.  When when called with two array references, it performs
  166. the functions of bind_param, execute and bind_columns similar to the
  167. following:
  168.  
  169.     $sth->execute(@bind_values);
  170.     $sth->bind_columns(undef, @bind_cols);
  171.  
  172. In addition, execute will accept tainted @bind_values.  I can't think of
  173. what a malicious user could do with a tainted bind value (in the general
  174. case. Your application may vary.)
  175.  
  176. Thus a typical idiom would be:
  177.  
  178.     $sth->execute([$this, $that], [\($foo, $bar)]);
  179.  
  180. Of course, this method provides no way of passing bind attributes
  181. through to bind_param or bind_columns. If that is necessary, then you
  182. must perform the bind_param, execute, bind_col sequence yourself.
  183.  
  184. =head2 fetch
  185.  
  186.     $row_ref = $sth->fetch;
  187.     @row     = $sth->fetch;
  188.  
  189. A context sensitive version of fetch(). When in scalar context, it will
  190. act as fetchrow_arrayref. In list context it will use fetchrow_array.
  191.  
  192. =head2 fetch_hash
  193.  
  194.     $row_ref = $sth->fetch_hash;
  195.     %row     = $sth->fetch_hash;
  196.  
  197. A modification on fetchrow_hashref. When in scalar context, it acts just
  198. as fetchrow_hashref() does. In list context it returns the complete hash.
  199.  
  200. =head2 fetchall
  201.  
  202.     $rows_ref = $sth->fetchall;
  203.     @rows     = $sth->fetchall;
  204.  
  205. A modification on fetchall_arrayref. In scalar context it acts as
  206. fetchall_arrayref. In list it returns an array of references to rows
  207. fetched.
  208.  
  209. =head2 fetchall_hash
  210.  
  211.     $rows_ref = $sth->fetchall_hash;
  212.     @rows     = $sth->fetchall_hash;
  213.  
  214. A mating of fetchall_arrayref() with fetchrow_hashref(). It gets all rows
  215. from the hash, each as hash references. In scalar context it returns
  216. a reference to an array of hash references. In list context it returns
  217. a list of hash references.
  218.  
  219. =head1 ORIGINAL AUTHOR 
  220.  
  221. Michael G Schwern as part of Ima::DBI
  222.  
  223. =head1 CURRENT MAINTAINER
  224.  
  225. Tony Bowden <tony@tmtm.com>
  226.  
  227. =head1 LICENSE
  228.  
  229. This library is free software; you can redistribute it and/or modify
  230. it under the same terms as Perl itself.
  231.  
  232. =head1 SEE ALSO
  233.  
  234. L<DBI>. L<Ima::DBI>. L<Class::DBI>.
  235.  
  236.