File Coverage

blib/lib/Class/DBI/Frozen/301.pm
Criterion Covered Total %
statement 203 638 31.8
branch 36 228 15.7
condition 15 97 15.4
subroutine 57 145 39.3
pod 7 57 12.2
total 318 1165 27.3


line stmt bran cond sub pod time code
1             package Class::DBI::Frozen::301;
2              
3             BEGIN {
4 24     24   33866 my @cdbi_packages = qw(Column ColumnGrouper Iterator Relationship Query
5             Relationship::HasA Relationship::MightHave
6             Relationship::HasMany);
7              
8 24         84 my @cdbi_modules = qw(Column ColumnGrouper Iterator Relationship Query
9             Relationship/HasA Relationship/MightHave
10             Relationship/HasMany);
11            
12 24         74 $INC{'Class/DBI.pm'} = 'Set by Class::DBI::Frozen::301';
13             $INC{"Class/DBI/${_}.pm"} = 'Set by Class::DBI::Frozen::301'
14 24         814 for @cdbi_modules;
15              
16 24     24   1935 eval "use Class::DBI::Frozen::301::$_;" for @cdbi_packages;
  24     24   22154  
  24     24   82  
  24     24   8014  
  24     24   26253  
  24     24   87  
  24     24   2142  
  24     24   25151  
  24         79  
  24         11948  
  24         23843  
  24         76  
  24         1946  
  24         28774  
  24         328  
  24         3252  
  24         24594  
  24         80  
  24         3133  
  24         22174  
  24         103  
  24         2358  
  24         20619  
  24         78  
  24         1815  
17             }
18              
19             package Class::DBI::__::Base;
20              
21             require 5.00502;
22              
23 24     24   30181 use Class::Trigger 0.07;
  24         66105  
  24         169  
24 24     24   1595 use base qw(Class::Accessor Class::Data::Inheritable Ima::DBI);
  24         53  
  24         33295  
25              
26             package Class::DBI;
27              
28 24     24   1007029 use strict;
  24         1449  
  24         3846  
29              
30 24     24   2076 use base "Class::DBI::__::Base";
  24         49  
  24         21303  
31              
32 24     24   1563 use vars qw($VERSION);
  24         4528  
  24         2846  
33             $VERSION = '3.0.1';
34              
35 24     24   1741 use Class::DBI::ColumnGrouper;
  24         1446  
  24         10780  
36 24     24   142 use Class::DBI::Query;
  24         47  
  24         337  
37 24     24   633 use Carp ();
  24         43  
  24         386  
38 24     24   130 use List::Util;
  24         39  
  24         3231  
39 24     24   37186 use UNIVERSAL::moniker;
  24         343  
  24         855  
40              
41 24     24   137 use vars qw($Weaken_Is_Available);
  24         45  
  24         2184  
42              
43             BEGIN {
44 24     24   49 $Weaken_Is_Available = 1;
45 24         47 eval {
46 24         133 require Scalar::Util;
47 24         1852 import Scalar::Util qw(weaken);
48             };
49 24 50       1734 if ($@) {
50 0         0 $Weaken_Is_Available = 0;
51             }
52             }
53              
54             use overload
55 0     0   0 '""' => sub { shift->stringify_self },
56 0     0   0 bool => sub { not shift->_undefined_primary },
57 24     24   138 fallback => 1;
  24         50  
  24         325  
58              
59             sub stringify_self {
60 0     0 0 0 my $self = shift;
61 0 0 0     0 return (ref $self || $self) unless $self; # empty PK
62 0         0 my @cols = $self->columns('Stringify');
63 0 0       0 @cols = $self->primary_columns unless @cols;
64 0         0 return join "/", $self->get(@cols);
65             }
66              
67             sub _undefined_primary {
68 0     0   0 my $self = shift;
69 0         0 return grep !defined, $self->_attrs($self->primary_columns);
70             }
71              
72             {
73             my %deprecated = (
74             croak => "_croak", # 0.89
75             carp => "_carp", # 0.89
76             min => "minimum_value_of", # 0.89
77             max => "maximum_value_of", # 0.89
78             normalize_one => "_normalize_one", # 0.89
79             _primary => "primary_column", # 0.90
80             primary => "primary_column", # 0.89
81             primary_key => "primary_column", # 0.90
82             essential => "_essential", # 0.89
83             column_type => "has_a", # 0.90
84             associated_class => "has_a", # 0.90
85             is_column => "find_column", # 0.90
86             has_column => "find_column", # 0.94
87             add_hook => "add_trigger", # 0.90
88             run_sql => "retrieve_from_sql", # 0.90
89             rollback => "discard_changes", # 0.91
90             commit => "update", # 0.91
91             autocommit => "autoupdate", # 0.91
92             new => 'create', # 0.93
93             _commit_vals => '_update_vals', # 0.91
94             _commit_line => '_update_line', # 0.91
95             make_filter => 'add_constructor', # 0.93
96             );
97              
98 24     24   8322 no strict 'refs';
  24         69  
  24         84918  
99             while (my ($old, $new) = each %deprecated) {
100             *$old = sub {
101 1     1   6 my @caller = caller;
102 1         15 warn
103             "Use of '$old' is deprecated at $caller[1] line $caller[2]. Use '$new' instead\n";
104 1         432 goto &$new;
105             };
106             }
107             }
108              
109 0     0 0 0 sub normalize { shift->_carp("normalize is deprecated") } # 0.94
110 0     0 0 0 sub normalize_hash { shift->_carp("normalize_hash is deprecated") } # 0.94
111              
112             #----------------------------------------------------------------------
113             # Our Class Data
114             #----------------------------------------------------------------------
115             __PACKAGE__->mk_classdata('__AutoCommit');
116             __PACKAGE__->mk_classdata('__hasa_list');
117             __PACKAGE__->mk_classdata('_table');
118             __PACKAGE__->mk_classdata('_table_alias');
119             __PACKAGE__->mk_classdata('sequence');
120             __PACKAGE__->mk_classdata('__grouper');
121             __PACKAGE__->mk_classdata('__data_type');
122             __PACKAGE__->mk_classdata('__driver');
123             __PACKAGE__->__data_type({});
124              
125             __PACKAGE__->mk_classdata('iterator_class');
126             __PACKAGE__->iterator_class('Class::DBI::Iterator');
127             __PACKAGE__->__grouper(Class::DBI::ColumnGrouper->new());
128              
129             __PACKAGE__->mk_classdata('purge_object_index_every');
130             __PACKAGE__->purge_object_index_every(1000);
131              
132             __PACKAGE__->add_relationship_type(
133             has_a => "Class::DBI::Relationship::HasA",
134             has_many => "Class::DBI::Relationship::HasMany",
135             might_have => "Class::DBI::Relationship::MightHave",
136             );
137             __PACKAGE__->mk_classdata('__meta_info');
138             __PACKAGE__->__meta_info({});
139              
140             #----------------------------------------------------------------------
141             # SQL we'll need
142             #----------------------------------------------------------------------
143             __PACKAGE__->set_sql(MakeNewObj => <<'');
144             INSERT INTO __TABLE__ (%s)
145             VALUES (%s)
146              
147             __PACKAGE__->set_sql(update => <<"");
148             UPDATE __TABLE__
149             SET %s
150             WHERE __IDENTIFIER__
151              
152             __PACKAGE__->set_sql(Nextval => <<'');
153             SELECT NEXTVAL ('%s')
154              
155             __PACKAGE__->set_sql(SearchSQL => <<'');
156             SELECT %s
157             FROM %s
158             WHERE %s
159              
160             __PACKAGE__->set_sql(RetrieveAll => <<'');
161             SELECT __ESSENTIAL__
162             FROM __TABLE__
163              
164             __PACKAGE__->set_sql(Retrieve => <<'');
165             SELECT __ESSENTIAL__
166             FROM __TABLE__
167             WHERE %s
168              
169             __PACKAGE__->set_sql(Flesh => <<'');
170             SELECT %s
171             FROM __TABLE__
172             WHERE __IDENTIFIER__
173              
174             __PACKAGE__->set_sql(single => <<'');
175             SELECT %s
176             FROM __TABLE__
177              
178             __PACKAGE__->set_sql(DeleteMe => <<"");
179             DELETE
180             FROM __TABLE__
181             WHERE __IDENTIFIER__
182              
183              
184             # Override transform_sql from Ima::DBI to provide some extra
185             # transformations
186             sub transform_sql {
187 0     0 1 0 my ($self, $sql, @args) = @_;
188              
189 0         0 my %cmap;
190             my $expand_table = sub {
191 0     0   0 my ($class, $alias) = split /=/, shift, 2;
192 0 0       0 my $table = $class ? $class->table : $self->table;
193 0   0     0 $cmap{ $alias || $table } = $class || ref $self || $self;
      0        
194 0   0     0 ($alias ||= "") &&= " AS $alias";
      0        
195 0         0 return $table . $alias;
196 0         0 };
197              
198             my $expand_join = sub {
199 0     0   0 my $joins = shift;
200 0         0 my @table = split /\s+/, $joins;
201 0         0 my %tojoin = map { $table[$_] => $table[ $_ + 1 ] } 0 .. $#table - 1;
  0         0  
202 0         0 my @sql;
203 0         0 while (my ($t1, $t2) = each %tojoin) {
204 0   0     0 my ($c1, $c2) = map $cmap{$_}
205             || $self->_croak("Don't understand table '$_' in JOIN"), ($t1, $t2);
206              
207             my $join_col = sub {
208 0         0 my ($c1, $c2) = @_;
209 0         0 my $meta = $c1->meta_info('has_a');
210 0         0 my ($col) = grep $meta->{$_}->foreign_class eq $c2, keys %$meta;
211 0         0 $col;
212 0         0 };
213              
214 0   0     0 my $col = $join_col->($c1 => $c2) || do {
215             ($c1, $c2) = ($c2, $c1);
216             ($t1, $t2) = ($t2, $t1);
217             $join_col->($c1 => $c2);
218             };
219              
220 0 0       0 $self->_croak("Don't know how to join $c1 to $c2") unless $col;
221 0         0 push @sql, sprintf " %s.%s = %s.%s ", $t1, $col, $t2,
222             $c2->primary_column;
223             }
224 0         0 return join " AND ", @sql;
225 0         0 };
226              
227 0         0 $sql =~ s/__TABLE\(?(.*?)\)?__/$expand_table->($1)/eg;
  0         0  
228 0         0 $sql =~ s/__JOIN\((.*?)\)__/$expand_join->($1)/eg;
  0         0  
229 0         0 $sql =~ s/__ESSENTIAL__/join ", ", $self->_essential/eg;
  0         0  
230 0         0 $sql =~
231 0         0 s/__ESSENTIAL\((.*?)\)__/join ", ", map "$1.$_", $self->_essential/eg;
232 0 0       0 if ($sql =~ /__IDENTIFIER__/) {
233 0         0 my $key_sql = join " AND ", map "$_=?", $self->primary_columns;
234 0         0 $sql =~ s/__IDENTIFIER__/$key_sql/g;
235             }
236 0         0 return $self->SUPER::transform_sql($sql => @args);
237             }
238              
239             #----------------------------------------------------------------------
240             # EXCEPTIONS
241             #----------------------------------------------------------------------
242              
243             sub _carp {
244 0     0   0 my ($self, $msg) = @_;
245 0   0     0 Carp::carp($msg || $self);
246 0         0 return;
247             }
248              
249             sub _croak {
250 1     1   3 my ($self, $msg) = @_;
251 1   33     304 Carp::croak($msg || $self);
252             }
253              
254             #----------------------------------------------------------------------
255             # SET UP
256             #----------------------------------------------------------------------
257              
258             sub connection {
259 3     3 1 265436 my $class = shift;
260 3         34 $class->set_db(Main => @_);
261             }
262              
263             {
264             my %Per_DB_Attr_Defaults = (
265             pg => { AutoCommit => 0 },
266             oracle => { AutoCommit => 0 },
267             );
268              
269             sub _default_attributes {
270 3     3   115 my $class = shift;
271             return (
272 3 50       36 $class->SUPER::_default_attributes,
273             FetchHashKeyName => 'NAME_lc',
274             ShowErrorStatement => 1,
275             AutoCommit => 1,
276             ChopBlanks => 1,
277 3         1146 %{ $Per_DB_Attr_Defaults{ lc $class->__driver } || {} },
278             );
279             }
280             }
281              
282             sub set_db {
283 3     3 1 9 my ($class, $db_name, $data_source, $user, $password, $attr) = @_;
284              
285             # 'dbi:Pg:dbname=foo' we want 'Pg'. I think this is enough.
286 3         22 my ($driver) = $data_source =~ /^dbi:(\w+)/i;
287 3         40 $class->__driver($driver);
288 3         10397 $class->SUPER::set_db('Main', $data_source, $user, $password, $attr);
289             }
290              
291             sub table {
292 9     9 0 3815 my ($proto, $table, $alias) = @_;
293 9   33     70 my $class = ref $proto || $proto;
294 9 100       89 $class->_table($table) if $table;
295 9 50       419 $class->table_alias($alias) if $alias;
296 9   33     42 return $class->_table || $class->_table($class->table_alias);
297             }
298              
299             sub table_alias {
300 1     1 0 3 my ($proto, $alias) = @_;
301 1   33     7 my $class = ref $proto || $proto;
302 1 50       4 $class->_table_alias($alias) if $alias;
303 1   33     9 return $class->_table_alias || $class->_table_alias($class->moniker);
304             }
305              
306             sub columns {
307 49     49 1 15533 my $proto = shift;
308 49   33     433 my $class = ref $proto || $proto;
309 49   100     148 my $group = shift || "All";
310 49 100       269 return $class->_set_columns($group => @_) if @_;
311 19 100       130 return $class->all_columns if $group eq "All";
312 9 100       32 return $class->primary_column if $group eq "Primary";
313 5 100       212 return $class->_essential if $group eq "Essential";
314 1         6 return $class->__grouper->group_cols($group);
315             }
316              
317             sub _set_columns {
318 30     30   88 my ($class, $group, @columns) = @_;
319              
320             # Careful to take copy
321 30         172 $class->__grouper(Class::DBI::ColumnGrouper->clone($class->__grouper)
322             ->add_group($group => @columns));
323 30         887 $class->_mk_column_accessors(@columns);
324 30         121 return @columns;
325             }
326              
327 10     10 0 42 sub all_columns { shift->__grouper->all_columns }
328              
329             sub id {
330 0     0 0 0 my $self = shift;
331 0 0       0 my $class = ref($self)
332             or return $self->_croak("Can't call id() as a class method");
333              
334             # we don't use get() here because all objects should have
335             # exisitng values for PK columns, or else loop endlessly
336 0         0 my @pk_values = $self->_attrs($self->primary_columns);
337 0 0       0 return @pk_values if wantarray;
338 0 0       0 $self->_croak(
339             "id called in scalar context for class with multiple primary key columns")
340             if @pk_values > 1;
341 0         0 return $pk_values[0];
342             }
343              
344             sub primary_column {
345 15     15 0 705 my $self = shift;
346 15         63 my @primary_columns = $self->__grouper->primary;
347 15 100       106 return @primary_columns if wantarray;
348 2 50       9 $self->_carp(
349             ref($self)
350             . " has multiple primary columns, but fetching in scalar context")
351             if @primary_columns > 1;
352 2         12 return $primary_columns[0];
353             }
354             *primary_columns = \&primary_column;
355              
356 4     4   19 sub _essential { shift->__grouper->essential }
357              
358             sub find_column {
359 5     5 0 1547 my ($class, $want) = @_;
360 5         21 return $class->__grouper->find_column($want);
361             }
362              
363             sub _find_columns {
364 31     31   531 my $class = shift;
365 31         107 my $cg = $class->__grouper;
366 31         292 return map $cg->find_column($_), @_;
367             }
368              
369             sub has_real_column { # is really in the database
370 0     0 0 0 my ($class, $want) = @_;
371 0   0     0 return ($class->find_column($want) || return)->in_database;
372             }
373              
374             sub data_type {
375 0     0 0 0 my $class = shift;
376 0         0 my %datatype = @_;
377 0         0 while (my ($col, $type) = each %datatype) {
378 0         0 $class->_add_data_type($col, $type);
379             }
380             }
381              
382             sub _add_data_type {
383 0     0   0 my ($class, $col, $type) = @_;
384 0         0 my $datatype = $class->__data_type;
385 0         0 $datatype->{$col} = $type;
386 0         0 $class->__data_type($datatype);
387             }
388              
389             # Make a set of accessors for each of a list of columns. We construct
390             # the method name by calling accessor_name() and mutator_name() with the
391             # normalized column name.
392              
393             # mutator_name will be the same as accessor_name unless you override it.
394              
395             # If both the accessor and mutator are to have the same method name,
396             # (which will always be true unless you override mutator_name), a read-write
397             # method is constructed for it. If they differ we create both a read-only
398             # accessor and a write-only mutator.
399              
400             sub _mk_column_accessors {
401 30     30   51 my $class = shift;
402 30         166 foreach my $obj ($class->_find_columns(@_)) {
403 57         460 my %method = (
404             ro => $obj->accessor($class->accessor_name($obj->name)),
405             wo => $obj->mutator($class->mutator_name($obj->name)),
406             );
407 57         1220 my $both = ($method{ro} eq $method{wo});
408 57         148 foreach my $type (keys %method) {
409 114         181 my $name = $method{$type};
410 114 100       985 my $acc_type = $both ? "make_accessor" : "make_${type}_accessor";
411 114         340 my $accessor = $class->$acc_type($obj->name_lc);
412 114         2143 $class->_make_method($_, $accessor) for ($name, "_${name}_accessor");
413             }
414             }
415             }
416              
417             sub _make_method {
418 456     456   718 my ($class, $name, $method) = @_;
419 456 100       464 return if defined &{"$class\::$name"};
  456         3263  
420 228 50 33     3616 $class->_carp("Column '$name' in $class clashes with built-in method")
      66        
421             if Class::DBI->can($name)
422             and not($name eq "id" and join(" ", $class->primary_columns) eq "id");
423 24     24   248 no strict 'refs';
  24         52  
  24         132696  
424 228         381 *{"$class\::$name"} = $method;
  228         1126  
425 228         713 $class->_make_method(lc $name => $method);
426             }
427              
428             sub accessor_name {
429 92     92 0 597 my ($class, $column) = @_;
430 92         319 return $column;
431             }
432              
433             sub mutator_name {
434 41     41 0 1613 my ($class, $column) = @_;
435 41         97 return $class->accessor_name($column);
436             }
437              
438             sub autoupdate {
439 0     0 0 0 my $proto = shift;
440 0 0       0 ref $proto ? $proto->_obj_autoupdate(@_) : $proto->_class_autoupdate(@_);
441             }
442              
443             sub _obj_autoupdate {
444 0     0   0 my ($self, $set) = @_;
445 0         0 my $class = ref $self;
446 0 0       0 $self->{__AutoCommit} = $set if defined $set;
447 0 0       0 defined $self->{__AutoCommit}
448             ? $self->{__AutoCommit}
449             : $class->_class_autoupdate;
450             }
451              
452             sub _class_autoupdate {
453 0     0   0 my ($class, $set) = @_;
454 0 0       0 $class->__AutoCommit($set) if defined $set;
455 0         0 return $class->__AutoCommit;
456             }
457              
458             sub make_read_only {
459 0     0 0 0 my $proto = shift;
460 0     0   0 $proto->add_trigger("before_$_" => sub { _croak "$proto is read only" })
461 0         0 foreach qw/create delete update/;
462 0         0 return $proto;
463             }
464              
465             sub find_or_create {
466 0     0 0 0 my $class = shift;
467 0 0       0 my $hash = ref $_[0] eq "HASH" ? shift: {@_};
468 0         0 my ($exists) = $class->search($hash);
469 0 0       0 return defined($exists) ? $exists : $class->create($hash);
470             }
471              
472             sub create {
473 0     0 0 0 my $class = shift;
474 0 0       0 return $class->_croak("create needs a hashref") unless ref $_[0] eq 'HASH';
475 0         0 my $info = { %{ +shift } }; # make sure we take a copy
  0         0  
476              
477 0         0 my $data;
478 0         0 while (my ($k, $v) = each %$info) {
479             my $col = $class->find_column($k)
480 0     0   0 || (List::Util::first { $_->mutator eq $k } $class->columns)
481 0   0 0   0 || (List::Util::first { $_->accessor eq $k } $class->columns)
  0         0  
482             || $class->_croak("$k is not a column of $class");
483 0         0 $data->{$col} = $v;
484             }
485              
486 0         0 $class->normalize_column_values($data);
487 0         0 $class->validate_column_values($data);
488 0         0 return $class->_create($data);
489             }
490              
491             sub _attrs {
492 0     0   0 my ($self, @atts) = @_;
493 0         0 return @{$self}{@atts};
  0         0  
494             }
495             *_attr = \&_attrs;
496              
497             sub _attribute_store {
498 0     0   0 my $self = shift;
499 0 0       0 my $vals = @_ == 1 ? shift: {@_};
500 0         0 my (@cols) = keys %$vals;
501 0         0 @{$self}{@cols} = @{$vals}{@cols};
  0         0  
  0         0  
502             }
503              
504             # If you override this method, you must use the same mechanism to log changes
505             # for future updates, as other parts of Class::DBI depend on it.
506             sub _attribute_set {
507 0     0   0 my $self = shift;
508 0 0       0 my $vals = @_ == 1 ? shift: {@_};
509              
510             # We increment instead of setting to 1 because it might be useful to
511             # someone to know how many times a value has changed between updates.
512 0         0 for my $col (keys %$vals) { $self->{__Changed}{$col}++; }
  0         0  
513 0         0 $self->_attribute_store($vals);
514             }
515              
516             sub _attribute_delete {
517 0     0   0 my ($self, @attributes) = @_;
518 0         0 delete @{$self}{@attributes};
  0         0  
519             }
520              
521             sub _attribute_exists {
522 0     0   0 my ($self, $attribute) = @_;
523 0         0 exists $self->{$attribute};
524             }
525              
526             # keep an index of live objects using weak refs
527             my %Live_Objects;
528             my $Init_Count = 0;
529              
530             sub _init {
531 0     0   0 my $class = shift;
532 0   0     0 my $data = shift || {};
533 0         0 my $obj;
534 0         0 my $obj_key = "";
535              
536 0         0 my @primary_columns = $class->primary_columns;
537 0 0       0 if (@primary_columns == grep defined, @{$data}{@primary_columns}) {
  0         0  
538              
539             # create single unique key for this object
540 0         0 $obj_key = join "|", $class, map { $_ . '=' . $data->{$_} }
  0         0  
541             sort @primary_columns;
542             }
543              
544 0 0       0 unless (defined($obj = $Live_Objects{$obj_key})) {
545              
546             # not in the object_index, or we don't have all keys yet
547 0         0 $obj = bless {}, $class;
548 0         0 $obj->_attribute_store(%$data);
549              
550             # don't store it unless all keys are present
551 0 0 0     0 if ($obj_key && $Weaken_Is_Available) {
552 0         0 weaken($Live_Objects{$obj_key} = $obj);
553              
554             # time to clean up your room?
555 0 0       0 $class->purge_dead_from_object_index
556             if ++$Init_Count % $class->purge_object_index_every == 0;
557             }
558             }
559              
560 0         0 return $obj;
561             }
562              
563             sub purge_dead_from_object_index {
564 0     0 0 0 delete @Live_Objects{ grep !defined $Live_Objects{$_}, keys %Live_Objects };
565             }
566              
567             sub remove_from_object_index {
568 0     0 0 0 my $self = shift;
569 0         0 my @primary_columns = $self->primary_columns;
570 0         0 my %data;
571 0         0 @data{@primary_columns} = $self->get(@primary_columns);
572 0         0 my $obj_key = join "|", ref $self, map $_ . '=' . $data{$_},
573             sort @primary_columns;
574 0         0 delete $Live_Objects{$obj_key};
575             }
576              
577             sub clear_object_index {
578 0     0 0 0 %Live_Objects = ();
579             }
580              
581             sub _prepopulate_id {
582 0     0   0 my $self = shift;
583 0         0 my @primary_columns = $self->primary_columns;
584 0 0       0 return $self->_croak(
585             sprintf "Can't create %s object with null primary key columns (%s)",
586             ref $self, $self->_undefined_primary)
587             if @primary_columns > 1;
588 0 0       0 $self->_attribute_store($primary_columns[0] => $self->_next_in_sequence)
589             if $self->sequence;
590             }
591              
592             sub _create {
593 0     0   0 my ($proto, $data) = @_;
594 0   0     0 my $class = ref $proto || $proto;
595              
596 0         0 my $self = $class->_init($data);
597 0         0 $self->call_trigger('before_create');
598 0         0 $self->call_trigger('deflate_for_create');
599              
600 0 0       0 $self->_prepopulate_id if $self->_undefined_primary;
601              
602             # Reinstate data
603 0         0 my ($real, $temp) = ({}, {});
604 0         0 foreach my $col (grep $self->_attribute_exists($_), $self->all_columns) {
605 0 0       0 ($class->has_real_column($col) ? $real : $temp)->{$col} =
606             $self->_attrs($col);
607             }
608 0         0 $self->_insert_row($real);
609              
610 0         0 my @primary_columns = $class->primary_columns;
611 0 0       0 $self->_attribute_store(
612             $primary_columns[0] => $real->{ $primary_columns[0] })
613             if @primary_columns == 1;
614              
615 0         0 delete $self->{__Changed};
616              
617 0         0 my %primary_columns;
618 0         0 @primary_columns{@primary_columns} = ();
619 0         0 my @discard_columns = grep !exists $primary_columns{$_}, keys %$real;
620 0         0 $self->call_trigger('create', discard_columns => \@discard_columns); # XXX
621              
622             # Empty everything back out again!
623 0         0 $self->_attribute_delete(@discard_columns);
624 0         0 $self->call_trigger('after_create');
625 0         0 return $self;
626             }
627              
628             sub _next_in_sequence {
629 0     0   0 my $self = shift;
630 0         0 return $self->sql_Nextval($self->sequence)->select_val;
631             }
632              
633             sub _auto_increment_value {
634 0     0   0 my $self = shift;
635 0         0 my $dbh = $self->db_Main;
636              
637             # the DBI will provide a standard attribute soon, meanwhile...
638             my $id = $dbh->{mysql_insertid} # mysql
639 0   0     0 || eval { $dbh->func('last_insert_rowid') }; # SQLite
640 0 0       0 $self->_croak("Can't get last insert id") unless defined $id;
641 0         0 return $id;
642             }
643              
644             sub _insert_row {
645 0     0   0 my $self = shift;
646 0         0 my $data = shift;
647 0         0 eval {
648 0         0 my @columns = keys %$data;
649 0         0 my $sth = $self->sql_MakeNewObj(
650             join(', ', @columns),
651             join(', ', map $self->_column_placeholder($_), @columns),
652             );
653 0         0 $self->_bind_param($sth, \@columns);
654 0         0 $sth->execute(values %$data);
655 0         0 my @primary_columns = $self->primary_columns;
656 0 0 0     0 $data->{ $primary_columns[0] } = $self->_auto_increment_value
657             if @primary_columns == 1
658             && !defined $data->{ $primary_columns[0] };
659             };
660 0 0       0 if ($@) {
661 0         0 my $class = ref $self;
662 0         0 return $self->_croak(
663             "Can't insert new $class: $@",
664             err => $@,
665             method => 'create'
666             );
667             }
668 0         0 return 1;
669             }
670              
671             sub _bind_param {
672 0     0   0 my ($class, $sth, $keys) = @_;
673 0 0       0 my $datatype = $class->__data_type or return;
674 0         0 for my $i (0 .. $#$keys) {
675 0 0       0 if (my $type = $datatype->{ $keys->[$i] }) {
676 0         0 $sth->bind_param($i + 1, undef, $type);
677             }
678             }
679             }
680              
681             sub retrieve {
682 1     1 0 1874 my $class = shift;
683 1 50       8 my @primary_columns = $class->primary_columns
684             or return $class->_croak(
685             "Can't retrieve unless primary columns are defined");
686 0         0 my %key_value;
687 0 0 0     0 if (@_ == 1 && @primary_columns == 1) {
688 0         0 my $id = shift;
689 0 0       0 return unless defined $id;
690 0 0       0 return $class->_croak("Can't retrieve a reference") if ref($id);
691 0         0 $key_value{ $primary_columns[0] } = $id;
692             } else {
693 0         0 %key_value = @_;
694 0 0       0 $class->_croak(
695             "$class->retrieve(@_) parameters don't include values for all primary key columns (@primary_columns)"
696             )
697             if keys %key_value < @primary_columns;
698             }
699 0         0 my @rows = $class->search(%key_value);
700 0 0       0 $class->_carp("$class->retrieve(@_) selected " . @rows . " rows")
701             if @rows > 1;
702 0         0 return $rows[0];
703             }
704              
705             # Get the data, as a hash, but setting certain values to whatever
706             # we pass. Used by copy() and move().
707             # This can take either a primary key, or a hashref of all the columns
708             # to change.
709             sub _data_hash {
710 0     0   0 my $self = shift;
711 0         0 my @columns = $self->all_columns;
712 0         0 my %data;
713 0         0 @data{@columns} = $self->get(@columns);
714 0         0 my @primary_columns = $self->primary_columns;
715 0         0 delete @data{@primary_columns};
716 0 0       0 if (@_) {
717 0         0 my $arg = shift;
718 0 0       0 unless (ref $arg) {
719 0 0       0 $self->_croak("Need hash-ref to edit copied column values")
720             unless @primary_columns == 1;
721 0         0 $arg = { $primary_columns[0] => $arg };
722             }
723 0         0 @data{ keys %$arg } = values %$arg;
724             }
725 0         0 return \%data;
726             }
727              
728             sub copy {
729 0     0 0 0 my $self = shift;
730 0         0 return $self->create($self->_data_hash(@_));
731             }
732              
733             #----------------------------------------------------------------------
734             # CONSTRUCT
735             #----------------------------------------------------------------------
736              
737             sub construct {
738 0     0 0 0 my ($proto, $data) = @_;
739 0   0     0 my $class = ref $proto || $proto;
740 0         0 my $self = $class->_init($data);
741 0         0 $self->call_trigger('select');
742 0         0 return $self;
743             }
744              
745             sub move {
746 0     0 0 0 my ($class, $old_obj, @data) = @_;
747 0         0 $class->_carp("move() is deprecated. If you really need it, "
748             . "you should tell me quickly so I can abandon my plan to remove it.");
749 0 0 0     0 return $old_obj->_croak("Can't move to an unrelated class")
750             unless $class->isa(ref $old_obj)
751             or $old_obj->isa($class);
752 0         0 return $class->create($old_obj->_data_hash(@data));
753             }
754              
755             sub delete {
756 0     0 0 0 my $self = shift;
757 0 0       0 return $self->_search_delete(@_) if not ref $self;
758 0         0 $self->call_trigger('before_delete');
759              
760 0         0 eval { $self->sql_DeleteMe->execute($self->id) };
  0         0  
761 0 0       0 if ($@) {
762 0         0 return $self->_croak("Can't delete $self: $@", err => $@);
763             }
764 0         0 $self->call_trigger('after_delete');
765 0         0 undef %$self;
766 0         0 bless $self, 'Class::DBI::Object::Has::Been::Deleted';
767 0         0 return 1;
768             }
769              
770             sub _search_delete {
771 0     0   0 my ($class, @args) = @_;
772 0         0 $class->_carp(
773             "Delete as class method is deprecated. Use search and delete_all instead."
774             );
775 0         0 my $it = $class->search_like(@args);
776 0         0 while (my $obj = $it->next) { $obj->delete }
  0         0  
777 0         0 return 1;
778             }
779              
780             # Return the placeholder to be used in UPDATE and INSERT queries.
781             # Overriding this is deprecated in favour of
782             # __PACKAGE__->find_column('entered')->placeholder('IF(1, CURDATE(), ?));
783              
784             sub _column_placeholder {
785 0     0   0 my ($self, $column) = @_;
786 0         0 return $self->find_column($column)->placeholder;
787             }
788              
789             sub update {
790 0     0 0 0 my $self = shift;
791 0 0       0 my $class = ref($self)
792             or return $self->_croak("Can't call update as a class method");
793              
794 0         0 $self->call_trigger('before_update');
795 0 0       0 return 1 unless my @changed_cols = $self->is_changed;
796 0         0 $self->call_trigger('deflate_for_update');
797 0         0 my @primary_columns = $self->primary_columns;
798 0         0 my $sth = $self->sql_update($self->_update_line);
799 0         0 $class->_bind_param($sth, \@changed_cols);
800 0         0 my $rows = eval { $sth->execute($self->_update_vals, $self->id); };
  0         0  
801 0 0       0 return $self->_croak("Can't update $self: $@", err => $@) if $@;
802              
803             # enable this once new fixed DBD::SQLite is released:
804 0         0 if (0 and $rows != 1) { # should always only update one row
805             $self->_croak("Can't update $self: row not found") if $rows == 0;
806             $self->_croak("Can't update $self: updated more than one row");
807             }
808              
809 0         0 $self->call_trigger('after_update', discard_columns => \@changed_cols);
810              
811             # delete columns that changed (in case adding to DB modifies them again)
812 0         0 $self->_attribute_delete(@changed_cols);
813 0         0 delete $self->{__Changed};
814 0         0 return 1;
815             }
816              
817             sub _update_line {
818 0     0   0 my $self = shift;
819 0         0 join(', ', map "$_ = " . $self->_column_placeholder($_), $self->is_changed);
820             }
821              
822             sub _update_vals {
823 0     0   0 my $self = shift;
824 0         0 $self->_attrs($self->is_changed);
825             }
826              
827             sub DESTROY {
828 0     0   0 my ($self) = shift;
829 0 0       0 if (my @changed = $self->is_changed) {
830 0         0 my $class = ref $self;
831 0         0 $self->_carp("$class $self destroyed without saving changes to "
832             . join(', ', @changed));
833             }
834             }
835              
836             sub discard_changes {
837 0     0 0 0 my $self = shift;
838 0 0       0 return $self->_croak("Can't discard_changes while autoupdate is on")
839             if $self->autoupdate;
840 0         0 $self->_attribute_delete($self->is_changed);
841 0         0 delete $self->{__Changed};
842 0         0 return 1;
843             }
844              
845             # We override the get() method from Class::Accessor to fetch the data for
846             # the column (and associated) columns from the database, using the _flesh()
847             # method. We also allow get to be called with a list of keys, instead of
848             # just one.
849              
850             sub get {
851 0     0 1 0 my $self = shift;
852 0 0       0 return $self->_croak("Can't fetch data as class method") unless ref $self;
853              
854 0         0 my @cols = $self->_find_columns(@_);
855 0 0       0 return $self->_croak("Can't get() nothing!") unless @cols;
856              
857 0 0       0 if (my @fetch_cols = grep !$self->_attribute_exists($_), @cols) {
858 0         0 $self->_flesh($self->__grouper->groups_for(@fetch_cols));
859             }
860              
861 0         0 return $self->_attrs(@cols);
862             }
863              
864             sub _flesh {
865 0     0   0 my ($self, @groups) = @_;
866 0         0 my @real = grep $_ ne "TEMP", @groups;
867 0 0       0 if (my @want = grep !$self->_attribute_exists($_),
868             $self->__grouper->columns_in(@real)) {
869 0         0 my %row;
870 0         0 @row{@want} = $self->sql_Flesh(join ", ", @want)->select_row($self->id);
871 0         0 $self->_attribute_store(\%row);
872 0         0 $self->call_trigger('select');
873             }
874 0         0 return 1;
875             }
876              
877             # We also override set() from Class::Accessor so we can keep track of
878             # changes, and either write to the database now (if autoupdate is on),
879             # or when update() is called.
880             sub set {
881 0     0 1 0 my $self = shift;
882 0         0 my $column_values = {@_};
883              
884 0         0 $self->normalize_column_values($column_values);
885 0         0 $self->validate_column_values($column_values);
886              
887 0         0 while (my ($column, $value) = each %$column_values) {
888 0 0       0 my $col = $self->find_column($column) or die "No such column: $column\n";
889 0         0 $self->_attribute_set($col => $value);
890              
891             # $self->SUPER::set($column, $value);
892              
893 0         0 eval { $self->call_trigger("after_set_$column") }; # eg inflate
  0         0  
894 0 0       0 if ($@) {
895 0         0 $self->_attribute_delete($column);
896 0         0 return $self->_croak("after_set_$column trigger error: $@", err => $@);
897             }
898             }
899              
900 0 0       0 $self->update if $self->autoupdate;
901 0         0 return 1;
902             }
903              
904             sub is_changed {
905 0     0 0 0 my $self = shift;
906 0         0 grep $self->has_real_column($_), keys %{ $self->{__Changed} };
  0         0  
907             }
908              
909 0     0 0 0 sub any_changed { keys %{ shift->{__Changed} } }
  0         0  
910              
911             # By default do nothing. Subclasses should override if required.
912             #
913             # Given a hash ref of column names and proposed new values,
914             # edit the values in the hash if required.
915             # For create $self is the class name (not an object ref).
916             sub normalize_column_values {
917 0     0 0 0 my ($self, $column_values) = @_;
918             }
919              
920             # Given a hash ref of column names and proposed new values
921             # validate that the whole set of new values in the hash
922             # is valid for the object in relation to its current values
923             # For create $self is the class name (not an object ref).
924             sub validate_column_values {
925 0     0 0 0 my ($self, $column_values) = @_;
926 0         0 my @errors;
927 0         0 foreach my $column (keys %$column_values) {
928 0         0 eval {
929 0         0 $self->call_trigger("before_set_$column", $column_values->{$column},
930             $column_values);
931             };
932 0 0       0 push @errors, $column => $@ if $@;
933             }
934 0 0       0 return unless @errors;
935 0         0 $self->_croak(
936             "validate_column_values error: " . join(" ", @errors),
937             method => 'validate_column_values',
938             data => {@errors}
939             );
940             }
941              
942             # We override set_sql() from Ima::DBI so it has a default database connection.
943             sub set_sql {
944 216     216 1 559 my ($class, $name, $sql, $db, @others) = @_;
945 216   50     806 $db ||= 'Main';
946 216         957 $class->SUPER::set_sql($name, $sql, $db, @others);
947 216 100       11545 $class->_generate_search_sql($name) if $sql =~ /select/i;
948 216         582 return 1;
949             }
950              
951             sub _generate_search_sql {
952 144     144   1343 my ($class, $name) = @_;
953 144         272 my $method = "search_$name";
954 144 50       156 defined &{"$class\::$method"}
  144         887  
955             and return $class->_carp("$method() already exists");
956 144         272 my $sql_method = "sql_$name";
957 24     24   293 no strict 'refs';
  24         63  
  24         24001  
958 144         867 *{"$class\::$method"} = sub {
959 0     0   0 my ($class, @args) = @_;
960 0         0 return $class->sth_to_objects($name, \@args);
961 144         656 };
962             }
963              
964 0     0 0 0 sub dbi_commit { my $proto = shift; $proto->SUPER::commit(@_); }
  0         0  
965 0     0 0 0 sub dbi_rollback { my $proto = shift; $proto->SUPER::rollback(@_); }
  0         0  
966              
967             #----------------------------------------------------------------------
968             # Constraints / Triggers
969             #----------------------------------------------------------------------
970              
971             sub constrain_column {
972 0     0 0 0 my $class = shift;
973 0 0       0 my $col = $class->find_column(+shift)
974             or return $class->_croak("constraint_column needs a valid column");
975 0 0       0 my $how = shift
976             or return $class->_croak("constrain_column needs a constraint");
977 0 0       0 if (ref $how eq "ARRAY") {
    0          
978 0         0 my %hash = map { $_ => 1 } @$how;
  0         0  
979 0     0   0 $class->add_constraint(list => $col => sub { exists $hash{ +shift } });
  0         0  
980             } elsif (ref $how eq "Regexp") {
981 0     0   0 $class->add_constraint(regexp => $col => sub { shift =~ $how });
  0         0  
982             } else {
983 0         0 my $try_method = sprintf '_constrain_by_%s', $how->moniker;
984 0 0       0 if (my $dispatch = $class->can($try_method)) {
985 0         0 $class->$dispatch($col => ($how, @_));
986             } else {
987 0         0 $class->_croak("Don't know how to constrain $col with $how");
988             }
989             }
990             }
991              
992             sub add_constraint {
993 0     0 0 0 my $class = shift;
994 0 0       0 $class->_invalid_object_method('add_constraint()') if ref $class;
995 0 0       0 my $name = shift or return $class->_croak("Constraint needs a name");
996 0 0       0 my $column = $class->find_column(+shift)
997             or return $class->_croak("Constraint $name needs a valid column");
998 0 0       0 my $code = shift
999             or return $class->_croak("Constraint $name needs a code reference");
1000 0 0       0 return $class->_croak("Constraint $name '$code' is not a code reference")
1001             unless ref($code) eq "CODE";
1002              
1003 0         0 $column->is_constrained(1);
1004             $class->add_trigger(
1005             "before_set_$column" => sub {
1006 0     0   0 my ($self, $value, $column_values) = @_;
1007 0 0       0 $code->($value, $self, $column, $column_values)
1008             or return $self->_croak(
1009             "$class $column fails '$name' constraint with '$value'");
1010             }
1011 0         0 );
1012             }
1013              
1014             sub add_trigger {
1015 5     5 0 58 my ($self, $name, @args) = @_;
1016 5 50       14 return $self->_croak("on_setting trigger no longer exists")
1017             if $name eq "on_setting";
1018 5 50 33     32 $self->_carp(
1019             "$name trigger deprecated: use before_$name or after_$name instead")
1020             if ($name eq "create" or $name eq "delete");
1021 5         27 $self->SUPER::add_trigger($name => @args);
1022             }
1023              
1024             #----------------------------------------------------------------------
1025             # Inflation
1026             #----------------------------------------------------------------------
1027              
1028             sub add_relationship_type {
1029 24     24 0 133 my ($self, %rels) = @_;
1030 24         187 while (my ($name, $class) = each %rels) {
1031 72         200 $self->_require_class($class);
1032 24     24   188 no strict 'refs';
  24         54  
  24         31269  
1033 72         2867 *{"$self\::$name"} = sub {
1034 2     2   23 my $proto = shift;
1035 2         31 $class->set_up($name => $proto => @_);
1036 72         280 };
1037             }
1038             }
1039              
1040             sub _extend_meta {
1041 2     2   61 my ($class, $type, $subtype, $val) = @_;
1042 2 50       4 my %hash = %{ $class->__meta_info || {} };
  2         9  
1043 2         24 $hash{$type}->{$subtype} = $val;
1044 2         15 $class->__meta_info(\%hash);
1045             }
1046              
1047             sub meta_info {
1048 1     1 0 3 my ($class, $type, $subtype) = @_;
1049 1         9 my $meta = $class->__meta_info;
1050 1 50       11 return $meta unless $type;
1051 1 50       8 return $meta->{$type} unless $subtype;
1052 0         0 return $meta->{$type}->{$subtype};
1053             }
1054              
1055             sub _simple_bless {
1056 0     0   0 my ($class, $pri) = @_;
1057 0         0 return $class->_init({ $class->primary_column => $pri });
1058             }
1059              
1060             sub _deflated_column {
1061 0     0   0 my ($self, $col, $val) = @_;
1062 0 0 0     0 $val ||= $self->_attrs($col) if ref $self;
1063 0 0       0 return $val unless ref $val;
1064 0 0       0 my $meta = $self->meta_info(has_a => $col) or return $val;
1065 0         0 my ($a_class, %meths) = ($meta->foreign_class, %{ $meta->args });
  0         0  
1066 0 0       0 if (my $deflate = $meths{'deflate'}) {
1067 0 0       0 $val = $val->$deflate(ref $deflate eq 'CODE' ? $self : ());
1068 0 0       0 return $val unless ref $val;
1069             }
1070 0 0       0 return $self->_croak("Can't deflate $col: $val is not a $a_class")
1071             unless UNIVERSAL::isa($val, $a_class);
1072 0 0       0 return $val->id if UNIVERSAL::isa($val => 'Class::DBI');
1073 0         0 return "$val";
1074             }
1075              
1076             #----------------------------------------------------------------------
1077             # SEARCH
1078             #----------------------------------------------------------------------
1079              
1080 0     0 0 0 sub retrieve_all { shift->sth_to_objects('RetrieveAll') }
1081              
1082             sub retrieve_from_sql {
1083 0     0 0 0 my ($class, $sql, @vals) = @_;
1084 0         0 $sql =~ s/^\s*(WHERE)\s*//i;
1085 0         0 return $class->sth_to_objects($class->sql_Retrieve($sql), \@vals);
1086             }
1087              
1088 0     0 0 0 sub search_like { shift->_do_search(LIKE => @_) }
1089 0     0 0 0 sub search { shift->_do_search("=" => @_) }
1090              
1091             sub _do_search {
1092 0     0   0 my ($proto, $search_type, @args) = @_;
1093 0   0     0 my $class = ref $proto || $proto;
1094              
1095 0 0       0 @args = %{ $args[0] } if ref $args[0] eq "HASH";
  0         0  
1096 0         0 my (@cols, @vals);
1097 0 0       0 my $search_opts = @args % 2 ? pop @args : {};
1098 0         0 while (my ($col, $val) = splice @args, 0, 2) {
1099             my $column = $class->find_column($col)
1100 0   0 0   0 || (List::Util::first { $_->accessor eq $col } $class->columns)
  0         0  
1101             || $class->_croak("$col is not a column of $class");
1102 0         0 push @cols, $column;
1103 0         0 push @vals, $class->_deflated_column($column, $val);
1104             }
1105              
1106 0 0       0 my $frag = join " AND ",
1107             map defined($vals[$_]) ? "$cols[$_] $search_type ?" : "$cols[$_] IS NULL",
1108             0 .. $#cols;
1109 0 0       0 $frag .= " ORDER BY $search_opts->{order_by}"
1110             if $search_opts->{order_by};
1111 0         0 return $class->sth_to_objects($class->sql_Retrieve($frag),
1112             [ grep defined, @vals ]);
1113              
1114             }
1115              
1116             #----------------------------------------------------------------------
1117             # CONSTRUCTORS
1118             #----------------------------------------------------------------------
1119              
1120             sub add_constructor {
1121 2     2 0 26 my ($class, $method, $fragment) = @_;
1122 2 50       10 return $class->_croak("constructors needs a name") unless $method;
1123 24     24   197 no strict 'refs';
  24         48  
  24         35366  
1124 2         7 my $meth = "$class\::$method";
1125 2 50       12 return $class->_carp("$method already exists in $class")
1126             if *$meth{CODE};
1127             *$meth = sub {
1128 0     0   0 my $self = shift;
1129 0         0 $self->sth_to_objects($self->sql_Retrieve($fragment), \@_);
1130 2         17 };
1131             }
1132              
1133             sub sth_to_objects {
1134 0     0 0 0 my ($class, $sth, $args) = @_;
1135 0 0       0 $class->_croak("sth_to_objects needs a statement handle") unless $sth;
1136 0 0       0 unless (UNIVERSAL::isa($sth => "DBI::st")) {
1137 0         0 my $meth = "sql_$sth";
1138 0         0 $sth = $class->$meth();
1139             }
1140 0         0 my (%data, @rows);
1141 0         0 eval {
1142 0 0       0 $sth->execute(@$args) unless $sth->{Active};
1143 0         0 $sth->bind_columns(\(@data{ @{ $sth->{NAME_lc} } }));
  0         0  
1144 0         0 push @rows, {%data} while $sth->fetch;
1145             };
1146 0 0       0 return $class->_croak("$class can't $sth->{Statement}: $@", err => $@)
1147             if $@;
1148 0         0 return $class->_ids_to_objects(\@rows);
1149             }
1150             *_sth_to_objects = \&sth_to_objects;
1151              
1152             sub _my_iterator {
1153 0     0   0 my $self = shift;
1154 0         0 my $class = $self->iterator_class;
1155 0         0 $self->_require_class($class);
1156 0         0 return $class;
1157             }
1158              
1159             sub _ids_to_objects {
1160 0     0   0 my ($class, $data) = @_;
1161 0 0       0 return $#$data + 1 unless defined wantarray;
1162 0 0       0 return map $class->construct($_), @$data if wantarray;
1163 0         0 return $class->_my_iterator->new($class => $data);
1164             }
1165              
1166             #----------------------------------------------------------------------
1167             # SINGLE VALUE SELECTS
1168             #----------------------------------------------------------------------
1169              
1170             sub _single_row_select {
1171 0     0   0 my ($self, $sth, @args) = @_;
1172 0         0 Carp::confess("_single_row_select is deprecated in favour of select_row");
1173 0         0 return $sth->select_row(@args);
1174             }
1175              
1176             sub _single_value_select {
1177 0     0   0 my ($self, $sth, @args) = @_;
1178 0         0 $self->_carp("_single_value_select is deprecated in favour of select_val");
1179 0         0 return $sth->select_val(@args);
1180             }
1181              
1182 0     0 0 0 sub count_all { shift->sql_single("COUNT(*)")->select_val }
1183              
1184             sub maximum_value_of {
1185 0     0 0 0 my ($class, $col) = @_;
1186 0         0 $class->sql_single("MAX($col)")->select_val;
1187             }
1188              
1189             sub minimum_value_of {
1190 0     0 0 0 my ($class, $col) = @_;
1191 0         0 $class->sql_single("MIN($col)")->select_val;
1192             }
1193              
1194             sub _unique_entries {
1195 0     0   0 my ($class, %tmp) = shift;
1196 0         0 return grep !$tmp{$_}++, @_;
1197             }
1198              
1199             sub _invalid_object_method {
1200 0     0   0 my ($self, $method) = @_;
1201 0         0 $self->_carp(
1202             "$method should be called as a class method not an object method");
1203             }
1204              
1205             #----------------------------------------------------------------------
1206             # misc stuff
1207             #----------------------------------------------------------------------
1208              
1209             sub _extend_class_data {
1210 2     2   72 my ($class, $struct, $key, $value) = @_;
1211 2 100       5 my %hash = %{ $class->$struct() || {} };
  2         25  
1212 2         30 $hash{$key} = $value;
1213 2         18 $class->$struct(\%hash);
1214             }
1215              
1216             my %required_classes; # { required_class => class_that_last_required_it, ... }
1217              
1218             sub _require_class {
1219 74     74   245 my ($self, $load_class) = @_;
1220 74   33     648 $required_classes{$load_class} ||= my $for_class = ref($self) || $self;
      33        
1221              
1222             # return quickly if class already exists
1223 24     24   182 no strict 'refs';
  24         51  
  24         14203  
1224 74 50       84 return if exists ${"$load_class\::"}{ISA};
  74         626  
1225 0           (my $load_module = $load_class) =~ s!::!/!g;
1226 0 0         return if eval { require "$load_module.pm" };
  0            
1227              
1228             # Only ignore "Can't locate" errors for the specific module we're loading
1229 0 0         return if $@ =~ /^Can't locate \Q$load_module\E\.pm /;
1230              
1231             # Other fatal errors (syntax etc) must be reported (as per base.pm).
1232 0           chomp $@;
1233              
1234             # This error message prefix is especially handy when dealing with
1235             # classes that are being loaded by other classes recursively.
1236             # The final message shows the path, e.g.:
1237             # Foo can't load Bar: Bar can't load Baz: syntax error at line ...
1238 0           $self->_croak("$for_class can't load $load_class: $@");
1239             }
1240              
1241             sub _check_classes { # may automatically call from CHECK block in future
1242 0     0     while (my ($load_class, $by_class) = each %required_classes) {
1243 0 0         next if $load_class->isa("Class::DBI");
1244 0           $by_class->_croak(
1245             "Class $load_class used by $by_class has not been loaded");
1246             }
1247             }
1248              
1249             #----------------------------------------------------------------------
1250             # Deprecations
1251             #----------------------------------------------------------------------
1252              
1253             __PACKAGE__->mk_classdata('__hasa_rels');
1254             __PACKAGE__->__hasa_rels({});
1255              
1256             sub ordered_search {
1257             shift->_croak(
1258 0     0 0   "Ordered search no longer exists. Pass order_by to search instead.");
1259             }
1260              
1261             sub hasa {
1262 0     0 0   my ($class, $f_class, $f_col) = @_;
1263 0           $class->_carp(
1264             "hasa() is deprecated in favour of has_a(). Using it instead.");
1265 0           $class->has_a($f_col => $f_class);
1266             }
1267              
1268             sub hasa_list {
1269 0     0 0   my $class = shift;
1270 0           $class->_carp("hasa_list() is deprecated in favour of has_many()");
1271 0           $class->has_many(@_[ 2, 0, 1 ], { nohasa => 1 });
1272             }
1273              
1274             1;
1275              
1276             __END__