File Coverage

lib/Class/DBI/Lite.pm
Criterion Covered Total %
statement 575 624 92.1
branch 128 168 76.1
condition 23 54 42.5
subroutine 99 105 94.2
pod 27 50 54.0
total 852 1001 85.1


line stmt bran cond sub pod time code
1              
2             package Class::DBI::Lite;
3              
4 17     17   681 use strict;
  17         26  
  17         442  
5 17     17   81 use warnings 'all';
  17         26  
  17         475  
6 17     17   78 use base 'Ima::DBI::Contextual';
  17         26  
  17         7343  
7 17     17   296440 use Carp qw( cluck confess );
  17         41  
  17         779  
8 17     17   10642 use SQL::Abstract;
  17         158159  
  17         950  
9 17     17   8879 use SQL::Abstract::Limit;
  17         123850  
  17         769  
10 17     17   5908 use Class::DBI::Lite::Iterator;
  17         49  
  17         497  
11 17     17   5499 use Class::DBI::Lite::Pager;
  17         48  
  17         480  
12 17     17   5265 use Class::DBI::Lite::RootMeta;
  17         39  
  17         460  
13 17     17   5348 use Class::DBI::Lite::EntityMeta;
  17         56  
  17         477  
14 17     17   100 use Digest::MD5 'md5_hex';
  17         30  
  17         683  
15 17     17   8177 use POSIX 'ceil';
  17         86705  
  17         96  
16             use overload
17 39     39   3765 '""' => sub { eval { $_[0]->id } },
  39         146  
18 440282     440282   538464 bool => sub { eval { $_[0]->id } },
  440282         659578  
19 17     17   23473 fallback => 1;
  17         1632  
  17         170  
20              
21             our $VERSION = '1.034';
22             our $meta;
23              
24             our %DBI_OPTIONS = (
25             FetchHashKeyName => 'NAME_lc',
26             ShowErrorStatement => 1,
27             ChopBlanks => 1,
28             AutoCommit => 1,
29             RaiseError => 1,
30             );
31              
32             BEGIN {
33 17     17   2160 use vars qw( $Weaken_Is_Available %Live_Objects );
  17         30  
  17         1224  
34              
35 17     17   55 $Weaken_Is_Available = 1;
36 17         26 eval {
37 17         73 require Scalar::Util;
38 17         748 import Scalar::Util qw(weaken isweak);
39             };
40 17 50       790 $Weaken_Is_Available = 0 if $@;
41             }# end BEGIN:
42              
43              
44             #==============================================================================
45             # Abstract methods:
46             sub set_up_table;
47             sub get_last_insert_id;
48              
49              
50             #==============================================================================
51             sub import
52             {
53 62     62   4601 my $class = shift;
54              
55 17     17   94 no strict 'refs';
  17         57  
  17         8454  
56 62         96 $class->_load_class( ( @{$class.'::ISA'} )[0] );
  62         316  
57 62 100       134 if( my $table = eval { ( @{$class.'::ISA'} )[0]->table } )
  62         90  
  62         250  
58             {
59 1         4 $class->set_up_table( $table );
60             }# end if()
61             }# end import()
62              
63              
64             #==============================================================================
65             sub clear_object_index
66             {
67 3     3 0 314 my $s = shift;
68            
69 3 100       8 my $class = ref($s) ? ref($s) : $s;
70 3         9 my $key_starter = $s->root_meta->schema . ":" . $class;
71 3         11 map { delete($Live_Objects{$_}) } grep { m/^$key_starter\:\d+/o } keys(%Live_Objects);
  2         8  
  2         42  
72             }# end clear_object_index()
73              
74              
75             #==============================================================================
76             sub find_column
77             {
78 52     52 1 291 my ($class, $name) = @_;
79            
80 52 100       116 my ($col) = grep { $_ eq $name } $class->columns('All')
  160         392  
81             or return;
82 16         48 return $col;
83             }# end find_column()
84              
85              
86             #==============================================================================
87             sub construct
88             {
89 112633     112633 1 155603 my ($s, $data, $is_void_context) = @_;
90            
91 112633 100       179102 my $class = ref($s) ? ref($s) : $s;
92              
93 112633         175865 my $PK = $class->primary_column;
94 112633         188102 my $key = join ':', grep { defined($_) } ( $s->root_meta->schema, $class, $data->{ $PK } );
  337899         550453  
95 112633 100       222993 return $Live_Objects{$key} if $Live_Objects{$key};
96            
97 2610         4603 $data->{__id} = $data->{ $PK };
98 2610         4075 $data->{__Changed} = { };
99            
100 2610         4055 my $obj = bless $data, $class;
101 2610 100 66     10102 if( $Weaken_Is_Available && ! $is_void_context )
102             {
103 2475         7184 $Live_Objects{$key} = $obj;
104            
105 2475         7337 weaken( $Live_Objects{$key} );
106 2475         5891 return $Live_Objects{$key};
107             }
108             else
109             {
110 135         351 return $obj;
111             }# end if()
112             }# end construct()
113              
114              
115             #==============================================================================
116             sub deconstruct
117             {
118 203     203 0 368 my $s = shift;
119            
120 203         1112 bless $s, 'Class::DBI::Lite::Object::Has::Been::Deleted';
121             }# end deconstruct()
122              
123              
124             #==============================================================================
125 2     2 0 859 sub schema { $_[0]->root_meta->schema }
126 2     2 0 7 sub dsn { $_[0]->root_meta->dsn }
127 11832     11832 1 19578 sub table { $_[0]->_meta->{table} }
128 4     4 0 6 sub triggers { @{ $_[0]->_meta->{triggers}->{ $_[1] } } }
  4         12  
129       109     sub _meta { }
130 1     1 0 2 sub set_cache { my ($class, $cache) = @_; $class->_meta->{cache} = $cache }
  1         4  
131 200103     200103 0 316927 sub cache { shift->_meta->{cache} }
132              
133              
134             #==============================================================================
135             sub _init_meta
136             {
137 51     51   125 my ($class, $entity) = @_;
138            
139 17     17   115 no strict 'refs';
  17         34  
  17         462  
140 17     17   81 no warnings qw( once redefine );
  17         36  
  17         3866  
141 51         207 my $schema = $class->root_meta->schema;
142            
143 51         269 my $_class_meta = Class::DBI::Lite::EntityMeta->new( $class, $schema, $entity );
144            
145             # If we are re-initializing meta (i.e. changed schema) then remove accessors first:
146 50         139 foreach my $col ( eval { $class->columns } )
  50         278  
147             {
148 3     3   13 local $SIG{__WARN__} = sub { };
149 3         4 *{"$class\::$col"} = undef;
  3         27  
150             }# end foreach()
151            
152 50     483365   289 *{"$class\::_meta"} = sub { $_class_meta };
  50         220  
  483365         1029072  
153            
154 50         127 my $pk = ($class->columns('Primary'))[0];
155 50     576540   153 *{"$class\::primary_column"} = sub { $pk };
  50         264  
  576540         2309555  
156 50     220   141 *{"$class\::$pk"} = sub { $_[0]->{$pk} };
  50         189  
  220         541  
157            
158             # Install the column accessors:
159 50         119 foreach my $col ( grep { $_ ne $pk } $class->columns )
  154         324  
160             {
161 104         207 my $setter = "_set_$col";
162 104         162 my $getter = "_get_$col";
163 104         370 *{"$class\::$setter"} = sub {
164 1165     1165   1974 my ($s, $newval) = @_;
165 17     17   105 no warnings 'uninitialized';
  17         34  
  17         8051  
166 1165 100       3768 return $newval if $newval eq $s->{$col};
167 25         147 $s->_call_triggers( "before_set_$col", $s->{$col}, $newval );
168             $s->{__Changed}->{$col} = {
169 25         104 oldval => $s->{$col}
170             };
171 25         74 return $s->{$col} = $newval;
172 104         316 };
173            
174 104         377 *{"$class\::$getter"} = sub {
175 1282     1282   4196 shift->{$col};
176 104         262 };
177            
178 104         489 *{"$class\::$col"} = sub {
179 2447     2447   7031 my $s = shift;
180            
181 2447 100       5609 exists($s->{$col}) or $s->_flesh_out;
182 2447 100       6729 @_ ? $s->$setter( @_ ) : $s->$getter( @_ );
183 104         304 };
184             }# end foreach()
185             }# end _init_meta()
186              
187              
188             #==============================================================================
189             sub connection
190             {
191 18     18 1 228 my ($class, @DSN) = @_;
192            
193 18 50       75 return $class->db_Main unless @DSN;
194            
195 18         98 $class->set_master( @DSN );
196 18         1376 1;
197             }# end connection()
198              
199              
200             sub db_RO
201             {
202 10295     10295 0 12232 my $s = shift;
203            
204             # If we're inside a transaction or don't have any slaves, return the master:
205 10295 50 66     21540 unless( $s->db_Main->{AutoCommit} && $s->root_meta->has_slaves )
206             {
207 10295         22688 return $s->db_Main;
208             }# end unless()
209            
210             # Otherwise return the slave if we have any:
211 0 0       0 $s->root_meta->has_slaves ? $s->db_Slave : $s->db_Main;
212             }# end db_RO()
213              
214              
215             sub set_master
216             {
217 18     18 0 48 my ($class, @DSN) = @_;
218 18         97 my $root = $class->root_meta;
219            
220 18         104 $class->_mk_connection('Main', @DSN);
221             }# end set_master()
222              
223              
224             sub set_slaves
225             {
226 0     0 0 0 my ($class, @connections) = @_;
227            
228 0         0 my $root = $class->root_meta;
229 0         0 $root->add_slave( $_ ) for grep { $_ } @connections;
  0         0  
230            
231             # Select a connection at random and use it:
232 0         0 my $conn = $connections[ int(rand() * @connections) - 1 ];
233 0         0 $class->_mk_connection('Slave', @$conn);
234             }# end set_slaves()
235              
236              
237             sub switch_slave
238             {
239 0     0 0 0 my ($class, $trace) = @_;
240            
241 0         0 my $old_slave = $class->root_meta->slaves->[0];
242 0         0 $class->_mk_connection('Slave', @{ $class->root_meta->random_slave } );
  0         0  
243 0         0 my $new_slave = $class->root_meta->slaves->[0];
244            
245 0 0       0 warn "[Debug] Switched slave from $old_slave->[0] to $new_slave->[0]\n"
246             if $trace;
247             }# end switch_slave()
248              
249             our $root_metas = { };
250             sub _mk_connection
251             {
252 18     18   56 my ($class, $name, @DSN) = @_;
253            
254             # Set up the root meta:
255 17     17   111 no strict 'refs';
  17         34  
  17         438  
256 17     17   79 no warnings 'redefine';
  17         32  
  17         3139  
257             # unless( $class->_has_root_meta )
258 18         44 my $meta_key = join ':', ( $class );
259 18 100       66 unless( $root_metas->{ $meta_key } )
260             {
261 17         176 $root_metas->{$meta_key} = Class::DBI::Lite::RootMeta->new(
262             \@DSN
263             );
264 17         46 my $caller = caller(2);
265 17     17   65 *{ "$caller\::root" } = sub { $caller };
  17         78  
  17         74  
266 17         53 *{ $class->root . "::root_meta" } = sub {
267             # use Data::Dumper; warn Dumper($root_metas);
268 223215     223215   1374893 return $root_metas->{$meta_key};
269 17         49 };
270             # ${ $class->root . "::_has_root_meta" } = 1;
271             }# end unless()
272            
273             # Connect:
274 18         81 undef(%Live_Objects);
275 18         75 local $^W = 0;
276 18         211 $class->set_db($name => @DSN, {
277             RaiseError => 1,
278             AutoCommit => 1,
279             PrintError => 0,
280             Taint => 1,
281             # RootClass => "DBIx::ContextualFetch"
282             });
283             }# end _mk_connection()
284              
285              
286             #==============================================================================
287             sub root
288             {
289 16     16 0 37 __PACKAGE__;
290             }# end root()
291              
292              
293             #==============================================================================
294             sub root_meta
295             {
296 16     16 0 58 my $s = shift;
297            
298 17     17   103 no strict 'refs';
  17         36  
  17         951  
299 16         65 my $root = $s->root;
300              
301 16         33 ${"$root\::root_meta"};
  16         67  
302             }# end root_meta()
303              
304 17     17   82 sub _has_root_meta { no strict 'refs'; my $root = $_[0]->root; ${"$root\::_has_root_meta"} }
  17     0   26  
  17         53552  
  0         0  
  0         0  
  0         0  
305              
306              
307             #==============================================================================
308             sub id
309             {
310 452115     452115 1 694521 $_[0]->{ $_[0]->primary_column };
311             }# end id()
312              
313              
314             #==============================================================================
315             my %ok_types = (
316             All => 1,
317             Essential => 1,
318             Primary => 1,
319             );
320             sub columns
321             {
322 13002     13002 1 18326 my ($s) = shift;
323            
324            
325 13002 100       23879 if( my $type = shift(@_) )
326             {
327 12897 100       27493 confess "Unknown column group '$type'" unless $ok_types{$type};
328 12895 100       24065 if( my @cols = @_ )
329             {
330 4         13 $s->_meta->columns->{$type} = \@cols;
331             }
332             else
333             {
334             # Get: my ($PK) = $class->columns('Primary');
335 12891         15317 return @{ $s->_meta->columns->{$type} };
  12891         19992  
336             }# end if()
337             }
338             else
339             {
340 105         182 return @{ $s->_meta->columns->{All} };
  105         308  
341             }# end if()
342              
343             }# end columns()
344              
345              
346             #==============================================================================
347             sub retrieve_all
348             {
349 32     32 1 4456 my ($s) = @_;
350            
351 32         223 return $s->retrieve_from_sql( );
352             }# end retrieve_all()
353              
354              
355             #==============================================================================
356             sub retrieve
357             {
358 10122     10122 1 37709 my ($s, $id) = @_;
359            
360 10122 50       16155 if( my $data = $s->_call_triggers( before_retrieve => $id ) )
361             {
362 0         0 return $s->construct( $data );
363             }# end if()
364            
365 10122         13963 my ($obj) = $s->retrieve_from_sql(<<"", $id);
366 10122         14663 @{[ $s->primary_column ]} = ?
367              
368 10122 50       17949 return unless $obj;
369 10122         22948 $obj->_call_triggers( after_retrieve => $obj );
370 10122         19395 return $obj;
371             }# end retrieve()
372              
373              
374             #==============================================================================
375             sub create
376             {
377 1257     1257 1 3485 my $s = shift;
378            
379 1257 100       4332 my $data = ref($_[0]) ? $_[0] : { @_ };
380            
381 1257         2751 my $PK = $s->primary_column;
382 2527         6944 my %create_fields = map { $_ => $data->{$_} }
383 1257 100       3043 grep { exists($data->{$_}) && $_ ne $PK }
  3784         13767  
384             $s->columns('All');
385            
386 1257 100       5532 my $pre_obj = bless {
387             __id => undef,
388             __Changed => { },
389             %create_fields
390             }, ref($s) ? ref($s) : $s;
391            
392             # Cal the "before" trigger:
393 1257         3601 $pre_obj->_call_triggers( before_create => \%create_fields );
394            
395             # Changes may have happened to the original creation data (from the trigger(s)) - re-evaluate now:
396 2525         7190 %create_fields = map { $_ => $pre_obj->{$_} }
397 1256 100       2634 grep { defined($pre_obj->{$_}) && $_ ne $PK }
  3781         14109  
398             $pre_obj->columns('All');
399 1256         5138 $data = { %$pre_obj };
400            
401 1256         3432 my @fields = map { $_ } sort grep { exists($data->{$_}) } keys(%create_fields);
  2525         4714  
  2525         5865  
402 1256         2591 my @vals = map { $data->{$_} } sort grep { exists($pre_obj->{$_}) } keys(%create_fields);
  2525         4809  
  2525         5008  
403            
404 1256         2262 my $sql = <<"";
405 1256         2979 INSERT INTO @{[ $s->table ]} (
406 1256         3324 @{[ join ',', @fields ]}
407             )
408             VALUES (
409 1256         2072 @{[ join ',', map {"?"} @vals ]}
  2525         5464  
410             )
411              
412 1256 50       3229 if( $s->_meta->trace )
413             {
414 0   0     0 my $class = ref($s) || $s;
415 0         0 cluck "$class: create($sql, values[" . join( ",", map {qq('$_')} @vals) . "])";
  0         0  
416             }# end if()
417            
418 1256         3458 my $sth = $s->db_Main->prepare_cached( $sql );
419 1256         886842 $sth->execute( @vals );
420 1256 50       6277 my $id = $s->get_last_insert_id
421             or confess "ERROR - CANNOT get last insert id";
422 1256         123479 $sth->finish();
423            
424 1256         7654 my $new_obj = $s->construct( {
425             %$pre_obj,
426             $PK => $id,
427             }, defined wantarray );
428 1256         3877 $pre_obj->discard_changes;
429              
430 1256         3080 $new_obj->_call_triggers( after_create => $new_obj );
431 1256 50       4490 $new_obj->update if $new_obj->{__Changed};
432 1256         3344 $new_obj;
433             }# end create()
434              
435              
436             #==============================================================================
437             sub do_transaction
438             {
439 20     20 1 1332 my ($s, $code) = @_;
440            
441 20         95 local $s->db_Main->{AutoCommit};
442 20         2979 my ($res, @res);
443 20 50       48 wantarray ? @res = eval { $code->( ) } : $res = eval { $code->( ) };
  0         0  
  20         58  
444            
445 20 100       100 if( my $trans_error = $@ )
446             {
447 1         2 eval { $s->dbi_rollback };
  1         7  
448 1 50       158 if( my $rollback_error = $@ )
449             {
450 0         0 confess join "\n\t", "Both transaction and rollback failed:",
451             "Transaction error: $trans_error",
452             "Rollback Error: $rollback_error";
453             }
454             else
455             {
456 1         190 confess join "\n\t", "Transaction failed but rollback succeeded:",
457             "Transaction error: $trans_error";
458             }# end if()
459             }
460             else
461             {
462             # Success:
463 19         140 $s->dbi_commit;
464 19 50       130373 wantarray ? return @res : return $res;
465             }# end if()
466             }# end do_transaction()
467              
468              
469             #==============================================================================
470             sub update
471             {
472 1279     1279 1 2414 my $s = shift;
473 1279 100       3046 confess "$s\->update cannot be called without an object" unless ref($s);
474            
475 1278 100       2011 return 1 unless eval { keys(%{ $s->{__Changed} }) };
  1278         1633  
  1278         3895  
476            
477 6         21 $s->_call_triggers( before_update => $s );
478            
479 5         12 my $changed = $s->{__Changed};
480 5         32 foreach my $field ( grep { $changed->{$_} } sort keys(%$s) )
  27         49  
481             {
482 5         24 $s->_call_triggers( "before_update_$field", $changed->{$field}->{oldval}, $s->{$field} );
483             }# end foreach()
484            
485            
486             # Make our SQL:
487 5         28 my @fields = map { "$_ = ?" } grep { $changed->{$_} } sort keys(%$s);
  5         21  
  27         40  
488 5         21 my @vals = map { $s->{$_} } grep { $changed->{$_} } sort keys(%$s);
  5         14  
  27         38  
489 5         15 my $sql = <<"";
490 5         18 UPDATE @{[ $s->table ]} SET
491 5         22 @{[ join ', ', @fields ]}
492 5         15 WHERE @{[ $s->primary_column ]} = ?
493              
494 5 50       18 if( $s->_meta->trace )
495             {
496 0   0     0 my $class = ref($s) || $s;
497 0         0 cluck "$class: update($sql, values[" . join( ",", map {qq('$_')} @vals) . "])";
  0         0  
498             }# end if()
499 5         23 my $sth = $s->db_Main->prepare_cached( $sql );
500 5         979 $sth->execute( @vals, $s->id );
501 5         108 $sth->finish();
502            
503 5         60 foreach my $field ( grep { $changed->{$_} } sort keys(%$s) )
  27         76  
504             {
505 5         24 my $old_val = $changed->{$field}->{oldval};
506 5         49 $s->_call_triggers( "after_update_$field", $old_val, $s->{$field} );
507             }# end foreach()
508            
509 5         17 $s->{__Changed} = undef;
510 5         17 $s->_call_triggers( after_update => $s );
511 5         36 return 1;
512             }# end update()
513              
514              
515             #==============================================================================
516             sub delete
517             {
518 205     205 1 1283 my $s = shift;
519            
520 205 100       680 confess "$s\->delete cannot be called without an object" unless ref($s);
521            
522 204         505 $s->_call_triggers( before_delete => $s );
523            
524 203         325 my $sql = <<"";
525 203         592 DELETE FROM @{[ $s->table ]}
526 203         437 WHERE @{[ $s->primary_column ]} = ?
527              
528 203 50       564 if( $s->_meta->trace )
529             {
530 0   0     0 my $class = ref($s) || $s;
531 0         0 cluck "$class: delete($sql, values[" . $s->id . "])\n";
532             }# end if()
533 203         732 my $sth = $s->db_Main->prepare_cached( $sql );
534 203         29198 $sth->execute( $s->id );
535 203         2677 $sth->finish();
536            
537 203         825 my $deleted = bless { $s->primary_column => $s->id }, ref($s);
538 203         773 my $key = join ':', grep { defined($_) } ($s->root_meta->{schema}, ref($s), $s->id );
  609         1821  
539 203         889 $s->_call_triggers( after_delete => $deleted );
540 203         755 delete($Live_Objects{$key});
541 203         810 undef(%$deleted);
542            
543 203         635 undef(%$s);
544              
545 203         683 $s->deconstruct;
546             }# end delete()
547              
548              
549             #==============================================================================
550             sub ad_hoc
551             {
552 2     2 0 15 my ($s, %args) = @_;
553            
554 2         12 my $sth = $s->db_RO->prepare( $args{sql} );
555 2   50     526 $args{args} ||= [ ];
556 2   100     13 $args{isa} ||= 'Class::DBI::Lite';
557 2         4 $sth->execute( @{ $args{args} } );
  2         128  
558 2         7 my @data = ( );
559 2         470 require Class::DBI::Lite::AdHocEntity;
560 2         63 while( my $rec = $sth->fetchrow_hashref )
561             {
562             push @data, Class::DBI::Lite::AdHocEntity->new(
563             isa => $args{isa},
564             sql => \$args{sql},
565             args => $args{args},
566             primary_key => $args{primary_key},
567 2         11 data => $rec,
568             );
569             }# end while()
570 2         10 $sth->finish();
571            
572 2 50       28 return wantarray ? @data : Class::DBI::Lite::Iterator->new( \@data );
573             }# end ad_hoc()
574              
575              
576             #==============================================================================
577             sub retrieve_from_sql
578             {
579 10269     10269 0 19203 my ($s, $sql, @bind) = @_;
580            
581 10269 100       12349 $sql = "SELECT @{[ join ', ', $s->columns('Essential') ]} " .
  10269         18371  
582 10269         20587 "FROM @{[ $s->table ]}" . ( $sql ? " WHERE $sql " : "" );
583              
584 10269 50       18642 if( $s->_meta->trace )
585             {
586 0   0     0 my $class = ref($s) || $s;
587 0         0 cluck "$class: search*($sql, values[" . join( ",", map {qq('$_')} @bind) . "])";
  0         0  
588             }# end if()
589             SCOPE: {
590 10269         13466 my $sth = $s->db_RO->prepare_cached( $sql );
  10269         17850  
591 10269         1261093 $sth->execute( @bind );
592            
593 10269         36796 return $s->sth_to_objects( $sth, $sql );
594             }
595             }# end retrieve_from_sql()
596              
597              
598             #==============================================================================
599             sub sth_to_objects
600             {
601 10289     10289 1 18525 my ($s, $sth, $sql) = @_;
602            
603 10289 100       21318 my $class = ref($s) ? ref($s) : $s;
604 10289         11930 my @vals;
605 10289         156711 while( my $rec = $sth->fetchrow_hashref )
606             {
607 11357         96134 push @vals, $rec;
608             }# end while()
609 10289         31115 $sth->finish();
610            
611 10289         21783 return $s->_prepare_result( @ vals );
612             }# end sth_to_objects()
613              
614              
615             #==============================================================================
616             sub search
617             {
618 100021     100021 1 490051 my ($s, %args) = @_;
619              
620 100021         190234 my @cached = grep { $_ } $s->_call_triggers( before_search => \%args );
  99960         153381  
621 100021 100       193052 if( @cached )
622             {
623 99960         167919 return $s->_prepare_result( @cached );
624             }# end if()
625            
626 61         103 my $sql = "";
627 61         158 my @sql_parts = map { "$_ = ?" } sort keys(%args);
  75         204  
628 61         147 my @sql_vals = map { $args{$_} } sort keys(%args);
  75         196  
629 61         149 $sql .= join ' AND ', @sql_parts;
630              
631 61         220 my @vals = $s->retrieve_from_sql( $sql, @sql_vals );
632 61         217 $s->_call_triggers( after_search => ( \%args, \@vals ) );
633 61         146 return $s->_prepare_result( @vals );
634             }# end search()
635              
636              
637             sub _prepare_result
638             {
639 110310     110310   178462 my ($class, @vals) = @_;
640 110310 100       160767 if( wantarray )
641             {
642 110234         143301 my @out = map { $class->construct( $_ ) } @vals;
  110833         172663  
643 110234         312819 return @out;
644             }
645             else
646             {
647             my $iter = Class::DBI::Lite::Iterator->new(
648             [
649 76         289 map { $class->construct( $_ ) } @vals
  543         1028  
650             ]
651             );
652 76         640 return $iter;
653             }# end if()
654             }# end _prepare_result()
655              
656              
657             #==============================================================================
658             sub count_search
659             {
660 2     2 1 441 my ($s, %args) = @_;
661            
662 2         6 my $sql = "SELECT COUNT(*) FROM @{[ $s->table ]} WHERE ";
  2         8  
663              
664 2         10 my @sql_parts = map { "$_ = ?" } sort keys(%args);
  2         11  
665 2         6 my @sql_vals = map { $args{$_} } sort keys(%args);
  2         7  
666 2         7 $sql .= join ' AND ', @sql_parts;
667            
668 2 50       12 if( $s->_meta->trace )
669             {
670 0   0     0 my $class = ref($s) || $s;
671 0         0 cluck "$class: count_search($sql, values[" . join( ",", map {qq('$_')} @sql_vals) . "])";
  0         0  
672             }# end if()
673             SCOPE: {
674 2         5 my $sth = $s->db_RO->prepare_cached( $sql );
  2         9  
675 2         538 $sth->execute( @sql_vals );
676 2         31 my ($count) = $sth->fetchrow;
677 2         12 $sth->finish();
678            
679 2         11 return $count;
680             };
681             }# end count_search()
682              
683              
684             #==============================================================================
685             sub search_like
686             {
687 1     1 1 491 my ($s, %args) = @_;
688            
689 1         3 my $sql = "";
690              
691 1         4 my @sql_parts = map { "$_ LIKE ?" } sort keys(%args);
  1         4  
692 1         5 my @sql_vals = map { $args{$_} } sort keys(%args);
  1         3  
693 1         4 $sql .= join ' AND ', @sql_parts;
694            
695 1         5 return $s->retrieve_from_sql( $sql, @sql_vals );
696             }# end search_like()
697              
698              
699             #==============================================================================
700             sub count_search_like
701             {
702 1     1 1 13 my ($s, %args) = @_;
703            
704 1         3 my $sql = "SELECT COUNT(*) FROM @{[ $s->table ]} WHERE ";
  1         4  
705              
706 1         5 my @sql_parts = map { "$_ LIKE ?" } sort keys(%args);
  1         6  
707 1         3 my @sql_vals = map { $args{$_} } sort keys(%args);
  1         4  
708 1         3 $sql .= join ' AND ', @sql_parts;
709            
710 1 50       4 if( $s->_meta->trace )
711             {
712 0   0     0 my $class = ref($s) || $s;
713 0         0 cluck "$class: count_search_like($sql, values[" . join( ",", map {qq('$_')} @sql_vals) . "])";
  0         0  
714             }# end if()
715             SCOPE: {
716 1         3 my $sth = $s->db_RO->prepare_cached( $sql );
  1         4  
717 1         237 $sth->execute( @sql_vals );
718 1         12 my ($count) = $sth->fetchrow;
719 1         4 $sth->finish();
720            
721 1         6 return $count;
722             };
723             }# end count_search_like()
724              
725              
726             #==============================================================================
727             sub search_where
728             {
729 53     53 1 1697 my $s = shift;
730            
731 53 100       166 my $where = (ref $_[0]) ? $_[0] : { @_ };
732 53 100       138 my $attr = (ref $_[0]) ? $_[1] : undef;
733 53 100       165 my $order = ($attr) ? delete($attr->{order_by}) : undef;
734 53 100       145 my $limit = ($attr) ? delete($attr->{limit}) : undef;
735 53 100       132 my $offset = ($attr) ? delete($attr->{offset}) : undef;
736            
737 53         269 my $sql = SQL::Abstract::Limit->new(%$attr, limit_dialect => $s->db_Main );
738 53         9715 my($phrase, @bind) = $sql->where($where, $order, $limit, $offset);
739 53         19438 $phrase =~ s/^\s*WHERE\s*//i;
740            
741 53         235 return $s->retrieve_from_sql($phrase, @bind);
742             }# end search_where()
743              
744              
745             #==============================================================================
746             sub pager
747             {
748 6     6 1 3288 my ($s, $where, $attr) = @_;
749            
750 6 50 33     45 unless( $where && keys %$where )
751             {
752 6         28 $where = { 1 => 1 };
753             }# end unless()
754              
755 6         26 foreach(qw( page_size page_number ))
756             {
757             confess "Required attribute '$_' was not provided"
758 12 50       51 unless $attr->{$_};
759             }# end foreach()
760            
761             # Limits:
762 6         18 my $page_size = $attr->{page_size};
763 6         39 my $page_number = $attr->{page_number};
764 6 100       28 my $offset = $page_number == 1 ? 0 : ($page_number - 1) * $page_size;
765              
766 6 50       30 my $order = $attr ? $attr->{order_by} : undef;
767 6         61 my $sql = SQL::Abstract::Limit->new(%$attr, limit_dialect => $s->db_Main );
768 6         1710 my($phrase, @bind) = $sql->where($where, $order);
769 6         2258 $phrase =~ s/^\s*WHERE\s*//i;
770            
771 6         40 my $total = $s->count_search_where( $where );
772 6 50       62 my $total_pages = $total < $page_size ? 1 : POSIX::ceil($total / $page_size);
773            
774 6 50       68 return Class::DBI::Lite::Pager->new(
775             where => $where,
776             order_by => $order,
777             class => ref($s) ? ref($s) : $s,
778             page_number => $page_number,
779             page_size => $page_size,
780             total_pages => $total_pages,
781             total_items => $total,
782             start_item => $offset + 1,
783             stop_item => $offset + $page_size,
784             );
785             }# end pager()
786              
787              
788             #==============================================================================
789             sub sql_pager
790             {
791 3     3 1 462 my ($s, $args, $attr) = @_;
792            
793 3 50       13 confess "\$args is required" unless $args;
794 3         10 foreach( qw( data_sql count_sql ) )
795             {
796 6 50       21 confess "\$args->{$_} is required" unless $args->{$_};
797             }# end foreach()
798 3   100     18 $args->{sql_args} ||= [ ];
799              
800 3         7 foreach(qw( page_size page_number ))
801             {
802             confess "Required attribute '$_' was not provided"
803 6 50       18 unless $attr->{$_};
804             }# end foreach()
805            
806             # Limits:
807 3         8 my $page_size = $attr->{page_size};
808 3         5 my $page_number = $attr->{page_number};
809 3 100       14 my $offset = $page_number == 1 ? 0 : ($page_number - 1) * $page_size;
810              
811             # Get the total items:
812 3         12 my $sth = $s->db_RO->prepare( $args->{count_sql} );
813 3         545 $sth->execute( @{ $args->{sql_args} } );
  3         200  
814 3         40 my ($total) = $sth->fetchrow;
815 3         16 $sth->finish;
816            
817 3 50       30 my $total_pages = $total < $page_size ? 1 : POSIX::ceil($total / $page_size);
818            
819             return Class::DBI::Lite::Pager->new(
820             data_sql => $args->{data_sql},
821             count_sql => $args->{count_sql},
822             sql_args => $args->{sql_args},
823 3 50       35 class => ref($s) ? ref($s) : $s,
824             page_number => $page_number,
825             page_size => $page_size,
826             total_pages => $total_pages,
827             total_items => $total,
828             start_item => $offset + 1,
829             stop_item => $offset + $page_size,
830             );
831             }# end sql_pager()
832              
833              
834             #==============================================================================
835             sub dataset
836             {
837 1     1 0 439 my ($s) = shift;
838 1         289 require Class::DBI::Lite::Dataset;
839 1         7 Class::DBI::Lite::Dataset->new( @_ );
840             }# end dataset()
841              
842              
843             #==============================================================================
844             sub count_search_where
845             {
846 17     17 1 123 my $s = shift;
847            
848 17 100       52 my $where = (ref $_[0]) ? $_[0] : { @_ };
849 17         30 my $phrase = "";
850 17         31 my @bind;
851 17 100 66     188 if( keys( %$where ) == 1 && (keys %$where)[0] eq '1' && (values %$where)[0] eq '1' )
      66        
852             {
853             # No phrase:
854             }
855             else
856             {
857 11         36 my $abstract = SQL::Abstract::Limit->new();
858 11         508 ( $phrase, @bind ) = $abstract->where($where);
859             }# end if()
860            
861 17         1880 my $sql = "SELECT COUNT(*) FROM @{[ $s->table ]} $phrase";
  17         149  
862 17 50       54 if( $s->_meta->trace )
863             {
864 0   0     0 my $class = ref($s) || $s;
865 0         0 cluck "$class: count_search_where($sql, values[" . join( ",", map {qq('$_')} @bind) . "])";
  0         0  
866             }# end if()
867             SCOPE: {
868 17         32 my $sth = $s->db_RO->prepare_cached($sql);
  17         59  
869 17         3324 $sth->execute( @bind );
870 17         208 my ($count) = $sth->fetchrow;
871 17         74 $sth->finish;
872            
873 17         68 return $count;
874             };
875             }# end count_search_where()
876              
877              
878             #==============================================================================
879             sub find_or_create
880             {
881 14     14 1 849 my ($s, %args) = @_;
882            
883 14         33 my $result = eval {
884             $s->do_transaction(sub {
885            
886 14 100   14   122 if( my ($obj) = $s->search( %args ) )
887             {
888 2         8 return $obj;
889             }# end if()
890            
891 12         80 my $obj = $s->create( %args );
892 12         59 return $obj;
893 14         164 });
894             };
895 14 50       160 if( $@ )
896             {
897 0         0 die $@;
898             }# end if()
899            
900 14         1437 return $result;
901             }# end find_or_create()
902              
903              
904             #==============================================================================
905             sub belongs_to
906             {
907 31     31 1 210 my ($class, $method, $otherClass, $fk) = @_;
908            
909 31         153 $class->_load_class( $otherClass );
910              
911 31         137 $class->_meta->{belongs_to_rels}->{$method} = {
912             class => $otherClass,
913             fk => $fk
914             };
915            
916 17     17   146 no strict 'refs';
  17         37  
  17         2089  
917 31         147 *{"$class\::$method"} = sub {
918 117     117   4077 my $s = shift;
919            
920 117         300 $otherClass->retrieve( $s->$fk );
921 31         115 };
922             }# end belongs_to()
923             *has_a = \&belongs_to;
924              
925              
926             #==============================================================================
927             sub has_many
928             {
929 16     16 1 251 my ($class, $method, $otherClass, $fk) = @_;
930            
931 16         95 $class->_load_class( $otherClass );
932 16         84 $class->_meta->{has_many_rels}->{$method} = {
933             class => $otherClass,
934             fk => $fk,
935             };
936            
937 17     17   105 no strict 'refs';
  17         31  
  17         3149  
938 16         72 *{"$class\::$method"} = sub {
939 22     22   1712 my ($s, $args, $attrs) = @_;
940 22 100       68 $args = { } unless $args;
941 22         97 $args->{ $fk } = $s->id;
942 22   100     113 $attrs ||= { };
943 22         121 $otherClass->search_where( $args, $attrs );
944 16         66 };
945            
946 16         79 *{"$class\::add_to_$method"} = sub {
947 123     123   904 my $s = shift;
948 123 100       359 my %options = ref($_[0]) ? %{$_[0]} : @_;
  121         407  
949 123         502 $otherClass->create(
950             %options,
951             $fk => $s->id,
952             );
953 16         82 };
954             }# end has_many()
955              
956              
957             #==============================================================================
958             sub has_one
959             {
960 15     15 0 102 my ($class, $method, $otherClass, $fk) = @_;
961            
962 15         51 $class->_load_class( $otherClass );
963 15         94 $class->_meta->{has_one_rels}->{$method} = {
964             class => $otherClass,
965             fk => $fk,
966             };
967            
968 17     17   111 no strict 'refs';
  17         40  
  17         16206  
969 15         59 *{"$class\::$method"} = sub {
970 2     2   7 my $s = shift;
971 2 50       72 my ($item) = $otherClass->search( $fk => $s->id )
972             or return;
973 2         42 return $item;
974 15         57 };
975            
976 15         75 *{"$class\::set_$method"} = sub {
977 0     0   0 my $s = shift;
978 0 0       0 my %options = ref($_[0]) ? %{$_[0]} : @_;
  0         0  
979 0         0 $otherClass->create(
980             %options,
981             $fk => $s->id,
982             );
983 15         50 };
984             }# end has_one()
985              
986              
987             #==============================================================================
988             sub add_trigger
989             {
990 65     65 1 1922 my ($s, $event, $handler) = @_;
991            
992 65 50       170 confess "add_trigger called but the handler is not a subref"
993             unless ref($handler) eq 'CODE';
994            
995 65   100     116 $s->_meta->{triggers}->{$event} ||= [ ];
996 65         129 my $handlers = $s->_meta->{triggers}->{$event};
997 65 100       153 return if grep { $_ eq $handler } @$handlers;
  10         40  
998              
999 64         143 push @$handlers, $handler;
1000             }# end add_trigger()
1001              
1002              
1003             #==============================================================================
1004             sub _call_triggers
1005             {
1006 123292     123292   168717 my ($s, $event) = @_;
1007              
1008 123292   100     187906 $s->_meta->{triggers}->{ $event } ||= [ ];
1009 123292 100       146755 return unless my @handlers = @{ $s->_meta->{triggers}->{ $event } };
  123292         176444  
1010 101236         123727 shift;shift;
  101236         111116  
1011 101236         118919 my @return_values;
1012             my $return_value;
1013 101236         137435 foreach my $handler ( @handlers )
1014             {
1015 101271 100       158508 if( wantarray )
1016             {
1017 100000 50       123402 eval {
1018 100000         179344 my @val = $handler->( $s, @_ );
1019 100000 100       204970 push @return_values, @val if @val;
1020 100000         227847 1;
1021             } or confess $@;
1022             }
1023             else
1024             {
1025 1271 100       1901 eval {
1026 1271         3234 $return_value = $handler->( $s, @_ );
1027 1268         3858 1;
1028             } or confess $@;
1029             }# end if()
1030             }# end foreach()
1031            
1032 101233 100       205530 return wantarray ? @return_values : $return_value;
1033             }# end _call_triggers()
1034              
1035              
1036             #==============================================================================
1037             sub dbi_commit
1038             {
1039 20     20 0 53 my $s = shift;
1040 20 100       72 return if $s->db_Main->{AutoCommit};
1041 19         2102 $s->db_Main->commit( @_ );
1042             }# end dbi_commit()
1043              
1044              
1045             #==============================================================================
1046             sub remove_from_object_index
1047             {
1048 1     1 0 4 my $s = shift;
1049 1         11 my $obj = $Live_Objects{ $s->get_cache_key };
1050 1         5 delete($Live_Objects{ $s->get_cache_key });
1051 1         7 undef(%$obj);
1052             }# end remove_from_object_index()
1053              
1054              
1055             sub get_cache_key
1056             {
1057 100042     100042 0 124645 my $s = shift;
1058 100042 100       151153 if( my $id = shift )
1059             {
1060 100040 50       149459 my $class = ref($s) ? ref($s) : $s;
1061 100040         151774 return join ':', ( $s->root_meta->{schema}, $class, $id );
1062             }
1063             else
1064             {
1065 2         8 return $s->root_meta->{schema} . ':' . ref($s) . ':' . $s->id
1066             }# end if()
1067             }# end get_cache_key()
1068              
1069              
1070             sub as_hashref
1071             {
1072 40     40 0 48 my $s = shift;
1073 40         159 my %data = %$s;
1074 40         79 delete( $data{__Changed} );
1075 40         52 delete( $data{__id} );
1076 40         109 \%data;
1077             }# end as_hashref()
1078              
1079              
1080             #==============================================================================
1081             sub dbi_rollback
1082             {
1083 2     2 0 10 my $s = shift;
1084 2         7 $s->db_Main->rollback( @_ );
1085             }# end dbi_rollback()
1086              
1087              
1088             #==============================================================================
1089             sub discard_changes
1090             {
1091 1258     1258 1 3157 my $s = shift;
1092            
1093             map {
1094             $s->{$_} = $s->{__Changed}->{$_}->{oldval}
1095 1258         1683 } keys(%{$s->{__Changed}});
  18         130  
  1258         3024  
1096            
1097 1258         2401 $s->{__Changed} = { };
1098            
1099 1258         2061 1;
1100             }# end discard_changes()
1101              
1102              
1103             #==============================================================================
1104             *_load_class = \&load_class;
1105             sub load_class
1106             {
1107 124     124 0 241 my (undef, $class) = @_;
1108            
1109 124         491 (my $file = "$class.pm") =~ s/::/\//g;
1110 124 100       369 unless( $INC{$file} )
1111             {
1112 30         52 eval {
1113 30         7454 require $file;
1114 30         303 $class->import;
1115             };
1116             }# end unless();
1117             }# end load_class()
1118              
1119              
1120             #==============================================================================
1121             sub trace
1122             {
1123 0     0 1 0 my $s = shift;
1124 0         0 $s->_meta->trace( @_ );
1125             }# end trace()
1126              
1127              
1128             #==============================================================================
1129             sub _flesh_out
1130             {
1131 1     1   2 my $s = shift;
1132            
1133 1         4 my @missing_fields = grep { ! exists($s->{$_}) } $s->columns('All');
  3         8  
1134 1         2 my $sql = <<"";
1135 1         6 SELECT @{[ join ', ', @missing_fields ]}
1136 1         4 FROM @{[ $s->table ]}
1137 1         3 WHERE @{[ $s->primary_column ]} = ?
1138              
1139 1         5 my $sth = $s->db_RO->prepare($sql);
1140              
1141 1 50       142 if( $s->_meta->trace )
1142             {
1143 0   0     0 my $class = ref($s) || $s;
1144 0         0 cluck "$class: flesh_out($sql, values[" . $s->id . "])";
1145             }# end if()
1146 1         4 $sth->execute( $s->id );
1147 1         20 my $rec = $sth->fetchrow_hashref;
1148 1         6 $sth->finish();
1149            
1150 1         18 $s->{$_} = $rec->{$_} foreach @missing_fields;
1151 1         14 return 1;
1152             }# end _flesh_out()
1153              
1154              
1155             #==============================================================================
1156             sub DESTROY
1157             {
1158 3862     3862   118990 my $s = shift;
1159            
1160 3862 100 100     8756 if( $s->{__Changed} && keys(%{ $s->{__Changed} }) )
  3655         12116  
1161             {
1162 1         25 my $changed = join ', ', sort keys(%{ $s->{__Changed} });
  1         41  
1163 1         156 cluck ref($s) . " #$s->{__id} DESTROY'd without saving changes to $changed";
1164             }# end if()
1165            
1166 3862         24526 delete($s->{$_}) foreach keys(%$s);
1167             }# end DESTROY()
1168              
1169             {
1170             # This is deleted-object-heaven:
1171             package
1172             Class::DBI::Lite::Object::Has::Been::Deleted;
1173              
1174             use overload
1175 0     0   0 '""' => sub { '' },
1176 1     1   12 bool => sub { undef },
1177 17     17   119 fallback => 1;
  17         37  
  17         165  
1178             }
1179              
1180              
1181             sub lock_table;
1182             sub unlock_table;
1183              
1184             1;# return true:
1185              
1186              
1187             =pod
1188              
1189             =head1 NAME
1190              
1191             Class::DBI::Lite - Lightweight ORM for Perl
1192              
1193             =head1 SYNOPSIS
1194              
1195             Please take a look at L for an introduction to using this module.
1196              
1197             =head1 DESCRIPTION
1198              
1199             C offers a simple way to deal with databases in an object-oriented way.
1200              
1201             One class (the B class) defines your connection to the database (eg: connectionstring, username and password)
1202             and your other classes define interaction with one table each (your B classes).
1203              
1204             The Entity classes subclass the Model class and automatically inherit its connection.
1205              
1206             C relies heavily on L, L and L.
1207              
1208             C does not leak memory and is well-suited for use within mod_perl, Fast CGI, CGI
1209             and anywhere else you might need it.
1210              
1211             =head1 BACKGROUND
1212              
1213             I used L for a few years, a few years ago, on a very large project, under mod_perl.
1214             This was back in 2002-2003 when the ORM (Object-Relational Mapper) scene was still fairly new.
1215              
1216             While it saved me a great deal of typing, I was amazed at the complexity of C's internal code.
1217             After some time I found myself spending more effort working around problems caused by C
1218             than I could stand.
1219              
1220             Many people encountered the same problems I encountered (transactions, database connection sharing issues, performance, etc)
1221             and they all went and began writing L.
1222              
1223             L went in a direction away from the database while I wanted to get closer to
1224             the database. As close as I could possibly get without wasting time. I also wanted
1225             to keep some simple logic in my Entity classes (those classes that represent individual tables).
1226             I didn't want my ORM to do too much magic, think too much or do anything not immediately apparent.
1227             I didn't care about many-to-many relationships or automatic SQL join clauses. Vendor-specific
1228             LIMIT expressions simply were not a concern of mine.
1229              
1230             So...I reimplemented (most) of the C interface in a way that I preferred. I left out some
1231             things that didn't matter to me (eg: many-to-many relationships, column groups) and added some things
1232             I needed frequently (eg: transactions, single-field triggers, mod_perl compatibility).
1233              
1234             =head1 PHILOSOPHY
1235              
1236             C is intended to minimize the boiler-plate code typically written
1237             in most applications. It is not intended to completely insulate developers from
1238             interacting with the database directly.
1239              
1240             C is not a way to avoid I SQL - it is a way to avoid I
1241             boring, repetitive, "boiler-plate" SQL.
1242              
1243             =head1 PUBLIC PROPERTIES
1244              
1245             =head2 connection( $dsn, $username, $password )
1246              
1247             Sets the DSN for your classes.
1248              
1249             package App::db::model;
1250            
1251             use base 'Class::DBI::Lite::mysql';
1252            
1253             __PACKAGE__->connection('DBI:mysql:dbname:localhost', 'username', 'password' );
1254              
1255             =head2 db_Main
1256              
1257             Returns the active database handle in use by the class.
1258              
1259             Example:
1260              
1261             my $dbh = App::db::artist->db_Main;
1262             my $sth = $dbh->prepare("select * from artists");
1263             $sth->execute();
1264             ...
1265              
1266             =head2 table
1267              
1268             Returns the name of the table that the class is assigned to.
1269              
1270             Example:
1271              
1272             print App::db::artist->table; # 'artists'
1273              
1274             =head2 columns
1275              
1276             Returns a list of field names in the table that the class represents.
1277              
1278             Given the following table:
1279              
1280             create table artists (
1281             artist_id integer unsigned not null primary key auto_increment,
1282             name varchar(100) not null,
1283             ) engine=innodb charset=utf8;
1284              
1285             We get this:
1286              
1287             print join ", ", App::db::artist->columns;
1288             # artist_id, name
1289              
1290             =head2 trace( 1:0 )
1291              
1292             (New in version 1.018)
1293              
1294             Setting C to 1 or 0 will turn on or off SQL logging to STDERR.
1295              
1296             Example:
1297              
1298             # Start seeing all the SQL:
1299             App::db::artist->trace( 1 );
1300            
1301             # We will see some SQL when the next line is executed:
1302             my @users = App::db::artist->search_like( name => 'Rob%' );
1303            
1304             # Turn it off again:
1305             App::db::artist->trace( 0 );
1306              
1307             By default, C is turned off.
1308              
1309             =head1 STATIC METHODS
1310              
1311             =head2 create( %info )
1312              
1313             Creates a new object and returns it.
1314              
1315             Example:
1316              
1317             my $artist = App::db::artist->create( name => 'Bob Marley' );
1318              
1319             =head2 find_or_create( %info )
1320              
1321             Using C<%info> a search will be performed. If a matching result is found it is returned. Otherwise
1322             a new record will be created using C<%info> as arguments.
1323              
1324             Example:
1325              
1326             my $artist = App::db::artist->find_or_create( name => 'Bob Marley' );
1327              
1328             =head2 retrieve( $id )
1329              
1330             Given the id of a record in the database, returns that object.
1331              
1332             Example:
1333              
1334             my $artist = App::db::artist->retrieve( 1 );
1335              
1336             Same as the following SQL:
1337              
1338             SELECT *
1339             FROM artists
1340             WHERE artist_id = 1
1341              
1342             =head2 retrieve_all( )
1343              
1344             Returns all objects in the database table.
1345              
1346             Example:
1347              
1348             my @artists = App::db::artist->retrieve_all;
1349              
1350             Same as the following SQL:
1351              
1352             SELECT * FROM artists
1353              
1354             B If you want to sort all of the records or do paging, use C
1355             like this:
1356              
1357             my @artists = App::db::artist->search_where({ 1 => 1}, {order_by => 'name DESC'});
1358              
1359             Same as the following SQL:
1360              
1361             SELECT *
1362             FROM artists
1363             WHERE 1 = 1
1364             ORDER BY name DESC
1365              
1366             That "C" is a funny way of telling the database "give them all to me".
1367              
1368             =head2 has_many( ... )
1369              
1370             Declares a "one-to-many" relationship between this two classes.
1371              
1372             package App::db::artist;
1373             ...
1374             __PACKAGE__->has_many(
1375             albums =>
1376             'App::db::album' =>
1377             'album_id'
1378             );
1379              
1380             The syntax is:
1381              
1382             __PACKAGE__->has_many(
1383             $what_they_are_called =>
1384             $the_class_name =>
1385             $the_foreign_key_field_from_the_other_class
1386             );
1387              
1388             The result is this:
1389              
1390             my @albums = $artist->albums;
1391             $artist->add_to_albums( name => 'Legend' );
1392              
1393             That's the same as:
1394              
1395             my @albums = App::db::artist->search(
1396             artist_id => $artist->id
1397             );
1398              
1399             =head2 belongs_to( ... )
1400              
1401             Declares that instances "this" class exists only as a feature of instances of another class.
1402              
1403             For example, "songs" exist as features of "albums" - not the other way around.
1404              
1405             Example:
1406              
1407             package App::db::album;
1408             ...
1409             __PACKAGE__->belongs_to(
1410             artist =>
1411             'App::db::artist' =>
1412             'artist_id'
1413             );
1414              
1415             So that's:
1416              
1417             __PACKAGE__->belongs_to(
1418             $the_method_name =>
1419             $the_class_name =>
1420             $my_foreign_key_field
1421             );
1422              
1423             =head2 construct( $hashref )
1424              
1425             Blesses the object into the given class, even if we don't have all the information
1426             about the object (as long as we get its primary field value).
1427              
1428             Example:
1429              
1430             for( 1..5 ) {
1431             my $artist = App::db::artist->construct({ artist_id => $_ });
1432            
1433             # name is automatically "fleshed out":
1434             print $artist->name;
1435             }
1436              
1437             =head2 eval { do_transaction( sub { ... } ) }
1438              
1439             Executes a block of code within the context of a transaction.
1440              
1441             Example:
1442              
1443             # Safely update the name of every album:
1444             eval {
1445             App::db::artist->do_transaction( sub {
1446            
1447             # Your transaction code goes here:
1448             my $artist = App::db::artist->retrieve( 1 );
1449             foreach my $album ( $artist->albums ) {
1450             $album->name( $artist->name . ': ' . $album->name );
1451             $album->update;
1452             }
1453             });
1454             };
1455            
1456             if( $@ ) {
1457             # There was an error:
1458             die $@;
1459             }
1460             else {
1461             # Everything was OK:
1462             }
1463              
1464             =head2 search( %args )
1465              
1466             Returns any objects that match all elements in C<%args>.
1467              
1468             Example:
1469              
1470             my @artists = App::db::artist->search( name => 'Bob Marley' );
1471            
1472             my $artist_iterator = App::db::artist->search( name => 'Bob Marley' );
1473              
1474             Returns an array in list context or a L in scalar context.
1475              
1476             =head2 search_like( %args )
1477              
1478             Returns any objects that match all elements in C<%args> using the C operator.
1479              
1480             Example:
1481              
1482             my @artists = App::db::artist->search_like( name => 'Bob%' );
1483            
1484             my $artist_iterator = App::db::artist->search_like( name => 'Bob%' );
1485              
1486             Returns an array in list context or a L in scalar context.
1487              
1488             Both examples would execute the following SQL:
1489              
1490             SELECT * FROM artists WHERE name LIKE 'Bob%'
1491              
1492             =head2 search_where( \%args, [\%sort_and_limit] )
1493              
1494             Returns any objects that match all elements in C<%args> as specified by C<%sort_and_limit>.
1495              
1496             Returns an array in list context or a L in scalar context.
1497              
1498             Example 1:
1499              
1500             my @artists = App::db::artist->search_where({
1501             name => 'Bob Marley'
1502             });
1503              
1504             Same as this SQL:
1505              
1506             SELECT *
1507             FROM artists
1508             WHERE name = 'Bob Marley'
1509              
1510             Example 2:
1511              
1512             my @artists = App::db::artist->search_where({
1513             name => 'Bob Marley'
1514             }, {
1515             order_by => 'name ASC LIMIT 0, 10'
1516             });
1517              
1518             Same as this SQL:
1519              
1520             SELECT *
1521             FROM artists
1522             WHERE name = 'Bob Marley'
1523             ORDER BY name
1524             LIMIT 0, 10
1525              
1526             Example 3:
1527              
1528             my @artists = App::db::artist->search_where([
1529             name => { '!=' => 'Bob Marley' },
1530             genre => 'Rock',
1531             ]);
1532              
1533             Same as this SQL:
1534              
1535             SELECT *
1536             FROM artists
1537             WHERE name != 'Bob Marley'
1538             OR genre = 'Rock'
1539              
1540             Because C uses L to generate the SQL for the database,
1541             you can look there for more detailed examples.
1542              
1543             Specifying OrderBy, Limit and Offset separately:
1544              
1545             my @artists = App::db::artist->search_where({
1546             name => 'Bob Marley'
1547             }, {
1548             order_by => 'name ASC',
1549             limit => $how_many,
1550             offset => $start_where,
1551             });
1552              
1553             So if your C<$how_many> were 10, and your C<$start_where> were zero (C<0>) then that would be the same as:
1554              
1555             SELECT *
1556             FROM artists
1557             WHERE name = 'Bob Marley'
1558             ORDER BY name ASC
1559             LIMIT 0, 10
1560              
1561             =head2 count_search( %args )
1562              
1563             Returns the number of records that match C<%args>.
1564              
1565             Example:
1566              
1567             my $count = App::db::album->count_search( name => 'Greatest Hits' );
1568              
1569             =head2 count_search_like( %args )
1570              
1571             Returns the number of records that match C<%args> using the C operator.
1572              
1573             Example:
1574              
1575             my $count = App::db::artist->count_search_like(
1576             name => 'Bob%'
1577             );
1578              
1579             =head2 count_search_where( \%args )
1580              
1581             Returns the number of records that match C<\%args>.
1582              
1583             Examples:
1584              
1585             my $count = App::db::album->count_search_where({
1586             name => { LIKE => 'Best Of%' }
1587             });
1588            
1589             my $count = App::db::album->count_search_where({
1590             genre => { '!=' => 'Country/Western' }
1591             });
1592              
1593             As with C, the C class method uses L
1594             to generate the SQL for the database.
1595              
1596             =head2 sth_to_objects( $sth )
1597              
1598             Takes a statement handle that is ready to fetch records from. Returns the results
1599             as objects.
1600              
1601             Example:
1602              
1603             my $sth = App::db::artist->db_Main->prepare("SELECT * FROM artists");
1604             $sth->execute();
1605             my @artists = App::db::artist->sth_to_objects( $sth );
1606              
1607             This method is very useful for when your SQL query is too complicated for C.
1608              
1609             =head2 add_trigger( $event => \&sub )
1610              
1611             Specifies a callback to be executed when a specific event happens.
1612              
1613             Examples:
1614              
1615             package App::db::artist;
1616             ...
1617             __PACKAGE__->add_trigger( after_create => sub {
1618             my ($self) = @_;
1619            
1620             warn "You just created a new artist: " . $self->name;
1621             });
1622              
1623             There are 6 main trigger points at the class level and 2 trigger points for
1624             every field:
1625              
1626             =head3 Class Triggers
1627              
1628             =head4 before_create( $self )
1629              
1630             Called just before a new record is created. C<$self> is a hashref blessed into
1631             the object's class and contains only the values that were provided for its creation.
1632              
1633             So, given this trigger:
1634              
1635             package App::db::album;
1636             ...
1637             __PACKAGE__->add_trigger( before_create => sub {
1638             my ($self) = @_;
1639            
1640             warn "ID = '$self->{album_id}', Name = '$self->{name}";
1641             });
1642              
1643             If we ran this code:
1644              
1645             my $album = App::db::album->create( name => 'Legend' );
1646              
1647             We would see this output:
1648              
1649             ID = '', Name = 'Legend'
1650              
1651             Because the value for C has not been assigned by the database it does
1652             not yet have a value.
1653              
1654             =head4 after_create( $self )
1655              
1656             Called just after a new record is created. C<$self> is the new object itself.
1657              
1658             So given this trigger:
1659              
1660             package App::db::album;
1661             ...
1662             __PACKAGE__->add_trigger( after_create => sub {
1663             my ($self) = @_;
1664            
1665             warn "ID = '$self->{album_id}', Name = '$self->{name}";
1666             });
1667              
1668             If we ran this code:
1669              
1670             my $album = App::db::album->create( name => 'Legend' );
1671              
1672             We would see this output:
1673              
1674             ID = '1', Name = 'Legend'
1675              
1676             =head4 before_update( $self )
1677              
1678             Called just before changes are saved to the database. C<$self> is the object
1679             to be updated.
1680              
1681             Example:
1682              
1683             package App::db::album;
1684             ...
1685             __PACKAGE__->add_trigger( before_update => sub {
1686             my ($self) = @_;
1687            
1688             warn "About to update album " . $self->name;
1689             });
1690              
1691             =head4 after_update( $self )
1692              
1693             Called just after changes are saved to the database. C<$self> is the object
1694             that was updated.
1695              
1696             Example:
1697              
1698             package App::db::album;
1699             ...
1700             __PACKAGE__->add_trigger( after_update => sub {
1701             my ($self) = @_;
1702            
1703             warn "Finished updating album " . $self->name;
1704             });
1705              
1706             B If you make changes to C<$self> from within an C you could
1707             enter into a recursive loop in which an update is made that causes an update to
1708             be made which causes an update to be made which causes an update to be made which causes an update to be made which
1709             causes an update to be made which causes an update to be made which causes an update to be made which
1710             causes an update to be made which causes an update to be made which causes an update to be made which
1711             causes an update to be made which causes an update to be made which causes an update to be made which
1712             causes an update to be made which causes an update to be made which causes an update to be made which
1713             causes an update to be made which causes an update to be made which causes an update to be made which...and so on.
1714              
1715             B:
1716              
1717             package App::db::album;
1718             ...
1719             __PACKAGE__->add_trigger( after_update => sub {
1720             my ($self) = @_;
1721            
1722             # This will cause problems:
1723             warn "Making a recursive problem:";
1724             $self->name( 'Hello ' . rand() );
1725             $self->update;
1726             });
1727              
1728             =head4 before_delete( $self )
1729              
1730             Called just before something is deleted.
1731              
1732             Example:
1733              
1734             package App::db::album;
1735             ...
1736             __PACKAGE__->add_trigger( before_delete => sub {
1737             my ($self) = @_;
1738            
1739             warn "About to delete " . $self->name;
1740             });
1741              
1742             =head4 after_delete( {$primary_field => $id} )
1743              
1744             Called just after something is deleted.
1745              
1746             B Since the object itself is deleted from the database B memory, all
1747             that is left is the id of the original object.
1748              
1749             So, given this trigger...
1750              
1751             package App::db::album;
1752             ...
1753             use Data::Dumper;
1754             __PACKAGE__->add_trigger( after_delete => sub {
1755             my ($obj) = @_;
1756            
1757             warn "Deleted an album: " . Dumper($obj);
1758             });
1759              
1760             ...we might see the following output:
1761              
1762             Deleted an album: $VAR1 = {
1763             album_id => 123
1764             };
1765              
1766             =head3 Field Triggers
1767              
1768             =head4 before_update_( $self, $old_value, $new_value )
1769              
1770             Called just B a field's value is updated.
1771              
1772             So, given the following trigger...
1773              
1774             package App::db::album;
1775             ...
1776             __PACKAGE__->add_trigger( before_update_name => sub {
1777             my ($self, $old_value, $new_value) = @_;
1778            
1779             warn "About to change name from '$old_value' to '$new_value'";
1780             });
1781              
1782             ...called with the following code...
1783              
1784             my $artist = App::db::artist->create( name => 'Bob Marley' );
1785             my $album = $artist->add_to_albums( name => 'Legend' );
1786            
1787             # Now change the name:
1788             $album->name( 'Greatest Hits' );
1789             $album->update; # <--- the trigger is called right here.
1790              
1791             ...we would see the following output:
1792              
1793             About to change the name from 'Legend' to 'Greatest Hits'
1794              
1795             =head4 after_update_( $self, $old_value, $new_value )
1796              
1797             Called just B a field's value is updated.
1798              
1799             So, given the following trigger...
1800              
1801             package App::db::album;
1802             ...
1803             __PACKAGE__->add_trigger( after_update_name => sub {
1804             my ($self, $old_value, $new_value) = @_;
1805            
1806             warn "Changed name from '$old_value' to '$new_value'";
1807             });
1808              
1809             ...called with the following code...
1810              
1811             my $artist = App::db::artist->create( name => 'Bob Marley' );
1812             my $album = $artist->add_to_albums( name => 'Legend' );
1813            
1814             # Now change the name:
1815             $album->name( 'Greatest Hits' );
1816             $album->update; # <--- the trigger is called right here.
1817              
1818             ...we would see the following output:
1819              
1820             Changed the name from 'Legend' to 'Greatest Hits'
1821              
1822             =head2 find_column( $name )
1823              
1824             Returns the name of the column, if the class has that column.
1825              
1826             Example:
1827              
1828             if( App::db::artist->find_column('name') ) {
1829             warn "Artists have names!";
1830             }
1831              
1832             =head2 get_table_info( )
1833              
1834             Returns a L object fully-populated with all of the
1835             information available about the table represented by a class.
1836              
1837             So, given the following table structure:
1838              
1839             create table artists (
1840             artist_id integer unsigned not null primary key auto_increment,
1841             name varchar(100) not null
1842             ) engine=innodb charset=utf8;
1843              
1844             Here is the example:
1845              
1846             my $info = App::db::artist->get_table_info();
1847            
1848             my $column = $info->column('name');
1849             warn $column->name; # 'name'
1850             warn $column->type; # varchar
1851             warn $column->length; # 100
1852             warn $column->is_pk; # '0' (because it's not the Primary Key)
1853             warn $column->is_nullable; # 0 (because `not null` was specified on the table)
1854             warn $column->default_value; # undef because no default value was specified
1855             warn $column->key; # undef because not UNIQUE or PRIMARY KEY
1856            
1857             foreach my $column ( $info->columns ) {
1858             warn $column->name;
1859             warn $column->type;
1860             warn $column->length;
1861             warn $column->is_pk;
1862             ...
1863             # If the column is an 'enum' field:
1864             warn join ', ', @{ $column->enum_values };
1865             }
1866              
1867             =head2 pager( \%where, { order_by => 'fields ASC', page_number => 1, page_size => 10 } )
1868              
1869             Returns a L object.
1870              
1871             Example:
1872              
1873             # Step 1: Get our pager:
1874             my $pager = App::db::artist->pager({
1875             name => { LIKE => 'Bob%' }
1876             }, {
1877             order_by => 'name ASC',
1878             page_number => 1,
1879             page_size => 20,
1880             });
1881            
1882             # Step 2: Show the items in that recordset:
1883             foreach my $artist ( $pager->items ) {
1884             # Do stuff with $artist:
1885             print $artist->name;
1886             }
1887              
1888             See L for more details and examples.
1889              
1890             =head2 sql_pager( { data_sql => $str, count_sql => $str, sql_args => \@array }, { page_number => 1, page_size => 10 } )
1891              
1892             Returns a L object.
1893              
1894             Example:
1895              
1896             # Step 1: Get our pager:
1897             my $pager = App::db::artist->sql_pager({
1898             data_sql => "SELECT * FROM artists WHERE name LIKE ?",
1899             count_sql => "SELECT COUNT(*) FROM artists WHERE name LIKE ?",
1900             sql_args => [ 'Bob%' ],
1901             }, {
1902             page_number => 1,
1903             page_size => 20,
1904             });
1905            
1906             # Step 2: Show the items in that recordset:
1907             foreach my $artist ( $pager->items ) {
1908             # Do stuff with $artist:
1909             print $artist->name;
1910             }
1911              
1912             See L for more details and examples.
1913              
1914             =head1 OBJECT METHODS
1915              
1916             =head2 Field Methods
1917              
1918             For each of the fields in your table, an "accessor" method will be created.
1919              
1920             So, given the following table structure:
1921              
1922             create table artists (
1923             artist_id integer unsigned not null primary key auto_increment,
1924             name varchar(100) not null,
1925             ) engine=innodb charset=utf8;
1926              
1927             And the following class:
1928              
1929             package App::db::artist;
1930            
1931             use strict;
1932             use warnings 'all';
1933             use base 'My::Model';
1934            
1935             __PACKAGE__->set_up_table('artists');
1936            
1937             1;# return true:
1938              
1939             The C class would have the following methods created:
1940              
1941             =over 4
1942              
1943             =item * artist_id
1944              
1945             Returns the value of the C field the database. This value is read-only
1946             and cannot be changed.
1947              
1948             =item * name
1949              
1950             Gets or sets the value of the C field the database.
1951              
1952             To get the value of the C field, do this:
1953              
1954             my $value = $artist->name;
1955              
1956             To set the value of the C field, do this:
1957              
1958             $artist->name( "New Name" );
1959              
1960             To save those changes to the database you must call C:
1961              
1962             $artist->update;
1963              
1964             =back
1965              
1966             =head2 Overriding Setters and Getters
1967              
1968             The accessors/mutators ("setters" and "getters") can be individually overridden
1969             within your entity class by implementing C<_set_foo($self, $value)> or
1970             C<_get_foo($self)> methods.
1971              
1972             B In practice this may be more useful for the C<_get_*> methods, as the C<_set_*>
1973             methods are usually best left to triggers.
1974              
1975             =head2 id
1976              
1977             Always returns the value of the object's primary column.
1978              
1979             Example:
1980              
1981             $album->id == $album->album_id;
1982             $artist->id == $artist->artist_id;
1983              
1984             =head2 update()
1985              
1986             Causes any changes to an object to be saved to the database.
1987              
1988             Example:
1989              
1990             $artist->name( 'Big Bob' );
1991             $artist->update;
1992              
1993             =head2 delete()
1994              
1995             Deletes the object from the database. The object is then re-blessed into the special
1996             class C.
1997              
1998             Example:
1999              
2000             $album->delete;
2001              
2002             =head2 discard_changes()
2003              
2004             Causes any changes made to the object that have not been stored in the database
2005             to be forgotten.
2006              
2007             Example:
2008              
2009             my $artist = App::db::artist->create( name => 'Bob Marley' );
2010             $artist->name( 'Big Bob' );
2011            
2012             $artist->discard_changes;
2013              
2014             =head1 ADVANCED TOPICS
2015              
2016             =head2 Master/Slave Configuration
2017              
2018             In your My::db::model class:
2019              
2020             Instead of:
2021              
2022             __PACKAGE__->connection( $dsn, $user, $pass );
2023              
2024             Do this:
2025              
2026             __PACKAGE__->set_master( $dsn, $user, $pass );
2027              
2028             __PACKAGE__->set_slaves(
2029             [ $dsn1, $user1, $pass1 ],
2030             [ $dsn2, $user2, $pass2 ],
2031             [ $dsn3, $user3, $pass3 ],
2032             );
2033              
2034             Your slaves will be shuffled.
2035              
2036             Writes will always* go to the master, reads will always go to the slaves.
2037              
2038             *Unless you are inside of a transaction, in which case all reads will also go to the master.
2039              
2040             If you want to switch to a different slave, call 'switch_slave' on your main model class:
2041              
2042             My::db::model->switch_slave();
2043              
2044             In an ASP4 environment you could add a line like that to an ASP4::RequestFilter.
2045              
2046             =head1 SEE ALSO
2047              
2048             L
2049              
2050             =head1 AUTHOR
2051              
2052             Copyright John Drago . All rights reserved.
2053              
2054             =head1 LICENSE
2055              
2056             This software is B software and may be used and redistributed under the
2057             same terms as perl itself.
2058              
2059             =cut
2060