File Coverage

blib/lib/DBIx/DWIW.pm
Criterion Covered Total %
statement 26 625 4.1
branch 0 342 0.0
condition 0 77 0.0
subroutine 9 58 15.5
pod 38 39 97.4
total 73 1141 6.4


line stmt bran cond sub pod time code
1             package DBIx::DWIW;
2              
3 1     1   10262 use 5.005;
  1         3  
  1         43  
4 1     1   5 use strict;
  1         2  
  1         32  
5 1     1   3921 use DBI;
  1         26855  
  1         77  
6 1     1   12 use Carp;
  1         2  
  1         67  
7 1     1   1124 use Sys::Hostname; ## for reporting errors
  1         1733  
  1         59  
8 1     1   8080 use Time::HiRes; ## for fast timeouts
  1         2197  
  1         5  
9              
10             our $VERSION = '0.50';
11             our $SAFE = 1;
12              
13             =head1 NAME
14              
15             DBIx::DWIW - Robust and simple DBI wrapper to Do What I Want (DWIW)
16              
17             =head1 SYNOPSIS
18              
19             When used directly:
20              
21             use DBIx::DWIW;
22              
23             my $db = DBIx::DWIW->Connect(DB => $database,
24             User => $user,
25             Pass => $password,
26             Host => $host);
27              
28             my @records = $db->Array("select * from foo");
29              
30             When sub-classed for full functionality:
31              
32             use MyDBI; # class inherits from DBIx::DWIW
33              
34             my $db = MyDBI->Connect('somedb') or die;
35              
36             my @records = $db->Hashes("SELECT * FROM foo ORDER BY bar");
37              
38             =head1 DESCRIPTION
39              
40             NOTE: This module is currently specific to MySQL, but needn't be. We just
41             haven't had a need to talk to any other database server.
42              
43             DBIx::DWIW was developed (over the course of roughly 1.5 years) in Yahoo!
44             Finance (http://finance.yahoo.com/) to suit our needs. Parts of the API may
45             not make sense and the documentation may be lacking in some areas. We've
46             been using it for so long (in one form or another) that these may not be
47             readily obvious to us, so feel free to point that out. There's a reason the
48             version number is currently < 1.0.
49              
50             This module was B extracted from Yahoo-specific code, so things
51             may be a little strange yet while we smooth out any bumps and blemishes
52             left over form that.
53              
54             DBIx::DWIW is B. Doing so gives you all the
55             benefits it can provide and the ability to easily customize some of its
56             features. You can, of course, use it directly if it meets your needs as-is.
57             But you'll be accepting its default behavior in some cases where it may not
58             be wise to do so.
59              
60             The DBIx::DWIW distribution comes with a sample sub-class in the file
61             C which illustrates some of what you might want to do in
62             your own class(es).
63              
64             This module provides three main benefits:
65              
66             =head2 Centralized Configuration
67              
68             Rather than store the various connection parameters (username, password,
69             hostname, port number, database name) in each and every script or
70             application which needs them, you can easily put them in once place--or
71             even generate them on the fly by writing a bit of custom code.
72              
73             If this is all you need, consider looking at Brian Aker's fine
74             C module on the CPAN. It may be sufficient.
75              
76             =head2 API Simplicity
77              
78             Taking a lesson from Python (gasp!), this module promotes one obvious way
79             to do most things. If you want to run a query and get the results back as a
80             list of hashrefs, there's one way to do that. The API may sacrifice speed
81             in some cases, but new users can easily learn the simple and descriptive
82             method calls. (Nobody is forcing you to use it.)
83              
84             =head2 Fault Tolerance
85              
86             Databases sometimes go down. Networks flake out. Bad stuff happens. Rather
87             than have your application die, DBIx::DWIW provides a way to handle
88             outages. You can build custom wait/retry/fail logic which does anything you
89             might want (such as ringing your pager or sending e-mail).
90              
91             =head2 Transaction Handling
92              
93             As of version 0.25, three transaction related methods were added to DWIW.
94             These methods were designed to make transaction programming easier in a
95             couple of ways.
96              
97             Consider a code snippet like this:
98              
99             sub do_stuff_with_thing
100             {
101             $db->Begin();
102             $db->Execute("some sql here");
103             $db->Execute("another query here");
104             $db->Commit();
105             }
106              
107             That's all well an good. You have a function that you can call and it will
108             perform 2 discrete actions as part of a transaction. However, what if you
109             need to call that in the context of a larger transaction from time to time?
110             What you'd like to do is this:
111              
112             $db->Begin();
113             for my $thing (@thing_list)
114             {
115             do_stuff_with_thing($thing);
116             }
117             $db->Commit();
118              
119             and have it all wrapped up in once nice juicy transaction.
120              
121             With DBIx::DWIW, you can. That is, in fact, the default behavior. You can
122             call C as many times as you want, but it'll only ever let you
123             start a single transaction until you call the corresponding commit. It does
124             this by tracking the number of times you call C and C. A
125             counter is incremented each time you call C and decremented each
126             time you call C. When the count reaches zero, the original
127             transaction is actually committed.
128              
129             Of course, there are problems with that method, so DBIx::DWIW provides an
130             alternative. You can use I. Using named transactions
131             instead, the code above would look like this:
132              
133             sub do_stuff_with_thing
134             {
135             $db->Begin('do_stuff transaction');
136             $db->Execute("some sql here");
137             $db->Execute("another query here");
138             $db->Commit('do_stuff transaction');
139             }
140              
141             and:
142              
143             $db->Begin('Big Transaction');
144             for my $thing (@thing_list)
145             {
146             do_stuff_with_thing($thing);
147             }
148             $db->Commit('Big Transaction');
149              
150             In that way, you can avoid problems that might be caused by not calling
151             C and C the same number of times. Once a named
152             transaction is begun, the module simply ignores any C or
153             C calls that don't have a name or whose name doesn't match that
154             assigned to the currently open transaction.
155              
156             The only exception to this rule is C. Because a transaction
157             rollback usually signifies a big problem, calling C B
158             ends the currently running transaction.
159              
160             Return values for these functions are a bit different, too. C and
161             C can return undef, 0, or 1. undef means there was an error. 0
162             means that nothing was done (but there was no error either), and 1 means
163             that work was done.
164              
165             The methods are:
166              
167             =over
168              
169             =item Begin
170              
171             Start a new transaction if one is not already running.
172              
173             =item Commit
174              
175             Commit the current transaction, if one is running.
176              
177             =item Rollback
178              
179             Rollback the current transaction, if one is running.
180              
181             =back
182              
183             See the detailed method descriptions below for all the gory details.
184              
185             Note that C, C, and C are not protected by
186             DBIx::DWIW's normal wait/retry logic if a network connection fails. This
187             because I'm not sure that it it makes sense. If your connection drops and
188             the other end notices, it'll probably rollback for you anyway.
189              
190             =head1 DBIx::DWIW CLASS METHODS
191              
192             The following methods are available from DBIx::DWIW objects. Any function
193             or method not documented should be considered private. If you call it, your
194             code may break someday and it will be B fault.
195              
196             The methods follow the Perl tradition of returning false values when an
197             error occurs (and usually setting $@ with a descriptive error message).
198              
199             Any method which takes an SQL query string can also be passed bind values
200             for any placeholders in the query string:
201              
202             $db->Hashes("SELECT * FROM foo WHERE id = ?", $id);
203              
204             Any method which takes an SQL query string can also be passed a prepared
205             DWIW statement handle:
206              
207             $db->Hashes($sth, $id);
208              
209             =over
210              
211             =cut
212              
213             ##
214             ## This is the cache of currently-open connections, filled with
215             ## $CurrentConnections{host,user,password,db . class} = $db
216             ##
217             my %CurrentConnections;
218              
219             ##
220             ## Autoload to trap method calls that we haven't defined. The default (when
221             ## running in unsafe mode) behavior is to check $dbh to see if it can()
222             ## field the call. If it can, we call it. Otherwise, we die.
223             ##
224              
225 1     1   180 use vars '$AUTOLOAD';
  1         2  
  1         7171  
226              
227             sub AUTOLOAD
228             {
229 0     0   0 my $method = $AUTOLOAD;
230 0         0 my $self = shift;
231              
232 0         0 $method =~ s/.*:://; ## strip the package name
233              
234 0         0 my $orig_method = $method;
235              
236 0 0       0 if ($self->{SAFE})
237             {
238 0 0       0 if (not $method =~ s/^dbi_//)
239             {
240 0         0 $@ = "undefined or unsafe method ($orig_method) called";
241 0         0 Carp::croak("$@");
242             }
243             }
244              
245 0 0 0     0 if ($self->{DBH} and $self->{DBH}->can($method))
246             {
247 0         0 $self->{DBH}->$method(@_);
248             }
249             else
250             {
251 0         0 Carp::croak("undefined method ($orig_method) called");
252             }
253             }
254              
255             ##
256             ## Allow the user to explicitly tell us if they want SAFE on or off.
257             ##
258              
259             sub import
260             {
261 1     1   8 my $class = shift;
262              
263 1         3009 while (my $arg = shift @_)
264             {
265 0 0         if ($arg eq 'unsafe')
    0          
266             {
267 0           $SAFE = 0;
268             }
269             elsif ($arg eq 'safe')
270             {
271 0           $SAFE = 1;
272             }
273             else
274             {
275 0           warn "unknown use argument: $arg";
276             }
277             }
278             }
279              
280             ##
281             ## This is an 'our' variable so that it can be easily overridden with
282             ## 'local', e.g.
283             ##
284             ## {
285             ## local($DBIx::DWIW::ConnectTimeoutOverride) = $DBIx::DWIW::ShorterTimeout($ConnectTimeoutOverride, 1.5)
286             ## Some::Routine::That::Connects();
287             ## }
288             ##
289             ## It has the following semantics:
290             ## undef -- unset; no impact
291             ## 0 -- infinite timeout (no timeout)
292             ## > 0 -- timeout, in seconds
293             ##
294             our $ConnectTimeoutOverride;
295             our %ConnectTimeoutOverrideByHost; ## on a per-host basis
296              
297             our $QueryTimeoutOverride;
298             our %QueryTimeoutOverrideByHost; ## on a per-host basis
299              
300             ##
301             ## Given two timeouts, return the one that's shorter. Note that a false
302             ## value is the same as an infinite timeout, so 1 is shorter than 0.
303             ##
304             sub ShorterTimeout($$)
305             {
306 0     0 0   my $a = shift;
307 0           my $b = shift;
308              
309 0 0         if (not defined $a) {
    0          
    0          
    0          
    0          
310 0           return $b;
311             } elsif (not defined $b) {
312 0           return $a;
313             } elsif (not $a) {
314 0           return $b;
315             } elsif (not $b) {
316 0           return $a;
317             } elsif ($a < $b) {
318 0           return $a;
319             } else {
320 0           return $b;
321             }
322             }
323              
324              
325             =item Connect()
326              
327             The C constructor creates and returns a database connection
328             object through which all database actions are conducted. On error, it
329             calls C, so you may want to C the call. The
330             C option (described below) controls that behavior.
331              
332             C accepts ``hash-style'' key/value pairs as arguments. The
333             arguments which it recognizes are:
334              
335             =over
336              
337             =item Host
338              
339             The name of the host to connect to. Use C to force a socket
340             connection on the local machine.
341              
342             =item User
343              
344             The database user to authenticate as.
345              
346             =item Pass
347              
348             The password to authenticate with.
349              
350             =item DB
351              
352             The name of the database to use.
353              
354             =item Socket
355              
356             NOT IMPLEMENTED.
357              
358             The path to the Unix socket to use.
359              
360             =item Port
361              
362             The port number to connect to.
363              
364             =item Proxy
365              
366             Set to true to connect to a DBI::ProxyServer proxy. You'll also need
367             to set ProxyHost, ProxyKey, and ProxyPort. You may also want to set
368             ProxyKey and ProxyCipher.
369              
370             =item ProxyHost
371              
372             The hostname of the proxy server.
373              
374             =item ProxyPort
375              
376             The port number on which the proxy is listening. This is probably
377             different than the port number on which the database server is
378             listening.
379              
380             =item ProxyKey
381              
382             If the proxy server you're using requires encryption, supply the
383             encryption key (as a hex string).
384              
385             =item ProxyCipher
386              
387             If the proxy server requires encryption, supply the name of the
388             package which provides encryption. Typically this is something
389             like C or C.
390              
391             =item Unique
392              
393             A boolean which controls connection reuse.
394              
395             If false (the default), multiple Cs with the same connection
396             parameters (User, Pass, DB, Host) return the same open
397             connection. If C is true, it returns a connection distinct
398             from all other connections.
399              
400             If you have a process with an active connection that fork()s, be aware
401             that you CANNOT share the connection between the parent and child.
402             Well, you can if you're REALLY CAREFUL and know what you're doing.
403             But don't do it.
404              
405             Instead, acquire a new connection in the child. Be sure to set this
406             flag when you do, or you'll end up with the same connection and spend
407             a lot of time pulling your hair out over why the code does mysterious
408             things.
409              
410             As of version 0.27, DWIW also checks the class name of the caller and
411             guarantees unique connections across different classes. So if you
412             call Connect() from SubClass1 and SubClass2, each class gets its own
413             connection.
414              
415             =item Verbose
416              
417             Turns verbose reporting on. See C.
418              
419             =item Quiet
420              
421             Turns off warning messages. See C.
422              
423             =item NoRetry
424              
425             If true, the C fails immediately if it can't connect to
426             the database. Normally, it retries based on calls to
427             C. C affects only C, and has no effect
428             on the fault-tolerance of the package once connected.
429              
430             =item NoAbort
431              
432             If there is an error in the arguments, or in the end the database
433             can't be connected to, C normally prints an error message
434             and dies. If C is true, it puts the error string into
435             C<$@> and return false.
436              
437             =item Timeout
438              
439             The amount of time (in seconds) after which C should give up and
440             return. You may use fractional seconds. A Timeout of zero is the same as
441             not having one at all.
442              
443             If you set the timeout, you probably also want to set C to a
444             true value. Otherwise you'll be surprised when a server is down and
445             your retry logic is running.
446              
447             =item QueryTimeout
448              
449             The amount of time (in seconds) after which query operations should give up
450             and return. You may use fractional seconds. A Timeout of zero is the same
451             as not having one at all.
452              
453             =back
454              
455             There are a minimum of four components to any database connection: DB,
456             User, Pass, and Host. If any are not provided, there may be defaults
457             that kick in. A local configuration package, such as the C
458             example class that comes with DBIx::DWIW, may provide appropriate
459             default connection values for several database. In such a case, a
460             client may be able to simply use:
461              
462             my $db = MyDBI->Connect(DB => 'Finances');
463              
464             to connect to the C database.
465              
466             As a convenience, you can just give the database name:
467              
468             my $db = MyDBI->Connect('Finances');
469              
470             See the local configuration package appropriate to your installation
471             for more information about what is and isn't preconfigured.
472              
473             =cut
474              
475             sub Connect($@)
476             {
477 0     0 1   my $class = shift;
478 0           my $use_slave_hack = 0;
479 0           my $config_name;
480              
481             ##
482             ## If the user asks for a slave connection like this:
483             ##
484             ## Connect('Slave', 'ConfigName')
485             ##
486             ## We'll try calling FindSlave() to find a slave server.
487             ##
488 0 0 0       if (@_ == 2 and ($_[0] eq 'Slave' or $_[0] eq 'ReadOnly'))
      0        
489             {
490 0           $use_slave_hack = 1;
491 0           shift;
492             }
493              
494 0           my %Options;
495              
496             ##
497             ## Handle $self->Connect('SomeConfig')
498             ##
499 0 0         if (@_ % 2 != 0)
500             {
501 0           $config_name = shift;
502 0 0         if (my $config = $class->LocalConfig($config_name))
503             {
504 0           %Options = (%{$config}, @_);
  0            
505             }
506             else
507             {
508 0           die "unknown local config \"$config_name\", or bad number of arguments to Connect: " . join(", ", $config_name, @_);
509             }
510             }
511             else
512             {
513 0           %Options = @_;
514             }
515              
516 0           my $UseSlave = delete($Options{UseSlave});
517              
518 0 0         if ($use_slave_hack)
519             {
520 0           $UseSlave = 1;
521             }
522              
523             ## Find a slave to use, if we can.
524              
525 0 0         if ($UseSlave)
526             {
527 0 0         if ($class->can('FindSlave'))
528             {
529 0           %Options = $class->FindSlave(%Options);
530             }
531             else
532             {
533 0           warn "$class doesn't know how to find slaves";
534             }
535             }
536              
537             ##
538             ## Fetch the arguments.
539             ##
540 0   0       my $DB = delete($Options{DB}) || $class->DefaultDB();
541 0   0       my $User = delete($Options{User}) || $class->DefaultUser($DB);
542 0           my $Password = delete($Options{Pass});
543 0   0       my $Port = delete($Options{Port}) || $class->DefaultPort($DB);
544 0           my $Unique = delete($Options{Unique});
545 0           my $Retry = !delete($Options{NoRetry});
546 0           my $Quiet = delete($Options{Quiet});
547 0           my $NoAbort = delete($Options{NoAbort});
548 0           my $ConnectTimeout = delete($Options{Timeout});
549 0           my $QueryTimeout = delete($Options{QueryTimeout});
550 0           my $Verbose = delete($Options{Verbose}); # undef = no change
551             # true = on
552             # false = off
553             ## allow empty passwords
554 0 0         $Password = $class->DefaultPass($DB) if not defined $Password;
555              
556 0 0         $config_name = $DB unless defined $config_name;
557              
558             ## respect the DB_DOWN hack
559 0 0         $Quiet = 1 if $ENV{DB_DOWN};
560              
561             ##
562             ## Host parameter is special -- we want to recognize
563             ## Host => undef
564             ## as being "no host", so we have to check for its existence in the hash,
565             ## and default to nothing ("") if it exists but is empty.
566             ##
567 0           my $Host;
568 0 0         if (exists $Options{Host})
569             {
570 0   0       $Host = delete($Options{Host}) || "";
571             }
572             else
573             {
574 0   0       $Host = $class->DefaultHost($DB) || "";
575             }
576              
577 0 0         if (not $DB)
578             {
579 0           $@ = "missing DB parameter to Connect";
580 0 0         die $@ unless $NoAbort;
581 0           return ();
582             }
583              
584 0 0         if (not $User)
585             {
586 0           $@ = "missing User parameter to Connect";
587 0 0         die $@ unless $NoAbort;
588 0           return ();
589             }
590              
591 0 0         if (not defined $Password)
592             {
593 0           $@ = "missing Pass parameter to Connect";
594 0 0         die $@ unless $NoAbort;
595 0           return ();
596             }
597              
598             # if (%Options)
599             # {
600             # my $keys = join(', ', keys %Options);
601             # $@ = "bad parameters [$keys] to Connect()";
602             # die $@ unless $NoAbort;
603             # return ();
604             # }
605              
606 0           my $myhost = hostname();
607 0           my $desc;
608              
609 0 0         if (defined $Host)
610             {
611 0           $desc = "connection to $Host\'s MySQL server from $myhost";
612             }
613             else
614             {
615 0           $desc = "local connection to MySQL server on $myhost";
616             }
617              
618             ## we're going to build the dsn up incrementally...
619 0           my $dsn;
620              
621             ## proxy details
622             ##
623             ## This can be factored together once I'm sure it is working.
624              
625             # DBI:Proxy:cipher=Crypt::DES;key=$key;hostname=$proxy_host;port=8192;dsn=DBI:mysql:$db:$host
626              
627 0 0         if ($Options{Proxy})
628             {
629 0 0 0       if (not ($Options{ProxyHost} and $Options{ProxyPort}))
630             {
631 0           $@ = "ProxyHost and ProxyPort are required when Proxy is set";
632 0 0         die $@ unless $NoAbort;
633 0           return ();
634             }
635              
636 0           $dsn = "DBI:Proxy";
637              
638 0           my $proxy_port = $Options{ProxyPort};
639 0           my $proxy_host = $Options{ProxyHost};
640              
641 0 0 0       if ($Options{ProxyCipher} and $Options{ProxyKey})
642             {
643 0           my $proxy_cipher = $Options{ProxyCipher};
644 0           my $proxy_key = $Options{ProxyKey};
645              
646 0           $dsn .= ":cipher=$proxy_cipher;key=$proxy_key";
647             }
648              
649 0           $dsn .= ";hostname=$proxy_host;port=$proxy_port";
650 0           $dsn .= ";dsn=DBI:mysql:$DB:$Host;mysql_client_found_rows=1";
651             }
652             else
653             {
654 0 0         if ($Port)
655             {
656 0           $dsn .= "DBI:mysql:$DB:$Host;port=$Port;mysql_client_found_rows=1";
657             }
658             else
659             {
660 0           $dsn .= "DBI:mysql:$DB:$Host;mysql_client_found_rows=1";
661             }
662             }
663              
664 0 0         warn "DSN: $dsn\n" if $ENV{DEBUG};
665              
666             ##
667             ## If we're not looking for a unique connection, and we already have
668             ## one with the same options, use it.
669             ##
670 0 0         if (not $Unique)
671             {
672 0 0         if (my $db = $CurrentConnections{$dsn . $class})
673             {
674 0 0         if (defined $Verbose)
675             {
676 0           $db->{VERBOSE} = $Verbose;
677             }
678              
679 0           return $db;
680             }
681             }
682              
683              
684 0 0 0       if ($Host and my $Override = $ConnectTimeoutOverrideByHost{$Host})
    0          
685             {
686 0           $ConnectTimeout = ShorterTimeout($ConnectTimeout, $Override);
687             }
688             elsif ($ConnectTimeoutOverride)
689             {
690 0           $ConnectTimeout = ShorterTimeout($ConnectTimeout, $ConnectTimeoutOverride);
691             }
692              
693 0 0 0       if ($Host and my $Override = $QueryTimeoutOverrideByHost{$Host})
    0          
694             {
695 0           $QueryTimeout = ShorterTimeout($QueryTimeout, $Override);
696             }
697             elsif ($QueryTimeoutOverride)
698             {
699 0           $QueryTimeout = ShorterTimeout($QueryTimeout, $QueryTimeoutOverride);
700             }
701              
702 0           my $self = {
703             ## Connection info
704             DB => $DB,
705             DBH => undef,
706             DESC => $desc,
707             HOST => $Host,
708             PASS => $Password,
709             QUIET => $Quiet,
710             RETRY => 1,
711             UNIQUE => $Unique,
712             USER => $User,
713             PORT => $Port,
714             VERBOSE => $Verbose,
715             SAFE => $SAFE,
716             DSN => $dsn,
717             UNIQUE_KEY => $dsn . $class,
718             CONNECT_TIMEOUT => $ConnectTimeout,
719             QUERY_TIMEOUT => $QueryTimeout,
720             RetryCount => 0,
721              
722             ## Transaction info
723             BeginCount => 0, ## ++ on Begin, -- on Commit, reset Rollback
724             TrxRunning => 0, ## true after a Begin
725             TrxName => undef,
726             };
727              
728 0           $self = bless $self, $class;
729              
730 0 0         if ($ENV{DBIxDWIW_VERBOSE}) {
731 0           $self->{VERBOSE} = 1;
732             }
733              
734 0 0         if (my $routine = $self->can("PreConnectHook")) {
735 0           $routine->($self);
736             }
737              
738 0 0         if ($ENV{DBIxDWIW_CONNECTION_DEBUG}) {
739 0           require Data::Dumper;
740              
741 0           local($Data::Dumper::Indent) = 2;
742 0           local($Data::Dumper::Purity) = 0;
743 0           local($Data::Dumper::Terse) = 1;
744              
745 0           Carp::cluck("DBIx::DWIW Connecting:\n" . Data::Dumper::Dumper($self) . "\n\t");
746             }
747              
748 0           my $dbh;
749 0           my $done = 0;
750              
751 0           while (not $done)
752             {
753 0           local($SIG{PIPE}) = 'IGNORE';
754              
755             ## If the user wants a timeout, we need to set that up and do
756             ## it here. This looks complex, but it's really a no-op
757             ## unless the user wants it.
758             ##
759             ## Notice that if a timeout is hit, then the RetryWait() stuff
760             ## will never have a chance to run. That's good, but we need
761             ## to make sure that users expect that.
762              
763 0 0         if ($self->{CONNECT_TIMEOUT})
764             {
765             eval
766 0           {
767 0     0     local $SIG{ALRM} = sub { die "alarm\n" };
  0            
768              
769 0           Time::HiRes::alarm($self->{CONNECT_TIMEOUT});
770 0           $dbh = DBI->connect($dsn, $User, $Password, { PrintError => 0 });
771 0           Time::HiRes::alarm(0);
772             };
773 0 0         if ($@ eq "alarm\n")
774             {
775 0 0         if (my $routine = $self->can("ConnectTimeoutHook")) {
776 0           $routine->($self);
777             }
778              
779 0           my $timeout = $self->{CONNECT_TIMEOUT};
780 0           undef $self; # this fires the DESTROY, which sets $@, so must
781             # do before setting $@ below.
782              
783 0           $@ = "connection timeout ($timeout sec passed)";
784 0           return ();
785             }
786             }
787             else
788             {
789 0           $dbh = DBI->connect($dsn, $User, $Password, { PrintError => 0 });
790             }
791              
792 0 0         if (not ref $dbh)
793             {
794 0 0 0       if (not $DBI::errstr and $@)
795             {
796             ##
797             ## Must be a problem with loading DBD or something --
798             ## a *perl* problem as opposed to a network/credential
799             ## problem. If we clear $Retry now, we'll ensure to drop
800             ## into the die 'else' clause below.
801             ##
802 0           $Retry = 0;
803             }
804              
805 0 0 0       if ($Retry
      0        
      0        
806             and
807             ($DBI::errstr =~ m/can\'t connect/i
808             or
809             $DBI::errstr =~ m/Too many connections/i
810             or
811             $DBI::errstr =~ m/Lost connection to MySQL server/i)
812             and
813             $self->RetryWait($DBI::errstr))
814             {
815 0           $done = 0; ## Heh.
816             }
817             else
818             {
819 0   0       my $ERROR = ($DBI::errstr || $@ || "internal error");
820              
821             ##
822             ## If DBI::ProxyServer is being used and the target mmysql
823             ## server refuses the connection (wrong password, trying to
824             ## access a db that they've not been given permission for,
825             ## etc.) DBI::ProxyServer just reports "Unexpected EOF from
826             ## server". Let's give the user a hint as to what that
827             ## might mean.
828             ##
829 0 0         if ($ERROR =~ m/^Cannot log in to DBI::ProxyServer: Unexpected EOF from server/) {
830 0           $ERROR = "Cannot log in via DBI::ProxyServer: Unexpected EOF from server (check user's MySQL credentials and privileges)";
831             }
832 0 0         if (not $NoAbort) {
    0          
833 0           die $ERROR;
834             }
835             elsif (not $Quiet) {
836 0           warn $ERROR;
837             }
838              
839 0           $@ = $ERROR;
840 0           $self->_OperationFailed();
841              
842 0           undef $self; # This fires the DESTROY, which sets $@.
843 0           $@ = $ERROR; # Just in case the DESTROY did set $@.
844 0           return ();
845             }
846             }
847             else
848             {
849 0           eval { $dbh->{AutoCommit} = 1};
  0            
850 0           $dbh->{mysql_auto_reconnect} = 1;
851 0           $done = 1; ## it worked!
852             }
853             } ## end while not done
854              
855             ##
856             ## We got through....
857             ##
858 0           $self->_OperationSuccessful();
859 0           $self->{DBH} = $dbh;
860              
861             ##
862             ## Save this one if it's not to be unique.
863             ##
864 0 0         if (not $Unique)
865             {
866 0           $CurrentConnections{$self->{UNIQUE_KEY}} = $self;
867             }
868              
869 0           return $self;
870             }
871              
872             *new = \&Connect;
873              
874             =item Dump()
875              
876             Dump the internal configuration to stdout. This is mainly useful for
877             debugging DBIx::DWIW. You probably don't need to call it unless you
878             know what you're doing. :-)
879              
880             =cut
881              
882             sub Dump
883             {
884 0     0 1   my $self = shift;
885              
886             ## Trivial dumping of key/value pairs.
887 0           for my $key (sort keys %$self)
888             {
889 0 0         print "$key: $self->{$key}\n" unless not defined $self->{$key};
890             }
891             }
892              
893             =item Timeout()
894              
895             Like the QueryTimeout argument to Connect(), sets (or resets) the amount of
896             time (in seconds) after which queries should give up and return. You may
897             use fractional seconds. A timeout of zero is the same as not having one at
898             all.
899              
900             C called with any (or no) arguments returns the current
901             query timeout value.
902              
903             =cut
904              
905             sub Timeout(;$)
906             {
907 0     0 1   my $self = shift;
908 0           my $time = shift;
909              
910 0 0         if (defined $time)
911             {
912 0           $self->{QUERY_TIMEOUT} = $time;
913             }
914              
915 0 0         print "QUERY_TIMEOUT SET TO: $self->{QUERY_TIMEOUT}\n" if $self->{VERBOSE};
916              
917 0           return $self->{QUERY_TIMEOUT};
918             }
919              
920             =item Disconnect()
921              
922             Closes the connection. Upon program exit, this is called automatically
923             on all open connections. Returns true if the open connection was
924             closed, false if there was no connection or there was some other
925             error (with the error being returned in C<$@>).
926              
927             =cut
928              
929             sub Disconnect($)
930             {
931 0     0 1   my $self = shift;
932 0           my $class = ref $self;
933              
934 0 0         if (not $self->{UNIQUE})
935             {
936 0           delete $CurrentConnections{$self->{UNIQUE_KEY}};
937             }
938              
939 0 0         if (not $self->{DBH})
940             {
941             # Not an error, since this gets called as part of the destructor --
942             # might not be connected even though the object exists.
943 0           return ();
944             }
945              
946             ## clean up a lingering sth if there is one...
947              
948 0 0         if (defined $self->{RecentExecutedSth})
949             {
950 0           $self->{RecentExecutedSth}->finish();
951             }
952              
953 0 0         if (not $self->{DBH}->disconnect())
954             {
955 0           $@ = "couldn't disconnect (or wasn't disconnected)";
956 0           $self->{DBH} = undef;
957 0           return ();
958             }
959             else
960             {
961 0           $@ = "";
962 0           $self->{DBH} = undef;
963 0           return 1;
964             }
965             }
966              
967             sub DESTROY($)
968             {
969 0     0     my $self = shift;
970 0           $self->Disconnect();
971             }
972              
973             =item Quote(@values)
974              
975              
976             Calls the DBI C function on each value, returning a list of
977             properly quoted values. As per quote(), NULL is returned for
978             items that are not defined.
979              
980             =cut
981              
982             sub Quote($@)
983             {
984 0     0 1   my $self = shift;
985 0           my $dbh = $self->dbh();
986 0           my @ret;
987              
988 0           for my $item (@_)
989             {
990 0           push @ret, $dbh->quote($item);
991             }
992              
993 0 0         if (wantarray)
994             {
995 0           return @ret;
996             }
997              
998 0 0         if (@ret > 1)
999             {
1000 0           return join ', ', @ret;
1001             }
1002              
1003 0           return $ret[0];
1004             }
1005              
1006             =item InList($field => @values)
1007              
1008             Given a field and a value or values, returns SQL appropriate for a
1009             WHERE clause in the form
1010              
1011             field = 'value'
1012              
1013             or
1014              
1015             field IN ('value1', 'value2', ...)
1016              
1017             depending on the number of values. Each value is passed through
1018             C while building the SQL.
1019              
1020             If no values are provided, nothing is returned.
1021              
1022             This function is useful because MySQL apparently does not optimize
1023              
1024             field IN ('val')
1025              
1026             as well as it optimizes
1027              
1028             field = 'val'
1029              
1030             =item InListUnquoted($field => @values)
1031              
1032             Just like C, but the values are not passed through C.
1033              
1034             =cut
1035              
1036             sub InListUnquoted
1037             {
1038 0     0 1   my $self = shift;
1039 0           my $field = shift;
1040 0           my @values = @_;
1041              
1042 0 0         if (@values == 1) {
    0          
1043 0           return "$field = $values[0]";
1044             } elsif (@values > 1) {
1045 0           return "$field IN (" . join(', ', @values) . ')';
1046             } else {
1047 0           return ();
1048             }
1049             }
1050              
1051             sub InList
1052             {
1053 0     0 1   my $self = shift;
1054 0           my $field = shift;
1055 0           my @values = $self->Quote(@_);
1056              
1057 0           return $self->InListUnquoted($field => @values);
1058             }
1059              
1060              
1061             =pod
1062              
1063             =item ExecuteReturnCode()
1064              
1065             Returns the return code from the most recently Execute()d query. This
1066             is what Execute() returns, so there's little reason to call it
1067             directly. But it didn't use to be that way, so old code may be
1068             relying on this.
1069              
1070             =cut
1071              
1072             sub ExecuteReturnCode($)
1073             {
1074 0     0 1   my $self = shift;
1075 0           return $self->{ExecuteReturnCode};
1076             }
1077              
1078             ## Private version of Execute() that deals with statement handles
1079             ## ONLY. Given a statement handle, call execute and insulate it from
1080             ## common problems.
1081              
1082             sub _Execute()
1083             {
1084 0     0     my $self = shift;
1085 0           my $statement = shift;
1086 0           my @bind_vals = @_;
1087              
1088 0 0         if (not ref $statement)
1089             {
1090 0           $@ = "non-reference passed to _Execute()";
1091 0 0         warn "$@" unless $self->{QUIET};
1092 0           return ();
1093             }
1094              
1095 0           my $sth = $statement->{DBI_STH};
1096              
1097 0 0         print "_EXECUTE: $statement->{SQL}: ", join(" | ", @bind_vals), "\n" if $self->{VERBOSE};
1098              
1099             ##
1100             ## Execute the statement. Retry if requested.
1101             ##
1102 0           my $done = 0;
1103              
1104             ## mysql_auto_reconnect (DBD::mysql >= 2.9) should always be in
1105             ## lockstep with AutoCommit.
1106 0           $self->{DBH}->{mysql_auto_reconnect} = $self->{DBH}->{AutoCommit};
1107              
1108 0           while (not $done)
1109             {
1110 0           local($SIG{PIPE}) = 'IGNORE';
1111              
1112             ## If the user wants a timeout, we need to set that up and do
1113             ## it here. This looks complex, but it's really a no-op
1114             ## unless the user wants it.
1115             ##
1116             ## Notice that if a timeout is hit, the RetryWait() stuff
1117             ## will never have a chance to run. That's good, but we need
1118             ## to make sure that users expect that.
1119              
1120 0 0         if ($self->{QUERY_TIMEOUT})
1121             {
1122             eval
1123 0           {
1124 0     0     local $SIG{ALRM} = sub { die "alarm\n" };
  0            
1125              
1126 0           Time::HiRes::alarm($self->{QUERY_TIMEOUT});
1127 0           $self->{ExecuteReturnCode} = $sth->execute(@bind_vals);
1128 0           Time::HiRes::alarm(0);
1129             };
1130 0 0         if ($@ eq "alarm\n")
1131             {
1132 0 0         if (my $routine = $self->can("ExecuteTimeoutHook")) {
1133 0           $routine->($self, $statement);
1134             }
1135              
1136 0           $@ = "query timeout ($self->{QUERY_TIMEOUT} sec passed)";
1137 0           return ();
1138             }
1139             }
1140             else
1141             {
1142 0           $self->{ExecuteReturnCode} = $sth->execute(@bind_vals);
1143             }
1144              
1145             ##
1146             ## Otherwise, if it's an error that we know is "retryable" and
1147             ## the user wants to retry (based on the RetryWait() call),
1148             ## we'll try again. But we will not retry if in the midst of a
1149             ## transaction.
1150             ##
1151 0 0         if (not defined $self->{ExecuteReturnCode})
1152             {
1153 0           my $err = $self->{DBH}->errstr;
1154              
1155 0 0 0       if (not $self->{TrxRunning}
      0        
      0        
1156             and
1157             $self->{RETRY}
1158             and (
1159             $err =~ m/Lost connection/
1160             or
1161             $err =~ m/server has gone away/
1162             or
1163             $err =~ m/Server shutdown in progress/
1164             ))
1165             {
1166 0 0         if ($self->RetryWait($err))
1167             {
1168 0           next;
1169             }
1170             }
1171              
1172             ##
1173             ## It is really an error that we cannot (or should not)
1174             ## retry, so spit it out if needed.
1175             ##
1176 0           $@ = "$err [in prepared statement]";
1177 0 0         Carp::cluck "execute of prepared statement returned undef [$err]" if $self->{VERBOSE};
1178 0           $self->_OperationFailed();
1179 0           return ();
1180             }
1181             else
1182             {
1183 0           $done = 1;
1184             }
1185             }
1186              
1187             ##
1188             ## Got through.
1189             ##
1190 0           $self->_OperationSuccessful();
1191              
1192 0 0         print "EXECUTE successful\n" if $self->{VERBOSE};
1193              
1194             ##
1195             ## Save this as the most-recent successful statement handle.
1196             ##
1197 0           $self->{RecentExecutedSth} = $sth;
1198              
1199             ##
1200             ## Execute worked -- return the statement handle.
1201             ##
1202 0           return $self->{ExecuteReturnCode}
1203             }
1204              
1205             ## Public version of Execute that deals with SQL only and calls
1206             ## _Execute() to do the real work.
1207              
1208             =item Execute($sql)
1209              
1210             Executes the given SQL, returning true if successful, false if not
1211             (with the error in C<$@>).
1212              
1213             C is a synonym for C
1214              
1215             =cut
1216              
1217             sub Execute($$@)
1218             {
1219 0     0 1   my $self = shift;
1220 0           my $sql = shift;
1221 0           my @bind_vals = @_;
1222              
1223 0 0         if (not $self->{DBH})
1224             {
1225 0           $@ = "not connected in Execute()";
1226 0 0         Carp::croak "not connected to the database" unless $self->{QUIET};
1227             }
1228              
1229 0           my $sth;
1230              
1231 0 0         if (ref $sql)
1232             {
1233 0           $sth = $sql;
1234             }
1235             else
1236             {
1237 0 0         print "EXECUTE> $sql\n" if $self->{VERBOSE};
1238 0           $sth = $self->Prepare($sql, 0+@bind_vals);
1239             }
1240              
1241 0           return $sth->Execute(@bind_vals);
1242             }
1243              
1244             ##
1245             ## Do is a synonym for Execute.
1246             ##
1247             *Do = \&Execute;
1248              
1249             =item Prepare($sql)
1250              
1251             Prepares the given sql statement, but does not execute it (just like
1252             DBI). Instead, it returns a statement handle C<$sth> that you can
1253             later execute by calling its Execute() method:
1254              
1255             my $sth = $db->Prepare("INSERT INTO foo VALUES (?, ?)");
1256              
1257             $sth->Execute($a, $b);
1258              
1259             The statement handle returned is not a native DBI statement
1260             handle. It's a DBIx::DWIW::Statement handle.
1261              
1262             When called from Execute(), Scalar(), Hashes(), etc. AND there
1263             are values to substitute, the statement handle is cached.
1264             This benefits a typical case where ?-substitutions being done
1265             lazily in an Execute call inside a loop.
1266             Meanwhile, interpolated sql queries, non-? queries, and
1267             manually Prepare'd statements are unaffected. These typically
1268             do not benefit from moving caching the prepare.
1269              
1270             Note: prepare-caching is of no benefit until Mysql 4.1.
1271              
1272             =cut
1273              
1274             sub Prepare($$;$)
1275             {
1276 0     0 1   my $self = shift;
1277 0           my $sql = shift;
1278 0           my $has_bind = shift;
1279              
1280 0 0         if (not $self->{DBH})
1281             {
1282 0           $@ = "not connected in Prepare()";
1283              
1284 0 0         if (not $self->{QUIET})
1285             {
1286 0           carp scalar(localtime) . ": not connected to the database";
1287             }
1288 0           return ();
1289             }
1290              
1291 0           $@ = ""; ## ensure $@ is clear if not error.
1292              
1293 0 0         if ($self->{VERBOSE})
1294             {
1295 0           print "PREPARE> $sql\n";
1296             }
1297              
1298             ## Automatically cache the prepare if there are bind args.
1299              
1300 0 0         my $dbi_sth = $has_bind ?
1301             $self->{DBH}->prepare_cached($sql) :
1302             $self->{DBH}->prepare($sql);
1303              
1304             ## Build the new statement handle object and bless it into
1305             ## DBIx::DWIW::Statement. Then return that object.
1306              
1307 0           $self->{RecentPreparedSth} = $dbi_sth;
1308              
1309 0           my $sth = {
1310             SQL => $sql, ## save the sql
1311             DBI_STH => $dbi_sth, ## the real statement handle
1312             PARENT => $self, ## remember who created us
1313             };
1314              
1315 0           return bless $sth, 'DBIx::DWIW::Statement';
1316             }
1317              
1318             =item RecentSth()
1319              
1320             Returns the DBI statement handle (C<$sth>) of the most-recently
1321             I statement.
1322              
1323             =cut
1324              
1325             sub RecentSth($)
1326             {
1327 0     0 1   my $self = shift;
1328 0           return $self->{RecentExecutedSth};
1329             }
1330              
1331             =item RecentPreparedSth()
1332              
1333             Returns the DBI statement handle (C<$sth>) of the most-recently
1334             prepared DBI statement handle (which may or may not have already been
1335             executed).
1336              
1337             =cut
1338              
1339             sub RecentPreparedSth($)
1340             {
1341 0     0 1   my $self = shift;
1342 0           return $self->{RecentPreparedSth};
1343             }
1344              
1345             =item InsertedId()
1346              
1347             Returns the C associated with the most recently
1348             executed statement. Returns nothing if there is none.
1349              
1350             Synonyms: C, C, and C
1351              
1352             =cut
1353              
1354             sub InsertedId($)
1355             {
1356 0     0 1   my $self = shift;
1357 0 0 0       if ($self->{RecentExecutedSth}
1358             and
1359             defined($self->{RecentExecutedSth}->{mysql_insertid}))
1360             {
1361 0           return $self->{RecentExecutedSth}->{mysql_insertid};
1362             }
1363             else
1364             {
1365 0           return ();
1366             }
1367             }
1368              
1369             ## Aliases for people who like Id or ID and Last or not Last. :-)
1370              
1371             *InsertID = \&InsertedId;
1372             *LastInsertID = \&InsertedId;
1373             *LastInsertId = \&InsertedId;
1374              
1375             =item RowsAffected()
1376              
1377             Returns the number of rows affected for the most recently executed
1378             statement. This is valid only if it was for a non-SELECT. (For
1379             SELECTs, count the return values). As per the DBI, -1 is returned
1380             if there was an error.
1381              
1382             =cut
1383              
1384             sub RowsAffected($)
1385             {
1386 0     0 1   my $self = shift;
1387 0 0         if ($self->{RecentExecutedSth})
1388             {
1389 0           return $self->{RecentExecutedSth}->rows();
1390             }
1391             else
1392             {
1393 0           return ();
1394             }
1395             }
1396              
1397             =item RecentSql()
1398              
1399             Returns the SQL of the most recently executed statement.
1400              
1401             =cut
1402              
1403             sub RecentSql($)
1404             {
1405 0     0 1   my $self = shift;
1406 0 0         if ($self->{RecentExecutedSth})
1407             {
1408 0           return $self->{RecentExecutedSth}->{Statement};
1409             }
1410             else
1411             {
1412 0           return ();
1413             }
1414             }
1415              
1416             =item PreparedSql()
1417              
1418             Returns the SQL of the most recently prepared statement.
1419             (Useful for showing SQL that doesn't parse.)
1420              
1421             =cut
1422              
1423             sub PreparedSql($)
1424             {
1425 0     0 1   my $self = shift;
1426 0 0         if ($self->{RecentpreparedSth})
1427             {
1428 0           return $self->{RecentPreparedSth}->{SQL};
1429             }
1430             else
1431             {
1432 0           return ();
1433             }
1434             }
1435              
1436             =item Hash($sql)
1437              
1438             A generic query routine. Pass an SQL statement that returns a single
1439             record, and it returns a hashref with all the key/value pairs of
1440             the record.
1441              
1442             The example at the bottom of page 50 of DuBois's I book would
1443             return a value similar to:
1444              
1445             my $hashref = {
1446             last_name => 'McKinley',
1447             first_name => 'William',
1448             };
1449              
1450             On error, C<$@> has the error text, and false is returned. If the
1451             query doesn't return a record, false is returned, but C<$@> is also
1452             false.
1453              
1454             Use this routine only if the query will return a single record. Use
1455             C for queries that might return multiple records.
1456              
1457             Because calling C on a larger recordset can use a lot of
1458             memory, you may wish to call C once with a valid query and
1459             call it repeatedly with no SQL to retrieve records one at a time.
1460             It'll take more CPU to do this, but it is more memory efficient:
1461              
1462             my $record = $db->Hash("SELECT * FROM big_table");
1463             do {
1464             # ... do something with $record
1465             } while (defined($record = $db->Hash()));
1466              
1467             Note that a call to any other DWIW query resets the iterator, so only
1468             do so when you are finished with the current query.
1469              
1470             This seems like it breaks the principle of having only one obvious way
1471             to do things with this package. But it's really not all that obvious,
1472             now is it? :-)
1473              
1474             =cut
1475              
1476             sub Hash($$@)
1477             {
1478 0     0 1   my $self = shift;
1479 0   0       my $sql = shift || "";
1480 0           my @bind_vals = @_;
1481              
1482 0           $@ = "";
1483              
1484 0 0         if (not $self->{DBH})
1485             {
1486 0           $@ = "not connected in Hash()";
1487 0           return ();
1488             }
1489              
1490 0 0         print "HASH: $sql\n" if ($self->{VERBOSE});
1491              
1492 0           my $result = undef;
1493              
1494 0 0 0       if ($sql eq "" or $self->Execute($sql, @bind_vals))
1495             {
1496 0           my $sth = $self->{RecentExecutedSth};
1497 0           $result = $sth->fetchrow_hashref;
1498              
1499 0 0         if (not $result)
1500             {
1501 0 0         if ($sth->err)
1502             {
1503 0           $@ = $sth->errstr . " [$sql] ($sth)";
1504             }
1505             else
1506             {
1507 0           $@ = "";
1508             }
1509 0           $sth->finish; ## (else get error about statement handle still active)
1510             }
1511             }
1512 0 0         return $result ? $result : ();
1513             }
1514              
1515             =item Hashes($sql)
1516              
1517             A generic query routine. Given an SQL statement, returns a list of
1518             hashrefs, one per returned record, containing the key/value pairs of
1519             each record.
1520              
1521             The example in the middle of page 50 of DuBois's I would return
1522             a value similar to:
1523              
1524             my @hashrefs = (
1525             { last_name => 'Tyler', first_name => 'John', birth => '1790-03-29' },
1526             { last_name => 'Buchanan', first_name => 'James', birth => '1791-04-23' },
1527             { last_name => 'Polk', first_name => 'James K', birth => '1795-11-02' },
1528             { last_name => 'Fillmore', first_name => 'Millard', birth => '1800-01-07' },
1529             { last_name => 'Pierce', first_name => 'Franklin',birth => '1804-11-23' },
1530             );
1531              
1532             On error, C<$@> has the error text, and false is returned. If the
1533             query doesn't return a record, false is returned, but C<$@> is also
1534             false.
1535              
1536             =cut
1537              
1538             sub Hashes($$@)
1539             {
1540 0     0 1   my $self = shift;
1541 0           my $sql = shift;
1542 0           my @bind_vals = @_;
1543              
1544 0           $@ = "";
1545              
1546 0 0         if (not $self->{DBH})
1547             {
1548 0           $@ = "not connected in Hashes()";
1549 0           return ();
1550             }
1551              
1552 0 0         print "HASHES: $sql\n" if $self->{VERBOSE};
1553              
1554 0           my @records;
1555              
1556 0 0         if ($self->Execute($sql, @bind_vals))
1557             {
1558 0           my $sth = $self->{RecentExecutedSth};
1559              
1560 0           while (my $ref = $sth->fetchrow_hashref)
1561             {
1562 0           push @records, $ref;
1563             }
1564             }
1565 0           $self->{RecentExecutedSth}->finish;
1566 0           return @records;
1567             }
1568              
1569             =item Array($sql)
1570              
1571             Similar to C, but returns a list of values from the matched
1572             record. On error, the empty list is returned and the error can be
1573             found in C<$@>. If the query matches no records, an empty list is
1574             returned but C<$@> is false.
1575              
1576             The example at the bottom of page 50 of DuBois's I would return
1577             a value similar to:
1578              
1579             my @array = ( 'McKinley', 'William' );
1580              
1581             Use this routine only if the query will return a single record. Use
1582             C or C for queries that might return multiple
1583             records.
1584              
1585             =cut
1586              
1587             sub Array($$@)
1588             {
1589 0     0 1   my $self = shift;
1590 0           my $sql = shift;
1591 0           my @bind_vals = @_;
1592              
1593 0           $@ = "";
1594              
1595 0 0         if (not $self->{DBH})
1596             {
1597 0           $@ = "not connected Array()";
1598 0           return ();
1599             }
1600              
1601 0 0         print "ARRAY: $sql\n" if $self->{VERBOSE};
1602              
1603 0           my @result;
1604              
1605 0 0         if ($self->Execute($sql, @bind_vals))
1606             {
1607 0           my $sth = $self->{RecentExecutedSth};
1608 0           @result = $sth->fetchrow_array;
1609              
1610 0 0         if (not @result)
1611             {
1612 0 0         if ($sth->err)
1613             {
1614 0           $@ = $sth->errstr . " [$sql]";
1615             }
1616             else
1617             {
1618 0           $@ = "";
1619             }
1620             }
1621 0           $sth->finish; ## (else get error about statement handle still active)
1622             }
1623 0           return @result;
1624             }
1625              
1626             =pod
1627              
1628             =item Arrays($sql)
1629              
1630             A generic query routine. Given an SQL statement, returns a list of
1631             array refs, one per returned record, containing the values of each
1632             record.
1633              
1634             The example in the middle of page 50 of DuBois's I would return
1635             a value similar to:
1636              
1637             my @arrayrefs = (
1638             [ 'Tyler', 'John', '1790-03-29' ],
1639             [ 'Buchanan', 'James', '1791-04-23' ],
1640             [ 'Polk', 'James K', '1795-11-02' ],
1641             [ 'Fillmore', 'Millard', '1800-01-07' ],
1642             [ 'Pierce', 'Franklin', '1804-11-23' ],
1643             );
1644              
1645             On error, C<$@> has the error text, and false is returned. If the
1646             query doesn't return a record, false is returned, but C<$@> is also
1647             false.
1648              
1649             =cut
1650              
1651             sub Arrays($$@)
1652             {
1653 0     0 1   my $self = shift;
1654 0           my $sql = shift;
1655 0           my @bind_vals = @_;
1656              
1657 0           $@ = "";
1658              
1659 0 0         if (not $self->{DBH})
1660             {
1661 0           $@ = "not connected Arrays()";
1662 0           return ();
1663             }
1664              
1665 0 0         print "ARRAYS: $sql\n" if $self->{VERBOSE};
1666              
1667 0           my @records;
1668              
1669 0 0         if ($self->Execute($sql, @bind_vals))
1670             {
1671 0           my $sth = $self->{RecentExecutedSth};
1672              
1673 0           while (my $ref = $sth->fetchrow_arrayref)
1674             {
1675 0           push @records, [@{$ref}]; ## perldoc DBI to see why!
  0            
1676             }
1677             }
1678 0           return @records;
1679             }
1680              
1681             =pod
1682              
1683             =item FlatArray($sql)
1684              
1685             A generic query routine. Pass an SQL string, and all matching fields
1686             of all matching records are returned in one big list.
1687              
1688             If the query matches a single records, C ends up being
1689             the same as C. But if there are multiple records matched, the
1690             return list will contain a set of fields from each record.
1691              
1692             The example in the middle of page 50 of DuBois's I would return
1693             a value similar to:
1694              
1695             my @items = (
1696             'Tyler', 'John', '1790-03-29', 'Buchanan', 'James', '1791-04-23',
1697             'Polk', 'James K', '1795-11-02', 'Fillmore', 'Millard',
1698             '1800-01-07', 'Pierce', 'Franklin', '1804-11-23'
1699             );
1700              
1701             C tends to be most useful when the query returns one
1702             column per record, as with
1703              
1704             my @names = $db->FlatArray('select distinct name from mydb');
1705              
1706             or two records with a key/value relationship:
1707              
1708             my %IdToName = $db->FlatArray('select id, name from mydb');
1709              
1710             But you never know.
1711              
1712             =cut
1713              
1714             sub FlatArray($$@)
1715             {
1716 0     0 1   my $self = shift;
1717 0           my $sql = shift;
1718 0           my @bind_vals = @_;
1719              
1720 0           $@ = "";
1721              
1722 0 0         if (not $self->{DBH})
1723             {
1724 0           $@ = "not connected in FlatArray()";
1725 0           return ();
1726             }
1727              
1728 0 0         print "FLATARRAY: $sql\n" if $self->{VERBOSE};
1729              
1730 0           my @records;
1731              
1732 0 0         if ($self->Execute($sql, @bind_vals))
1733             {
1734 0           my $sth = $self->{RecentExecutedSth};
1735              
1736 0           while (my $ref = $sth->fetchrow_arrayref)
1737             {
1738 0           push @records, @{$ref};
  0            
1739             }
1740             }
1741 0           return @records;
1742             }
1743              
1744             =pod
1745              
1746             =item FlatArrayRef($sql)
1747              
1748             Works just like C but returns a ref to the array instead
1749             of copying it. This is a big win if you have very large arrays.
1750              
1751             =cut
1752              
1753             sub FlatArrayRef($$@)
1754             {
1755 0     0 1   my $self = shift;
1756 0           my $sql = shift;
1757 0           my @bind_vals = @_;
1758              
1759 0           $@ = "";
1760              
1761 0 0         if (not $self->{DBH})
1762             {
1763 0           $@ = "not connected in FlatArray()";
1764 0           return ();
1765             }
1766              
1767 0 0         print "FLATARRAY: $sql\n" if $self->{VERBOSE};
1768              
1769 0           my @records;
1770              
1771 0 0         if ($self->Execute($sql, @bind_vals))
1772             {
1773 0           my $sth = $self->{RecentExecutedSth};
1774              
1775 0           while (my $ref = $sth->fetchrow_arrayref)
1776             {
1777 0           push @records, @{$ref};
  0            
1778             }
1779             }
1780 0           return \@records;
1781             }
1782              
1783             =pod
1784              
1785             =item Scalar($sql)
1786              
1787             A generic query routine. Pass an SQL string, and a scalar is
1788             returned.
1789              
1790             If the query matches a single row column pair this is what you want.
1791             C is useful for computational queries, count(*), max(xxx),
1792             etc.
1793              
1794             my $max = $dbh->Scalar('select max(id) from personnel');
1795              
1796             If the result set contains more than one value, the first value is returned
1797             and a warning is issued.
1798              
1799             =cut
1800              
1801             sub Scalar()
1802             {
1803 0     0 1   my $self = shift;
1804 0           my $sql = shift;
1805 0           my @bind_vals = @_;
1806 0           my $ret;
1807              
1808 0           $@ = "";
1809              
1810 0 0         if (not $self->{DBH})
1811             {
1812 0           $@ = "not connected in Scalar()";
1813 0           return ();
1814             }
1815              
1816 0 0         print STDERR "SCALAR: $sql\n" if $self->{VERBOSE};
1817              
1818 0 0         if ($self->Execute($sql, @bind_vals))
1819             {
1820 0           my $sth = $self->{RecentExecutedSth};
1821              
1822 0 0 0       if ($sth->rows() > 1 or $sth->{NUM_OF_FIELDS} > 1)
1823             {
1824 0           warn "$sql in DWIW::Scalar returned more than 1 row and/or column";
1825             }
1826 0           my $ref = $sth->fetchrow_arrayref;
1827 0           $ret = ${$ref}[0];
  0            
1828 0           $sth->finish; ## (else get error about statement handle still active)
1829             }
1830 0           return $ret;
1831             }
1832              
1833             =pod
1834              
1835             =item CSV($sql)
1836              
1837             A generic query routine. Pass an SQL string, and a CSV scalar is
1838             returned.
1839              
1840             my $max = $dbh->CSV('select * from personnel');
1841              
1842             The example in the middle of page 50 of DuBois\'s I would
1843             return a value similar to:
1844              
1845             my $item = <
1846             "Tyler","John","1790-03-29"
1847             "Buchanan","James","1791-04-23"
1848             "Polk","James K","1795-11-02"
1849             "Fillmore","Millard","1800-01-07",
1850             "Pierce","Franklin","1804-11-23"
1851             END_OF_CSV
1852              
1853             =cut
1854              
1855             sub CSV()
1856             {
1857 0     0 1   my $self = shift;
1858 0           my $sql = shift;
1859 0           my $ret;
1860              
1861 0           $@ = "";
1862              
1863 0 0         if (not $self->{DBH})
1864             {
1865 0           $@ = "not connected in Scalar()";
1866 0           return ();
1867             }
1868              
1869 0 0         print STDERR "SCALAR: $sql\n" if $self->{VERBOSE};
1870              
1871 0 0         if ($self->Execute($sql))
1872             {
1873 0           my $sth = $self->{RecentExecutedSth};
1874              
1875 0           while (my $ref = $sth->fetchrow_arrayref)
1876             {
1877 0           my $col = 0;
1878 0           foreach (@{$ref})
  0            
1879             {
1880 0 0         if (defined($_))
1881             {
1882 0 0         $ret .= ($sth->{mysql_type_name}[$col++] =~
1883             /(char|text|binary|blob)/) ?
1884             "\"$_\"," : "$_,";
1885             }
1886             else
1887             {
1888 0           $ret .= "NULL,";
1889             }
1890             }
1891              
1892 0           $ret =~ s/,$/\n/;
1893             }
1894             }
1895              
1896 0           return $ret;
1897             }
1898              
1899             =pod
1900              
1901             =item Verbose([boolean])
1902              
1903             Returns the value of the verbose flag associated with the connection.
1904             If a value is provided, it is taken as the new value to install.
1905             Verbose is OFF by default. If you pass a true value, you'll get some
1906             verbose output each time a query executes.
1907              
1908             Returns the current value.
1909              
1910             =cut
1911              
1912             sub Verbose()
1913             {
1914 0     0 1   my $self = shift;
1915 0           my $val = $self->{VERBOSE};
1916              
1917 0 0         if (@_)
1918             {
1919 0           $self->{VERBOSE} = shift;
1920             }
1921              
1922 0           return $val;
1923             }
1924              
1925             =pod
1926              
1927             =item Quiet()
1928              
1929             When errors occur, a message will be sent to STDOUT if Quiet is true
1930             (it is by default). Pass a false value to disable it.
1931              
1932             Returns the current value.
1933              
1934             =cut
1935              
1936             sub Quiet()
1937             {
1938 0     0 1   my $self = shift;
1939              
1940 0 0         if (@_)
1941             {
1942 0           $self->{QUIET} = shift;
1943             }
1944              
1945 0           return $self->{QUIET};
1946             }
1947              
1948             =pod
1949              
1950             =item Safe()
1951              
1952             Enable or disable "safe" mode (on by default). In "safe" mode, you
1953             must prefix a native DBI method call with "dbi_" in order to call it.
1954             If safe mode is off, you can call native DBI methods using their real
1955             names.
1956              
1957             For example, in safe mode, you'd write something like this:
1958              
1959             $db->dbi_commit;
1960              
1961             but in unsafe mode you could use:
1962              
1963             $db->commit;
1964              
1965             The rationale behind having a safe mode is that you probably don't
1966             want to mix DBIx::DWIW and DBI method calls on an object unless you
1967             know what you're doing. You need to opt in.
1968              
1969             C returns the current value.
1970              
1971             =cut
1972              
1973             sub Safe($;$)
1974             {
1975 0     0 1   my $self = shift;
1976              
1977 0 0         if (@_)
1978             {
1979 0           $self->{SAFE} = shift;
1980             }
1981              
1982 0           return $self->{SAFE};
1983             }
1984              
1985             =pod
1986              
1987             =item dbh()
1988              
1989             Returns the real DBI database handle for the connection.
1990              
1991             =cut
1992              
1993             sub dbh($)
1994             {
1995 0     0 1   my $self = shift;
1996 0           return $self->{DBH};
1997             }
1998              
1999             =pod
2000              
2001             =item RetryWait($error)
2002              
2003             This method is called each time there is a error (usually caused by a
2004             network outage or a server going down) which a sub-class may want to
2005             examine and decide how to continue.
2006              
2007             If C returns 1, the operation which was being attempted when
2008             the failure occurred is retried. If C returns 0, the action
2009             fails.
2010              
2011             The default implementation causes your application to make up to three
2012             immediate reconnect attempts, and if all fail, emit a message to STDERR
2013             (via a C call) and then sleep for 30 seconds. After 30 seconds, the
2014             warning and sleep repeat until successful.
2015              
2016             You probably want to override this so method that it will eventually give
2017             up. Otherwise your application may hang forever. The default method does
2018             maintain a count of how many times the retry has been attempted in
2019             C<$self->{RetryCount}>.
2020              
2021             Note that RetryWait() is not be called in the middle of transaction.
2022             In that case, we assume that the transaction will have been rolled
2023             back by the server and you'll get an error.
2024              
2025             =cut
2026              
2027             sub RetryWait($$)
2028             {
2029 0     0 1   my $self = shift;
2030 0           my $error = shift;
2031              
2032 0 0         if ($self->{RetryCount} > 9) # we failed too many times, die already.
2033             {
2034 0           return 0;
2035             }
2036              
2037             ##
2038             ## Immediately retry a few times, to pick up timed-out connections
2039             ##
2040 0 0         if ($self->{RetryCount}++ <= 2)
    0          
2041             {
2042 0           return 1;
2043             }
2044             elsif (not $self->{RetryStart})
2045             {
2046 0           $self->{RetryStart} = time;
2047 0           $self->{RetryCommand} = $0;
2048 0           $0 = "(waiting on db) $0";
2049             }
2050              
2051 0 0         if (not $self->{QUIET}) {
2052 0           my $now = localtime;
2053 0           warn "$now: db connection down ($error), retry in 30 seconds";
2054             }
2055 0           sleep 30;
2056              
2057 0           return 1;
2058             }
2059              
2060             ##
2061             ## [non-public member function]
2062             ##
2063             ## Called whenever a database operation has been successful, to reset the
2064             ## internal counters, and to send a "back up" message, if appropriate.
2065             ##
2066             sub _OperationSuccessful($)
2067             {
2068 0     0     my $self = shift;
2069              
2070 0 0 0       if (not $self->{QUIET} and $self->{RetryCount} > 1)
2071             {
2072 0           my $now = localtime;
2073 0           my $since = localtime($self->{RetryStart});
2074 0           warn "$now: $self->{DESC} is back up (down since $since)\n";
2075             }
2076              
2077 0 0         if ($self->{RetryCommand}) {
2078 0           $0 = $self->{RetryCommand};
2079 0           undef $self->{RetryCommand};
2080             }
2081 0           $self->{RetryCount} = 0;
2082 0           undef $self->{RetryStart};
2083             }
2084              
2085             ##
2086             ## [non-public member function]
2087             ##
2088             ## Called whenever a database operation has finally failed after all the
2089             ## retries that will be done for it.
2090             ##
2091             sub _OperationFailed($)
2092             {
2093 0     0     my $self = shift;
2094 0 0         $0 = $self->{RetryCommand} if $self->{RetryCommand};
2095              
2096 0           $self->{RetryCount} = 0;
2097 0           $self->{RetryStart} = undef;
2098 0           $self->{RetryCommand}= undef;
2099             }
2100              
2101             =pod
2102              
2103             =back
2104              
2105             =head1 Local Configuration
2106              
2107             There are two ways to to configure C for your local
2108             databases. The simplest (but least flexible) way is to create a
2109             package like:
2110              
2111             package MyDBI;
2112             @ISA = 'DBIx::DWIW';
2113             use strict;
2114              
2115             sub DefaultDB { "MyDatabase" }
2116             sub DefaultUser { "defaultuser" }
2117             sub DefaultPass { "paSSw0rd" }
2118             sub DefaultHost { "mysql.somehost.com" }
2119             sub DefaultPort { 3306 }
2120              
2121             The four routines override those in C, and explicitly
2122             provide exactly what's needed to contact the given database.
2123              
2124             The user can then use
2125              
2126             use MyDBI
2127             my $db = MyDBI->Connect();
2128              
2129             and not have to worry about the details.
2130              
2131             A more flexible approach appropriate for multiple-database or
2132             multiple-user installations is to create a more complex package, such
2133             as the C which was included in the C sub-directory
2134             of the DBIx::DWIW distribution.
2135              
2136             In that setup, you have quit a bit of control over what connection
2137             parameters are used. And, since it's Just Perl Code, you can do
2138             anything you need in there.
2139              
2140             =head2 Methods Related to Connection Defaults
2141              
2142             The following methods are provided to support this in sub-classes:
2143              
2144             =over
2145              
2146             =item LocalConfig($name)
2147              
2148             Passed a configuration name, C should return a list of
2149             connection parameters suitable for passing to C.
2150              
2151             By default, C simply returns an empty list.
2152              
2153             =cut
2154              
2155             sub LocalConfig($$)
2156             {
2157 0     0 1   return ();
2158             }
2159              
2160             =pod
2161              
2162             =item DefaultDB($config_name)
2163              
2164             Returns the default database name for the given configuration. Calls
2165             C to get it.
2166              
2167             =cut
2168              
2169             sub DefaultDB($)
2170             {
2171 0     0 1   my ($class, $DB) = @_;
2172              
2173 0 0         if (my $DbConfig = $class->LocalConfig($DB))
2174             {
2175 0           return $DbConfig->{DB};
2176             }
2177              
2178 0           return ();
2179             }
2180              
2181             =pod
2182              
2183             =item DefaultUser($config_name)
2184              
2185             Returns the default username for the given configuration. Calls
2186             C to get it.
2187              
2188             =cut
2189              
2190             sub DefaultUser($$)
2191             {
2192 0     0 1   my ($class, $DB) = @_;
2193              
2194 0 0         if (my $DbConfig = $class->LocalConfig($DB))
2195             {
2196 0           return $DbConfig->{User};
2197             }
2198 0           return ();
2199             }
2200              
2201             =pod
2202              
2203             =item DefaultPass($config_name)
2204              
2205             Returns the default password for the given configuration.
2206             Calls C to get it.
2207              
2208             =cut
2209              
2210             sub DefaultPass($$)
2211             {
2212 0     0 1   my ($class, $DB, $User) = @_;
2213 0 0         if (my $DbConfig = $class->LocalConfig($DB))
2214             {
2215 0 0         if (defined $DbConfig->{Pass})
2216             {
2217 0           return $DbConfig->{Pass};
2218             }
2219             }
2220 0           return ();
2221             }
2222              
2223             =pod
2224              
2225             =item DefaultHost($config_name)
2226              
2227             Returns the default hostname for the given configuration. Calls
2228             C to get it.
2229              
2230             =cut
2231              
2232             sub DefaultHost($$)
2233             {
2234 0     0 1   my ($class, $DB) = @_;
2235 0 0         if (my $DbConfig = $class->LocalConfig($DB))
2236             {
2237 0 0         if ($DbConfig->{Host})
2238             {
2239 0           return $DbConfig->{Host};
2240             }
2241             }
2242 0           return ();
2243             }
2244              
2245             =pod
2246              
2247             =item DefaultPort($config_name)
2248              
2249             Returns the default port number for the given configuration. Calls
2250             C to get it.
2251              
2252             =cut
2253              
2254             sub DefaultPort($$)
2255             {
2256 0     0 1   my ($class, $DB) = @_;
2257 0 0         if (my $DbConfig = $class->LocalConfig($DB))
2258             {
2259 0 0         if ($DbConfig->{Port})
2260             {
2261 0 0         if ($DbConfig->{Host} eq hostname)
2262             {
2263 0           return (); #use local connection
2264             }
2265             else
2266             {
2267 0           return $DbConfig->{Host};
2268             }
2269             }
2270             }
2271 0           return ();
2272             }
2273              
2274             =pod
2275              
2276             =head2 Transaction Methods
2277              
2278             =over
2279              
2280             =item Begin([name)
2281              
2282             Begin a new transaction, optionally naming it.
2283              
2284             =cut
2285              
2286             sub Begin
2287             {
2288 0     0 1   my $self = shift;
2289 0           my $name = shift;
2290              
2291             ## if one is already running, just increment count if we need to
2292 0 0         if ($self->{TrxRunning})
2293             {
2294 0 0         print "Begin() called with running transaction - " if $self->{VERBOSE};
2295 0 0 0       if ($self->{BeginCount} and not defined $name)
2296             {
2297 0 0         print "$self->{BeginCount}\n" if $self->{VERBOSE};
2298 0           $self->{BeginCount}++;
2299             }
2300             else
2301             {
2302 0 0         print "$self->{TrxName}\n" if $self->{VERBOSE};
2303             }
2304              
2305 0           return 1;
2306             }
2307              
2308 0 0         print "Begin() starting new transaction - " if $self->{VERBOSE};
2309              
2310             ## it is either named or not.
2311 0 0         if (defined $name)
2312             {
2313 0           $self->{TrxName} = $name;
2314 0 0         print "$name\n" if $self->{VERBOSE};
2315             }
2316             else
2317             {
2318 0           $self->{BeginCount} = 1;
2319 0 0         print "(auto-count)\n" if $self->{VERBOSE};
2320             }
2321              
2322 0           $self->{TrxRunning} = 1;
2323 0           eval { $self->{DBH}->{AutoCommit} = 0 };
  0            
2324 0           $self->{DBH}->{mysql_auto_reconnect} = 0;
2325 0           return $self->{DBH}->begin_work;
2326             }
2327              
2328             =pod
2329              
2330             =item Commit([name)
2331              
2332             Commit the current transaction (or named transaction).
2333              
2334             =cut
2335              
2336             sub Commit
2337             {
2338 0     0 1   my $self = shift;
2339 0           my $name = shift;
2340              
2341             ## if there is no transaction running now
2342 0 0         if (not $self->{TrxRunning})
2343             {
2344 0 0         print "Commit() called without a transaction\n" if $self->{VERBOSE};
2345 0           return 0;
2346             }
2347              
2348             ## if the controlling transaction was auto-counting
2349 0 0         if ($self->{BeginCount})
2350             {
2351             ## if this commit was named, skip it.
2352 0 0         if (defined $name)
2353             {
2354 0 0         print "Commit() skipping named commit on auto-counting transaction"
2355             if $self->{VERBOSE};
2356 0           return 0;
2357             }
2358              
2359             ## decrement
2360 0           $self->{BeginCount}--;
2361              
2362             ## need to commit
2363 0 0         if ($self->{BeginCount} == 0)
    0          
2364             {
2365 0 0         print "Commit()ing auto-counting transaction\n" if $self->{VERBOSE};
2366 0           my $rc = $self->{DBH}->commit;
2367 0           $self->{TrxRunning} = 0;
2368 0           eval { $self->{DBH}->{AutoCommit} = 1; };
  0            
2369 0           $self->{DBH}->{mysql_auto_reconnect} = 1;
2370 0           $self->{BeginCount} = 0;
2371 0           $self->{TrxName} = undef; ## just in case
2372 0           return $rc;
2373             }
2374             elsif ($self->{BeginCount} > 0)
2375             {
2376 0 0         print "Commit() decremented BeginCount\n" if $self->{VERBOSE};
2377 0           return 0;
2378             }
2379             else
2380             {
2381 0 0         print "Commit() is confused -- BeginCount went negative!\n"
2382             if $self->{VERBOSE};
2383 0           $@ = "Commit() is confused. BeginCount went negative!";
2384 0           return ();
2385             }
2386              
2387             }
2388              
2389             ## if the controlling transaction was named, deal with it.
2390              
2391 0 0         if (defined $self->{TrxName})
2392             {
2393             ## if the commit was not named, do nothing.
2394 0 0         if (not defined $name)
2395             {
2396 0 0         print "Commit() skipping unnamed commit on named begin\n"
2397             if $self->{VERBOSE};
2398 0           return 0;
2399             }
2400              
2401             ## if the commit was named, the names need to match.
2402 0 0         if ($name ne $self->{TrxName})
2403             {
2404 0 0         print "Commit() skipping named commit due to name mismatch\n"
2405             if $self->{VERBOSE};
2406 0           return 0;
2407             }
2408              
2409 0           my $rc;
2410              
2411             ## if they match, commit.
2412 0 0         if ($name eq $self->{TrxName})
2413             {
2414 0 0         print "Commit()ing transaction - $self->{TrxName}\n"
2415             if $self->{VERBOSE};
2416 0           $rc = $self->{DBH}->commit;
2417 0           $self->{TrxRunning} = 0;
2418 0           eval { $self->{DBH}->{AutoCommit} = 1 };
  0            
2419 0           $self->{DBH}->{mysql_auto_reconnect} = 1;
2420 0           $self->{BeginCount} = 0; ## just in case
2421 0           $self->{TrxName} = undef;
2422 0           return $rc;
2423             }
2424             }
2425              
2426             ## otherwise, we're confused. we should never end up here.
2427             else
2428             {
2429 0 0         print "Commit() is confused -- something is wonky\n" if $self->{VERBOSE};
2430 0           $@ = "Commit() is confused. Internal state problem.";
2431 0           return ();
2432             }
2433              
2434             }
2435              
2436             =pod
2437              
2438             =item Rollback()
2439              
2440             Rollback the current transaction.
2441              
2442             =cut
2443              
2444             sub Rollback
2445             {
2446 0     0 1   my $self = shift;
2447              
2448 0 0         if (not $self->{TrxRunning})
2449             {
2450 0 0         print "Rollback() called without a transaction\n" if $self->{VERBOSE};
2451 0           return;
2452             }
2453              
2454             ## rollback via DBI and reset things
2455 0           my $rc = $self->{DBH}->rollback;
2456 0           $self->{TrxRunning} = 0;
2457 0           eval { $self->{DBH}->{AutoCommit} = 1 };
  0            
2458 0           $self->{DBH}->{mysql_auto_reconnect} = 1;
2459 0           $self->{BeginCount} = 0;
2460 0           $self->{TrxName} = undef;
2461 0 0         print "Rollback() transaction\n" if $self->{VERBOSE};
2462 0           return $rc;
2463             }
2464              
2465             =pod
2466              
2467             =back
2468              
2469             =cut
2470              
2471             ######################################################################
2472              
2473             =pod
2474              
2475             =back
2476              
2477             =head1 The DBIx::DWIW::Statement CLASS
2478              
2479             Calling C on a database handle returns a
2480             DBIx::DWIW::Statement object which acts like a limited DBI statement
2481             handle.
2482              
2483             =head2 Methods
2484              
2485             The following methods can be called on a statement object.
2486              
2487             =over
2488              
2489             =cut
2490              
2491             package DBIx::DWIW::Statement;
2492              
2493 1     1   10 use vars '$AUTOLOAD';
  1         2  
  1         281  
2494              
2495             sub AUTOLOAD
2496             {
2497 0     0     my $self = shift;
2498 0           my $method = $AUTOLOAD;
2499              
2500 0           $method =~ s/.*:://; ## strip the package name
2501              
2502 0           my $orig_method = $method;
2503              
2504 0 0         if ($self->{SAFE})
2505             {
2506 0 0         if (not $method =~ s/^dbi_//)
2507             {
2508 0           Carp::cluck("undefined or unsafe method ($orig_method) called in");
2509             }
2510             }
2511              
2512 0 0 0       if ($self->{DBI_STH} and $self->{DBI_STH}->can($method))
2513             {
2514 0           $self->{DBI_STH}->$method(@_);
2515             }
2516             else
2517             {
2518 0           Carp::cluck("undefined method ($orig_method) called");
2519             }
2520             }
2521              
2522             ## This looks funny, so I should probably explain what is going on.
2523             ## When Execute() is called on a statement handle, we need to know
2524             ## which $db object to use for execution. Luckily that was stashed
2525             ## away in $self->{PARENT} when the statement was created. So we call
2526             ## the _Execute method on our parent $db object and pass ourselves.
2527             ## Since $db->_Execute() only accepts Statement objects, this is just
2528             ## as it should be.
2529              
2530             =pod
2531              
2532             =item Execute([@values])
2533              
2534             Executes the statement. If values are provided, they'll be substituted
2535             for the appropriate placeholders in the SQL.
2536              
2537             =cut
2538              
2539             sub Execute(@)
2540             {
2541 0     0     my $self = shift;
2542 0           my @bind_vals = @_;
2543 0           my $db = $self->{PARENT};
2544              
2545 0           return $db->_Execute($self, @bind_vals);
2546             }
2547              
2548             sub DESTROY
2549 0     0     {
2550             # my $self = shift;
2551              
2552             # return unless defined $self;
2553             # return unless ref($self);
2554              
2555             # if ($self->{DBI_STH})
2556             # {
2557             # $self->{DBI_STH}->finish();
2558             # }
2559             }
2560              
2561             1;
2562              
2563             =pod
2564              
2565             =back
2566              
2567             =head1 AUTHORS
2568              
2569             DBIx::DWIW evolved out of some Perl modules that we developed and used
2570             in Yahoo! Finance (http://finance.yahoo.com). The following people
2571             contributed to its development:
2572              
2573             Jeffrey Friedl (jfriedl@yahoo.com)
2574             rayg (rayg@bitbaron.com)
2575             John Hagelgans
2576             Jeremy Zawodny (Jeremy@Zawodny.com)
2577              
2578             =head1 CREDITS
2579              
2580             The following folks have provided feedback, patches, and other help
2581             along the way:
2582              
2583             Eric E. Bowles (bowles@ambisys.com)
2584             David Yan (davidyan@yahoo-inc.com)
2585             DH
2586             Toby Elliott (telliott@yahoo-inc.com)
2587             Keith C. Ivey (keith@smokefreedc.org)
2588             Brian Webb (brianw@yahoo-inc.com)
2589             Steve Friedl (steve@unixwiz.net)
2590              
2591             Please direct comments, questions, etc to Jeremy for the time being.
2592             Thanks.
2593              
2594             =head1 COPYRIGHT
2595              
2596             DBIx::DWIW is Copyright (c) 2001, Yahoo! Inc. All rights reserved.
2597              
2598             You may distribute under the same terms of the Artistic License, as
2599             specified in the Perl README file.
2600              
2601             =head1 SEE ALSO
2602              
2603             L, L
2604              
2605             Jeremy's presentation at the 2001 Open Source Database Summit, which
2606             introduced DBIx::DWIW is available from:
2607              
2608             http://jeremy.zawodny.com/mysql/
2609              
2610             =cut