File Coverage

blib/lib/Data/Phrasebook/SQL/Query.pm
Criterion Covered Total %
statement 99 103 96.1
branch 35 50 70.0
condition 8 12 66.6
subroutine 21 21 100.0
pod 10 10 100.0
total 173 196 88.2


line stmt bran cond sub pod time code
1             package Data::Phrasebook::SQL::Query;
2 6     6   5244 use strict;
  6         14  
  6         226  
3 6     6   32 use warnings FATAL => 'all';
  6         11  
  6         242  
4 6     6   30 use base qw( Data::Phrasebook::Debug );
  6         10  
  6         460  
5 6     6   33 use vars qw( $AUTOLOAD );
  6         12  
  6         244  
6 6     6   37 use Carp qw( croak );
  6         17  
  6         296  
7              
8 6     6   35 use vars qw($VERSION);
  6         11  
  6         6903  
9             $VERSION = '0.35';
10              
11             =head1 NAME
12              
13             Data::Phrasebook::SQL::Query - Query Extension to the SQL/DBI Phrasebook Model.
14              
15             =head1 SYNOPSIS
16              
17             my $q = $book->query( 'find_author' );
18             my $q = $book->query( 'find_author', 'Dictionary' );
19              
20             =head1 DESCRIPTION
21              
22             An extension to the SQL class to specifically handle the DBI interface for
23             each query requested.
24              
25             =head1 CONSTRUCTOR
26              
27             =head2 new
28              
29             Not to be accessed directly, but via the parent L, by
30             specifying the class as SQL.
31              
32             =head1 METHODS
33              
34             =head2 sql
35              
36             Get/set the current C statement, in a form suitable for passing
37             straight to DBI.
38              
39             =head2 sth
40              
41             Get/set the current statement handle.
42              
43             =head2 args
44              
45             Return list of arguments that will be used as bind parameters to any
46             placeholders. Any given arguments will replace the whole list.
47              
48             Returns list in list context, arrayref in scalar.
49              
50             =head2 order
51              
52             As for C, but regarding the corresponding list of argument
53             B.
54              
55             The assorted C methods are supported as for C.
56              
57             =head2 dbh
58              
59             Get/set the database handle.
60              
61             =cut
62              
63             sub new {
64 6     6 1 11 my $self = shift;
65 6         33 my %hash = @_;
66 6 50       30 $self->store(3,"$self->new IN") if($self->debug);
67 6         12 my $atts = \%hash;
68 6         16 bless $atts, $self;
69 6         20 return $atts;
70             }
71              
72             sub DESTROY {
73 6     6   537 my $self = shift;
74 6 50       16 $self->sth->finish if($self->sth);
75 6         262 return;
76             }
77              
78             sub sql {
79 10     10 1 660 my $self = shift;
80 10 100       42 return @_ ? $self->{sql} = shift : $self->{sql};
81             }
82             sub dbh {
83 9     9 1 918 my $self = shift;
84 9 100       68 return @_ ? $self->{dbh} = shift : $self->{dbh};
85             }
86             sub sth {
87 110     110 1 1265 my $self = shift;
88 110 100       409 return @_ ? $self->{sth} = shift : $self->{sth};
89             }
90             sub args {
91 18     18 1 23 my $self = shift;
92 18         27 my @args = @_;
93 18 100       41 $self->{args} = \@args if(@_);
94 18         43 return $self->{args};
95             }
96             sub order {
97 9     9 1 13 my $self = shift;
98 9         17 my @args = @_;
99 9 50       25 $self->{order} = \@args if(@_);
100 9 50       32 return @{$self->{order}} if($self->{order});
  9         29  
101 0         0 return ();
102             }
103              
104             =head1 PREPARATION / EXECUTING METHODS
105              
106             =head2 execute
107              
108             Executes the query. Returns the result of C.
109              
110             Any arguments are given to C with the return of that method
111             being used as arguments to C. If no arguments, uses those
112             already specified.
113              
114             Calls C if necessary.
115              
116             =cut
117              
118             sub execute {
119 10     10 1 1475 my $self = shift;
120 10 50       32 $self->store(3,"->execute IN: @_") if($self->debug);
121 10         25 my $sth = $self->sth;
122 10 100       36 my @args = @_ ? $self->order_args( @_ ) : ();
123 10 50 66     45 @args = () if(@args && !defined $args[0]);
124 10 100       27 $sth = $self->prepare() unless $sth;
125              
126 10 100       26 unless(@args) {
127 5         16 $self->rebind;
128 5         16 return $sth->execute();
129             }
130              
131 5 0       19 $self->store(4,"->execute args[".join(",",map {$_||'undef'} @args)."]") if($self->debug);
  0 50       0  
132 5         11 return $sth->execute( map { $$_ } @args );
  5         26  
133             }
134              
135             =head2 order_args
136              
137             Given a hash or hashref of keyword to value mappings, organises
138             an array of arguments suitable for use as bind parameters
139             in the order needed by the query itself.
140              
141             =cut
142              
143             sub order_args {
144 9     9 1 12 my $self = shift;
145 9 100       30 my %args = (@_ == 1 ? %{$_[0]} : @_);
  4         12  
146 9         30 my @order = $self->order;
147 9         29 my @args = $self->args;
148              
149 9         31 for (0..$#order)
150             {
151 9         15 my $key = $order[$_];
152 9 50       27 if (exists $args{ $key })
153             {
154 9         18 my $val = $args{ $key };
155 9 100       42 $args[$_] = (ref $val) ? $val : \$val;
156             }
157             }
158              
159 9         35 return @args;
160             }
161              
162             =head2 prepare
163              
164             Prepares the query for execution. This method is called
165             implicitly in most cases so you generally don't need
166             to know about it.
167              
168             =cut
169              
170             sub prepare {
171 8     8 1 2423 my $self = shift;
172 8 50       24 $self->store(3,"$self->prepare IN") if($self->debug);
173 8         23 my $sql = $self->sql;
174 8 50       23 $self->store(4,"$self->prepare sql=[$sql]") if($self->debug);
175 8 50       20 croak "Can't prepare without SQL" unless defined $sql;
176 8         26 my $sth = $self->dbh->prepare_cached( $sql );
177 7         87 $self->sth( $sth );
178 7         20 return $sth;
179             }
180              
181             =head2 rebind
182              
183             Rebinds any bound values. Lets one pass a scalar reference in
184             the arguments to C and have the bound value update
185             if the original scalar changes.
186              
187             This method is not needed externally to this class.
188              
189             =cut
190              
191             sub rebind {
192 5     5 1 8 my $self = shift;
193 5         10 my $sth = $self->sth;
194 5         12 my $args = $self->args;
195 5         8 for my $x (0..$#{$args})
  5         15  
196             {
197 5 50       15 $self->store(4,'->rebind param['.($x+1).','.(${ $args->[$x] }).']') if($self->debug);
  0         0  
198 5         10 $sth->bind_param( $x+1, ${ $args->[$x] } )
  5         31  
199             }
200 5         34 return;
201             }
202              
203             =head1 DELEGATED METHODS
204              
205             Any method not mentioned above is given to the statement
206             handle.
207              
208             All these delegations will implicitly call C.
209              
210             =cut
211              
212             # Currently the following is not true, but will be fixed at some point:
213             #
214             #Any C methods will additionally call C
215             #unless the statement handle is already active.
216              
217             sub _call_other {
218 68     68   127 my ($self, $execute, $method) = splice @_, 0, 3;
219 68   33     114 my $sth = $self->sth || $self->prepare();
220 68 100 100     263 $self->execute() if $execute and not $sth->{Active};
221 68         187 return $sth->$method( @_ );
222             }
223              
224             sub AUTOLOAD {
225 6     6   1272 my $self = shift;
226 6         48 my ($method) = $AUTOLOAD =~ /([^:]+)$/;
227             #print STDERR "\n#[$AUTOLOAD][$method]\n";
228 6   66     23 my $sth = $self->sth || $self->prepare();
229              
230 6 50       22 if ($sth->can($method))
231             {
232 6     6   36 no strict 'refs';
  6         10  
  6         832  
233 6 100       39 my $execute = $method =~ /^fetch/ ? 1 : 0 ;
234 6         22 *{$method} = sub {
235 68     68   2676 my $s = shift;
236 68         139 $s->_call_other( $execute, $method, @_ )
237 6         29 };
238 6         18 return $self->$method( @_ );
239             }
240 0           return;
241             }
242              
243             1;
244              
245             __END__