File Coverage

lib/Class/DBI/Lite.pm
Criterion Covered Total %
statement 345 393 87.7
branch 52 92 56.5
condition 16 20 80.0
subroutine 57 65 87.6
pod 2 33 6.0
total 472 603 78.2


line stmt bran cond sub pod time code
1              
2             package Class::DBI::Lite;
3              
4 3     3   551 use strict;
  3         4  
  3         67  
5 3     3   8 use warnings 'all';
  3         3  
  3         86  
6 3     3   9 use base 'Ima::DBI';
  3         3  
  3         1348  
7 3     3   46833 use Carp qw( cluck confess );
  3         6  
  3         143  
8 3     3   1926 use SQL::Abstract;
  3         25258  
  3         162  
9 3     3   1848 use SQL::Abstract::Limit;
  3         20370  
  3         128  
10 3     3   988 use Class::DBI::Lite::Iterator;
  3         3  
  3         177  
11             use overload
12 3     3   557 '""' => sub { eval { $_[0]->id } },
  3         11  
13 538     538   533 bool => sub { eval { $_[0]->id } },
  538         650  
14 3     3   844 fallback => 1;
  3         704  
  3         26  
15              
16             our $VERSION = '0.010_03';
17             our $meta;
18              
19             our %DBI_OPTIONS = (
20             FetchHashKeyName => 'NAME_lc',
21             ShowErrorStatement => 1,
22             ChopBlanks => 1,
23             AutoCommit => 1,
24             RaiseError => 1,
25             RootClass => 'DBIx::ContextualFetch',
26             );
27              
28             BEGIN {
29 3     3   295 use vars qw( $Weaken_Is_Available %Live_Objects );
  3         3  
  3         209  
30              
31 3     3   4 $Weaken_Is_Available = 1;
32 3         4 eval {
33 3         9 require Scalar::Util;
34 3         140 import Scalar::Util qw(weaken);
35             };
36 3 50       122 $Weaken_Is_Available = 0 if $@;
37             }# end BEGIN:
38              
39              
40             #==============================================================================
41             # Abstract methods:
42             sub set_up_table;
43             sub get_last_insert_id;
44              
45              
46             #==============================================================================
47             sub _init_meta
48             {
49 10     10   11 my $class = shift;
50            
51 3     3   12 no strict 'refs';
  3         2  
  3         106  
52 3     3   10 no warnings 'once';
  3         3  
  3         1025  
53 10   100     10 ${"$class\::meta"} ||= {
  10         149  
54             table => undef, # Class-based
55             columns => { # Class-based
56             All => [ ],
57             Primary => [ ],
58             Essential => [ ],
59             },
60             triggers => { # Class-based
61             before_create => [ ],
62             after_create => [ ],
63             before_update => [ ],
64             after_update => [ ],
65             before_delete => [ ],
66             after_delete => [ ],
67             },
68             has_a_rels => { }, # Class-based
69             has_many_rels => { }, # Class-based
70             };
71 10   100     15 ${__PACKAGE__ . "::meta"} ||= {
  10         51  
72             dsn => [ ], # Global
73             schema => undef, # Global
74             };
75            
76             }# end _init_meta()
77              
78              
79             #==============================================================================
80             sub find_column
81             {
82 0     0 0 0 my ($class, $name) = @_;
83            
84 0 0       0 my ($col) = grep { $_ eq $name } $class->columns('All')
  0         0  
85             or return;
86 0         0 return $col;
87             }# end find_column()
88              
89              
90             #==============================================================================
91             sub primary_column
92             {
93 1964     1964 0 1953 my $s = shift;
94 1964         2621 $s->_meta->{columns}->{Primary}->[0];
95             }# end primary_column()
96              
97              
98             #==============================================================================
99             sub construct
100             {
101 401     401 0 477 my ($s, $data) = @_;
102            
103 401 50       692 my $class = ref($s) ? ref($s) : $s;
104            
105 401         546 my $PK = $class->primary_column;
106 401         600 my $key = join ':', grep { defined($_) } ( $class, $data->{ $PK } );
  802         1312  
107 401 100       979 return $Live_Objects{$key} if $Live_Objects{$key};
108            
109             my $obj = bless {
110             %$data,
111 139         859 __id => $data->{ $PK },
112             __Changed => { },
113             }, $class;
114             #warn "ADDED $key: " . ref($obj);
115 139         311 $Live_Objects{$key} = $obj;
116             # weaken( $Live_Objects{$key} = $obj )
117             # if $Weaken_Is_Available;
118 139         419 return $obj;
119             }# end construct()
120              
121              
122             #==============================================================================
123             sub deconstruct
124             {
125 125     125 0 172 my $s = shift;
126            
127 125         1755 bless $s, 'Class::DBI::Lite::Object::Has::Been::Deleted';
128             }# end deconstruct()
129              
130              
131             #==============================================================================
132 0     0 0 0 sub schema { $_[0]->root_meta->{schema} }
133 0     0 0 0 sub dsn { $_[0]->root_meta->{dsn} }
134 419     419 0 878 sub table { $_[0]->_meta->{table} }
135 0     0 0 0 sub triggers { @{ $_[0]->_meta->{triggers}->{ $_[1] } } }
  0         0  
136             sub _meta
137             {
138 4939   66 4939   9736 my $class = ref($_[0]) || $_[0];
139 3     3   11 no strict 'refs';
  3         2  
  3         447  
140 4939         3742 ${"$class\::meta"};
  4939         22699  
141             }# end _meta()
142              
143              
144             #==============================================================================
145             sub connection
146             {
147 4     4 1 99 my ($class, @DSN) = @_;
148            
149 4         16 $class->_init_meta;
150 4         34 ($class->root_meta->{schema}) = $DSN[0] =~ m/^DBI\:.*?\:([^:]+)/;
151 4         9 $class->root_meta->{dsn} = \@DSN;
152            
153 4         11 undef(%Live_Objects);
154 4         12 local $^W = 0;
155 4         28 $class->set_db('Main' => @DSN);
156             }# end connection()
157              
158              
159             #==============================================================================
160             sub root
161             {
162 8     8 0 16 __PACKAGE__;
163             }# end root()
164              
165              
166             #==============================================================================
167             sub root_meta
168             {
169 8     8 0 6 my $s = shift;
170            
171 3     3   11 no strict 'refs';
  3         3  
  3         5749  
172 8         19 my $root = $s->root;
173              
174 8         10 ${"$root\::meta"};
  8         21  
175             }# end root_meta()
176              
177              
178             #==============================================================================
179             sub id
180             {
181 1046     1046 0 4134 $_[0]->{ $_[0]->primary_column };
182             }# end id()
183              
184              
185             #==============================================================================
186             sub columns
187             {
188 736     736 1 887 my ($s) = shift;
189            
190 736 50       1372 if( my $type = shift(@_) )
191             {
192 736 50       3067 confess "Unknown column group '$type'" unless $type =~ m/^(All|Essential|Primary)$/;
193 736 100       1340 if( my @cols = @_ )
194             {
195 20         36 $s->_meta->{columns}->{$type} = \@cols;
196             }
197             else
198             {
199 716 50       1319 return unless $s->_meta->{columns}->{$type};
200 716         778 return @{ $s->_meta->{columns}->{$type} };
  716         923  
201             }# end if()
202             }
203             else
204             {
205 0         0 return @{ $s->_meta->{columns}->{All} };
  0         0  
206             }# end if()
207             }# end columns()
208              
209              
210             #==============================================================================
211             sub retrieve_all
212             {
213 12     12 0 2821 my ($s) = @_;
214            
215 12         37 return $s->retrieve_from_sql( "" );
216             }# end retrieve_all()
217              
218              
219             #==============================================================================
220             sub retrieve
221             {
222 139     139 0 953 my ($s, $id) = @_;
223            
224 139         252 my ($obj) = $s->retrieve_from_sql(<<"", $id);
225 139         302 @{[ $s->primary_column ]} = ?
226              
227             #use Data::Dumper;
228             #warn "retrieve($s,$id): " . Dumper( $obj );
229 139         342 return $obj;
230             }# end retrieve()
231              
232              
233             #==============================================================================
234             sub create
235             {
236 125     125 0 244 my $s = shift;
237 125 100       471 my $data = ref($_[0]) ? $_[0] : { @_ };
238            
239 125         361 my $PK = $s->primary_column;
240 252         744 my %create_fields = map { $_ => $data->{$_} }
241 125 100       459 grep { exists($data->{$_}) && $_ ne $PK }
  377         1541  
242             $s->columns('All');
243            
244 125 50       859 my $pre_obj = bless {
245             __id => undef,
246             __Changed => { },
247             %create_fields
248             }, ref($s) ? ref($s) : $s;
249            
250 125         466 local $s->db_Main->{AutoCommit} = 0;
251 125         7205 my $obj = eval {
252             # Cal the "before" trigger:
253 125         599 $pre_obj->_call_triggers( before_create => \%create_fields );
254            
255             # Changes may have happened to the original creation data (from the trigger(s)) - re-evaluate now:
256 252         828 %create_fields = map { $_ => $pre_obj->{$_} }
257 125 100 66     397 grep { exists($pre_obj->{$_}) && defined($pre_obj->{$_}) && $_ ne $PK }
  377         2000  
258             $pre_obj->columns('All');
259 125         634 $data = { %$pre_obj };
260            
261 125         414 my @fields = map { $_ } sort grep { exists($data->{$_}) } keys(%create_fields);
  252         452  
  252         778  
262 125         281 my @vals = map { $data->{$_} } sort grep { exists($data->{$_}) } keys(%create_fields);
  252         439  
  252         436  
263            
264 125         265 my $sql = <<"";
265 125         395 INSERT INTO @{[ $s->table ]} (
266 125         507 @{[ join ',', @fields ]}
267             )
268             VALUES (
269 125         224 @{[ join ',', map {"?"} @vals ]}
  252         638  
270             )
271              
272 125         429 my $sth = $s->db_Main->prepare_cached( $sql );
273 125         7806 $sth->execute( map { $pre_obj->$_ } @fields );
  252         1300  
274 125 50       33020 my $id = $s->get_last_insert_id
275             or confess "ERROR - CANNOT get last insert id";
276 125         5186 $sth->finish();
277            
278 125         407 my $obj = $s->retrieve( $id );
279 125         297 $obj->_call_triggers( after_create => $obj );
280 125         319 delete($pre_obj->{__Changed});
281 125         302 undef(%$pre_obj);
282 125         271 $s->dbi_commit;
283 125         903668 $obj;
284             };
285 125 50       546 if( my $trans_error = $@ )
286             {
287 0         0 eval { $s->dbi_rollback };
  0         0  
288 0 0       0 if( my $rollback_error = $@ )
289             {
290 0         0 confess join "\n\t", "Both transaction and rollback failed:",
291             "Transaction error: $trans_error",
292             "Rollback Error: $rollback_error";
293             }
294             else
295             {
296 0         0 confess join "\n\t", "Transaction failed but rollback succeeded:",
297             "Transaction error: $trans_error";
298             }# end if()
299             }
300             else
301             {
302             # Success:
303 125         2919 return $obj;
304             }# end if()
305             }# end create()
306              
307              
308             #==============================================================================
309             sub update
310             {
311 3     3 0 7 my $s = shift;
312 3 50       7 confess "$s\->update cannot be called without an object" unless ref($s);
313            
314 3 100 66     11 return unless $s->{__Changed} && keys(%{ $s->{__Changed} });
  3         13  
315            
316 2         7 local $s->db_Main->{AutoCommit} = 0;
317 2         92 eval {
318 2         5 $s->_call_triggers( before_update => $s );
319            
320 2         3 my $changed = $s->{__Changed};
321 2         14 my @fields = map { "$_ = ?" } grep { $changed->{$_} } sort keys(%$s);
  2         6  
  14         12  
322 2         9 my @vals = map { $s->{$_} } grep { $changed->{$_} } sort keys(%$s);
  2         5  
  14         11  
323            
324 2         5 foreach my $field ( keys(%$s) )
325             {
326 14         30 $s->_call_triggers( "before_update_$field", $changed->{$field}->{oldval}, $s->{$field} );
327             }# end foreach()
328            
329             # Make our SQL:
330 2         3 my $sql = <<"";
331 2         4 UPDATE @{[ $s->table ]} SET
332 2         7 @{[ join ', ', @fields ]}
333 2         7 WHERE @{[ $s->primary_column ]} = ?
334              
335 2         6 my $sth = $s->db_Main->prepare_cached( $sql );
336 2         142 $sth->execute( @vals, $s->id );
337 2         370 $sth->finish();
338            
339 2         9 foreach my $field ( keys(%$s) )
340             {
341 14         30 $s->_call_triggers( "after_update_$field", $changed->{$field}->{oldval}, $s->{$field} );
342             }# end foreach()
343            
344 2         4 $s->{__Changed} = undef;
345 2         3 $s->_call_triggers( after_update => $s );
346 2         4 $s->dbi_commit;
347             };
348            
349 2 50       15043 if( my $trans_error = $@ )
350             {
351 0         0 eval { $s->dbi_rollback };
  0         0  
352 0 0       0 if( my $rollback_error = $@ )
353             {
354 0         0 confess join "\n\t", "Both transaction and rollback failed:",
355             "Transaction error: $trans_error",
356             "Rollback Error: $rollback_error";
357             }
358             else
359             {
360 0         0 confess join "\n\t", "Transaction failed but rollback succeeded:",
361             "Transaction error: $trans_error";
362             }# end if()
363             }
364             else
365             {
366             # Success:
367 2         42 return 1;
368             }# end if()
369             }# end update()
370              
371              
372             #==============================================================================
373             sub delete
374             {
375 125     125 0 218 my $s = shift;
376            
377 125 50       407 confess "$s\->delete cannot be called without an object" unless ref($s);
378            
379 125         373 local $s->db_Main->{AutoCommit} = 0;
380 125         5987 eval {
381 125         493 $s->_call_triggers( before_delete => $s );
382            
383 125         202 my $sql = <<"";
384 125         333 DELETE FROM @{[ $s->table ]}
385 125         347 WHERE @{[ $s->primary_column ]} = ?
386              
387 125         391 my $sth = $s->db_Main->prepare_cached( $sql );
388 125         7586 $sth->execute( $s->id );
389 125         31441 $sth->finish();
390            
391 125         360 my $deleted = bless { $s->primary_column => $s->id }, ref($s);
392 125         341 my $key = join ':', grep { defined($_) } ( ref($s), $s->id );
  250         643  
393 125         371 $s->_call_triggers( after_delete => $deleted );
394 125         401 delete($Live_Objects{$key});
395 125         293 undef(%$deleted);
396            
397 125         362 undef(%$s);
398 125         261 $s->dbi_commit;
399             };
400 125 50       412 if( my $trans_error = $@ )
401             {
402 0         0 eval { $s->dbi_rollback };
  0         0  
403 0 0       0 if( my $rollback_error = $@ )
404             {
405 0         0 confess join "\n\t", "Both transaction and rollback failed:",
406             "Transaction error: $trans_error",
407             "Rollback Error: $rollback_error";
408             }
409             else
410             {
411 0         0 confess join "\n\t", "Transaction failed but rollback succeeded:",
412             "Transaction error: $trans_error";
413             }# end if()
414             }
415             else
416             {
417             # Success:
418 125         488 $s->deconstruct;
419             }# end if()
420             }# end delete()
421              
422              
423             #==============================================================================
424             sub retrieve_from_sql
425             {
426 163     163 0 562 my ($s, $sql, @bind) = @_;
427            
428 163 100       296 $sql = "SELECT @{[ join ', ', $s->columns('Essential') ]} FROM @{[ $s->table ]}" . ( $sql ? " WHERE $sql " : "" );
  163         317  
  163         367  
429 163         480 my $sth = $s->db_Main->prepare_cached( $sql );
430 163         9887 $sth->execute( @bind );
431            
432 163         7377 return $s->sth_to_objects( $sth, $sql );
433             }# end retrieve_from_sql()
434              
435              
436             #==============================================================================
437             sub sth_to_objects
438             {
439 163     163 0 322 my ($s, $sth, $sql) = @_;
440            
441 163 50       341 my $class = ref($s) ? ref($s) : $s;
442 163 100       289 if( wantarray )
443             {
444 148         557 my @vals = map { $class->construct( $_ ) } $sth->fetchall_hash;
  262         6981  
445 148         670 $sth->finish();
446 148         465 return @vals;
447             }
448             else
449             {
450             my $iter = Class::DBI::Lite::Iterator->new(
451             [
452 15         51 map { $class->construct( $_ ) } $sth->fetchall_hash
  139         2248  
453             ]
454             );
455 15         101 $sth->finish();
456 15         80 return $iter;
457             }# end if()
458             }# end sth_to_objects()
459              
460              
461             #==============================================================================
462             sub search
463             {
464 10     10 0 54 my ($s, %args) = @_;
465            
466 10         18 my $sql = "";
467              
468 10         33 my @sql_parts = map { "$_ = ?" } sort keys(%args);
  10         40  
469 10         28 my @sql_vals = map { $args{$_} } sort keys(%args);
  10         27  
470 10         27 $sql .= join ' AND ', @sql_parts;
471            
472 10         34 return $s->retrieve_from_sql( $sql, @sql_vals );
473             }# end search()
474              
475              
476             #==============================================================================
477             sub count_search
478             {
479 1     1 0 15 my ($s, %args) = @_;
480            
481 1         1 my $sql = "SELECT COUNT(*) FROM @{[ $s->table ]} WHERE ";
  1         4  
482              
483 1         4 my @sql_parts = map { "$_ = ?" } sort keys(%args);
  1         3  
484 1         3 my @sql_vals = map { $args{$_} } sort keys(%args);
  1         4  
485 1         3 $sql .= join ' AND ', @sql_parts;
486            
487 1         10 my $sth = $s->db_Main->prepare_cached( $sql );
488 1         120 $sth->execute( @sql_vals );
489 1         43 my ($count) = $sth->fetchrow;
490 1         4 $sth->finish();
491            
492 1         3 return $count;
493             }# end count_search()
494              
495              
496             #==============================================================================
497             sub search_like
498             {
499 1     1 0 359 my ($s, %args) = @_;
500            
501 1         2 my $sql = "";
502              
503 1         3 my @sql_parts = map { "$_ LIKE ?" } sort keys(%args);
  1         4  
504 1         3 my @sql_vals = map { $args{$_} } sort keys(%args);
  1         2  
505 1         3 $sql .= join ' AND ', @sql_parts;
506            
507 1         2 return $s->retrieve_from_sql( $sql, @sql_vals );
508             }# end search_like()
509              
510              
511             #==============================================================================
512             sub count_search_like
513             {
514 1     1 0 14 my ($s, %args) = @_;
515            
516 1         2 my $sql = "SELECT COUNT(*) FROM @{[ $s->table ]} WHERE ";
  1         2  
517              
518 1         4 my @sql_parts = map { "$_ LIKE ?" } sort keys(%args);
  1         4  
519 1         2 my @sql_vals = map { $args{$_} } sort keys(%args);
  1         2  
520 1         3 $sql .= join ' AND ', @sql_parts;
521            
522 1         4 my $sth = $s->db_Main->prepare_cached( $sql );
523 1         108 $sth->execute( @sql_vals );
524 1         66 my ($count) = $sth->fetchrow;
525 1         3 $sth->finish();
526            
527 1         3 return $count;
528             }# end count_search_like()
529              
530              
531             #==============================================================================
532             sub search_where
533             {
534 1     1 0 361 my $s = shift;
535            
536 1 50       4 my $where = (ref $_[0]) ? $_[0] : { @_ };
537 1 50       4 my $attr = (ref $_[0]) ? $_[1] : undef;
538 1 50       4 my $order = ($attr) ? delete($attr->{order_by}) : undef;
539 1 50       2 my $limit = ($attr) ? delete($attr->{limit}) : undef;
540 1 50       2 my $offset = ($attr) ? delete($attr->{offset}) : undef;
541            
542 1         15 my $sql = SQL::Abstract::Limit->new(%$attr);
543 1         78 my($phrase, @bind) = $sql->where($where, $order, $limit, $offset);
544 1         513 $phrase =~ s/^\s*WHERE\s*//i;
545            
546 1         6 return $s->retrieve_from_sql($phrase, @bind);
547             }# end search_where()
548              
549              
550             #==============================================================================
551             sub count_search_where
552             {
553 1     1 0 13 my $s = shift;
554            
555 1 50       4 my $where = (ref $_[0]) ? $_[0] : { @_ };
556 1 50       4 my $attr = (ref $_[0]) ? $_[1] : undef;
557 1 50       2 my $order = ($attr) ? delete($attr->{order_by}) : undef;
558 1 50       2 my $limit = ($attr) ? delete($attr->{limit}) : undef;
559 1 50       2 my $offset = ($attr) ? delete($attr->{offset}) : undef;
560            
561 1         5 my $abstract = SQL::Abstract::Limit->new(%$attr);
562 1         31 my($phrase, @bind) = $abstract->where($where, $order, $limit, $offset);
563 1         215 $phrase =~ s/^\s*WHERE\s*//i;
564            
565 1         3 my $sql = "SELECT COUNT(*) FROM @{[ $s->table ]} WHERE $phrase";
  1         3  
566 1         4 my $sth = $s->db_Main->prepare_cached($sql);
567 1         115 $sth->execute( @bind );
568 1         63 my ($count) = $sth->fetchrow;
569 1         4 $sth->finish;
570            
571 1         4 return $count;
572             }# end count_search_where()
573              
574              
575             #==============================================================================
576             sub has_a
577             {
578 2     2 0 15 my ($class, $method, $otherClass, $fk) = @_;
579            
580 2         9 $class->_meta->{has_a_rels}->{$method} = {
581             class => $otherClass,
582             fk => $fk
583             };
584            
585 3     3   17 no strict 'refs';
  3         4  
  3         279  
586 2         11 *{"$class\::$method"} = sub {
587 12     12   19 my $s = shift;
588            
589 12         47 $otherClass->retrieve( $s->$fk );
590 2         7 };
591             }# end has_a()
592              
593              
594             #==============================================================================
595             sub has_many
596             {
597 2     2 0 17 my ($class, $method, $otherClass, $fk) = @_;
598            
599 2         9 $class->_meta->{has_many_rels}->{$method} = {
600             class => $otherClass,
601             fk => $fk,
602             };
603            
604 3     3   10 no strict 'refs';
  3         4  
  3         1841  
605 2         12 *{"$class\::$method"} = sub {
606 7     7   521 my $s = shift;
607 7         46 $otherClass->search( $fk => $s->$fk );
608 2         14 };
609            
610 2         13 *{"$class\::add_to_$method"} = sub {
611 120     120   47403 my $s = shift;
612 120 50       447 my %options = ref($_[0]) ? %{$_[0]} : @_;
  120         611  
613 120         636 $otherClass->create(
614             %options,
615             $fk => $s->id,
616             );
617 2         8 };
618            
619             $class->add_trigger( after_delete => sub {
620 4     4   9 my $s = shift;
621 4         16 $_->delete foreach $s->$method;
622 2         13 });
623             }# end has_many()
624              
625              
626             #==============================================================================
627             sub add_trigger
628             {
629 22     22 0 137 my ($s, $event, $handler) = @_;
630            
631 22         32 my $handlers = $s->_meta->{triggers}->{$event};
632 22 50       42 return if grep { $_ eq $handler } @$handlers;
  2         11  
633            
634 22         44 push @$handlers, $handler;
635             }# end add_trigger()
636              
637              
638             #==============================================================================
639             sub _call_triggers
640             {
641 536     536   857 my ($s, $event) = @_;
642            
643 536   100     1221 $s->_meta->{triggers}->{ $event } ||= [ ];
644 536 100       520 return unless my @handlers = @{ $s->_meta->{triggers}->{ $event } };
  536         699  
645 12         10 shift;shift;
  12         10  
646 12         20 foreach my $handler ( @handlers )
647             {
648 13 50       14 eval {
649 13         34 $handler->( $s, @_ );
650 13         79 1;
651             } or confess $@;
652             }# end foreach()
653             }# end _call_triggers()
654              
655              
656             #==============================================================================
657             sub dbi_commit
658             {
659 515     515 0 16943 my $s = shift;
660 515         1171 $s->db_Main->commit;
661             }# end dbi_commit()
662              
663              
664             #==============================================================================
665             sub remove_from_object_index
666             {
667 1     1 0 13 my $s = shift;
668 1         6 my $obj = delete($Live_Objects{ ref($s) . ':' . $s->id });
669 1         6 undef(%$obj);
670             }# end remove_from_object_index()
671              
672              
673             #==============================================================================
674             sub dbi_rollback
675             {
676 0     0 0 0 my $s = shift;
677 0         0 $s->db_Main->rollback;
678             }# end dbi_rollback()
679              
680              
681             #==============================================================================
682             sub discard_changes
683             {
684 0     0 0 0 my $s = shift;
685            
686 0         0 $s->{__Changed} = { };
687 0         0 $s = ref($s)->retrieve( $s->id );
688             }# end discard_changes()
689              
690              
691             #==============================================================================
692             sub _flesh_out
693             {
694 0     0   0 my $s = shift;
695            
696 0         0 my @missing_fields = grep { ! exists($s->{$_}) } $s->columns('All');
  0         0  
697 0         0 my $sth = $s->db_Main->prepare(<<"");
698 0         0 SELECT @{[ join ', ', @missing_fields ]}
699 0         0 FROM @{[ $s->table ]}
700 0         0 WHERE @{[ $s->primary_column ]} = ?
701              
702 0         0 $sth->execute( $s->id );
703 0         0 my $rec = $sth->fetchrow_hashref;
704 0         0 $sth->finish();
705            
706 0         0 $s->{$_} = $rec->{$_} foreach @missing_fields;
707 0         0 return 1;
708             }# end _flesh_out()
709              
710              
711             #==============================================================================
712             sub AUTOLOAD
713             {
714 303     303   477 my $s = shift;
715 303         225 our $AUTOLOAD;
716 303         1814 my ($name) = $AUTOLOAD =~ m/([^:]+)$/;
717              
718 303 50       671 if( my ($col) = grep { $_ eq $name } $s->columns('All') )
  935         1626  
719             {
720 303 50       665 exists($s->{$col}) or $s->_flesh_out;
721 303 100       458 if( @_ )
722             {
723 5         8 my $newval = shift;
724 3     3   15 no warnings 'uninitialized';
  3         20  
  3         869  
725 5 100       45 return $newval if $newval eq $s->{$name};
726 4   100     14 $s->{__Changed} ||= { };
727 4         24 $s->_call_triggers( "before_set_$name", $s->{$name}, $newval );
728             $s->{__Changed}->{$name} = {
729 4         17 oldval => $s->{$name}
730             };
731 4         10 return $s->{$name} = $newval;
732             }
733             else
734             {
735 298         1488 return $s->{$name};
736             }# end if()
737             }
738             else
739             {
740 0 0       0 my $class = ref($s) ? ref($s) : $s;
741 0         0 confess "Uknown field or method '$name' for class $class";
742             }# end if()
743             }# end AUTOLOAD()
744              
745              
746             #==============================================================================
747             sub DESTROY
748             {
749 263     263   920717 my $s = shift;
750            
751 263 50 66     1439 if( $s->{__Changed} && keys(%{ $s->{__Changed} }) )
  11         38  
752             {
753 0         0 my $changed = join ', ', sort keys(%{ $s->{__Changed} });
  0         0  
754 0         0 cluck ref($s) . " #$s->{__id} DESTROY'd without saving changes to $changed";
755             }# end if()
756            
757 263 50       2686 $s->dbi_commit unless $s->db_Main->{AutoCommit};
758 263         9989 delete($s->{$_}) foreach keys(%$s);
759             }# end DESTROY()
760              
761             {
762             # This is deleted-object-heaven:
763             package Class::DBI::Lite::Object::Has::Been::Deleted;
764              
765             use overload
766 10     10   23 '""' => sub { '' },
767 0     0   0 bool => sub { undef },
768 3     3   16 fallback => 1;
  3         34  
  3         26  
769             }
770              
771             1;# return true:
772              
773             __END__