File Coverage

blib/lib/Basset/DB.pm
Criterion Covered Total %
statement 4 6 66.6
branch n/a
condition n/a
subroutine 2 2 100.0
pod n/a
total 6 8 75.0


line stmt bran cond sub pod time code
1             package Basset::DB;
2              
3             #Basset::DB 2002, 2003, 2004, 2005, 2006 James A Thomason III
4             #Basset::DB is distributed under the terms of the Perl Artistic License.
5              
6             $VERSION = '1.03';
7              
8             =pod
9              
10             =head1 NAME
11              
12             Basset::DB - talks to your database and gives you a few helper database methods.
13              
14             =head1 AUTHOR
15              
16             Jim Thomason, jim@jimandkoka.com
17              
18             =head1 SYNOPSIS
19              
20             #buried in the bowels of a module somewhere
21             my $driver = Basset::DB->new();
22             my $stmt = $driver->prepare('select * from some_table');
23              
24             =head1 DESCRIPTION
25              
26             You have a database. You're using Basset::Object::Persistent. You need to store objects. You need
27             to talk to your database. You're using Basset::DB::Table for all of your table related stuff. But,
28             some things are just simply database related (like connecting, transactions, etc.) for that, you
29             need something higher. Basset::DB does just that.
30              
31             =cut
32              
33 1     1   1428 use Basset::Object;
  1         3  
  1         47  
34 1     1   523 use DBI 1.32 qw(:sql_types);
  0            
  0            
35              
36             our @ISA = Basset::Object->pkg_for_type('object');
37              
38             use strict;
39             use warnings;
40              
41             =pod
42              
43             =head1 ATTRIBUTES
44              
45             =cut
46              
47             #read only attribute. Hands you back the internal DBI handle.
48              
49             __PACKAGE__->add_attr('handle');
50              
51             =pod
52              
53             =begin btest(handle)
54              
55             my $o = __PACKAGE__->new();
56             $test->ok($o, "Got object");
57             $test->is(scalar(__PACKAGE__->handle), undef, "could not call object method as class method");
58             $test->is(__PACKAGE__->errcode, "BO-08", "proper error code");
59             $test->is($o->handle('abc'), 'abc', 'set handle to abc');
60             $test->is($o->handle(), 'abc', 'read value of handle - abc');
61             my $h = {};
62             $test->ok($h, 'got hashref');
63             $test->is($o->handle($h), $h, 'set handle to hashref');
64             $test->is($o->handle(), $h, 'read value of handle - hashref');
65             my $a = [];
66             $test->ok($a, 'got arrayref');
67             $test->is($o->handle($a), $a, 'set handle to arrayref');
68             $test->is($o->handle(), $a, 'read value of handle - arrayref');
69              
70             my $poolkey = join(',', map{defined $_ ? $_ : 'undef'} ($o->dsn, $o->user, $o->pass));
71             delete $o->pool->{$poolkey};
72              
73             =end btest(handle)
74              
75             =cut
76              
77              
78             __PACKAGE__->add_attr('dsn');
79              
80             =pod
81              
82             =begin btest(dsn)
83              
84             my $o = __PACKAGE__->new();
85             my $dsn = $o->dsn;
86             $test->ok($o, "Got object");
87             $test->is(scalar(__PACKAGE__->dsn), undef, "could not call object method as class method");
88             $test->is(__PACKAGE__->errcode, "BO-08", "proper error code");
89             $test->is($o->dsn('abc'), 'abc', 'set dsn to abc');
90             $test->is($o->dsn(), 'abc', 'read value of dsn - abc');
91             my $h = {};
92             $test->ok($h, 'got hashref');
93             $test->is($o->dsn($h), $h, 'set dsn to hashref');
94             $test->is($o->dsn(), $h, 'read value of dsn - hashref');
95             my $a = [];
96             $test->ok($a, 'got arrayref');
97             $test->is($o->dsn($a), $a, 'set dsn to arrayref');
98             $test->is($o->dsn(), $a, 'read value of dsn - arrayref');
99             $test->is($o->dsn($dsn), $dsn, "reset dsn");
100              
101             my $poolkey = join(',', map{defined $_ ? $_ : 'undef'} ($o->dsn, $o->user, $o->pass));
102             delete $o->pool->{$poolkey};
103              
104             =end btest(dsn)
105              
106             =cut
107              
108             __PACKAGE__->add_attr('user');
109              
110             =pod
111              
112             =begin btest(user)
113              
114             my $o = __PACKAGE__->new();
115             my $user = $o->user;
116             $test->ok($o, "Got object");
117             $test->is(scalar(__PACKAGE__->user), undef, "could not call object method as class method");
118             $test->is(__PACKAGE__->errcode, "BO-08", "proper error code");
119             $test->is($o->user('abc'), 'abc', 'set user to abc');
120             $test->is($o->user(), 'abc', 'read value of user - abc');
121             my $h = {};
122             $test->ok($h, 'got hashref');
123             $test->is($o->user($h), $h, 'set user to hashref');
124             $test->is($o->user(), $h, 'read value of user - hashref');
125             my $a = [];
126             $test->ok($a, 'got arrayref');
127             $test->is($o->user($a), $a, 'set user to arrayref');
128             $test->is($o->user(), $a, 'read value of user - arrayref');
129             $test->is($o->user($user), $user, "reset user");
130              
131             my $poolkey = join(',', map{defined $_ ? $_ : 'undef'} ($o->dsn, $o->user, $o->pass));
132             delete $o->pool->{$poolkey};
133              
134             =end btest(user)
135              
136             =cut
137              
138             __PACKAGE__->add_attr('pass');
139              
140             =pod
141              
142             =begin btest(pass)
143              
144             my $o = __PACKAGE__->new();
145             my $pass = $o->pass();
146             $test->ok($o, "Got object");
147             $test->is(scalar(__PACKAGE__->pass), undef, "could not call object method as class method");
148             $test->is(__PACKAGE__->errcode, "BO-08", "proper error code");
149             $test->is(scalar($o->pass), undef, 'pass is undefined');
150             $test->is($o->pass('abc'), 'abc', 'set pass to abc');
151             $test->is($o->pass(), 'abc', 'read value of pass - abc');
152             my $h = {};
153             $test->ok($h, 'got hashref');
154             $test->is($o->pass($h), $h, 'set pass to hashref');
155             $test->is($o->pass(), $h, 'read value of pass - hashref');
156             my $a = [];
157             $test->ok($a, 'got arrayref');
158             $test->is($o->pass($a), $a, 'set pass to arrayref');
159             $test->is($o->pass(), $a, 'read value of pass - arrayref');
160             $test->is($o->pass($pass), $pass, "reset pass");
161              
162             my $poolkey = join(',', map{defined $_ ? $_ : 'undef'} ($o->dsn, $o->user, $o->pass));
163             delete $o->pool->{$poolkey};
164              
165             =end btest(pass)
166              
167             =cut
168              
169              
170             =pod
171              
172             =over
173              
174             =item failed
175              
176             Boolean attribute, set internally if the current transaction has been failed.
177              
178             =cut
179              
180             __PACKAGE__->add_attr('failed');
181              
182             =pod
183              
184             =begin btest(failed)
185              
186             my $o = __PACKAGE__->new();
187             $test->ok($o, "Got object");
188             $test->is(scalar(__PACKAGE__->failed), undef, "could not call object method as class method");
189             $test->is(__PACKAGE__->errcode, "BO-08", "proper error code");
190             $test->is(scalar($o->failed), undef, 'failed is undefined');
191             $test->is($o->failed('abc'), 'abc', 'set failed to abc');
192             $test->is($o->failed(), 'abc', 'read value of failed - abc');
193             my $h = {};
194             $test->ok($h, 'got hashref');
195             $test->is($o->failed($h), $h, 'set failed to hashref');
196             $test->is($o->failed(), $h, 'read value of failed - hashref');
197             my $a = [];
198             $test->ok($a, 'got arrayref');
199             $test->is($o->failed($a), $a, 'set failed to arrayref');
200             $test->is($o->failed(), $a, 'read value of failed - arrayref');
201              
202             my $poolkey = join(',', map{defined $_ ? $_ : 'undef'} ($o->dsn, $o->user, $o->pass));
203             delete $o->pool->{$poolkey};
204              
205             =end btest(failed)
206              
207             =back
208              
209             =cut
210              
211              
212              
213              
214             =pod
215              
216             =head1 METHODS
217              
218             =cut
219              
220             sub init {
221              
222             my $self = shift->SUPER::init(
223             'stack' => 0,
224             @_
225             ) or return;
226              
227             my $poolkey = join(',', map{defined $_ ? $_ : 'undef'} ($self->pkg, $self->dsn, $self->user, $self->pass));
228              
229             if (my $pooledobj = $self->pool->{$poolkey}) {
230             $self = $pooledobj;
231             }
232              
233             $self->recreate_handle() or return;
234              
235             $self->pool->{$poolkey} = $self;
236              
237             return $self;
238             }
239              
240             __PACKAGE__->add_class_attr('pool', {});
241              
242             =pod
243              
244             =begin btest(new__only)
245              
246             $test->ok(1, "Due to pooling, SUPER new tests cannot work. Assumes success");
247              
248             =end btest(new__only)
249              
250             =pod
251              
252             =begin btest(init)
253              
254             my $o = __PACKAGE__->new();
255             $test->ok($o, "got object for init");
256             $test->ok($o->dsn, "DSN is defined");
257             $test->ok($o->user, "user is defined");
258              
259             local $@ = undef;
260              
261             my $o2 = __PACKAGE__->new();
262             $test->ok($o, "got second object for init");
263             $test->is($o, $o2, "objects match, due to pooling");
264             $test->is($o->handle, $o2->handle, "handles match, due to pooling");
265              
266              
267             =end btest(init)
268              
269             =cut
270              
271             =pod
272              
273             =item recreate_handle
274              
275             recreates the database handle with the original parameters. This will blindly blow away the DBI handle,
276             so be careful with this method.
277              
278             =cut
279              
280             sub recreate_handle {
281             my $self = shift;
282            
283             if ($self->handle && $self->stack) {
284             $self->notify("warnings", "Warning - driver destroyed with transaction stack");
285             }
286              
287             if ($self->handle) {
288             $self->wipe();
289             $self->handle->disconnect;
290             }
291              
292             my $h = $self->create_handle(
293             'dsn' => $self->dsn,
294             'user' => $self->user,
295             'pass' => $self->pass,
296             'AutoCommit' => 0,
297             ) or return;
298            
299             return $self->handle($h);
300             }
301              
302             =pod
303              
304             =begin btest(recreate_handle)
305              
306             =end btest(recreate_handle)
307              
308             =cut
309              
310             =pod
311              
312             =over
313              
314             =item create_handle
315              
316             Takes a hash of values (dsh, user, pass) which are used to create a new database handel.
317             By default, uses DBI's connect_cached method. Can be overridden in subclasses.
318              
319             =cut
320              
321             sub create_handle {
322             my $class = shift;
323             my %init = @_;
324              
325             my $h = DBI->connect_cached(
326             $init{'dsn'},
327             $init{'user'},
328             $init{'pass'},
329             {'AutoCommit' => $init{'AutoCommit'}},
330             ) or return $class->error(DBI->errstr, "BD-01");
331              
332             return $h;
333             }
334              
335             =pod
336              
337             =begin btest(create_handle)
338              
339             local $@ = undef;
340             eval {
341             __PACKAGE__->create_handle(); #fails w/o args
342             };
343             $test->ok($@, "DBI connect failed");
344              
345             =end btest(create_handle)
346              
347             =cut
348              
349              
350             sub DESTROY {
351             my $self = shift;
352             if ($self->handle && $self->stack) {
353             $self->notify("warnings", "Warning - driver destroyed with transaction stack");
354             $self->stack(0);
355             $self->handle->rollback;
356             $self->handle->disconnect;
357             };
358             };
359              
360             =pod
361              
362             =begin btest(DESTROY)
363              
364             =end btest(DESTROY)
365              
366             =cut
367              
368              
369             =pod
370              
371             =item AUTOLOAD
372              
373             friggin' DBI cannot be subclassed. So AUTOLOAD sits in between. Any method called on a Basset::DB
374             object that it doesn't understand creates a new method that passes through to the internal handle
375             and calls the method on that. So, obviously, only use DBI methods.
376              
377             =cut
378              
379             sub AUTOLOAD {
380             my $self = shift;
381             (my $method = $Basset::DB::AUTOLOAD) =~ s/^(.+):://;
382            
383             if ($method ne 'DESTROY') {
384              
385             if (defined $self->handle){
386             no strict 'refs';
387             my $pkg = $self->pkg;
388            
389             *{$pkg . "::$method"} = sub {
390             my $self = shift;
391              
392             if (my $handle = $self->handle) {
393             local $@ = undef;
394             my $rc = undef;
395             eval {
396             $rc = $handle->$method(@_);
397             };
398             if ($@) {
399             return $self->error("Cannot call method ($method) : DBI does not support ($@)", "BD-14");
400             } else {
401             return $rc || $self->error($handle->errstr, "BD-11");
402             };
403             } else {
404             return $self->error("Cannot call method ($method) : no handle", "BD-12");
405             }
406             };
407              
408             return $self->$method(@_);
409             # shift->$accessor($method, @static_args, @_)};
410             # return $self->handle->$method(@_);
411             } else {
412             return $self->error("Cannot do anything without handle", "BD-09");
413             };
414             }
415              
416             };
417              
418             =pod
419              
420             =begin btest(AUTOLOAD)
421              
422             =end btest(AUTOLOAD)
423              
424             =cut
425              
426              
427             __PACKAGE__->add_attr('stack');
428              
429             {
430             my $stacks = {};
431              
432             =pod
433              
434             =item stack
435              
436             This is your transaction stack for your driver. You will rarely (if ever) need to see
437             this directly.
438              
439             $driver->begin();
440             print $driver->stack(); #1
441             $driver->begin();
442             print $driver->stack(); #2
443             $driver->begin();
444             print $driver->stack(); #3
445            
446             =cut
447            
448             =pod
449              
450             =begin btest(stack)
451              
452             my $o = __PACKAGE__->new();
453             $test->ok($o, "got object");
454             $test->is($o->stack, 0, "stack is 0");
455             $test->is($o->stack(5), 5, "stack does increment w/transatcions");
456             $test->is($o->stack, 5, "stack is at 5");
457              
458             my $poolkey = join(',', map{defined $_ ? $_ : 'undef'} ($o->dsn, $o->user, $o->pass));
459             delete $o->pool->{$poolkey};
460              
461             =end btest(stack)
462              
463             =cut
464              
465              
466             =pod
467              
468             =item begin
469              
470             Adds 1 to your transaction stack
471              
472             =cut
473              
474             sub begin {
475             my $self = shift;
476            
477             return $self->error("Cannot begin transaction - failed", "BD-13") if $self->failed;
478            
479             return $self->stack($self->stack + 1);
480             }
481              
482             =pod
483              
484             =begin btest(begin)
485              
486             my $o = __PACKAGE__->new();
487             $o->wipe;
488             $test->ok($o, "got transaction enabled object");
489             $test->is($o->stack, 0, "stack is 0");
490             $test->is($o->begin, 1, "began transaction, stack is 1");
491             $test->is($o->stack, 1, "stack is 1");
492             $test->is($o->begin, 2, "began transaction, stack is 2");
493             $test->is($o->stack, 2, "stack is 2");
494              
495             my $poolkey = join(',', map{defined $_ ? $_ : 'undef'} ($o->dsn, $o->user, $o->pass));
496             delete $o->pool->{$poolkey};
497              
498             =end btest(begin)
499              
500             =cut
501              
502              
503             =pod
504              
505             =item end
506              
507             Subtracts 1 from your transaction stack.
508              
509             =cut
510              
511             sub end {
512             my $self = shift;
513            
514             my $stack = $self->stack($self->stack - 1);
515              
516             if ($stack <= 0) {
517              
518             $self->stack(0);
519              
520             if ($self->failed) {
521             $self->notify('warnings', 'Silently unfailing failed stack with last end');
522             $self->unfail;
523             return $self->error("Cannot end transaction - failed", "BD-13");
524             }
525             else {
526             $self->finish() or return;
527             }
528              
529             return '0 but true';
530             } else {
531             return $stack;
532             };
533             }
534              
535             =pod
536              
537             =begin btest(end)
538              
539             my $o = __PACKAGE__->new();
540             $o->wipe;
541             $test->ok($o, "got transaction enabled object");
542             $test->is($o->stack, 0, "stack is 0");
543             $test->is($o->begin, 1, "began transaction, stack is 1");
544             $test->is($o->stack, 1, "stack is 1");
545             $test->is($o->begin, 2, "began transaction, stack is 2");
546             $test->is($o->stack, 2, "stack is 2");
547             $test->is($o->end, 1, "end transaction, stack is 1");
548             $test->is($o->stack, 1, "stack is 1");
549             $test->is($o->end, '0 but true', "end transaction, stack is 0 (but true)");
550             $test->is($o->stack, 0, "stack is 0");
551              
552             my $poolkey = join(',', map{defined $_ ? $_ : 'undef'} ($o->dsn, $o->user, $o->pass));
553             delete $o->pool->{$poolkey};
554              
555             =end btest(end)
556              
557             =cut
558              
559              
560             =pod
561              
562             =item finish
563              
564             automagically finishes your transaction and sets your stack back to 0, regardless of how many items are on your stack.
565             Use this method with extreme care.
566              
567             =cut
568              
569             sub finish {
570             my $self = shift;
571              
572             my $handle = $self->handle;
573              
574             $handle->commit()
575             or return $self->error($handle->errstr, "BD-07");
576              
577             $self->stack(0);
578             return 1;
579             }
580            
581             =pod
582              
583             =begin btest(finish)
584              
585             my $o = __PACKAGE__->new();
586             $o->wipe;
587             $test->ok($o, "got transaction enabled object");
588             $test->is($o->stack, 0, "stack is 0");
589             $test->is($o->begin, 1, "began transaction, stack is 1");
590             $test->is($o->stack, 1, "stack is 1");
591             $test->is($o->begin, 2, "began transaction, stack is 2");
592             $test->is($o->stack, 2, "stack is 2");
593             $test->is($o->finish, 1, "finished transaction");
594             $test->is($o->stack, 0, "stack is 0");
595              
596             my $poolkey = join(',', map{defined $_ ? $_ : 'undef'} ($o->dsn, $o->user, $o->pass));
597             delete $o->pool->{$poolkey};
598              
599             =end btest(finish)
600              
601             =cut
602              
603              
604              
605             =pod
606              
607             =item fail
608              
609             fails your transaction and rolls it back from the database. If you just want to fail your transaction
610             but otherwise not roll it back, then simply set failed = 1.
611              
612             =cut
613              
614             sub fail {
615             my $self = shift;
616            
617             return $self->wipe();
618             }
619            
620             =pod
621              
622             =begin btest(fail)
623              
624             my $o = __PACKAGE__->new();
625             $o->wipe;
626             $test->ok($o, "got transaction enabled object");
627             $test->is($o->stack, 0, "stack is 0");
628             $test->is($o->begin, 1, "began transaction, stack is 1");
629             $test->is($o->stack, 1, "stack is 1");
630             $test->is($o->begin, 2, "began transaction, stack is 2");
631             $test->is($o->stack, 2, "stack is 2");
632             $test->is($o->fail, 1, "failed transaction");
633             $test->is($o->stack, 0, "stack is 0");
634              
635             my $poolkey = join(',', map{defined $_ ? $_ : 'undef'} ($o->dsn, $o->user, $o->pass));
636             delete $o->pool->{$poolkey};
637              
638             =end btest(fail)
639              
640             =cut
641              
642             =pod
643              
644             =item unfail
645              
646             unfails a transaction. If a fatal error occurs and you want to continue, you must unfail
647              
648             =cut
649              
650             sub unfail {
651             my $self = shift;
652             $self->failed(0);
653             $self->handle->rollback();
654             return '0 but true';
655             }
656              
657             =pod
658              
659             =begin btest(unfail)
660              
661             my $o = __PACKAGE__->new();
662             $o->wipe;
663             $test->ok($o, "got transaction enabled object");
664             $test->is($o->failed(1), 1, "driver transaction failed");
665             $test->ok($o->unfail, "unfailed transaction");
666             $test->ok(! $o->failed, "transaction no longer failed");
667              
668             my $poolkey = join(',', map{defined $_ ? $_ : 'undef'} ($o->dsn, $o->user, $o->pass));
669             delete $o->pool->{$poolkey};
670              
671             =end btest(unfail)
672              
673             =cut
674              
675             =pod
676              
677             =item wipe
678              
679             fails your transaction and rolls it back from the database if you have pending items on your stack.
680              
681             =cut
682              
683             sub wipe {
684             my $self = shift;
685              
686             my $handle = $self->handle;
687             $handle->rollback()
688             or return $self->error($handle->errstr, "BD-08");
689            
690             $self->stack(0);
691             $self->failed(0);
692            
693             return 1;
694             };
695             };
696              
697             =pod
698              
699             =begin btest(wipe)
700              
701             my $o = __PACKAGE__->new();
702             $o->wipe;
703             $test->ok($o, "got transaction enabled object");
704             $test->is($o->stack, 0, "stack is 0");
705             $test->is($o->begin, 1, "began transaction, stack is 1");
706             $test->is($o->stack, 1, "stack is 1");
707             $test->is($o->begin, 2, "began transaction, stack is 2");
708             $test->is($o->stack, 2, "stack is 2");
709             $test->is($o->wipe, 1, "wiped transaction");
710             $test->is($o->stack, 0, "stack is 0");
711              
712             my $poolkey = join(',', map{defined $_ ? $_ : 'undef'} ($o->dsn, $o->user, $o->pass));
713             delete $o->pool->{$poolkey};
714              
715             =end btest(wipe)
716              
717             =cut
718              
719             =pod
720              
721             =item copy
722              
723             Copying Basset::DB objects is frowned upon. Nonetheless, if you must do it, you're still going
724             to get the same database handle back. That is to say, the exact same object.
725              
726             Note - as a result of how this has to work (and some DBI bitching), copying Basset::DB objects
727             is not thread safe.
728              
729             =cut
730              
731             sub copy {
732             my $self = shift;
733             if (@_) {
734             return $self->SUPER::copy(@_);
735             } else {
736             #grab our handle
737             my $h = $self->handle;
738             #wipe it out. Our copy is primitive and just dumps and evals the object
739             $self->handle(undef);
740             my $copy = $self->SUPER::copy;
741             #reset the handle
742             $self->handle($h);
743             #set it in the copy
744             $copy->handle($h);
745            
746             return $copy;
747             }
748             }
749              
750             =pod
751              
752             =begin btest(copy)
753              
754             my $obj = __PACKAGE__->new();
755             #$test->ok($obj, "Got object for copy test");
756             my $o2 = $obj->copy;
757             #$test->is($obj->copy, $o2->copy, "Copied objects match");
758              
759             =end btest(copy)
760              
761             =cut
762              
763              
764              
765             =pod
766              
767             =item sql_type
768              
769             This is a wrapper method to DBI's sql_types constants. Pass in a string value consisting of the
770             sql type string, and it spits back the relevant DBI constant.
771              
772             my $some_constant = Basset::DB->sql_type('SQL_INTEGER');
773              
774             Very useful if you're binding values or such.
775              
776             =cut
777              
778             our %cache = ();
779             sub sql_type {
780             my $class = shift;
781            
782             return $class->error("Cannot return type without type", "BD-02") unless @_;
783            
784             my $type = shift;
785              
786             return undef unless defined $type;
787              
788             #return $type if $type =~ /^\d+$/;
789              
790             my $return = $cache{$type} || eval $type || undef;
791              
792             $cache{$type} = $return;
793              
794             return $return;
795             };
796              
797             =pod
798              
799             =begin btest(sql_type)
800              
801             $test->is(scalar(__PACKAGE__->sql_type), undef, "Cannot return type w/o type");
802             $test->is(__PACKAGE__->errcode, "BD-02", "proper error code");
803             {
804             use DBI qw(:sql_types);
805             $test->is(__PACKAGE__->sql_type('SQL_INTEGER'), SQL_INTEGER(), "proper type for integer");
806             $test->is(__PACKAGE__->sql_type('SQL_INTEGER'), SQL_INTEGER(), "proper type for integer");
807             $test->is(__PACKAGE__->sql_type('SQL_VARCHAR'), SQL_VARCHAR(), "proper type for varchar");
808             $test->is(__PACKAGE__->sql_type(SQL_VARCHAR()), SQL_VARCHAR(), "proper type for varchar, given int");
809             $test->is(__PACKAGE__->sql_type('__j_junk_type'), undef, "unknown type returns undef");
810             $test->is(__PACKAGE__->sql_type(undef), undef, "undef type returns undef");
811             }
812              
813             =end btest(sql_type)
814              
815             =cut
816              
817              
818             =pod
819              
820             =item tables
821              
822             returns an array of all tables in your database. You may optionally pass in a database handle
823             to get all of the tables for that handle instead of the default
824              
825             =cut
826              
827             sub tables {
828             my $class = shift;
829              
830             my $driver = shift || $class->new();
831              
832             my $query = "show tables";
833              
834             my $stmt = $driver->prepare_cached($query)
835             or return $class->error($driver->errstr, "BD-03");
836              
837             $stmt->execute() or return $class->error($stmt->errstr, "BD-04");
838              
839             my @tables = ();
840             while (my ($table) = $stmt->fetchrow_array){
841             push @tables, $table;
842             };
843              
844             $stmt->finish()
845             or return $class->error($stmt->errstr, "BD-05");
846              
847             return @tables;
848              
849             };
850              
851             =pod
852              
853             =item ping
854              
855             just a wrapper around DBI's ping
856              
857             =cut
858              
859             sub ping {
860             return shift->handle->ping;
861             };
862              
863             =pod
864              
865             =begin btest(tables)
866              
867             =end btest(tables)
868              
869             =cut
870              
871              
872             =pod
873              
874             =item optimize_tables
875              
876             MySQL only, most likely. Calls the "optimize table" command on all tables in your database,
877             or only upon those tables that you've passed in, if you prefer.
878              
879             =cut
880              
881             sub optimize_tables {
882             my $class = shift;
883             my @tables = @_ || $class->tables;
884              
885             my $driver = $class->new();
886              
887             foreach my $table (@tables){
888             my $query = "optimize table $table";
889              
890             my $stmt = $driver->prepare_cached($query)
891             or return $class->error($driver->errstr, "BD-03");
892              
893             $stmt->execute() or return $class->error($stmt->errstr, "BD-04");
894              
895             $stmt->finish()
896             or return $class->error($stmt->errstr, "BD-05");
897             };
898              
899             return @tables;
900             };
901              
902             =pod
903              
904             =begin btest(optimize_tables)
905              
906             =end btest(optimize_tables)
907              
908             =cut
909              
910              
911             1;