File Coverage

blib/lib/Rose/DB/Object/Metadata.pm
Criterion Covered Total %
statement 923 1820 50.7
branch 296 868 34.1
condition 92 415 22.1
subroutine 141 248 56.8
pod 88 195 45.1
total 1540 3546 43.4


line stmt bran cond sub pod time code
1             package Rose::DB::Object::Metadata;
2              
3 61     61   450 use strict;
  61         180  
  61         1860  
4              
5 61     61   327 use Carp();
  61         113  
  61         1024  
6              
7 61     61   374 use Rose::Object;
  61         160  
  61         3351  
8             our @ISA = qw(Rose::Object);
9              
10 61     61   29949 use Rose::DB::Object::Util qw(lazy_column_values_loaded_key);
  61         190  
  61         4848  
11             use Rose::DB::Object::Constants
12 61     61   478 qw(PRIVATE_PREFIX STATE_IN_DB MODIFIED_COLUMNS);
  61         166  
  61         2965  
13              
14 61     61   45931 use Rose::DB::Object::ConventionManager;
  61         224  
  61         2678  
15 61     61   36582 use Rose::DB::Object::ConventionManager::Null;
  61         196  
  61         2341  
16 61     61   26933 use Rose::DB::Object::Metadata::PrimaryKey;
  61         190  
  61         2026  
17 61     61   461 use Rose::DB::Object::Metadata::UniqueKey;
  61         166  
  61         1222  
18 61     61   345 use Rose::DB::Object::Metadata::ForeignKey;
  61         139  
  61         1361  
19 61     61   33148 use Rose::DB::Object::Metadata::Column::Scalar;
  61         238  
  61         2471  
20 61     61   34504 use Rose::DB::Object::Metadata::Relationship::OneToOne;
  61         211  
  61         3799  
21              
22             # Attempt to load Scalar::Util::Clone at runtime and ignore any errors
23             # to keep it from being a "hard" requirement.
24             eval { local $@; require Scalar::Util::Clone };
25              
26 61     61   558 use Clone(); # This is the backup clone method
  61         143  
  61         5708  
27              
28             our $VERSION = '0.820';
29              
30             our $Debug = 0;
31              
32             #
33             # Object data
34             #
35              
36             use Rose::Object::MakeMethods::Generic
37             (
38 61         1027 scalar =>
39             [
40             'class',
41             'error',
42             'pre_init_hook',
43             'post_init_hook',
44             '_object_default_manager_base_class',
45             ],
46              
47             'scalar --get_set_init' =>
48             [
49             'db',
50             'db_id',
51             'primary_key',
52             'column_name_to_method_name_mapper',
53             'original_class',
54             'auto_prime_caches',
55             ],
56              
57             boolean =>
58             [
59             allow_inline_column_values => { default => 0 },
60             is_initialized => { default => 0 },
61             is_auto_initializating => { default => 0 },
62             allow_auto_initialization => { default => 0 },
63             was_auto_initialized => { default => 0 },
64             initialized_foreign_keys => { default => 0 },
65             default_load_speculative => { default => 0 },
66             auto_load_related_classes => { default => 1 },
67             default_update_changes_only => { default => 0 },
68             default_insert_changes_only => { default => 0 },
69             default_cascade_save => { default => 0 },
70             default_smart_modification => { default => 0 },
71             include_predicated_unique_indexes => { default => 0 },
72             ],
73              
74             'array --get_set_inited' =>
75             [
76             'columns_ordered',
77             'nonpersistent_columns_ordered',
78             ]
79 61     61   408 );
  61         135  
80              
81             #
82             # Class data
83             #
84              
85             use Rose::Class::MakeMethods::Generic
86             (
87 61         1754 inheritable_scalar =>
88             [
89             'dbi_prepare_cached',
90             'default_column_undef_overrides_default',
91             '_class_default_manager_base_class',
92             ],
93              
94             inheritable_hash =>
95             [
96             column_type_classes => { interface => 'get_set_all' },
97             column_type_names => { interface => 'keys', hash_key => 'column_type_classes' },
98             _column_type_class => { interface => 'get_set', hash_key => 'column_type_classes' },
99             _delete_column_type_class => { interface => 'delete', hash_key => 'column_type_classes' },
100              
101             auto_helper_classes => { interface => 'get_set_all' },
102             delete_auto_helper_class => { interface => 'delete', hash_key => 'auto_helper_classes' },
103              
104             relationship_type_classes => { interface => 'get_set_all' },
105             relationship_type_class => { interface => 'get_set', hash_key => 'relationship_type_classes' },
106             delete_relationship_type_class => { interface => 'delete', hash_key => 'relationship_type_classes' },
107              
108             class_registry => => { interface => 'get_set_all' },
109              
110             convention_manager_classes => { interface => 'get_set_all' },
111             convention_manager_class => { interface => 'get_set', hash_key => 'convention_manager_classes' },
112             delete_convention_manager_class => { interface => 'delete', hash_key => 'convention_manager_classes' },
113             ],
114 61     61   157742 );
  61         164  
115              
116             __PACKAGE__->default_manager_base_class('Rose::DB::Object::Manager');
117             __PACKAGE__->dbi_prepare_cached(1);
118              
119             __PACKAGE__->class_registry({});
120              
121             __PACKAGE__->auto_helper_classes
122             (
123             'informix' => 'Rose::DB::Object::Metadata::Auto::Informix',
124             'pg' => 'Rose::DB::Object::Metadata::Auto::Pg',
125             'mysql' => 'Rose::DB::Object::Metadata::Auto::MySQL',
126             'sqlite' => 'Rose::DB::Object::Metadata::Auto::SQLite',
127             'oracle' => 'Rose::DB::Object::Metadata::Auto::Oracle',
128             'generic' => 'Rose::DB::Object::Metadata::Auto::Generic',
129             );
130              
131             __PACKAGE__->convention_manager_classes
132             (
133             'default' => 'Rose::DB::Object::ConventionManager',
134             'null' => 'Rose::DB::Object::ConventionManager::Null',
135             );
136              
137             __PACKAGE__->column_type_classes
138             (
139             'scalar' => 'Rose::DB::Object::Metadata::Column::Scalar',
140              
141             'char' => 'Rose::DB::Object::Metadata::Column::Character',
142             'character' => 'Rose::DB::Object::Metadata::Column::Character',
143             'varchar' => 'Rose::DB::Object::Metadata::Column::Varchar',
144             'varchar2' => 'Rose::DB::Object::Metadata::Column::Varchar',
145             'nvarchar' => 'Rose::DB::Object::Metadata::Column::Varchar',
146             'nvarchar2' => 'Rose::DB::Object::Metadata::Column::Varchar',
147             'string' => 'Rose::DB::Object::Metadata::Column::Varchar',
148              
149             'text' => 'Rose::DB::Object::Metadata::Column::Text',
150             'blob' => 'Rose::DB::Object::Metadata::Column::Blob',
151             'bytea' => 'Rose::DB::Object::Metadata::Column::Pg::Bytea',
152              
153             'bits' => 'Rose::DB::Object::Metadata::Column::Bitfield',
154             'bitfield' => 'Rose::DB::Object::Metadata::Column::Bitfield',
155              
156             'bool' => 'Rose::DB::Object::Metadata::Column::Boolean',
157             'boolean' => 'Rose::DB::Object::Metadata::Column::Boolean',
158              
159             'int' => 'Rose::DB::Object::Metadata::Column::Integer',
160             'integer' => 'Rose::DB::Object::Metadata::Column::Integer',
161              
162             'tinyint' => 'Rose::DB::Object::Metadata::Column::Integer',
163             'smallint' => 'Rose::DB::Object::Metadata::Column::Integer',
164             'mediumint' => 'Rose::DB::Object::Metadata::Column::Integer',
165              
166             'bigint' => 'Rose::DB::Object::Metadata::Column::BigInt',
167              
168             'serial' => 'Rose::DB::Object::Metadata::Column::Serial',
169             'bigserial' => 'Rose::DB::Object::Metadata::Column::BigSerial',
170              
171             'enum' => 'Rose::DB::Object::Metadata::Column::Enum',
172              
173             'num' => 'Rose::DB::Object::Metadata::Column::Numeric',
174             #'number' => 'Rose::DB::Object::Metadata::Column::Numeric',
175             'numeric' => 'Rose::DB::Object::Metadata::Column::Numeric',
176             'decimal' => 'Rose::DB::Object::Metadata::Column::Numeric',
177             'float' => 'Rose::DB::Object::Metadata::Column::Float',
178              
179             'float8' => 'Rose::DB::Object::Metadata::Column::DoublePrecision',
180             'double precision' => 'Rose::DB::Object::Metadata::Column::DoublePrecision',
181              
182             'time' => 'Rose::DB::Object::Metadata::Column::Time',
183             'interval' => 'Rose::DB::Object::Metadata::Column::Interval',
184              
185             'date' => 'Rose::DB::Object::Metadata::Column::Date',
186             'datetime' => 'Rose::DB::Object::Metadata::Column::Datetime',
187             'timestamp' => 'Rose::DB::Object::Metadata::Column::Timestamp',
188              
189             'timestamp with time zone' => 'Rose::DB::Object::Metadata::Column::TimestampWithTimeZone',
190             'timestamp without time zone' => 'Rose::DB::Object::Metadata::Column::Timestamp',
191              
192             'datetime year to fraction' => 'Rose::DB::Object::Metadata::Column::DatetimeYearToFraction',
193             'datetime year to fraction(1)' => 'Rose::DB::Object::Metadata::Column::DatetimeYearToFraction1',
194             'datetime year to fraction(2)' => 'Rose::DB::Object::Metadata::Column::DatetimeYearToFraction2',
195             'datetime year to fraction(3)' => 'Rose::DB::Object::Metadata::Column::DatetimeYearToFraction3',
196             'datetime year to fraction(4)' => 'Rose::DB::Object::Metadata::Column::DatetimeYearToFraction4',
197             'datetime year to fraction(5)' => 'Rose::DB::Object::Metadata::Column::DatetimeYearToFraction5',
198              
199             'datetime year to second' => 'Rose::DB::Object::Metadata::Column::DatetimeYearToSecond',
200             'datetime year to minute' => 'Rose::DB::Object::Metadata::Column::DatetimeYearToMinute',
201              
202             'datetime year to month' => 'Rose::DB::Object::Metadata::Column::DatetimeYearToMonth',
203              
204             'epoch' => 'Rose::DB::Object::Metadata::Column::Epoch',
205             'epoch hires' => 'Rose::DB::Object::Metadata::Column::Epoch::HiRes',
206              
207             'array' => 'Rose::DB::Object::Metadata::Column::Array',
208             'set' => 'Rose::DB::Object::Metadata::Column::Set',
209              
210             'chkpass' => 'Rose::DB::Object::Metadata::Column::Pg::Chkpass',
211             );
212              
213             __PACKAGE__->relationship_type_classes
214             (
215             'one to one' => 'Rose::DB::Object::Metadata::Relationship::OneToOne',
216             'one to many' => 'Rose::DB::Object::Metadata::Relationship::OneToMany',
217             'many to one' => 'Rose::DB::Object::Metadata::Relationship::ManyToOne',
218             'many to many' => 'Rose::DB::Object::Metadata::Relationship::ManyToMany',
219             );
220              
221             #
222             # Methods
223             #
224              
225             sub init_column_name_to_method_name_mapper() { 0 }
226              
227             our %Objects;
228              
229             sub new
230             {
231 99     99 1 471 my($this_class, %args) = @_;
232 99 50       279 my $class = $args{'class'} or Carp::croak "Missing required 'class' parameter";
233 99   33     754 return $Objects{$class} ||= shift->SUPER::new(@_);
234             }
235              
236             sub init
237             {
238 99     99 1 813 my($self) = shift;
239              
240             # This attribute will be accessed many times, and a default
241             # of 0 is usually a "faster false" than undef.
242 99         333 $self->sql_qualify_column_names_on_load(0);
243              
244 99         335 $self->SUPER::init(@_);
245             }
246              
247 82     82 0 842 sub init_original_class { ref shift }
248              
249 75 50   75 0 851 sub init_auto_prime_caches { $ENV{'MOD_PERL'} ? 1 : 0 }
250              
251             sub default_manager_base_class
252             {
253 78     78 1 5131 my($self_or_class) = shift;
254              
255 78 100       392 if(ref($self_or_class))
256             {
257 12   66     77 return $self_or_class->_object_default_manager_base_class(@_) ||
258             ref($self_or_class)->_class_default_manager_base_class;
259             }
260              
261 66         473 return $self_or_class->_class_default_manager_base_class(@_);
262             }
263              
264             sub reset
265             {
266 0     0 0 0 my($self) = shift;
267              
268 0         0 $self->is_initialized(0);
269 0         0 $self->allow_auto_initialization(0);
270 0         0 $self->was_auto_initialized(0);
271 0         0 $self->initialized_foreign_keys(0);
272              
273 0         0 return;
274             }
275              
276             sub clone
277             {
278 0     0 0 0 my($self) = shift;
279              
280             # The easy way: use Scalar::Util::Clone
281 0 0       0 if(defined $Scalar::Util::Clone::VERSION)
282             {
283 0         0 return Scalar::Util::Clone::clone($self);
284             }
285              
286             # The hard way: Clone.pm plus mucking
287 0         0 my $meta = Clone::clone($self);
288              
289             # Reset all the parent back-links
290 0         0 foreach my $item (grep { defined } $meta->columns, $meta->primary_key,
  0         0  
291             $meta->unique_keys, $meta->foreign_keys,
292             $meta->relationships)
293             {
294 0         0 $item->parent($meta);
295             }
296              
297 0         0 return $meta;
298             }
299              
300             sub allow_inheritance_from_meta
301             {
302 0     0 0 0 my($class, $meta) = @_;
303 0 0       0 return $meta->num_columns > 0 ? 1 : 0;
304             }
305              
306             sub for_class
307             {
308 99     99 1 312 my($meta_class, $class) = (shift, shift);
309 99 100       325 return $Objects{$class} if($Objects{$class});
310              
311             # Clone an ancestor meta object
312 98         351 foreach my $parent_class (__get_parents($class))
313             {
314 198 50       489 if(my $parent_meta = $Objects{$parent_class})
315             {
316 0 0       0 next unless($meta_class->allow_inheritance_from_meta($parent_meta));
317              
318 0         0 my $meta = $parent_meta->clone;
319              
320 0         0 $meta->reset(0);
321 0         0 $meta->class($class);
322              
323 0         0 return $Objects{$class} = $meta;
324             }
325             }
326              
327 98         380 return $Objects{$class} = $meta_class->new(class => $class);
328             }
329              
330             sub __get_parents
331             {
332 198     198   373 my($class) = shift;
333 198         293 my @parents;
334              
335 61     61   126882 no strict 'refs';
  61         225  
  61         128107  
336 198         276 foreach my $sub_class (@{"${class}::ISA"})
  198         921  
337             {
338 198 100       1220 push(@parents, __get_parents($sub_class)) if($sub_class->isa('Rose::DB::Object'));
339             }
340              
341 198         507 return $class, @parents;
342             }
343              
344             sub clear_all_dbs
345             {
346 0     0 1 0 my($class) = shift;
347              
348 0         0 foreach my $obj_class ($class->registered_classes)
349             {
350 0         0 $obj_class->meta->db(undef);
351             }
352             }
353              
354             sub error_mode
355             {
356 0 0 0 0 1 0 return $_[0]->{'error_mode'} ||= $_[0]->init_error_mode
357             unless(@_ > 1);
358              
359 0         0 my($self, $mode) = @_;
360              
361 0 0       0 unless($mode =~ /^(?:return|carp|croak|cluck|confess|fatal)$/)
362             {
363 0         0 Carp::croak "Invalid error mode: '$mode'";
364             }
365              
366 0         0 return $self->{'error_mode'} = $mode;
367             }
368              
369 0     0 0 0 sub init_error_mode { 'fatal' }
370              
371             sub handle_error
372             {
373 0     0 0 0 my($self, $object) = @_;
374              
375 0         0 my $mode = $self->error_mode;
376              
377 0 0       0 return if($mode eq 'return');
378              
379 0         0 my $level = $Carp::CarpLevel;
380 0         0 local $Carp::CarpLevel = $level + 1;
381              
382 0 0 0     0 if($mode eq 'croak' || $mode eq 'fatal')
    0          
    0          
    0          
383             {
384 0         0 Carp::croak $object->error;
385             }
386             elsif($mode eq 'carp')
387             {
388 0         0 Carp::carp $object->error;
389             }
390             elsif($mode eq 'cluck')
391             {
392 0         0 Carp::cluck $object->error;
393             }
394             elsif($mode eq 'confess')
395             {
396 0         0 Carp::confess $object->error;
397             }
398             else
399             {
400 0         0 Carp::croak "(Invalid error mode set: '$mode') - ", $object->error;
401             }
402              
403 0         0 return 1;
404             }
405              
406             sub setup
407             {
408 5     5 1 67 my($self) = shift;
409              
410 5 50       14 return 1 if($self->is_initialized);
411              
412 5         42 my $init_args = [];
413 5         7 my $auto_init = 0;
414              
415 5         14 PAIR: while(@_)
416             {
417 9         53 my $method = shift;
418              
419 9 50       21 if(ref $method eq 'CODE')
420             {
421 0         0 $method->($self);
422 0         0 next PAIR;
423             }
424              
425 9         14 my $args = shift;
426              
427 9 50       49 if($method =~ /^((?:auto_(?!helper)|(?:default_)?perl_)\w*)$/)
428             {
429 0         0 $self->init_auto_helper;
430             }
431              
432 9 50 33     51 if($method eq 'initialize')
    50          
    50          
433             {
434 0 0       0 $init_args = ref $args ? $args : [ $args ];
435 0         0 next PAIR;
436             }
437             elsif($method eq 'auto_initialize' || $method eq 'auto')
438             {
439 0 0 0     0 unless($method eq 'auto' && !ref $args)
440             {
441 0 0       0 $init_args = ref $args ? $args : [ $args ];
442             }
443              
444 0         0 $auto_init = 1;
445 0         0 next PAIR;
446             }
447             elsif($method eq 'helpers')
448             {
449 0         0 require Rose::DB::Object::Helpers;
450              
451 0 0       0 Rose::DB::Object::Helpers->import(
452             '--target-class' => $self->class, (ref $args eq 'ARRAY' ? @$args : $args));
453              
454 0         0 next PAIR;
455             }
456              
457 9 50       36 unless($self->can($method))
458             {
459 0         0 Carp::croak "Invalid parameter name: '$method'";
460             }
461              
462 9 50       26 if(ref $args eq 'ARRAY')
463             {
464             # Special case for the unique_key and add_unique_key methods
465             # when the argument is a single array reference containing only
466             # non-reference values
467 9 50 33     36 if(($method eq 'unique_key' || $method eq 'add_unique_key') &&
      33        
468 0         0 !grep { ref } @$args)
469             {
470 0         0 $self->$method($args);
471             }
472             else
473             {
474 9         26 $self->$method(@$args);
475             }
476             }
477             else
478             {
479 0         0 $self->$method($args);
480             }
481             }
482              
483 5 50       21 if($auto_init)
484             {
485 0         0 $self->auto_initialize(@$init_args);
486             }
487             else
488             {
489 5         16 $self->initialize(@$init_args);
490             }
491              
492 4         13 return 1;
493             }
494              
495             sub init_db
496             {
497 235     235 0 852 my($self) = shift;
498              
499 235 50       672 my $class = $self->class or die "Missing class!";
500              
501 235 50       2792 my $db = $self->class->init_db or
502             Carp::croak "Could not init_db() for class $class - are you sure that ",
503             "Rose::DB's data sources are set up?";
504              
505 235         65660 $self->{'db_id'} = $db->{'id'};
506              
507 235         783 return $db;
508             }
509              
510             sub init_db_id
511             {
512 157     157 0 296 my($self) = shift;
513 157         406 $self->init_db;
514 157         2395 return $self->{'db_id'};
515             }
516              
517 93     93 1 2436 sub init_convention_manager { shift->convention_manager_class('default')->new }
518              
519             sub convention_manager
520             {
521 432     432 1 2265 my($self) = shift;
522              
523 432 100       983 if(@_)
524             {
525 3         8 my $mgr = shift;
526              
527             # Setting to undef means use the null convention manager
528 3 50       15 if(!defined $mgr)
    50          
    0          
529             {
530 0         0 return $self->{'convention_manager'} =
531             Rose::DB::Object::ConventionManager::Null->new(parent => $self);
532             }
533             elsif(!ref $mgr)
534             {
535 3 100       21 if(UNIVERSAL::isa($mgr, 'Rose::DB::Object::ConventionManager'))
536             {
537 1         31 $mgr = $mgr->new;
538             }
539             else
540             {
541 2 100       8 my $class = $self->convention_manager_class($mgr) or
542             Carp::croak "No convention manager class registered under the name '$mgr'";
543              
544 1         26 $mgr = $class->new;
545             }
546             }
547             elsif(!UNIVERSAL::isa($mgr, 'Rose::DB::Object::ConventionManager'))
548             {
549 0         0 Carp::croak "$mgr is not a Rose::DB::Object::ConventionManager-derived object";
550             }
551              
552 2         49 $mgr->parent($self);
553 2         7 return $self->{'convention_manager'} = $mgr;
554             }
555              
556 429 100       943 if(defined $self->{'convention_manager'})
557             {
558 336         1388 return $self->{'convention_manager'};
559             }
560              
561 93         257 my $mgr = $self->init_convention_manager;
562 93         2391 $mgr->parent($self);
563 93         465 return $self->{'convention_manager'} = $mgr;
564             }
565              
566 112     112 1 439 sub cached_objects_expire_in { shift->class->cached_objects_expire_in(@_) }
567 0     0 1 0 sub clear_object_cache { shift->class->clear_object_cache(@_) }
568              
569             sub prepare_select_options
570             {
571             @_ > 1 ? $_[0]->{'prepare_select_options'} = $_[1] :
572 0 0 0 0 0 0 $_[0]->{'prepare_select_options'} ||= {}
573             }
574              
575             sub prepare_insert_options
576             {
577             @_ > 1 ? $_[0]->{'prepare_insert_options'} = $_[1] :
578 0 0 0 0 0 0 $_[0]->{'prepare_insert_options'} ||= {}
579             }
580              
581             sub prepare_update_options
582             {
583             @_ > 1 ? $_[0]->{'prepare_update_options'} = $_[1] :
584 0 0 0 0 0 0 $_[0]->{'prepare_update_options'} ||= {}
585             }
586              
587             sub prepare_delete_options
588             {
589             @_ > 1 ? $_[0]->{'prepare_delete_options'} = $_[1] :
590 0 0 0 0 0 0 $_[0]->{'prepare_delete_options'} ||= {}
591             }
592              
593             sub prepare_bulk_delete_options
594             {
595             @_ > 1 ? $_[0]->{'prepare_bulk_delete_options'} = $_[1] :
596 0 0 0 0 0 0 $_[0]->{'prepare_bulk_delete_options'} ||=
597             $_[0]->prepare_delete_options;
598             }
599              
600             sub prepare_bulk_update_options
601             {
602             @_ > 1 ? $_[0]->{'prepare_bulk_update_options'} = $_[1] :
603 0 0 0 0 0 0 $_[0]->{'prepare_bulk_update_options'} ||=
604             $_[0]->prepare_update_options;
605             }
606              
607             sub prepare_options
608             {
609 0     0 0 0 my($self, $options) = @_;
610              
611 0 0       0 Carp::croak "Missing required hash ref argument to prepare_options()"
612             unless(ref $options eq 'HASH');
613              
614 0         0 $self->prepare_select_options({ %$options });
615 0         0 $self->prepare_insert_options({ %$options });
616 0         0 $self->prepare_update_options({ %$options });
617 0         0 $self->prepare_delete_options({ %$options });
618             }
619              
620             sub table
621             {
622 176 100   176 1 3071 unless(@_ > 1)
623             {
624 171   66     827 return $_[0]->{'table'} ||= $_[0]->convention_manager->auto_table_name;
625             }
626              
627 5         35 $_[0]->_clear_table_generated_values;
628 5         20 return $_[0]->{'table'} = $_[1];
629             }
630              
631             sub catalog
632             {
633 0 0   0 1 0 return $_[0]->{'catalog'} unless(@_ > 1);
634 0         0 $_[0]->_clear_table_generated_values;
635 0         0 return $_[0]->{'catalog'} = $_[1];
636             }
637              
638             sub select_catalog
639             {
640 77     77 0 179 my($self, $db) = @_;
641 77 50 33     366 return undef if($db && !$db->supports_catalog);
642 0   0     0 return $self->{'catalog'} || ($db ? $db->catalog : undef);
643             }
644              
645             sub schema
646             {
647 0 0   0 1 0 return $_[0]->{'schema'} unless(@_ > 1);
648 0         0 $_[0]->_clear_table_generated_values;
649 0         0 return $_[0]->{'schema'} = $_[1];
650             }
651              
652             sub select_schema
653             {
654 77     77 0 490 my($self, $db) = @_;
655 77 100 66     386 return undef if($db && !$db->supports_schema);
656 72   33     578 return $self->{'schema'} || ($db ? $db->schema : undef);
657             }
658              
659             sub sql_qualify_column_names_on_load
660             {
661 99     99 1 249 my($self) = shift;
662              
663 99 50       287 if(@_)
664             {
665 99 50       267 my $value = $_[0] ? 1 : 0;
666              
667 61     61   663 no warnings 'uninitialized';
  61         218  
  61         332097  
668 99 50       427 if($value != $self->{'sql_qualify_column_names_on_load'})
669             {
670 0         0 $self->{'sql_qualify_column_names_on_load'} = $value;
671 0         0 $self->_clear_column_generated_values;
672 0 0       0 $self->prime_caches if($self->is_initialized);
673             }
674             }
675              
676 99         218 return $self->{'sql_qualify_column_names_on_load'};
677             }
678              
679             sub key_column_names
680             {
681 0     0 0 0 my($self) = shift;
682              
683 0   0     0 $self->{'key_column_names'} ||=
684             [ $self->primary_key_columns, $self->unique_keys_column_names ];
685              
686 0 0       0 return wantarray ? @{$self->{'key_column_names'}} : $self->{'key_column_names'};
  0         0  
687             }
688              
689             sub init_primary_key
690             {
691 81     81 0 783 Rose::DB::Object::Metadata::PrimaryKey->new(parent => shift);
692             }
693              
694 0     0 1 0 sub primary_key_generator { shift->primary_key->generator(@_) }
695 76     76 1 258 sub primary_key_columns { shift->primary_key->columns(@_) }
696 645     645 1 1408 sub primary_key_column_names { shift->primary_key->column_names(@_) }
697 0     0 1 0 sub pk_columns { shift->primary_key_columns(@_) }
698              
699             sub primary_key_column_names_or_aliases
700             {
701 0     0 0 0 my($self) = shift;
702              
703 0 0       0 if($self->{'primary_key_column_names_or_aliases'})
704             {
705 0         0 return $self->{'primary_key_column_names_or_aliases'};
706             }
707              
708             return $self->{'primary_key_column_names_or_aliases'} =
709 0 0       0 [ map { $_->alias || $_->name } $self->primary_key_columns ];
  0         0  
710             }
711              
712             sub init_primary_key_column_info
713             {
714 84     84 0 140 my($self) = shift;
715              
716 84         181 my $pk_position = 0;
717              
718 84         193 foreach my $col_name ($self->primary_key_column_names)
719             {
720 88         150 $pk_position++;
721 88 100       247 my $column = $self->column($col_name) or next;
722 82         361 $column->is_primary_key_member(1);
723 82         553 $column->primary_key_position($pk_position);
724             }
725              
726 84         328 $self->_clear_primary_key_column_generated_values;
727              
728             # Init these by asking for them
729 84         268 $self->primary_key_column_accessor_names;
730 84         277 $self->primary_key_column_mutator_names;
731              
732 84         158 return;
733             }
734              
735             sub add_primary_key_columns
736             {
737 3     3 1 9 my($self) = shift;
738              
739 3         21 $self->primary_key->add_columns(@_);
740 3         16 $self->init_primary_key_column_info;
741              
742 3         9 return;
743             }
744              
745 3     3 1 15 sub add_primary_key_column { shift->add_primary_key_columns(@_) }
746              
747             sub add_unique_keys
748             {
749 0     0 1 0 my($self) = shift;
750              
751 0 0 0     0 if(@_ == 1 && ref $_[0] eq 'ARRAY')
752             {
753 0         0 push @{$self->{'unique_keys'}},
  0         0  
754             Rose::DB::Object::Metadata::UniqueKey->new(parent => $self, columns => $_[0]);
755             }
756             else
757             {
758 0         0 push @{$self->{'unique_keys'}}, map
759             {
760 0 0       0 UNIVERSAL::isa($_, 'Rose::DB::Object::Metadata::UniqueKey') ?
  0 0       0  
761             ($_->parent($self), $_) :
762             ref $_ eq 'HASH' ?
763             Rose::DB::Object::Metadata::UniqueKey->new(parent => $self, %$_) :
764             Rose::DB::Object::Metadata::UniqueKey->new(parent => $self, columns => $_)
765             }
766             @_;
767             }
768              
769 0         0 return;
770             }
771              
772             sub unique_key_by_name
773             {
774 0     0 1 0 my($self, $name) = @_;
775              
776 0         0 foreach my $uk ($self->unique_keys)
777             {
778 0 0       0 return $uk if($uk->name eq $name);
779             }
780              
781 0         0 return undef;
782             }
783              
784 0     0 1 0 sub add_unique_key { shift->add_unique_keys(@_) }
785 0     0 1 0 sub unique_key { \shift->add_unique_keys(@_) }
786              
787 0     0 1 0 sub delete_unique_keys { $_[0]->{'unique_keys'} = [] }
788              
789             sub unique_keys
790             {
791 229     229 1 423 my($self) = shift;
792              
793 229 50       473 if(@_)
794             {
795 0         0 $self->delete_unique_keys;
796 0         0 $self->add_unique_keys(@_);
797             }
798              
799 229 100 100     520 wantarray ? @{$self->{'unique_keys'} ||= []} : ($self->{'unique_keys'} ||= []);
  152   50     663  
800             }
801              
802             sub unique_keys_column_names
803             {
804 0   50     0 wantarray ? map { scalar $_->column_names } @{shift->{'unique_keys'} ||= []} :
  120         409  
805 120 50 0 120 1 231 [ map { scalar $_->column_names } @{shift->{'unique_keys'} ||= []} ];
  0         0  
  0         0  
806             }
807              
808             sub delete_column
809             {
810 0     0 1 0 my($self, $name) = @_;
811 0         0 delete $self->{'columns'}{$name};
812              
813             # Remove from ordered list too
814 0         0 my $columns = $self->columns_ordered;
815              
816 0         0 for(my $i = 0; $i < @$columns; $i++)
817             {
818 0 0       0 if($columns->[$i]->name eq $name)
819             {
820 0         0 splice(@$columns, $i, 1);
821 0         0 last;
822             }
823             }
824              
825 0         0 return;
826             }
827              
828             sub delete_columns
829             {
830 82     82 1 187 my($self, $name) = @_;
831 82         191 $self->{'columns'} = {};
832 82         250 $self->{'columns_ordered'} = [];
833 82         161 return;
834             }
835              
836             sub delete_nonpersistent_columns
837             {
838 0     0 1 0 my($self, $name) = @_;
839 0         0 $self->{'nonpersistent_columns'} = {};
840 0         0 $self->{'nonpersistent_columns_ordered'} = [];
841 0         0 return;
842             }
843              
844             sub delete_nonpersistent_column
845             {
846 0     0 1 0 my($self, $name) = @_;
847 0         0 delete $self->{'nonpersistent_columns'}{$name};
848              
849             # Remove from ordered list too
850 0         0 my $columns = $self->nonpersistent_columns_ordered;
851              
852 0         0 for(my $i = 0; $i < @$columns; $i++)
853             {
854 0 0       0 if($columns->[$i]->name eq $name)
855             {
856 0         0 splice(@$columns, $i, 1);
857 0         0 last;
858             }
859             }
860              
861 0         0 return;
862             }
863              
864 1     1 1 21 sub first_column { shift->columns_ordered->[0] }
865              
866             sub sync_keys_to_columns
867             {
868 77     77 0 151 my($self) = shift;
869              
870 77         208 $self->_clear_column_generated_values;
871              
872 77         245 my %columns = map { $_->name => 1 } $self->columns_ordered;
  201         1108  
873              
874 77         228 foreach my $col_name ($self->primary_key_column_names)
875             {
876 79 50       239 unless($columns{$col_name})
877             {
878 0         0 Carp::croak "Primary key column '$col_name' is not in the column list for ",
879             $self->class;
880             #$self->primary_key(undef);
881             #last;
882             }
883             }
884              
885 77         144 my @valid_uks;
886              
887 77         193 UK: foreach my $uk ($self->unique_keys)
888             {
889 0         0 foreach my $col_name ($uk->column_names)
890             {
891 0 0       0 unless($columns{$col_name})
892             {
893 0         0 Carp::croak "Column '$col_name' found in unique key is not in the column list for ",
894             $self->class;
895             #next UK;
896             }
897             }
898              
899 0         0 push(@valid_uks, $uk);
900             }
901              
902 77         266 $self->unique_keys(@valid_uks);
903              
904 77         150 return;
905             }
906              
907             sub replace_column
908             {
909 0     0 1 0 my($self) = shift;
910              
911 0 0       0 unless(@_ == 2)
912             {
913 0 0       0 Carp::croak "Missing column name and value arguments" if(@_ < 2);
914 0 0       0 Carp::croak "Too many arguments passed to replace_column()" if(@_ < 2);
915             }
916              
917 0         0 return $self->column(@_);
918             }
919              
920             sub column
921             {
922 3076     3076 1 4838 my($self, $name) = (shift, shift);
923              
924 3076 50       4746 if(@_)
925             {
926 0         0 $self->delete_column($name);
927 0         0 $self->add_column($name => @_);
928             }
929              
930 3076 100       6790 return $self->{'columns'}{$name} if($self->{'columns'}{$name});
931 81         352 return undef;
932             }
933              
934             sub nonpersistent_column
935             {
936 0     0 1 0 my($self, $name) = (shift, shift);
937              
938 0 0       0 if(@_)
939             {
940 0         0 $self->delete_nonpersistent_column($name);
941 0         0 $self->add_nonpersistent_column($name => @_);
942             }
943              
944 0 0       0 return $self->{'nonpersistent_columns'}{$name} if($self->{'nonpersistent_columns'}{$name});
945 0         0 return undef;
946             }
947              
948              
949             sub columns
950             {
951 94     94 1 1270 my($self) = shift;
952              
953 94 100       262 if(@_)
954             {
955 82         299 $self->delete_columns;
956 82         270 $self->add_columns(@_);
957             }
958              
959 94         330 return $self->columns_ordered;
960             }
961              
962             sub nonpersistent_columns
963             {
964 0     0 1 0 my($self) = shift;
965              
966 0 0       0 if(@_)
967             {
968 0         0 $self->delete_nonpersistent_columns;
969 0         0 $self->add_nonpersistent_columns(@_);
970             }
971              
972 0         0 return $self->nonpersistent_columns_ordered;
973             }
974              
975             sub num_columns
976             {
977 0     0 0 0 my($self) = shift;
978 0   0     0 return $self->{'num_columns'} ||= scalar(@{$self->columns_ordered});
  0         0  
979             }
980              
981             sub nonlazy_columns
982             {
983 0     0 0 0 my($self) = shift;
984              
985             return wantarray ?
986 0         0 (grep { !$_->lazy } $self->columns_ordered) :
987 0 0       0 [ grep { !$_->lazy } $self->columns_ordered ];
  0         0  
988             }
989              
990             sub lazy_columns
991             {
992 0     0 0 0 my($self) = shift;
993              
994             return wantarray ?
995 0         0 (grep { $_->lazy } $self->columns_ordered) :
996 0 0       0 [ grep { $_->lazy } $self->columns_ordered ];
  0         0  
997             }
998              
999             # XXX: Super-lame code sharing via dynamically-scoped flag var
1000             our $Nonpersistent;
1001              
1002             sub add_nonpersistent_columns
1003             {
1004 0     0 1 0 local $Nonpersistent = 1;
1005 0         0 shift->_add_columns(@_);
1006             }
1007              
1008 0     0 1 0 sub add_nonpersistent_column { shift->add_nonpersistent_columns(@_) }
1009              
1010             sub add_columns
1011             {
1012 85     85 1 207 local $Nonpersistent = 0;
1013 85         293 shift->_add_columns(@_);
1014             }
1015              
1016 1     1 1 4 sub add_column { shift->add_columns(@_) }
1017              
1018             sub _add_columns
1019             {
1020 85     85   170 my($self) = shift;
1021              
1022 85         188 my $class = ref $self;
1023              
1024 85         187 my(@columns, @nonpersistent_columns);
1025              
1026 85         295 ARG: while(@_)
1027             {
1028 219         361 my $name = shift;
1029              
1030 219 100       1021 if(UNIVERSAL::isa($name, 'Rose::DB::Object::Metadata::Column'))
1031             {
1032 1         3 my $column = $name;
1033              
1034 1 50       4 Carp::croak "Relationship $column lacks a name()"
1035             unless($column->name =~ /\S/);
1036              
1037 1         6 $column->parent($self);
1038 1 50       4 $column->nonpersistent(1) if($Nonpersistent);
1039              
1040 1 50       3 if($column->nonpersistent)
1041             {
1042 0         0 $self->{'nonpersistent_columns'}{$column->name} = $column;
1043 0         0 push(@nonpersistent_columns, $column);
1044             }
1045             else
1046             {
1047 1         10 $self->{'columns'}{$column->name} = $column;
1048 1         3 push(@columns, $column);
1049             }
1050              
1051 1         3 next;
1052             }
1053              
1054 218 100       543 unless(ref $_[0]) # bare column name, persistent only
1055             {
1056 166 50       407 my $column_class = $self->original_class->column_type_class('scalar')
1057             or Carp::croak "No column class set for column type 'scalar'";
1058              
1059             #$Debug && warn $self->class, " - adding scalar column $name\n";
1060 166         2456 $self->{'columns'}{$name} = $column_class->new(name => $name, parent => $self);
1061 166         725 push(@columns, $self->{'columns'}{$name});
1062 166         379 next;
1063             }
1064              
1065 52 50       242 if(UNIVERSAL::isa($_[0], 'Rose::DB::Object::Metadata::Column'))
    50          
1066             {
1067 0         0 my $column = $_[0];
1068 0         0 $column->name($name);
1069 0         0 $column->parent($self);
1070              
1071 0 0       0 $column->nonpersistent(1) if($Nonpersistent);
1072              
1073 0 0       0 if($column->nonpersistent)
1074             {
1075 0         0 $self->{'nonpersistent_columns'}{$column->name} = $column;
1076 0         0 push(@nonpersistent_columns, $column);
1077             }
1078             else
1079             {
1080 0         0 $self->{'columns'}{$column->name} = $column;
1081 0         0 push(@columns, $column);
1082             }
1083             }
1084             elsif(ref $_[0] eq 'HASH')
1085             {
1086 52         106 my $info = shift;
1087              
1088 52         112 my $alias = $info->{'alias'};
1089              
1090 52 100       132 if($info->{'primary_key'})
1091             {
1092             #$Debug && warn $self->class, " - adding primary key column $name\n";
1093 3         26 $self->add_primary_key_column($name);
1094             }
1095              
1096 52         102 my $methods = delete $info->{'methods'};
1097 52         91 my $add_methods = delete $info->{'add_methods'};
1098              
1099 52 50 33     166 if($methods && $add_methods)
1100             {
1101 0         0 Carp::croak "Cannot specify both 'methods' and 'add_methods' - ",
1102             "pick one or the other";
1103             }
1104              
1105 52   100     166 my $type = $info->{'type'} ||= 'scalar';
1106              
1107 52 50       180 my $column_class = $self->original_class->column_type_class($type)
1108             or Carp::croak "No column class set for column type '$type'";
1109              
1110 52 100       969 unless($self->column_class_is_loaded($column_class))
1111             {
1112 24         82 $self->load_column_class($column_class);
1113             }
1114              
1115 52         108 my %triggers;
1116              
1117 52         324 foreach my $event ($column_class->trigger_events)
1118             {
1119 364 100       681 $triggers{$event} = delete $info->{$event} if(exists $info->{$event});
1120             }
1121              
1122 52 50       161 if(delete $info->{'temp'}) # coerce temp to nonpersistent
1123             {
1124 0         0 $info->{'nonpersistent'} = 1;
1125             }
1126              
1127             #$Debug && warn $self->class, " - adding $name $column_class\n";
1128             # XXX: Order of args is important here! Parent must be set first
1129             # because some params rely on it being present when they're set.
1130 52         366 my $column =
1131             $column_class->new(parent => $self, %$info, name => $name);
1132              
1133 52 50       276 $column->nonpersistent(1) if($Nonpersistent);
1134              
1135 52 50       225 if($column->nonpersistent)
1136             {
1137 0         0 $self->{'nonpersistent_columns'}{$column->name} = $column;
1138 0         0 push(@nonpersistent_columns, $column);
1139             }
1140             else
1141             {
1142 52         399 $self->{'columns'}{$column->name} = $column;
1143 52         142 push(@columns, $column);
1144             }
1145              
1146             # Set or add auto-created method names
1147 52 50 33     242 if($methods || $add_methods)
1148             {
1149 0 0       0 my $auto_method_name =
1150             $methods ? 'auto_method_types' : 'add_auto_method_types';
1151              
1152 0   0     0 my $methods_arg = $methods || $add_methods;
1153              
1154 0 0       0 if(ref $methods_arg eq 'HASH')
1155             {
1156 0         0 $methods = [ keys %$methods_arg ];
1157              
1158 0         0 while(my($type, $name) = each(%$methods_arg))
1159             {
1160 0 0       0 next unless(defined $name);
1161 0         0 $column->method_name($type => $name);
1162             }
1163             }
1164             else
1165             {
1166 0         0 $methods = $methods_arg;
1167             }
1168              
1169 0         0 $column->$auto_method_name($methods);
1170             }
1171              
1172 52 50       142 if(defined $alias)
1173             {
1174 0         0 $column->alias($alias);
1175 0         0 $self->alias_column($name, $alias);
1176             }
1177              
1178 52 100       203 if(%triggers)
1179             {
1180 2         14 while(my($event, $value) = each(%triggers))
1181             {
1182 3 50       12 Carp::croak "Missing code reference for $event trigger"
1183             unless($value);
1184              
1185 3 100       16 foreach my $code (ref $value eq 'ARRAY' ? @$value : $value)
1186             {
1187 4         18 $column->add_trigger(event => $event,
1188             code => $code);
1189             }
1190             }
1191             }
1192             }
1193             else
1194             {
1195 0         0 Carp::croak "Invalid column name or specification: $_[0]";
1196             }
1197             }
1198              
1199             # Handle as-yet undocumented smart modification defaults.
1200             # Smart modification is only relevant
1201 85         210 foreach my $column (@columns)
1202             {
1203 219 50 33     2210 if($column->can('smart_modification') && !defined $column->{'smart_modification'})
1204             {
1205 219         546 $column->smart_modification($self->default_smart_modification);
1206             }
1207             }
1208              
1209 85 50       668 if(@columns)
1210             {
1211 85         131 push(@{$self->{'columns_ordered'}}, @columns);
  85         221  
1212 85         266 $self->_clear_column_generated_values;
1213             }
1214              
1215 85 50       233 if(@nonpersistent_columns)
1216             {
1217 0         0 push(@{$self->{'nonpersistent_columns_ordered'}}, @nonpersistent_columns);
  0         0  
1218 0         0 $self->_clear_nonpersistent_column_generated_values;
1219             }
1220              
1221 85 50       364 return wantarray ? (@columns, @nonpersistent_columns) : [ @columns, @nonpersistent_columns ];
1222             }
1223              
1224             sub relationship
1225             {
1226 57     57 1 132 my($self, $name) = (shift, shift);
1227              
1228 57 100       135 if(@_)
1229             {
1230 1         5 $self->delete_relationship($name);
1231 1         5 $self->add_relationship($name => $_[0]);
1232             }
1233              
1234 57 100       352 return $self->{'relationships'}{$name} if($self->{'relationships'}{$name});
1235 32         90 return undef;
1236             }
1237              
1238             sub delete_relationship
1239             {
1240 1     1 1 4 my($self, $name) = @_;
1241 1         3 delete $self->{'relationships'}{$name};
1242 1         3 return;
1243             }
1244              
1245             sub relationships
1246             {
1247 204     204 1 336 my($self) = shift;
1248              
1249 204 100       402 if(@_)
1250             {
1251 26         94 $self->delete_relationships;
1252 26         95 $self->add_relationships(@_);
1253             }
1254              
1255             return wantarray ?
1256 105   100     439 (sort { $a->name cmp $b->name } values %{$self->{'relationships'} ||= {}}) :
  178         758  
1257 204 100 50     402 [ sort { $a->name cmp $b->name } values %{$self->{'relationships'} ||= {}} ];
  0         0  
  26         310  
1258             }
1259              
1260             sub delete_relationships
1261             {
1262 26     26 1 53 my($self) = shift;
1263              
1264             # Delete everything except fk proxy relationships
1265 26 50       39 foreach my $name (keys %{$self->{'relationships'} || {}})
  26         212  
1266             {
1267             delete $self->{'relationships'}{$name}
1268 0 0       0 unless($self->{'relationships'}{$name}->foreign_key);
1269             }
1270              
1271 26         58 return;
1272             }
1273              
1274             sub add_relationships
1275             {
1276 74     74 1 124 my($self) = shift;
1277              
1278 74         128 my $class = ref $self;
1279              
1280 74         171 ARG: while(@_)
1281             {
1282 74         137 my $name = shift;
1283              
1284             # Relationship object
1285 74 100       283 if(UNIVERSAL::isa($name, 'Rose::DB::Object::Metadata::Relationship'))
1286             {
1287 32         55 my $relationship = $name;
1288              
1289 32 50       139 Carp::croak "Relationship $relationship lacks a name()"
1290             unless($relationship->name =~ /\S/);
1291              
1292 32 50       103 if(defined $self->{'relationships'}{$relationship->name})
1293             {
1294 0         0 Carp::croak $self->class, " already has a relationship named '",
1295             $relationship->name, "'";
1296             }
1297              
1298 32         94 $relationship->parent($self);
1299 32         86 $self->{'relationships'}{$relationship->name} = $relationship;
1300 32         96 next;
1301             }
1302              
1303             # Name and type only: recurse with hashref arg
1304 42 100       105 if(!ref $_[0])
1305             {
1306 15         28 my $type = shift;
1307              
1308 15         68 $self->add_relationships($name => { type => $type });
1309 15         55 next ARG;
1310             }
1311              
1312 27 100       160 if(UNIVERSAL::isa($_[0], 'Rose::DB::Object::Metadata::Relationship'))
    50          
1313             {
1314 1         2 my $relationship = shift;
1315              
1316 1         4 $relationship->name($name);
1317 1         4 $relationship->parent($self);
1318 1         3 $self->{'relationships'}{$name} = $relationship;
1319             }
1320             elsif(ref $_[0] eq 'HASH')
1321             {
1322 26         42 my $info = shift;
1323              
1324 26 50       85 if(defined $self->{'relationships'}{$name})
1325             {
1326 0         0 Carp::croak $self->class, " already has a relationship named '$name'";
1327             }
1328              
1329 26         64 my $methods = delete $info->{'methods'};
1330 26         53 my $add_methods = delete $info->{'add_methods'};
1331              
1332 26 50 33     89 if($methods && $add_methods)
1333             {
1334 0         0 Carp::croak "Cannot specify both 'methods' and 'add_methods' - ",
1335             "pick one or the other";
1336             }
1337              
1338 26 50       76 my $type = $info->{'type'} or
1339             Carp::croak "Missing type parameter for relationship '$name'";
1340              
1341 26         116 my $relationship = $self->{'relationships'}{$name} =
1342             $self->_build_relationship(name => $name,
1343             type => $type,
1344             info => $info);
1345              
1346             # Set or add auto-created method names
1347 26 50 33     169 if($methods || $add_methods)
1348             {
1349 0 0       0 my $auto_method_name =
1350             $methods ? 'auto_method_types' : 'add_auto_method_types';
1351              
1352 0   0     0 my $methods_arg = $methods || $add_methods;
1353              
1354 0 0       0 if(ref $methods_arg eq 'HASH')
1355             {
1356 0         0 $methods = [ keys %$methods_arg ];
1357              
1358 0         0 while(my($type, $name) = each(%$methods_arg))
1359             {
1360 0 0       0 next unless(defined $name);
1361 0         0 $relationship->method_name($type => $name);
1362             }
1363             }
1364             else
1365             {
1366 0         0 $methods = $methods_arg;
1367             }
1368              
1369 0         0 $relationship->$auto_method_name($methods);
1370             }
1371             }
1372             else
1373             {
1374 0         0 Carp::croak "Invalid relationship name or specification: $_[0]";
1375             }
1376             }
1377             }
1378              
1379             sub _build_relationship
1380             {
1381 26     26   118 my($self, %args) = @_;
1382              
1383 26         52 my $class = ref $self;
1384 26 50       72 my $name = $args{'name'} or Carp::croak "Missing name parameter";
1385 26 50       70 my $info = $args{'info'} or Carp::croak "Missing info parameter";
1386 26 50       69 my $type = $args{'type'} or
1387             Carp::croak "Missing type parameter for relationship '$name'";
1388              
1389 26 50       101 my $relationship_class = $class->relationship_type_class($type)
1390             or Carp::croak "No relationship class set for relationship type '$type'";
1391              
1392 26 100       456 unless($self->relationship_class_is_loaded($relationship_class))
1393             {
1394 5         15 $self->load_relationship_class($relationship_class);
1395             }
1396              
1397 26 50       82 $Debug && warn $self->class, " - adding $name $relationship_class\n";
1398 26   33     86 my $relationship =
1399             $self->convention_manager->auto_relationship($name, $relationship_class, $info) ||
1400             $relationship_class->new(%$info, name => $name);
1401              
1402 26 50       353 unless($relationship)
1403             {
1404 0         0 Carp::croak "$class - Incomplete relationship specification could not be ",
1405             "completed by convention manager: $name";
1406             }
1407              
1408 26         114 $relationship->parent($self);
1409              
1410 26         112 return $relationship;
1411             }
1412              
1413 33     33 1 775 sub add_relationship { shift->add_relationships(@_) }
1414              
1415             my %Class_Loaded;
1416              
1417             sub load_column_class
1418             {
1419 24     24 0 61 my($self, $column_class) = @_;
1420              
1421 24 100       148 unless(UNIVERSAL::isa($column_class, 'Rose::DB::Object::Metadata::Column'))
1422             {
1423 21         46 my $error;
1424              
1425             TRY:
1426             {
1427 21         36 local $@;
  21         51  
1428 21         1924 eval "require $column_class";
1429 21         114 $error = $@;
1430             }
1431              
1432 21 50       68 Carp::croak "Could not load column class '$column_class' - $error"
1433             if($error);
1434             }
1435              
1436 24         114 $Class_Loaded{$column_class}++;
1437             }
1438              
1439 52     52 0 203 sub column_class_is_loaded { $Class_Loaded{$_[1]} }
1440              
1441             sub column_type_class
1442             {
1443 218     218 1 1059 my($class, $type) = (shift, shift);
1444 218         814 return $class->_column_type_class(lc $type, @_)
1445             }
1446              
1447             sub delete_column_type_class
1448             {
1449 0     0 1 0 my($class, $type) = (shift, shift);
1450 0         0 return $class->_delete_column_type_class(lc $type, @_)
1451             }
1452              
1453             sub load_relationship_class
1454             {
1455 5     5 0 15 my($self, $relationship_class) = @_;
1456              
1457 5         8 my $error;
1458              
1459             TRY:
1460             {
1461 5         11 local $@;
  5         8  
1462 5         412 eval "require $relationship_class";
1463 5         26 $error = $@;
1464             }
1465              
1466 5 50       18 Carp::croak "Could not load relationship class '$relationship_class' - $error"
1467             if($error);
1468              
1469 5         21 $Class_Loaded{$relationship_class}++;
1470             }
1471              
1472 26     26 0 105 sub relationship_class_is_loaded { $Class_Loaded{$_[1]} }
1473              
1474             sub add_foreign_keys
1475             {
1476 44     44 1 88 my($self) = shift;
1477              
1478 44         104 ARG: while(@_)
1479             {
1480 58         95 my $name = shift;
1481              
1482             # Foreign key object
1483 58 100       225 if(UNIVERSAL::isa($name, 'Rose::DB::Object::Metadata::ForeignKey'))
1484             {
1485 26         41 my $fk = $name;
1486              
1487 26 50       62 Carp::croak "Foreign key $fk lacks a name()"
1488             unless($fk->name =~ /\S/);
1489              
1490 26 50       74 if(defined $self->{'foreign_keys'}{$fk->name})
1491             {
1492 0         0 Carp::croak $self->class, " already has a foreign key named '",
1493             $fk->name, "'";
1494             }
1495              
1496 26         90 $fk->parent($self);
1497              
1498 26         61 $self->{'foreign_keys'}{$fk->name} = $fk;
1499              
1500 26 50       57 unless(defined $self->relationship($fk->name))
1501             {
1502 26         83 $self->add_relationship(
1503             $self->relationship_type_class($fk->relationship_type)->new(
1504             parent => $self,
1505             name => $fk->name,
1506             class => $fk->class,
1507             foreign_key => $fk));
1508             }
1509              
1510 26         70 next ARG;
1511             }
1512              
1513             # Name only: try to get all the other info by convention
1514 32 100       77 if(!ref $_[0])
1515             {
1516 26 50       64 if(my $fk = $self->convention_manager->auto_foreign_key($name))
1517             {
1518 26         143 $self->add_foreign_keys($fk);
1519 26         66 next ARG;
1520             }
1521             else
1522             {
1523 0         0 Carp::croak $self->class,
1524             " - Incomplete foreign key specification could not be ",
1525             "completed by convention manager: $name";
1526             }
1527             }
1528              
1529             # Name and hashref spec
1530 6 50       42 if(ref $_[0] eq 'HASH')
1531             {
1532 6         10 my $info = shift;
1533              
1534 6 50       18 if(defined $self->{'foreign_keys'}{$name})
1535             {
1536 0         0 Carp::croak $self->class, " already has a foreign key named '$name'";
1537             }
1538              
1539 6         16 my $methods = delete $info->{'methods'};
1540 6         11 my $add_methods = delete $info->{'add_methods'};
1541              
1542 6 50 33     20 if($methods && $add_methods)
1543             {
1544 0         0 Carp::croak "Cannot specify both 'methods' and 'add_methods' - ",
1545             "pick one or the other";
1546             }
1547              
1548 6 50       17 $Debug && warn $self->class, " - adding $name foreign key\n";
1549 6   33     18 my $fk = $self->{'foreign_keys'}{$name} =
1550             $self->convention_manager->auto_foreign_key($name, $info) ||
1551             Rose::DB::Object::Metadata::ForeignKey->new(%$info, name => $name);
1552              
1553 6         63 $fk->parent($self);
1554              
1555             # Set or add auto-created method names
1556 6 50 33     40 if($methods || $add_methods)
1557             {
1558 0 0       0 my $auto_method_name =
1559             $methods ? 'auto_method_types' : 'add_auto_method_types';
1560              
1561 0   0     0 my $methods_arg = $methods || $add_methods;
1562              
1563 0 0       0 if(ref $methods_arg eq 'HASH')
1564             {
1565 0         0 $methods = [ keys %$methods_arg ];
1566              
1567 0         0 while(my($type, $name) = each(%$methods_arg))
1568             {
1569 0 0       0 next unless(defined $name);
1570 0         0 $fk->method_name($type => $name);
1571             }
1572             }
1573             else
1574             {
1575 0         0 $methods = $methods_arg;
1576             }
1577              
1578 0         0 $fk->$auto_method_name($methods);
1579             }
1580              
1581 6 50       23 unless(defined $self->relationship($name))
1582             {
1583 6         22 $self->add_relationship(
1584             $self->relationship_type_class($fk->relationship_type)->new(
1585             name => $name,
1586             class => $fk->class,
1587             foreign_key => $fk));
1588             }
1589             }
1590             else
1591             {
1592 0         0 Carp::croak "Invalid foreign key specification: $_[0]";
1593             }
1594             }
1595             }
1596              
1597 0     0 0 0 sub add_foreign_key { shift->add_foreign_keys(@_) }
1598              
1599             sub foreign_key
1600             {
1601 4     4 1 14 my($self, $name) = (shift, shift);
1602              
1603 4 50       17 if(@_)
1604             {
1605 0         0 $self->delete_foreign_key($name);
1606 0         0 $self->add_foreign_key($name => @_);
1607             }
1608              
1609 4 50       34 return $self->{'foreign_keys'}{$name} if($self->{'foreign_keys'}{$name});
1610 0         0 return undef;
1611             }
1612              
1613             sub delete_foreign_key
1614             {
1615 0     0 0 0 my($self, $name) = @_;
1616 0         0 delete $self->{'foreign_keys'}{$name};
1617 0         0 return;
1618             }
1619              
1620             sub delete_foreign_keys
1621             {
1622 18     18 0 39 my($self) = shift;
1623              
1624             # Delete fk proxy relationship
1625 18         31 foreach my $fk (values %{$self->{'foreign_keys'}})
  18         75  
1626             {
1627 0         0 foreach my $rel ($self->relationships)
1628             {
1629 61     61   886 no warnings 'uninitialized';
  61         200  
  61         44012  
1630 0 0       0 if($rel->foreign_key eq $fk)
1631             {
1632 0         0 $self->delete_relationship($rel->name);
1633             }
1634             }
1635             }
1636              
1637             # Delete fks
1638 18         55 $self->{'foreign_keys'} = {};
1639              
1640 18         30 return;
1641             }
1642              
1643             sub foreign_keys
1644             {
1645 298     298 1 491 my($self) = shift;
1646              
1647 298 100       524 if(@_)
1648             {
1649 18         71 $self->delete_foreign_keys;
1650 18         68 $self->add_foreign_keys(@_);
1651             }
1652              
1653             return wantarray ?
1654 133   100     374 (sort { $a->name cmp $b->name } values %{$self->{'foreign_keys'} ||= {}}) :
  280         1216  
1655 298 100 50     649 [ sort { $a->name cmp $b->name } values %{$self->{'foreign_keys'} ||= {}} ];
  14         61  
  18         112  
1656             }
1657              
1658             sub initialize
1659             {
1660 77     77 1 193 my($self) = shift;
1661 77         158 my(%args) = @_;
1662              
1663 77 50       180 $Debug && warn $self->class, " - initialize\n";
1664              
1665 77 50       265 if(my $code = $self->pre_init_hook)
1666             {
1667 0 0       0 foreach my $sub (ref $code eq 'ARRAY' ? @$code : $code)
1668             {
1669 0         0 $sub->($self, @_);
1670             }
1671             }
1672              
1673 77 50       237 my $class = $self->class
1674             or Carp::croak "Missing class for metadata object $self";
1675              
1676 77         240 $self->sync_keys_to_columns;
1677              
1678 77         231 my $table = $self->table;
1679 77 50 33     457 Carp::croak "$class - Missing table name"
1680             unless(defined $table && $table =~ /\S/);
1681              
1682 77         217 my @pk = $self->primary_key_column_names;
1683 77 50       205 Carp::croak "$class - Missing primary key for table '$table'" unless(@pk);
1684              
1685 77         301 $self->init_primary_key_column_info;
1686              
1687 77         248 my @column_names = $self->column_names;
1688 77 50       257 Carp::croak "$class - No columns defined for for table '$table'"
1689             unless(@column_names);
1690              
1691 77         205 foreach my $name ($self->primary_key_column_names)
1692             {
1693 79 50       187 my $column = $self->column($name) or
1694             Carp::croak "Could not find column for primary key column name '$name'";
1695              
1696 79 50       303 if($column->is_lazy)
1697             {
1698 0         0 Carp::croak "Column '$name' cannot be lazy: cannot load primary key ",
1699             "columns on demand";
1700             }
1701             }
1702              
1703 77         311 $self->make_methods(@_);
1704              
1705 76         292 $self->register_class;
1706              
1707 76 50       203 unless($args{'passive'})
1708             {
1709             # Retry deferred stuff
1710 76         271 $self->retry_deferred_tasks;
1711 76         292 $self->retry_deferred_foreign_keys;
1712 76         906 $self->retry_deferred_relationships;
1713             }
1714              
1715 75         314 $self->refresh_lazy_column_tracking;
1716              
1717 75 50       218 unless($args{'stay_connected'})
1718             {
1719 75         196 $self->db(undef); # make sure to ditch any db we may have retained
1720             }
1721              
1722 75         1861 $self->is_initialized(1);
1723              
1724 75 50       419 $Debug && warn $self->class, " - initialized\n";
1725              
1726 75 50       258 if(my $code = $self->post_init_hook)
1727             {
1728 0 0       0 foreach my $sub (ref $code eq 'ARRAY' ? @$code : $code)
1729             {
1730 0         0 $sub->($self, @_);
1731             }
1732             }
1733              
1734             # Regardless of cache priming, call this to ensure it's initialized,
1735             # since it is very likely to be used.
1736 75         243 $self->key_column_accessor_method_names_hash;
1737              
1738 75 50       272 $self->prime_caches if($self->auto_prime_caches);
1739              
1740 75         868 return;
1741             }
1742              
1743 61     61   600 use constant NULL_CATALOG => "\0";
  61         200  
  61         6412  
1744 61     61   566 use constant NULL_SCHEMA => "\0";
  61         196  
  61         531298  
1745              
1746             sub register_class
1747             {
1748 76     76 0 134 my($self) = shift;
1749              
1750 76 50       221 my $class = $self->class
1751             or Carp::croak "Missing class for metadata object $self";
1752              
1753 76         266 my $db = $self->db;
1754              
1755 76         314 my $catalog = $self->select_catalog($db);
1756 76 50 66     542 my $schema = $db ? ($db->registration_schema || $self->select_schema($db)) :
1757             $self->select_schema($db);;
1758              
1759 76 50       594 $catalog = NULL_CATALOG unless(defined $catalog);
1760 76 100       183 $schema = NULL_SCHEMA unless(defined $schema);
1761              
1762 76 50       282 my $default_schema = $db ? $db->default_implicit_schema : undef;
1763              
1764 76 50       393 my $table = $self->table
1765             or Carp::croak "Missing table for metadata object $self";
1766              
1767 76 100       310 $table = lc $table if($db->likes_lowercase_table_names);
1768              
1769 76         519 my $reg = $self->registry_key->class_registry;
1770              
1771             # Combine keys using $;, which is "\034" (0x1C) by default. But just to
1772             # make sure, I'll localize it. What I'm looking for is a value that
1773             # won't show up in a catalog, schema, or table name, so I'm guarding
1774             # against someone changing it to "-" (or whatever) elsewhere in the code.
1775 76         603 local $; = "\034";
1776              
1777             # Register with all available information.
1778             # Ug, have to store lowercase versions too because MySQL sometimes returns
1779             # lowercase names for tables that are actually mixed case. Grrr...
1780             $reg->{'catalog-schema-table',$catalog,$schema,$table} =
1781             $reg->{'table',$table} =
1782             $reg->{'lc-catalog-schema-table',$catalog,$schema,lc $table} =
1783 76         628 $reg->{'lc-table',lc $table} = $class;
1784              
1785 76 100       301 $reg->{'catalog-schema-table',$catalog,$default_schema,$table} = $class
1786             if(defined $default_schema);
1787              
1788 76         125 push(@{$reg->{'classes'}}, $class);
  76         172  
1789              
1790 76         163 return;
1791             }
1792              
1793 230     230 1 704 sub registry_key { __PACKAGE__ }
1794              
1795             sub registered_classes
1796             {
1797 152     152 1 217 my($self) = shift;
1798 152         339 my $reg = $self->registry_key->class_registry;
1799 152 50 100     1365 return wantarray ? @{$reg->{'classes'} ||= []} : $reg->{'classes'};
  152         1858  
1800             }
1801              
1802             sub unregister_all_classes
1803             {
1804 0     0 0 0 my($self) = shift;
1805 0         0 $self->registry_key->class_registry({});
1806 0         0 return;
1807             }
1808              
1809             sub class_for
1810             {
1811 2     2 1 12 my($self_or_class, %args) = @_;
1812              
1813 2 100       8 my $self = ref($self_or_class) ? $self_or_class : undef;
1814 2   66     8 my $class = ref($self) || $self_or_class;
1815              
1816 2 100       8 my $db = $self ? $self->db : undef;
1817              
1818 2         4 my $catalog = $args{'catalog'};
1819 2         4 my $schema = $args{'schema'};
1820              
1821 2 50       16 $catalog = NULL_CATALOG unless(defined $catalog);
1822 2 50       7 $schema = NULL_SCHEMA unless(defined $schema);
1823              
1824 2 100       9 my $default_schema = $db ? $db->default_implicit_schema : undef;
1825 2 100       8 $default_schema = NULL_SCHEMA unless(defined $default_schema);
1826              
1827 2 50       6 my $table = $args{'table'}
1828             or Carp::croak "Missing required table parameter";
1829              
1830 2 100 66     7 $table = lc $table if($db && $db->likes_lowercase_table_names);
1831              
1832 2         11 my $reg = $class->registry_key->class_registry;
1833              
1834             # Combine keys using $;, which is "\034" (0x1C) by default. But just to
1835             # make sure, we'll localize it. What we're looking for is a value that
1836             # wont' show up in a catalog, schema, or table name, so I'm guarding
1837             # against someone changing it to "-" elsewhere in the code or whatever.
1838 2         20 local $; = "\034";
1839              
1840             my $f_class =
1841             $reg->{'catalog-schema-table',$catalog,$schema,$table} ||
1842             $reg->{'catalog-schema-table',$catalog,$default_schema,$table} ||
1843 2   66     23 ($schema eq NULL_SCHEMA && $default_schema eq NULL_SCHEMA ? $reg->{'lc-table',$table} : undef);
1844              
1845             # Ug, have to check lowercase versions too because MySQL sometimes returns
1846             # lowercase names for tables that are actually mixed case. Grrr...
1847 2 50       7 unless($f_class)
1848             {
1849 0         0 $table = lc $table;
1850              
1851             return
1852             $reg->{'lc-catalog-schema-table',$catalog,$schema,$table} ||
1853             $reg->{'lc-catalog-schema-table',$catalog,$default_schema,$table} ||
1854 0   0     0 ($schema eq NULL_SCHEMA && $default_schema eq NULL_SCHEMA ? $reg->{'lc-table',$table} : undef);
1855             }
1856              
1857 2         11 return $f_class;
1858             }
1859              
1860             #sub made_method_for_column
1861             #{
1862             # (@_ > 2) ? ($_[0]->{'made_methods'}{$_[1]} = $_[2]) :
1863             # $_[0]->{'made_methods'}{$_[1]};
1864             #}
1865              
1866             sub make_column_methods
1867             {
1868 77     77 1 141 my($self) = shift;
1869 77         155 my(%args) = @_;
1870              
1871 77         201 my $class = $self->class;
1872              
1873 77         187 $args{'target_class'} = $class;
1874              
1875 77         226 my $aliases = $self->column_aliases;
1876              
1877 77         307 while(my($column_name, $alias) = each(%$aliases))
1878             {
1879 1         4 $self->column($column_name)->alias($alias);
1880             }
1881              
1882 77         195 foreach my $column ($self->columns_ordered)
1883             {
1884 194 50       1227 unless($column->validate_specification)
1885             {
1886 0         0 Carp::croak "Column specification for column '", $column->name,
1887             "' in class ", $self->class, " is invalid: ",
1888             $column->error;
1889             }
1890              
1891 194         413 my $name = $column->name;
1892 194         302 my $method;
1893              
1894 194         553 foreach my $type ($column->auto_method_types)
1895             {
1896 194 50       9556 $method = $self->method_name_from_column_name($name, $type)
1897             or Carp::croak "No method name defined for column '$name' ",
1898             "method type '$type'";
1899              
1900 194 100       459 if(my $reason = $self->method_name_is_reserved($method, $class))
1901             {
1902 1         255 Carp::croak "Cannot create method '$method' - $reason ",
1903             "Use alias_column() to map it to another name."
1904             }
1905              
1906 193         590 $column->method_name($type => $method);
1907             }
1908              
1909             #$Debug && warn $self->class, " - make methods for column $name\n";
1910              
1911 193         861 $column->make_methods(%args);
1912              
1913             # XXX: Re-enabling the ability to alias primary keys
1914             #if($column->is_primary_key_member && $column->alias && $column->alias ne $column->name)
1915             #{
1916             # Carp::croak "Primary key columns cannot be aliased (the culprit: '$name')";
1917             #}
1918             #
1919             #if($method ne $name)
1920             #{
1921             # # Primary key columns can be aliased, but we make a column-named
1922             # # method anyway.
1923             # foreach my $column ($self->primary_key_column_names)
1924             # {
1925             # if($name eq $column)
1926             # {
1927             # if(my $reason = $self->method_name_is_reserved($name, $class))
1928             # {
1929             # Carp::croak
1930             # "Cannot create method for primary key column '$name' ",
1931             # "- $reason Although primary keys may be aliased, doing ",
1932             # "so will not avoid conflicts with reserved method names ",
1933             # "because a method named after the primary key column ",
1934             # "itself must also be created.";
1935             # }
1936             #
1937             # no strict 'refs';
1938             # *{"${class}::$name"} = \&{"${class}::$method"};
1939             # }
1940             # }
1941             #}
1942             }
1943              
1944 76         290 $self->_clear_column_generated_values;
1945              
1946             # Initialize method name hashes
1947 76         276 $self->column_accessor_method_names;
1948 76         247 $self->column_mutator_method_names;
1949 76         257 $self->column_rw_method_names;
1950              
1951             # This rule is relaxed for now...
1952             # Must have an rw accessor for every column
1953             #my $columns = $self->columns_ordered;
1954             #
1955             #unless(keys %methods == @$columns)
1956             #{
1957             # Carp::croak "Rose::DB::Object-derived objects are required to have ",
1958             # "a 'get_set' method for every column. This class (",
1959             # $self->class, ") has ", scalar @$columns, "column",
1960             # (@$columns == 1 ? '' : 's'), " and ", scalar keys %methods,
1961             # " method", (scalar keys %methods == 1 ? '' : 's');
1962             #}
1963              
1964 76         237 return;
1965             }
1966              
1967             sub make_nonpersistent_column_methods
1968             {
1969 76     76 1 167 my($self) = shift;
1970 76         175 my(%args) = @_;
1971              
1972 76         200 my $class = $self->class;
1973              
1974 76         177 $args{'target_class'} = $class;
1975              
1976 76         263 foreach my $column ($self->nonpersistent_columns_ordered)
1977             {
1978 0 0       0 unless($column->validate_specification)
1979             {
1980 0         0 Carp::croak "Column specification for column '", $column->name,
1981             "' in class ", $self->class, " is invalid: ",
1982             $column->error;
1983             }
1984              
1985 0         0 my $name = $column->name;
1986 0         0 my $method;
1987              
1988 0         0 foreach my $type ($column->auto_method_types)
1989             {
1990 0 0       0 $method = $self->method_name_from_column_name($name, $type)
1991             or Carp::croak "No method name defined for column '$name' ",
1992             "method type '$type'";
1993              
1994 0 0       0 if(my $reason = $self->method_name_is_reserved($method, $class))
1995             {
1996 0         0 Carp::croak "Cannot create method '$method' - $reason ",
1997             "Use alias_column() to map it to another name."
1998             }
1999              
2000 0         0 $column->method_name($type => $method);
2001             }
2002              
2003             #$Debug && warn $self->class, " - make methods for column $name\n";
2004              
2005 0         0 $column->make_methods(%args);
2006             }
2007              
2008 76         939 $self->_clear_nonpersistent_column_generated_values;
2009              
2010             # Initialize method name hashes
2011 76         213 $self->nonpersistent_column_accessor_method_names;
2012              
2013 76         144 return;
2014             }
2015              
2016             sub make_foreign_key_methods
2017             {
2018 76     76 1 134 my($self) = shift;
2019 76         137 my(%args) = @_;
2020              
2021             #$self->retry_deferred_foreign_keys;
2022              
2023 76         150 my $class = $self->class;
2024 76         154 my $meta_class = ref $self;
2025              
2026 76         161 $args{'target_class'} = $class;
2027              
2028 76         250 foreach my $foreign_key ($self->foreign_keys)
2029             {
2030             #next unless($foreign_key->is_ready_to_make_methods);
2031              
2032 32         243 foreach my $type ($foreign_key->auto_method_types)
2033             {
2034 64   33     1487 my $method =
2035             $foreign_key->method_name($type) ||
2036             $foreign_key->build_method_name_for_type($type) ||
2037             Carp::croak "No method name defined for foreign key '",
2038             $foreign_key->name, "' method type '$type'";
2039              
2040 64 50       147 if(my $reason = $self->method_name_is_reserved($method, $class))
2041             {
2042 0         0 Carp::croak "Cannot create method '$method' - $reason ",
2043             "Choose a different foreign key name."
2044             }
2045              
2046 64         157 $foreign_key->method_name($type => $method);
2047             }
2048              
2049 32 50 33     104 if($self->auto_load_related_classes && (my $fclass = $foreign_key->class))
2050             {
2051 32 50       452 unless($fclass->isa('Rose::DB::Object'))
2052             {
2053 0         0 my $error;
2054              
2055             TRY:
2056             {
2057 0         0 local $@;
  0         0  
2058 0         0 eval "require $fclass";
2059 0         0 $error = $@;
2060             }
2061              
2062 0 0       0 $Debug && print STDERR "FK REQUIRES $fclass - $error\n";
2063              
2064 0 0       0 if($error)
2065             {
2066             # XXX: Need to distinguish recoverable errors from unrecoverable errors
2067 0 0 0     0 if($error !~ /\.pm in \@INC/ && !UNIVERSAL::isa($error, 'Rose::DB::Object::Exception::ClassNotReady'))
2068             {
2069 0         0 Carp::confess "Could not load $fclass - $error";
2070             }
2071             }
2072             }
2073             }
2074              
2075             # We may need to defer the creation of some foreign key methods until
2076             # all the required pieces are loaded.
2077 32 100       99 if($foreign_key->is_ready_to_make_methods)
2078             {
2079 20 50 33     60 if($Debug && !$args{'preserve_existing'})
2080             {
2081 0         0 warn $self->class, " - make methods for foreign key ",
2082             $foreign_key->name, "\n";
2083             }
2084              
2085 20         89 $foreign_key->make_methods(%args);
2086             }
2087             else
2088             {
2089             # Confirm that no info is missing. This prevents an improperly
2090             # configured foreign_key from being deferred "forever"
2091 12         37 $foreign_key->sanity_check;
2092              
2093 12 50       31 $Debug && warn $self->class, " - defer foreign key ", $foreign_key->name, "\n";
2094              
2095 12         44 $foreign_key->deferred_make_method_args(\%args);
2096 12         40 $meta_class->add_deferred_foreign_key($foreign_key);
2097             }
2098              
2099             # Keep foreign keys and their corresponding relationships in sync.
2100 32         252 my $fk_id = $foreign_key->id;
2101 32         258 my $fk_rel_type = $foreign_key->relationship_type;
2102              
2103 32         211 foreach my $relationship ($self->relationships)
2104             {
2105 60 50       308 next unless($relationship->type eq $fk_rel_type);
2106              
2107 60 100       149 if($fk_id eq $relationship->id)
2108             {
2109 32         419 $relationship->foreign_key($foreign_key);
2110             }
2111             }
2112             }
2113              
2114 76         279 $self->retry_deferred_foreign_keys;
2115              
2116 76         577 return;
2117             }
2118              
2119             our @Deferred_Tasks;
2120              
2121             sub deferred_tasks
2122             {
2123 0 0   0 0 0 return wantarray ? @Deferred_Tasks : \@Deferred_Tasks;
2124             }
2125              
2126             sub add_deferred_tasks
2127             {
2128 0     0 0 0 my($class) = shift;
2129              
2130 0         0 ARG: foreach my $arg (@_)
2131             {
2132 0         0 foreach my $task (@Deferred_Tasks)
2133             {
2134             next ARG if($arg->{'class'} eq $task->{'class'} &&
2135 0 0 0     0 $arg->{'method'} eq $task->{'method'});
2136             }
2137              
2138 0         0 push(@Deferred_Tasks, $arg);
2139             }
2140             }
2141              
2142 0     0 0 0 sub add_deferred_task { shift->add_deferred_tasks(@_) }
2143              
2144             sub has_deferred_tasks
2145             {
2146 0     0 0 0 my($self) = shift;
2147              
2148 0         0 my $class = $self->class;
2149 0         0 my $meta_class = ref $self;
2150              
2151             # Search among the deferred tasks too (icky)
2152 0         0 foreach my $task ($meta_class->deferred_tasks)
2153             {
2154 0 0       0 if($task->{'class'} eq $class)
2155             {
2156 0         0 return 1;
2157             }
2158             }
2159              
2160 0         0 return 0;
2161             }
2162              
2163             sub retry_deferred_tasks
2164             {
2165 76     76 0 140 my($self) = shift;
2166              
2167 76         150 my @tasks;
2168              
2169 76         196 foreach my $task (@Deferred_Tasks)
2170             {
2171 0         0 my $code = $task->{'code'};
2172 0         0 my $check = $task->{'check'};
2173              
2174 0         0 $code->();
2175              
2176 0 0       0 unless($check->())
2177             {
2178 0         0 push(@tasks, $task);
2179             }
2180             }
2181              
2182 76 50       336 if(join(',', sort @Deferred_Tasks) ne join(',', sort @tasks))
2183             {
2184 0         0 @Deferred_Tasks = @tasks;
2185             }
2186             }
2187              
2188             our @Deferred_Foreign_Keys;
2189              
2190             sub deferred_foreign_keys
2191             {
2192 152 50   152 0 407 return wantarray ? @Deferred_Foreign_Keys : \@Deferred_Foreign_Keys;
2193             }
2194              
2195             sub has_deferred_foreign_keys
2196             {
2197 0     0 0 0 my($self) = shift;
2198              
2199 0         0 my $class = $self->class;
2200 0         0 my $meta_class = ref $self;
2201              
2202 0         0 foreach my $fk ($meta_class->deferred_foreign_keys)
2203             {
2204 0 0       0 return 1 if($fk->class eq $class);
2205             }
2206              
2207             # Search among the deferred tasks too (icky)
2208 0         0 foreach my $task ($meta_class->deferred_tasks)
2209             {
2210 0 0 0     0 if($task->{'class'} eq $class && $task->{'method'} eq 'auto_init_foreign_keys')
2211             {
2212 0         0 return 1;
2213             }
2214             }
2215              
2216 0         0 return 0;
2217             }
2218              
2219             sub has_outstanding_metadata_tasks
2220             {
2221 12     12 0 29 my($self) = shift;
2222              
2223 12 50       107 return $self->{'has_outstanding_metadata_tasks'} = shift if(@_);
2224              
2225 0 0       0 if(defined $self->{'has_outstanding_metadata_tasks'})
2226             {
2227 0         0 return $self->{'has_outstanding_metadata_tasks'};
2228             }
2229              
2230 0 0 0     0 if($self->has_deferred_foreign_keys ||
      0        
2231             $self->has_deferred_relationships ||
2232             $self->has_deferred_tasks)
2233             {
2234 0         0 return $self->{'has_outstanding_metadata_tasks'} = 1;
2235             }
2236              
2237 0         0 return $self->{'has_outstanding_metadata_tasks'} = 0;
2238             }
2239              
2240             sub add_deferred_foreign_keys
2241             {
2242 12     12 0 38 my($class) = shift;
2243              
2244 12         19 my $check = 0;
2245              
2246 12         31 ARG: foreach my $arg (@_)
2247             {
2248 12         28 foreach my $fk (@Deferred_Foreign_Keys)
2249             {
2250 0 0       0 next ARG if($fk->id eq $arg->id);
2251             }
2252              
2253 12         36 $arg->parent->has_outstanding_metadata_tasks(1);
2254 12         39 push(@Deferred_Foreign_Keys, $arg);
2255             }
2256             }
2257              
2258 12     12 0 34 sub add_deferred_foreign_key { shift->add_deferred_foreign_keys(@_) }
2259              
2260             sub retry_deferred_foreign_keys
2261             {
2262 152     152 0 222 my($self) = shift;
2263              
2264 152         310 my $meta_class = ref $self;
2265              
2266 152         243 my @foreign_keys;
2267              
2268             # Check to see if any deferred foreign keys are ready now
2269 152         382 foreach my $foreign_key ($meta_class->deferred_foreign_keys)
2270             {
2271             # XXX: this is not necessary, so it's commented out for now.
2272             # Try to rebuild the relationship using the convention manager, since
2273             # new info may be available now. Otherwise, leave it as-is.
2274             # $foreign_key =
2275             # $self->convention_manager->auto_foreign_key(
2276             # $def_fk->name, scalar $def_fk->spec_hash) ||
2277             # $def_fk;
2278              
2279 36 100       113 if($foreign_key->is_ready_to_make_methods)
2280             {
2281 12 50       33 $Debug && warn $foreign_key->parent->class,
2282             " - (Retry) make methods for foreign key ",
2283             $foreign_key->name, "\n";
2284              
2285 12   50     52 my $args = $foreign_key->deferred_make_method_args || {};
2286 12         55 $foreign_key->make_methods(%$args); #, preserve_existing => 1);
2287             }
2288             else
2289             {
2290 24         53 push(@foreign_keys, $foreign_key);
2291             }
2292             }
2293              
2294 152 100       610 if(join(',', sort @Deferred_Foreign_Keys) ne join(',', sort @foreign_keys))
2295             {
2296 12         84 @Deferred_Foreign_Keys = @foreign_keys;
2297             }
2298              
2299             # Retry relationship auto-init for all other classes
2300 152         499 foreach my $class ($self->registered_classes)
2301             {
2302 4926         26603 my $meta = $class->meta;
2303 4926 50 33     7217 next unless($meta->allow_auto_initialization && $meta->has_outstanding_metadata_tasks);
2304 0 0       0 $meta->auto_init_relationships(%{ $meta->auto_init_args || {} },
  0         0  
2305             restore_types => 1);
2306             }
2307             }
2308              
2309             sub make_relationship_methods
2310             {
2311 76     76 1 135 my($self) = shift;
2312 76         147 my(%args) = @_;
2313              
2314             #$self->retry_deferred_relationships;
2315              
2316 76         149 my $meta_class = ref $self;
2317 76         172 my $class = $self->class;
2318              
2319 76         150 $args{'target_class'} = $class;
2320              
2321 76         153 my $preserve_existing_arg = $args{'preserve_existing'};
2322              
2323 76         244 REL: foreach my $relationship ($self->relationships)
2324             {
2325 58 50 33     241 next if($args{'name'} && $relationship->name ne $args{'name'});
2326             #next unless($relationship->is_ready_to_make_methods);
2327              
2328 58         312 foreach my $type ($relationship->auto_method_types)
2329             {
2330 134   33     2909 my $method =
2331             $relationship->method_name($type) ||
2332             $relationship->build_method_name_for_type($type) ||
2333             Carp::croak "No method name defined for relationship '",
2334             $relationship->name, "' method type '$type'";
2335              
2336 134 50       316 if(my $reason = $self->method_name_is_reserved($method, $class))
2337             {
2338 0         0 Carp::croak "Cannot create method '$method' - $reason ",
2339             "Choose a different relationship name."
2340             }
2341              
2342 134         372 $relationship->method_name($type => $method);
2343              
2344             # Initialize/reset preserve_existing flag
2345 134 50       338 if($self->is_auto_initializating)
2346             {
2347 0   0     0 $args{'preserve_existing'} = $preserve_existing_arg || $self->allow_auto_initialization;
2348             }
2349              
2350 134 100       1092 delete $args{'replace_existing'} if($args{'preserve_existing'});
2351              
2352             # If a corresponding foreign key exists, the preserve any existing
2353             # methods with the same names. This is a crude way to ensure that we
2354             # can have a foreign key and a corresponding relationship without any
2355             # method name clashes.
2356 134 50       416 if($relationship->can('id'))
2357             {
2358 134         349 my $rel_id = $relationship->id;
2359              
2360 134         1024 FK: foreach my $fk ($self->foreign_keys)
2361             {
2362 92 100       344 if($rel_id eq $fk->id)
2363             {
2364 64         424 $args{'preserve_existing'} = 1;
2365 64         111 delete $args{'replace_existing'};
2366 64         165 last FK;
2367             }
2368             }
2369             }
2370             }
2371              
2372 58 50       178 if($self->auto_load_related_classes)
2373             {
2374 58 100       597 if($relationship->can('class'))
2375             {
2376 44         115 my $fclass = $relationship->class;
2377              
2378 44 100 66     277 unless($fclass->isa('Rose::DB::Object') && $fclass->meta->is_initialized)
2379             {
2380 12         82 my $error;
2381              
2382             TRY:
2383             {
2384 12         17 local $@;
  12         19  
2385 12         815 eval "require $fclass";
2386 12         75 $error = $@;
2387             }
2388              
2389 12 50       37 $Debug && print STDERR "REL ", $relationship->name,
2390             " REQUIRES $fclass - $error\n";
2391              
2392 12 50       27 if($error)
2393             {
2394             # XXX: Need to distinguish recoverable errors from unrecoverable errors
2395 12 0 33     72 if($error !~ /\.pm in \@INC/ && !UNIVERSAL::isa($error, 'Rose::DB::Object::Exception::ClassNotReady'))
2396             #if($error =~ /syntax error at |requires explicit package name|not allowed while "strict|already has a relationship named|Can't modify constant item/)
2397             {
2398 0         0 Carp::confess "Could not load $fclass - $error";
2399             }
2400             }
2401             }
2402             }
2403              
2404 58 100       411 if($relationship->can('map_class'))
2405             {
2406 14         41 my $map_class = $relationship->map_class;
2407              
2408 14 100 66     119 unless($map_class->isa('Rose::DB::Object') && $map_class->meta->is_initialized)
2409             {
2410 2         63 my $error;
2411              
2412             TRY:
2413             {
2414 2         4 local $@;
  2         4  
2415 2         157 eval "require $map_class";
2416 2         12 $error = $@;
2417             }
2418              
2419 2 50       9 $Debug && print STDERR "REL ", $relationship->name,
2420             " REQUIRES $map_class - $error\n";
2421              
2422 2 50       6 if($error)
2423             {
2424             # XXX: Need to distinguish recoverable errors from unrecoverable errors
2425 2 0 33     12 if($error !~ /\.pm in \@INC/ && !UNIVERSAL::isa($error, 'Rose::DB::Object::Exception::ClassNotReady'))
2426             #if($error =~ /syntax error at |requires explicit package name|not allowed while "strict|already has a relationship named|Can't modify constant item/)
2427             {
2428 0         0 Carp::confess "Could not load $map_class - $error";
2429             }
2430             }
2431             }
2432             }
2433             }
2434              
2435             # We may need to defer the creation of some relationship methods until
2436             # all the required pieces are loaded.
2437 58 100 66     268 if($relationship->is_ready_to_make_methods)
    100          
2438             {
2439 44 50 33     150 if($Debug && !$args{'preserve_existing'})
2440             {
2441 0         0 warn $self->class, " - make methods for relationship ",
2442             $relationship->name, "\n";
2443             }
2444              
2445 44         172 $relationship->make_methods(%args);
2446             }
2447             elsif(!$relationship->can('foreign_key') || !$relationship->foreign_key)
2448             {
2449             # Confirm that no info is missing. This prevents an improperly
2450             # configured relationship from being deferred "forever"
2451 2         9 $relationship->sanity_check;
2452              
2453 2 50       4 $Debug && warn $self->class, " - defer relationship ", $relationship->name, "\n";
2454              
2455 2         11 $relationship->deferred_make_method_args(\%args);
2456 2         7 $meta_class->add_deferred_relationship($relationship);
2457             }
2458             }
2459              
2460             #$self->retry_deferred_relationships;
2461              
2462 76         418 return;
2463             }
2464              
2465             our @Deferred_Relationships;
2466              
2467             sub deferred_relationships
2468             {
2469 76 50   76 0 248 return wantarray ? @Deferred_Relationships : \@Deferred_Relationships;
2470             }
2471              
2472             sub has_deferred_relationships
2473             {
2474 0     0 0 0 my($self) = shift;
2475              
2476 0         0 my $class = $self->class;
2477 0         0 my $meta_class = ref $self;
2478              
2479 0         0 foreach my $rel ($meta_class->deferred_relationships)
2480             {
2481 0 0 0     0 if(($rel->can('class') && $rel->class eq $class) ||
      0        
      0        
2482             ($rel->can('map_class') && $rel->map_class eq $class))
2483             {
2484 0         0 return 1;
2485             }
2486             }
2487              
2488             # Search among the deferred tasks too (icky)
2489 0         0 foreach my $task ($meta_class->deferred_tasks)
2490             {
2491 0 0 0     0 if($task->{'class'} eq $class && $task->{'method'} eq 'auto_init_relationships')
2492             {
2493 0         0 return 1;
2494             }
2495             }
2496              
2497 0         0 return 0;
2498             }
2499              
2500             sub add_deferred_relationships
2501             {
2502 2     2 0 5 my($class) = shift;
2503              
2504 2         5 ARG: foreach my $arg (@_)
2505             {
2506 2         5 foreach my $rel (@Deferred_Relationships)
2507             {
2508 1 50       5 next ARG if($rel->id eq $arg->id);
2509             }
2510              
2511 2         19 push(@Deferred_Relationships, $arg);
2512             }
2513             }
2514              
2515 2     2 0 9 sub add_deferred_relationship { shift->add_deferred_relationships(@_) }
2516              
2517             sub retry_deferred_relationships
2518             {
2519 76     76 0 142 my($self) = shift;
2520              
2521 76         131 my $meta_class = ref $self;
2522              
2523 76         118 my @relationships;
2524              
2525             # Check to see if any deferred relationships are ready now
2526 76         223 foreach my $relationship ($self->deferred_relationships)
2527             {
2528             # Try to rebuild the relationship using the convention manager, since
2529             # new info may be available now. Otherwise, leave it as-is.
2530 7         20 my $rebuild_rel =
2531             $self->convention_manager->auto_relationship(
2532             $relationship->name, ref $relationship,
2533             scalar $relationship->spec_hash);
2534              
2535 7 50       121 if($rebuild_rel)
2536             {
2537             # XXX: This is pretty evil. I need some sort of copy operator, but
2538             # XXX: a straight hash copy will do for now...
2539 7         48 %$relationship = %$rebuild_rel;
2540             }
2541              
2542 7 100       26 if($relationship->is_ready_to_make_methods)
2543             {
2544 2 50       6 $Debug && warn $relationship->parent->class,
2545             " - (Retry) make methods for relationship ",
2546             $relationship->name, "\n";
2547              
2548 2   50     8 my $args = $relationship->deferred_make_method_args || {};
2549 2         6 $args->{'preserve_existing'} = 1;
2550 2         5 delete $args->{'replace_existing'};
2551              
2552 2         31 $relationship->make_methods(%$args);
2553              
2554             # Reassign to list in case we rebuild above
2555 1         4 $relationship->parent->relationship($relationship->name => $relationship);
2556             }
2557             else
2558             {
2559 5         42 push(@relationships, $relationship);
2560             }
2561             }
2562              
2563 75 100       347 if(join(',', sort @Deferred_Relationships) ne join(',', sort @relationships))
2564             {
2565 1         5 @Deferred_Relationships = @relationships;
2566             }
2567              
2568             # Retry relationship auto-init for all other classes
2569             #foreach my $class ($self->registered_classes)
2570             #{
2571             # next unless($class->meta->allow_auto_initialization && $meta->has_outstanding_metadata_tasks);
2572             # $self->auto_init_relationships(restore_types => 1);
2573             #}
2574             }
2575              
2576             sub make_methods
2577             {
2578 77     77 1 199 my($self) = shift;
2579              
2580 77         301 $self->make_column_methods(@_);
2581 76         315 $self->make_nonpersistent_column_methods(@_);
2582 76         295 $self->make_foreign_key_methods(@_);
2583 76         261 $self->make_relationship_methods(@_);
2584             }
2585              
2586             sub generate_primary_key_values
2587             {
2588 0     0 1 0 my($self, $db) = @_;
2589              
2590 0 0       0 if(my $code = $self->primary_key_generator)
2591             {
2592 0         0 return $code->($self, $db);
2593             }
2594              
2595 0         0 my @ids;
2596              
2597 0         0 my $seqs = $self->fq_primary_key_sequence_names(db => $db);
2598              
2599 0 0 0     0 if($seqs && @$seqs)
2600             {
2601 0         0 my $i = 0;
2602              
2603 0         0 foreach my $seq (@$seqs)
2604             {
2605 0         0 $i++;
2606              
2607 0 0       0 unless(defined $seq)
2608             {
2609 0         0 push(@ids, undef);
2610 0         0 next;
2611             }
2612              
2613 0         0 my $id = $db->next_value_in_sequence($seq);
2614              
2615 0 0       0 unless($id)
2616             {
2617 0         0 $self->error("Could not generate primary key for ", $self->class,
2618             " column '", ($self->primary_key_column_names)[$i],
2619             "' by selecting the next value in the sequence ",
2620             "'$seq' - $@");
2621 0         0 return undef;
2622             }
2623              
2624 0         0 push(@ids, $id);
2625             }
2626              
2627 0         0 return @ids;
2628             }
2629             else
2630             {
2631 0         0 return $db->generate_primary_key_values(scalar @{$self->primary_key_column_names});
  0         0  
2632             }
2633             }
2634              
2635             sub generate_primary_key_value
2636             {
2637 0     0 1 0 my @ids = shift->generate_primary_key_values(@_);
2638 0         0 return $ids[0];
2639             }
2640              
2641             sub generate_primary_key_placeholders
2642             {
2643 0     0 0 0 my($self, $db) = @_;
2644 0         0 return $db->generate_primary_key_placeholders(scalar @{$self->primary_key_column_names});
  0         0  
2645             }
2646              
2647             sub primary_key_column_accessor_names
2648             {
2649 84     84 0 161 my($self) = shift;
2650              
2651 84 50       233 if($self->{'primary_key_column_accessor_names'})
2652             {
2653 0         0 return @{$self->{'primary_key_column_accessor_names'}};
  0         0  
2654             }
2655              
2656 84         216 my @column_names = $self->primary_key_column_names;
2657 84         189 my @columns = grep { defined } map { $self->column($_) } @column_names;
  88         259  
  88         180  
2658              
2659 84 100       219 return unless(@column_names == @columns); # not ready yet
2660              
2661 78         159 my @methods = grep { defined } map { $self->column_accessor_method_name($_) }
  82         223  
  82         279  
2662             @column_names;
2663              
2664 78 100       221 return unless(@methods);
2665              
2666 1         4 $self->{'primary_key_column_accessor_names'} = \@methods;
2667 1         4 return @methods;
2668             }
2669              
2670             sub primary_key_column_mutator_names
2671             {
2672 84     84 0 145 my($self) = shift;
2673              
2674 84 50       232 if($self->{'primary_key_column_mutator_names'})
2675             {
2676 0         0 return @{$self->{'primary_key_column_mutator_names'}};
  0         0  
2677             }
2678              
2679 84         195 my @column_names = $self->primary_key_column_names;
2680 84         203 my @columns = grep { defined } map { $self->column($_) } @column_names;
  88         238  
  88         174  
2681              
2682 84 100       915 return unless(@column_names == @columns); # not ready yet
2683              
2684 78         156 my @methods = grep { defined } map { $self->column_mutator_method_name($_) }
  82         232  
  82         241  
2685             @column_names;
2686              
2687 78 100       211 return unless(@methods);
2688              
2689 1         4 $self->{'primary_key_column_mutator_names'} = \@methods;
2690 1         2 return @methods;
2691             }
2692              
2693             sub fq_primary_key_sequence_names
2694             {
2695 0     0 0 0 my($self, %args) = @_;
2696              
2697 0   0     0 my $db_id = $args{'db'}{'id'} || ($self->{'db_id'} ||= $self->init_db_id);
2698              
2699 0 0       0 if(defined $self->{'fq_primary_key_sequence_names'}{$db_id})
2700             {
2701 0 0       0 my $seqs = $self->{'fq_primary_key_sequence_names'}{$db_id} or return;
2702 0 0       0 return wantarray ? @$seqs : $seqs;
2703             }
2704              
2705 0 0       0 my $db = $args{'db'} or
2706             die "Cannot generate fully-qualified primary key sequence name without db argument";
2707              
2708 0         0 my @seqs = $self->primary_key_sequence_names($db);
2709              
2710 0 0       0 if(@seqs)
2711             {
2712 0         0 $self->primary_key->sequence_names(@seqs);
2713              
2714             # Add schema and catalog information only if it isn't present
2715             # XXX: crappy check - just looking for a '.'
2716 0         0 foreach my $seq (@seqs)
2717             {
2718 0 0 0     0 if(defined $seq && index($seq, '.') < 0)
2719             {
2720 0         0 $seq = $db->quote_identifier_for_sequence($self->select_catalog($db),
2721             $self->select_schema($db), $seq);
2722             }
2723             }
2724              
2725 0         0 $self->{'fq_primary_key_sequence_names'}{$db->{'id'}} = \@seqs;
2726 0 0       0 return wantarray ? @seqs : \@seqs;
2727             }
2728              
2729 0         0 return;
2730             }
2731              
2732             sub refresh_primary_key_sequence_names
2733             {
2734 0     0 0 0 my($self, $db) = @_;
2735 0 0       0 my $db_id = UNIVERSAL::isa($db, 'Rose::DB') ? $db->id : $db;
2736 0         0 $self->{'fq_primary_key_sequence_names'}{$db_id} = undef;
2737 0         0 $self->{'primary_key_sequence_names'}{$db_id} = undef;
2738 0         0 return;
2739             }
2740              
2741             sub primary_key_sequence_names
2742             {
2743 0     0 1 0 my($self) = shift;
2744              
2745 0         0 my($db, $db_id);
2746              
2747 0 0       0 $db = shift if(UNIVERSAL::isa($_[0], 'Rose::DB'));
2748 0 0       0 $db_id = $db ? $db->{'id'} : $self->init_db_id;
2749              
2750             # Set pk sequence names
2751 0 0       0 if(@_)
2752             {
2753             # Clear fully-qualified pk values
2754 0         0 $self->{'fq_primary_key_sequence_names'}{$db_id} = undef;
2755              
2756 0 0 0     0 my $ret = $self->{'primary_key_sequence_names'}{$db_id} =
2757             (@_ == 1 && ref $_[0]) ? $_[0] : [ @_ ];
2758              
2759             # Push down into pk metadata object too
2760 0 0       0 $self->primary_key->sequence_names(($db ? $db : ()), @$ret);
2761              
2762 0 0       0 return wantarray ? @$ret : $ret;
2763             }
2764              
2765 0 0       0 if($self->{'primary_key_sequence_names'}{$db_id})
2766             {
2767 0         0 my $ret = $self->{'primary_key_sequence_names'}{$db_id};
2768 0 0       0 return wantarray ? @$ret : $ret;
2769             }
2770              
2771             # Init pk sequence names
2772              
2773             # Start by considering the list of sequence names stored in the
2774             # primary key metadata object
2775 0         0 my @pks = $self->primary_key_column_names;
2776 0         0 my $seqs = $self->primary_key->sequence_names($db);
2777 0         0 my @seqs;
2778              
2779 0 0       0 if($seqs)
2780             {
2781             # If each pk column has a defined sequence name, accept them as-is
2782 0 0       0 if(@pks == grep { defined } @$seqs)
  0         0  
2783             {
2784 0         0 $self->{'primary_key_sequence_names'}{$db_id} = $seqs;
2785 0 0       0 return wantarray ? @$seqs : $seqs;
2786             }
2787             else # otherwise, use them as a starting point
2788             {
2789 0         0 @seqs = @$seqs;
2790             }
2791             }
2792              
2793 0 0       0 unless($db)
2794             {
2795 0         0 die "Cannot generate primary key sequence name without db argument";
2796             }
2797              
2798              
2799 0         0 my $cm = $self->convention_manager;
2800 0 0       0 my $table = $self->table or
2801             Carp::croak "Cannot generate primary key sequence name without table name";
2802              
2803 0         0 my $i = 0;
2804              
2805 0         0 foreach my $column ($self->primary_key_columns)
2806             {
2807 0         0 my $seq;
2808              
2809             # Go the extra mile and look up the sequence name (if any) for scalar
2810             # pk columns. These pk columns were probably set using the columns()
2811             # shortcut $meta->columns(qw(foo bar baz)) rather than the "long way"
2812             # with type information.
2813 0 0 0     0 if($column->type eq 'scalar')
    0          
2814             {
2815 0         0 $seq = $self->_sequence_name($db,
2816             $self->select_catalog($db),
2817             $self->select_schema($db),
2818             $table,
2819             $column);
2820             }
2821             # Set auto-created serial column sequence names
2822             elsif($column->type =~ /^(?:big)?serial$/ && $db->use_auto_sequence_name)
2823             {
2824 0         0 $seq = $cm->auto_column_sequence_name($table, $column, $db);
2825             }
2826              
2827 0 0 0     0 unless(exists $seqs[$i] && defined $seqs[$i])
2828             {
2829 0 0       0 $seqs[$i] = $seq if(defined $seq);
2830             }
2831              
2832 0         0 $i++;
2833             }
2834              
2835             # Only save if it looks like the class setup is finished
2836 0 0       0 if($self->is_initialized)
2837             {
2838 0         0 $self->{'primary_key_sequence_names'}{$db->{'id'}} = \@seqs;
2839             }
2840              
2841 0 0       0 return wantarray ? @seqs : \@seqs;
2842             }
2843              
2844             sub _sequence_name
2845             {
2846 0     0   0 my($self, $db, $catalog, $schema, $table, $column) = @_;
2847              
2848             # XXX: This is only beneficial in PostgreSQL right now
2849 0 0       0 return unless($db->driver eq 'pg');
2850              
2851 0 0       0 $table = lc $table if($db->likes_lowercase_table_names);
2852              
2853 0         0 my($col_info, $error);
2854              
2855             TRY:
2856             {
2857 0         0 local $@;
  0         0  
2858              
2859             eval
2860 0         0 {
2861 0         0 my $dbh = $db->dbh;
2862              
2863 0         0 local $dbh->{'RaiseError'} = 0;
2864 0         0 local $dbh->{'PrintError'} = 0;
2865              
2866 0 0       0 my $sth = $dbh->column_info($catalog, $schema, $table, $column) or return;
2867              
2868 0         0 $sth->execute;
2869 0         0 $col_info = $sth->fetchrow_hashref;
2870 0         0 $sth->finish;
2871             };
2872              
2873 0         0 $error = $@;
2874             }
2875              
2876 0 0 0     0 return if($error || !$col_info);
2877              
2878 0         0 $db->refine_dbi_column_info($col_info, $self);
2879              
2880 0         0 my $seq = $col_info->{'rdbo_default_value_sequence_name'};
2881              
2882 0         0 my $implicit_schema = $db->default_implicit_schema;
2883              
2884             # Strip off default implicit schema unless a schema is explicitly specified
2885 0 0 0     0 if(defined $seq && defined $implicit_schema && !defined $schema)
      0        
2886             {
2887 0         0 $seq =~ s/^$implicit_schema\.//;
2888             }
2889              
2890 0         0 return $seq;
2891             }
2892              
2893             sub column_names
2894             {
2895 537     537 1 763 my($self) = shift;
2896 537   100     1831 $self->{'column_names'} ||= [ map { $_->name } $self->columns_ordered ];
  570         3272  
2897 537 50       1124 return wantarray ? @{$self->{'column_names'}} : $self->{'column_names'};
  537         1174  
2898             }
2899              
2900             sub nonpersistent_column_names
2901             {
2902 76     76 1 121 my($self) = shift;
2903 76   50     275 $self->{'nonpersistent_column_names'} ||= [ map { $_->name } $self->nonpersistent_columns_ordered ];
  0         0  
2904 76 50       699 return wantarray ? @{$self->{'nonpersistent_column_names'}} : $self->{'nonpersistent_column_names'};
  76         314  
2905             }
2906              
2907             sub nonlazy_column_names
2908             {
2909 0     0 0 0 my($self) = shift;
2910 0   0     0 $self->{'nonlazy_column_names'} ||= [ map { $_->name } $self->nonlazy_columns ];
  0         0  
2911 0 0       0 return wantarray ? @{$self->{'nonlazy_column_names'}} : $self->{'nonlazy_column_names'};
  0         0  
2912             }
2913              
2914             sub lazy_column_names
2915             {
2916 0     0 0 0 my($self) = shift;
2917 0   0     0 $self->{'lazy_column_names'} ||= [ map { $_->name } $self->lazy_columns ];
  0         0  
2918 0 0       0 return wantarray ? @{$self->{'lazy_column_names'}} : $self->{'lazy_column_names'};
  0         0  
2919             }
2920              
2921             sub nonlazy_column_names_string_sql
2922             {
2923 0     0 0 0 my($self, $db) = @_;
2924              
2925             return $self->{'nonlazy_column_names_string_sql'}{$db->{'id'}} ||=
2926 0   0     0 join(', ', map { $_->name_sql($db) } $self->nonlazy_columns);
  0         0  
2927             }
2928              
2929             sub column_names_string_sql
2930             {
2931 0     0 0 0 my($self, $db) = @_;
2932              
2933             return $self->{'column_names_string_sql'}{$db->{'id'}} ||=
2934 0   0     0 join(', ', map { $_->name_sql($db) } $self->columns_ordered);
  0         0  
2935             }
2936              
2937             sub column_names_sql
2938             {
2939 0     0 0 0 my($self, $db) = @_;
2940              
2941             my $list = $self->{'column_names_sql'}{$db->{'id'}} ||=
2942 0   0     0 [ map { $_->name_sql($db) } $self->columns_ordered ];
  0         0  
2943              
2944 0 0       0 return wantarray ? @$list : $list;
2945             }
2946              
2947             sub select_nonlazy_columns_string_sql
2948             {
2949 0     0 0 0 my($self, $db) = @_;
2950              
2951             return $self->{'select_nonlazy_columns_string_sql'}{$db->{'id'}} ||=
2952 0   0     0 join(', ', @{ scalar $self->select_nonlazy_columns_sql($db) });
  0         0  
2953             }
2954              
2955             sub select_columns_string_sql
2956             {
2957 0     0 0 0 my($self, $db) = @_;
2958              
2959             return $self->{'select_columns_string_sql'}{$db->{'id'}} ||=
2960 0   0     0 join(', ', @{ scalar $self->select_columns_sql($db) });
  0         0  
2961             }
2962              
2963             sub select_columns_sql
2964             {
2965 0     0 0 0 my($self, $db) = @_;
2966              
2967 0         0 my $list = $self->{'select_columns_sql'}{$db->{'id'}};
2968              
2969 0 0       0 unless($list)
2970             {
2971 0         0 my $table = $self->table;
2972              
2973 0 0       0 if($self->sql_qualify_column_names_on_load)
2974             {
2975 0         0 $list = [ map { $_->select_sql($db, $table) } $self->columns_ordered ];
  0         0  
2976             }
2977             else
2978             {
2979 0         0 $list = [ map { $_->select_sql($db) } $self->columns_ordered ];
  0         0  
2980             }
2981              
2982 0         0 $self->{'select_columns_sql'}{$db->{'id'}} = $list;
2983             }
2984              
2985 0 0       0 return wantarray ? @$list : $list;
2986             }
2987              
2988             sub select_nonlazy_columns_sql
2989             {
2990 0     0 0 0 my($self, $db) = @_;
2991              
2992 0         0 my $list = $self->{'select_nonlazy_columns_sql'}{$db->{'id'}};
2993              
2994 0 0       0 unless($list)
2995             {
2996 0         0 my $table = $self->table;
2997              
2998 0 0       0 if($self->sql_qualify_column_names_on_load)
2999             {
3000 0         0 $list = [ map { $_->select_sql($db, $table) } $self->nonlazy_columns ];
  0         0  
3001             }
3002             else
3003             {
3004 0         0 $list = [ map { $_->select_sql($db) } $self->nonlazy_columns ];
  0         0  
3005             }
3006              
3007 0         0 $self->{'select_nonlazy_columns_sql'}{$db->{'id'}} = $list;
3008             }
3009              
3010 0 0       0 return wantarray ? @$list : $list;
3011             }
3012              
3013             sub method_column
3014             {
3015 0     0 1 0 my($self, $method) = @_;
3016              
3017 0 0       0 unless(defined $self->{'method_columns'})
3018             {
3019 0         0 foreach my $column ($self->columns_ordered)
3020             {
3021 0         0 foreach my $type ($column->defined_method_types)
3022             {
3023 0 0       0 if(my $method = $column->method_name($type))
3024             {
3025 0         0 $self->{'method_column'}{$method} = $column;
3026             }
3027             }
3028             }
3029             }
3030              
3031 0         0 return $self->{'method_column'}{$method};
3032             }
3033              
3034             sub column_rw_method_names
3035             {
3036 154     154 1 1894 my($self) = shift;
3037              
3038             $self->{'column_rw_method_names'} ||=
3039 154   100     518 [ map { $self->column_rw_method_name($_) } $self->column_names ];
  369         778  
3040              
3041 0         0 return wantarray ? @{$self->{'column_rw_method_names'}} :
3042 154 50       336 $self->{'column_rw_method_names'};
3043             }
3044              
3045             sub column_accessor_method_names
3046             {
3047 153     153 1 387 my($self) = shift;
3048              
3049             $self->{'column_accessor_method_names'} ||=
3050 153   50     1006 [ map { $self->column_accessor_method_name($_) } $self->column_names ];
  369         798  
3051              
3052 0         0 return wantarray ? @{$self->{'column_accessor_method_names'}} :
3053 153 50       412 $self->{'column_accessor_method_names'};
3054             }
3055              
3056             sub nonpersistent_column_accessor_method_names
3057             {
3058 76     76 1 130 my($self) = shift;
3059              
3060             $self->{'nonpersistent_column_accessor_method_names'} ||=
3061 76   50     354 [ map { $self->nonpersistent_column_accessor_method_name($_) } $self->nonpersistent_column_names ];
  0         0  
3062              
3063 0         0 return wantarray ? @{$self->{'nonpersistent_column_accessor_method_names'}} :
3064 76 50       196 $self->{'nonpersistent_column_accessor_method_names'};
3065             }
3066              
3067             sub nonlazy_column_accessor_method_names
3068             {
3069 0     0 0 0 my($self) = shift;
3070              
3071             $self->{'nonlazy_column_accessor_method_names'} ||=
3072 0   0     0 [ map { $self->column_accessor_method_name($_) } $self->nonlazy_column_names ];
  0         0  
3073              
3074 0         0 return wantarray ? @{$self->{'nonlazy_column_accessor_method_names'}} :
3075 0 0       0 $self->{'nonlazy_column_accessor_method_names'};
3076             }
3077              
3078             sub column_mutator_method_names
3079             {
3080 153     153 1 285 my($self) = shift;
3081              
3082             $self->{'column_mutator_method_names'} ||=
3083 153   50     591 [ map { $self->column_mutator_method_name($_) } $self->column_names ];
  369         707  
3084              
3085 0         0 return wantarray ? @{$self->{'column_mutator_method_names'}} :
3086 153 50       359 $self->{'column_mutator_method_names'};
3087             }
3088              
3089             sub nonpersistent_column_mutator_method_names
3090             {
3091 0     0 1 0 my($self) = shift;
3092              
3093             $self->{'nonpersistent_column_mutator_method_names'} ||=
3094 0   0     0 [ map { $self->nonpersistent_column_mutator_method_name($_) } $self->nonpersistent_column_names ];
  0         0  
3095              
3096 0         0 return wantarray ? @{$self->{'nonpersistent_column_mutator_method_names'}} :
3097 0 0       0 $self->{'nonpersistent_column_mutator_method_names'};
3098             }
3099              
3100             sub nonlazy_column_mutator_method_names
3101             {
3102 0     0 0 0 my($self) = shift;
3103              
3104             $self->{'nonlazy_column_mutator_method_names'} ||=
3105 0   0     0 [ map { $self->column_mutator_method_name($_) } $self->nonlazy_column_names ];
  0         0  
3106              
3107 0         0 return wantarray ? @{$self->{'nonlazy_column_mutator_method_names'}} :
3108 0 0       0 $self->{'nonlazy_column_mutator_method_names'};
3109             }
3110              
3111             sub column_db_value_hash_keys
3112             {
3113 0     0 0 0 my($self) = shift;
3114              
3115             $self->{'column_db_value_hash_keys'} ||=
3116 0   0     0 { map { $_->mutator_method_name => $_->db_value_hash_key } $self->columns_ordered };
  0         0  
3117              
3118 0         0 return wantarray ? %{$self->{'column_db_value_hash_keys'}} :
3119 0 0       0 $self->{'column_db_value_hash_keys'};
3120             }
3121              
3122             sub nonlazy_column_db_value_hash_keys
3123             {
3124 0     0 0 0 my($self) = shift;
3125              
3126             $self->{'nonlazy_column_db_value_hash_keys'} ||=
3127 0   0     0 { map { $_->mutator_method_name => $_->db_value_hash_key } $self->nonlazy_columns };
  0         0  
3128              
3129 0         0 return wantarray ? %{$self->{'nonlazy_column_db_value_hash_keys'}} :
3130 0 0       0 $self->{'nonlazy_column_db_value_hash_keys'};
3131             }
3132              
3133             sub primary_key_column_db_value_hash_keys
3134             {
3135 0     0 0 0 my($self) = shift;
3136              
3137             $self->{'primary_key_column_db_value_hash_keys'} ||=
3138 0   0     0 [ map { $_->db_value_hash_key } $self->primary_key_columns ];
  0         0  
3139              
3140 0         0 return wantarray ? @{$self->{'primary_key_column_db_value_hash_keys'}} :
3141 0 0       0 $self->{'primary_key_column_db_value_hash_keys'};
3142             }
3143              
3144             sub alias_column
3145             {
3146 1     1 1 361 my($self, $name, $new_name) = @_;
3147              
3148 1 50       5 Carp::croak "Usage: alias_column(column name, new name)"
3149             unless(@_ == 3);
3150              
3151             Carp::croak "No such column '$name' in table ", $self->table
3152 1 50       5 unless($self->{'columns'}{$name});
3153              
3154 1 50       5 Carp::cluck "Pointless alias for '$name' to '$new_name' for table ", $self->table
3155             unless($name ne $new_name);
3156              
3157             # XXX: Allow primary keys to be aliased
3158             # XXX: Was disabled because the Manager was not happy with this.
3159             #foreach my $column ($self->primary_key_column_names)
3160             #{
3161             # if($name eq $column)
3162             # {
3163             # Carp::croak "Primary key columns cannot be aliased (the culprit: '$name')";
3164             # }
3165             #}
3166              
3167 1         5 $self->_clear_column_generated_values;
3168              
3169 1 50       4 if(my $column = $self->column($name))
3170             {
3171 1         4 $column->method_name($new_name);
3172             }
3173              
3174 1         5 $self->{'column_aliases'}{$name} = $new_name;
3175             }
3176              
3177             sub column_aliases
3178             {
3179 116 50   116 1 772 return $_[0]->{'column_aliases'} unless(@_ > 1);
3180 0 0       0 return $_[0]->{'column_aliases'} = (ref $_[1] eq 'HASH') ? $_[1] : { @_[1 .. $#_] };
3181             }
3182              
3183             sub column_accessor_method_name
3184             {
3185 740 50 100 740 1 2576 $_[0]->{'column_accessor_method'}{$_[1]} ||=
3186             ($_[0]->column($_[1]) ? $_[0]->column($_[1])->accessor_method_name : undef);
3187             }
3188              
3189             sub nonpersistent_column_accessor_method_name
3190             {
3191 0 0 0 0 1 0 $_[0]->{'nonpersistent_column_accessor_method'}{$_[1]} ||=
3192             ($_[0]->nonpersistent_column($_[1]) ? $_[0]->nonpersistent_column($_[1])->accessor_method_name : undef);
3193             }
3194              
3195 0     0 0 0 sub column_accessor_method_names_hash { shift->{'column_accessor_method'} }
3196              
3197 0     0 0 0 sub nonpersistent_column_accessor_method_names_hash { shift->{'nonpersistent_column_accessor_method'} }
3198              
3199             sub key_column_accessor_method_names_hash
3200             {
3201 75     75 0 121 my($self) = shift;
3202              
3203 75 50       185 return $self->{'key_column_accessor_method'} if($self->{'key_column_accessor_method'});
3204              
3205 75         291 foreach my $column (grep { ref } $self->primary_key_columns)
  77         306  
3206             {
3207 77         247 $self->{'key_column_accessor_method'}{$column->name} = $column->accessor_method_name;
3208             }
3209              
3210 75         260 foreach my $uk ($self->unique_keys)
3211             {
3212 0         0 foreach my $column (grep { ref } $uk->columns)
  0         0  
3213             {
3214 0         0 $self->{'key_column_accessor_method'}{$column->name} = $column->accessor_method_name;
3215             }
3216             }
3217              
3218 75         167 return $self->{'key_column_accessor_method'};
3219             }
3220              
3221             sub column_mutator_method_name
3222             {
3223 503 50 100 503 1 1652 $_[0]->{'column_mutator_method'}{$_[1]} ||=
3224             ($_[0]->column($_[1]) ? $_[0]->column($_[1])->mutator_method_name : undef);
3225             }
3226              
3227             sub nonpersistent_column_mutator_method_name
3228             {
3229 0 0 0 0 1 0 $_[0]->{'nonpersistent_column_mutator_method'}{$_[1]} ||=
3230             ($_[0]->nonpersistent_column($_[1]) ? $_[0]->nonpersistent_column($_[1])->mutator_method_name : undef);
3231             }
3232              
3233 0     0 0 0 sub column_mutator_method_names_hash { shift->{'column_mutator_method'} }
3234              
3235             sub column_rw_method_name
3236             {
3237 369   33 369 1 1102 $_[0]->{'column_rw_method'}{$_[1]} ||=
3238             $_[0]->column($_[1])->rw_method_name;
3239             }
3240              
3241 0     0 0 0 sub column_rw_method_names_hash { shift->{'column_rw_method'} }
3242              
3243             sub fq_table_sql
3244             {
3245 1     1 0 527 my($self, $db) = @_;
3246             return $self->{'fq_table_sql'}{$db->{'id'}} ||=
3247 1   33     12 join('.', grep { defined } ($self->select_catalog($db),
  3         33  
3248             $self->select_schema($db),
3249             $db->auto_quote_table_name($self->table)));
3250             }
3251              
3252             sub fqq_table_sql
3253             {
3254 0     0 0 0 my($self, $db) = @_;
3255             return $self->{'fq_table_sql'}{$db->{'id'}} ||=
3256 0   0     0 join('.', grep { defined } ($self->select_catalog($db),
  0         0  
3257             $self->select_schema($db),
3258             $db->quote_table_name($self->table)));
3259             }
3260              
3261             sub fq_table
3262             {
3263 0     0 0 0 my($self, $db) = @_;
3264             return $self->{'fq_table'}{$db->{'id'}} ||=
3265 0   0     0 join('.', grep { defined } ($self->select_catalog($db),
  0         0  
3266             $self->select_schema($db),
3267             $self->table));
3268             }
3269              
3270             sub load_all_sql
3271             {
3272 0     0 0 0 my($self, $key_columns, $db) = @_;
3273              
3274 0   0     0 $key_columns ||= $self->primary_key_column_names;
3275              
3276 61     61   886 no warnings;
  61         215  
  61         13624  
3277             return $self->{'load_all_sql'}{$db->{'id'}}{join("\0", @$key_columns)} ||=
3278             'SELECT ' . $self->select_columns_string_sql($db) . ' FROM ' .
3279             $self->fq_table_sql($db) . ' WHERE ' .
3280             join(' AND ', map
3281             {
3282 0   0     0 my $c = $self->column($_);
  0         0  
3283              
3284 0 0       0 ($self->sql_qualify_column_names_on_load ?
3285             $db->auto_quote_column_with_table($c->name_sql, $self->table) : $c->name_sql($db)) .
3286             ' = ' . $c->query_placeholder_sql($db)
3287             }
3288             @$key_columns);
3289             }
3290              
3291             sub load_sql
3292             {
3293 0     0 0 0 my($self, $key_columns, $db) = @_;
3294              
3295 0   0     0 $key_columns ||= $self->primary_key_column_names;
3296              
3297 61     61   573 no warnings;
  61         204  
  61         13548  
3298             return $self->{'load_sql'}{$db->{'id'}}{join("\0", @$key_columns)} ||=
3299             'SELECT ' . $self->select_nonlazy_columns_string_sql($db) . ' FROM ' .
3300             $self->fq_table_sql($db) . ' WHERE ' .
3301             join(' AND ', map
3302             {
3303 0   0     0 my $c = $self->column($_);
  0         0  
3304 0 0       0 ($self->sql_qualify_column_names_on_load ?
3305             $db->auto_quote_column_with_table($c->name_sql, $self->table) : $c->name_sql($db)) .
3306             ' = ' . $c->query_placeholder_sql($db)
3307             }
3308             @$key_columns);
3309             }
3310              
3311             sub load_all_sql_with_null_key
3312             {
3313 0     0 0 0 my($self, $key_columns, $key_values, $db) = @_;
3314              
3315 0         0 my $i = 0;
3316              
3317 0         0 my $fq = $self->sql_qualify_column_names_on_load;
3318 0         0 my $table = $self->table;
3319              
3320 61     61   635 no warnings;
  61         199  
  61         11327  
3321             return
3322             'SELECT ' . $self->select_columns_string_sql($db) . ' FROM ' .
3323             $self->fq_table_sql($db) . ' WHERE ' .
3324             join(' AND ', map
3325             {
3326 0         0 my $c = $self->column($_);
  0         0  
3327 0 0       0 ($fq ? $db->auto_quote_column_with_table($c->name_sql, $table) : $c->name_sql($db)) .
    0          
3328             (defined $key_values->[$i++] ? ' = ' . $c->query_placeholder_sql : ' IS NULL')
3329             }
3330             @$key_columns);
3331             }
3332              
3333             sub load_sql_with_null_key
3334             {
3335 0     0 0 0 my($self, $key_columns, $key_values, $db) = @_;
3336              
3337 0         0 my $i = 0;
3338              
3339 0         0 my $fq = $self->sql_qualify_column_names_on_load;
3340 0         0 my $table = $self->table;
3341              
3342 61     61   499 no warnings;
  61         191  
  61         13952  
3343             return
3344             'SELECT ' . $self->select_nonlazy_columns_string_sql($db) . ' FROM ' .
3345             $self->fq_table_sql($db) . ' WHERE ' .
3346             join(' AND ', map
3347             {
3348 0         0 my $c = $self->column($_);
  0         0  
3349 0 0       0 ($fq ? $db->auto_quote_column_with_table($c->name_sql, $table) : $c->name_sql($db)) .
    0          
3350             (defined $key_values->[$i++] ? ' = ' . $c->query_placeholder_sql : ' IS NULL')
3351             }
3352             @$key_columns);
3353             }
3354              
3355             sub update_all_sql
3356             {
3357 0     0 0 0 my($self, $key_columns, $db) = @_;
3358              
3359 0   0     0 $key_columns ||= $self->primary_key_column_names;
3360              
3361 0         0 my $cache_key = "$db->{'id'}:" . join("\0", @$key_columns);
3362              
3363             return $self->{'update_all_sql'}{$cache_key}
3364 0 0       0 if($self->{'update_all_sql'}{$cache_key});
3365              
3366 0         0 my %key = map { ($_ => 1) } @$key_columns;
  0         0  
3367              
3368 61     61   523 no warnings;
  61         181  
  61         12943  
3369             return $self->{'update_all_sql'}{$cache_key} =
3370             'UPDATE ' . $self->fq_table_sql($db) . " SET \n" .
3371             join(",\n", map
3372             {
3373 0         0 ' ' . $_->name_sql($db) . ' = ' . $_->update_placeholder_sql($db)
3374             }
3375 0         0 grep { !$key{$_->name} } $self->columns_ordered) .
3376             "\nWHERE " .
3377             join(' AND ', map
3378             {
3379 0         0 my $c = $self->column($_);
  0         0  
3380 0         0 $c->name_sql($db) . ' = ' . $c->query_placeholder_sql
3381             }
3382             @$key_columns);
3383             }
3384              
3385 61     61   552 use constant LAZY_LOADED_KEY => lazy_column_values_loaded_key();
  61         199  
  61         438  
3386              
3387             sub update_sql
3388             {
3389 0     0 0 0 my($self, $obj, $key_columns, $db) = @_;
3390              
3391 0   0     0 $key_columns ||= $self->primary_key_column_names;
3392              
3393 0         0 my %key = map { ($_ => 1) } @$key_columns;
  0         0  
3394              
3395 61     61   526 no warnings 'uninitialized';
  61         186  
  61         28766  
3396              
3397             my @columns =
3398 0 0 0     0 grep { !$key{$_->name} && (!$_->lazy || $obj->{LAZY_LOADED_KEY()}{$_->name}) }
  0         0  
3399             $self->columns_ordered;
3400              
3401 0         0 my @exec;
3402              
3403 0 0       0 unless($self->dbi_requires_bind_param($db))
3404             {
3405 0         0 my $method_name = $self->column_accessor_method_names_hash;
3406              
3407 0         0 foreach my $column (@columns)
3408             {
3409 0         0 my $method = $method_name->{$column->{'name'}};
3410 0         0 push(@exec, $obj->$method());
3411             }
3412             }
3413              
3414             return (($self->{'update_sql_prefix'}{$db->{'id'}} ||
3415             $self->init_update_sql_prefix($db)) .
3416             join(",\n", map
3417             {
3418 0         0 ' ' . $_->name_sql($db) . ' = ' . $_->update_placeholder_sql($db)
3419             }
3420             @columns) .
3421             "\nWHERE " .
3422             join(' AND ', map
3423             {
3424 0   0     0 my $c = $self->column($_);
  0         0  
3425 0         0 $c->name_sql($db) . ' = ' . $c->query_placeholder_sql($db)
3426             }
3427             @$key_columns),
3428             \@exec,
3429             \@columns);
3430             }
3431              
3432             sub init_update_sql_prefix
3433             {
3434 0     0 0 0 my($self, $db) = @_;
3435 0         0 return $self->{'update_sql_prefix'}{$db->{'id'}} =
3436             'UPDATE ' . $self->fq_table_sql($db) . " SET \n";
3437             }
3438              
3439             sub update_changes_only_sql
3440             {
3441 0     0 0 0 my($self, $obj, $key_columns, $db) = @_;
3442              
3443 0   0     0 $key_columns ||= $self->primary_key_column_names;
3444              
3445 0         0 my %key = map { ($_ => 1) } @$key_columns;
  0         0  
3446              
3447 0 0       0 my @modified = map { $self->column($_) } grep { !$key{$_} } keys %{$obj->{MODIFIED_COLUMNS()} || {}};
  0         0  
  0         0  
  0         0  
3448              
3449 0 0       0 return unless(@modified);
3450              
3451 61     61   551 no warnings;
  61         162  
  61         27371  
3452             return ($self->{'update_sql_prefix'}{$db->{'id'}} ||=
3453             'UPDATE ' . $self->fq_table_sql($db) . " SET \n") .
3454             join(",\n", map
3455             {
3456 0         0 ' ' . $_->name_sql($db) . ' = ' . $_->update_placeholder_sql($db)
3457             }
3458             @modified) .
3459             "\nWHERE " .
3460             join(' AND ', map
3461             {
3462 0         0 my $c = $self->column($_);
3463 0         0 $c->name_sql($db) . ' = ' . $c->query_placeholder_sql($db)
3464             }
3465             @$key_columns),
3466 0   0     0 [ map { my $m = $_->accessor_method_name; $obj->$m() } @modified ],
  0         0  
  0         0  
3467             \@modified;
3468             }
3469              
3470             # This is nonsensical right now because the primary key always has to be
3471             # non-null, and any update will use the primary key instead of a unique
3472             # key. But I'll leave the code here (commented out) just in case.
3473             #
3474             # sub update_all_sql_with_null_key
3475             # {
3476             # my($self, $key_columns, $key_values, $db) = @_;
3477             #
3478             # my %key = map { ($_ => 1) } @$key_columns;
3479             # my $i = 0;
3480             #
3481             # no warnings;
3482             # return
3483             # 'UPDATE ' . $self->fq_table_sql($db) . " SET \n" .
3484             # join(",\n", map { ' ' . $self->column($_)->name_sql($db) . ' = ?' }
3485             # grep { !$key{$_} } $self->column_names) .
3486             # "\nWHERE " . join(' AND ', map { defined $key_values->[$i++] ? "$_ = ?" : "$_ IS NULL" }
3487             # map { $self->column($_)->name_sql($db) } @$key_columns);
3488             # }
3489             #
3490             # Ditto for this version of update_sql_with_inlining which handles null keys
3491             #
3492             # sub update_sql_with_inlining
3493             # {
3494             # my($self, $obj, $key_columns, $key_values) = @_;
3495             #
3496             # my $db = $obj->db or Carp::croak "Missing db";
3497             #
3498             # $key_columns ||= $self->primary_key_column_names;
3499             #
3500             # my %key = map { ($_ => 1) } @$key_columns;
3501             #
3502             # my @bind;
3503             # my @updates;
3504             #
3505             # foreach my $column (grep { !$key{$_} } $self->columns_ordered)
3506             # {
3507             # my $method = $self->column_method($column->name);
3508             # my $value = $obj->$method();
3509             #
3510             # if($column->should_inline_value($db, $value))
3511             # {
3512             # push(@updates, ' ' . $column->name_sql($db) . " = $value");
3513             # }
3514             # else
3515             # {
3516             # push(@updates, ' ' . $column->name_sql($db) . ' = ?');
3517             # push(@bind, $value);
3518             # }
3519             # }
3520             #
3521             # my $i = 0;
3522             #
3523             # no warnings;
3524             # return
3525             # (
3526             # ($self->{'update_sql_with_inlining_start'} ||=
3527             # 'UPDATE ' . $self->fq_table_sql($db) . " SET \n") .
3528             # join(",\n", @updates) . "\nWHERE " .
3529             # join(' AND ', map { defined $key_values->[$i++] ? "$_ = ?" : "$_ IS NULL" }
3530             # map { $self->column($_)->name_sql($db) } @$key_columns),
3531             # \@bind
3532             # );
3533             # }
3534              
3535             sub update_sql_with_inlining
3536             {
3537 0     0 0 0 my($self, $obj, $key_columns) = @_;
3538              
3539 0 0       0 my $db = $obj->db or Carp::croak "Missing db";
3540              
3541 0   0     0 $key_columns ||= $self->primary_key_column_names;
3542              
3543 0         0 my %key = map { ($_ => 1) } @$key_columns;
  0         0  
3544              
3545 0         0 my(@bind, @updates, @bind_params);
3546              
3547 0         0 my $do_bind_params = $self->dbi_requires_bind_param($db);
3548              
3549 0         0 foreach my $column (grep { !$key{$_} && (!$_->{'lazy'} ||
3550 0 0 0     0 $obj->{LAZY_LOADED_KEY()}{$_->{'name'}}) }
3551             $self->columns_ordered)
3552             {
3553 0         0 my $method = $self->column_accessor_method_name($column->name);
3554 0         0 my $value = $obj->$method();
3555              
3556 0 0       0 if($column->should_inline_value($db, $value))
3557             {
3558 0         0 push(@updates, $column->name_sql($db) . " = $value");
3559             }
3560             else
3561             {
3562 0         0 push(@updates, $column->name_sql($db) . ' = ' .
3563             $column->update_placeholder_sql($db));
3564 0         0 push(@bind, $value);
3565              
3566 0 0       0 if($do_bind_params)
3567             {
3568 0         0 push(@bind_params, $column->dbi_bind_param_attrs($db));
3569             }
3570             }
3571             }
3572              
3573 0         0 my $i = 0;
3574              
3575 61     61   543 no warnings;
  61         175  
  61         29229  
3576             return
3577             (
3578             ($self->{'update_sql_with_inlining_start'}{$db->{'id'}} ||
3579             $self->init_update_sql_with_inlining_start($db)) .
3580             join(",\n", @updates) . "\nWHERE " .
3581             join(' AND ', map
3582             {
3583 0 0 0     0 my $c = $self->column($_);
  0         0  
3584 0         0 $c->name_sql($db) . ' = ' . $c->query_placeholder_sql($db)
3585             }
3586             @$key_columns),
3587             \@bind,
3588             ($do_bind_params ? \@bind_params : ())
3589             );
3590             }
3591              
3592             sub init_update_sql_with_inlining_start
3593             {
3594 0     0 0 0 my($self, $db) = @_;
3595 0         0 return $self->{'update_sql_with_inlining_start'}{$db->{'id'}} =
3596             'UPDATE ' . $self->fq_table_sql($db) . " SET \n";
3597             }
3598              
3599             sub update_changes_only_sql_with_inlining
3600             {
3601 0     0 0 0 my($self, $obj, $key_columns) = @_;
3602              
3603 0 0       0 my $db = $obj->db or Carp::croak "Missing db";
3604              
3605 0   0     0 $key_columns ||= $self->primary_key_column_names;
3606              
3607 0         0 my %key = map { ($_ => 1) } @$key_columns;
  0         0  
3608              
3609 0         0 my $modified = $obj->{MODIFIED_COLUMNS()};
3610              
3611 0         0 my(@bind, @updates, @bind_params);
3612              
3613 0         0 my $do_bind_params = $self->dbi_requires_bind_param($db);
3614              
3615 0 0       0 foreach my $column (grep { !$key{$_->{'name'}} && $modified->{$_->{'name'}} } $self->columns_ordered)
  0         0  
3616             {
3617 0         0 my $method = $self->column_accessor_method_name($column->name);
3618 0         0 my $value = $obj->$method();
3619              
3620 0 0       0 if($column->should_inline_value($db, $value))
3621             {
3622 0         0 push(@updates, ' ' . $column->name_sql($db) . " = $value");
3623             }
3624             else
3625             {
3626 0         0 push(@updates, $column->name_sql($db) . ' = ' .
3627             $column->update_placeholder_sql($db));
3628 0         0 push(@bind, $value);
3629              
3630 0 0       0 if($do_bind_params)
3631             {
3632 0         0 push(@bind_params, $column->dbi_bind_param_attrs($db));
3633             }
3634             }
3635             }
3636              
3637 0 0       0 return unless(@updates);
3638              
3639 0         0 my $i = 0;
3640              
3641 61     61   554 no warnings;
  61         172  
  61         12927  
3642             return
3643             (
3644             ($self->{'update_sql_with_inlining_start'}{$db->{'id'}} ||=
3645             'UPDATE ' . $self->fq_table_sql($db) . " SET \n") .
3646             join(",\n", @updates) . "\nWHERE " .
3647             join(' AND ', map
3648             {
3649 0 0 0     0 my $c = $self->column($_);
  0         0  
3650 0         0 $c->name_sql($db) . ' = ' . $c->query_placeholder_sql($db)
3651             }
3652             @$key_columns),
3653             \@bind,
3654             ($do_bind_params ? \@bind_params : ())
3655             );
3656             }
3657              
3658             sub insert_sql
3659             {
3660 0     0 0 0 my($self, $db) = @_;
3661              
3662 61     61   548 no warnings;
  61         178  
  61         18476  
3663             return $self->{'insert_sql'}{$db->{'id'}} ||=
3664             'INSERT INTO ' . $self->fq_table_sql($db) . "\n(\n" .
3665 0   0     0 join(",\n", map { " $_" } $self->column_names_sql($db)) .
  0         0  
3666             "\n)\nVALUES\n(\n" . $self->insert_columns_placeholders_sql($db) .
3667             "\n)";
3668             }
3669              
3670             sub insert_changes_only_sql
3671             {
3672 0     0 0 0 my($self, $obj, $db) = @_;
3673              
3674 0   0     0 my $modified = $obj->{MODIFIED_COLUMNS()} || {};
3675 0 0       0 my @modified = grep { $modified->{$_->{'name'}} || $_->default_exists } $self->columns_ordered;
  0         0  
3676              
3677 0 0       0 unless(@modified)
3678             {
3679             # Make a last-ditch attempt to insert with no modified columns
3680             # using the DEFAULT keyword on an arbitrary column. This works
3681             # in MySQL and PostgreSQL.
3682 0 0       0 if($db->supports_arbitrary_defaults_on_insert)
3683             {
3684             return
3685 0         0 'INSERT INTO ' . $self->fq_table_sql($db) . ' (' .
3686             ($self->columns_ordered)[-1]->name_sql($db) . ') VALUES (DEFAULT)',
3687             [];
3688             }
3689             else
3690             {
3691 0         0 Carp::croak "Cannot insert row into table '", $self->table,
3692             "' - No columns have modified or default values";
3693             }
3694             }
3695              
3696 61     61   524 no warnings;
  61         162  
  61         44722  
3697             return ($self->{'insert_changes_only_sql_prefix'}{$db->{'id'}} ||
3698             $self->init_insert_changes_only_sql_prefix($db)) .
3699 0         0 join(",\n", map { $_->name_sql($db) } @modified) .
3700             "\n)\nVALUES\n(\n" .
3701 0         0 join(",\n", map { $_->insert_placeholder_sql($db) } @modified) . "\n)",
3702 0   0     0 [ map { my $m = $_->accessor_method_name; $obj->$m() } @modified ],
  0         0  
  0         0  
3703             \@modified;
3704             }
3705              
3706             sub init_insert_changes_only_sql_prefix
3707             {
3708 0     0 0 0 my($self, $db) = @_;
3709 0         0 return $self->{'insert_changes_only_sql_prefix'}{$db->{'id'}} =
3710             'INSERT INTO ' . $self->fq_table_sql($db) . "\n(\n";
3711             ;
3712             }
3713              
3714             sub insert_columns_placeholders_sql
3715             {
3716 0     0 0 0 my($self, $db) = @_;
3717             return $self->{'insert_columns_placeholders_sql'}{$db->{'id'}} ||=
3718 0   0     0 join(",\n", map { ' ' . $_->insert_placeholder_sql($db) } $self->columns_ordered)
  0         0  
3719             }
3720              
3721             sub insert_and_on_duplicate_key_update_sql
3722             {
3723 0     0 0 0 my($self, $obj, $db, $changes_only) = @_;
3724              
3725 0         0 my(@columns, @names, @bind);
3726              
3727 0 0       0 if($obj->{STATE_IN_DB()})
3728             {
3729 0         0 my %seen;
3730              
3731             @columns = $changes_only ?
3732 0         0 (map { $self->column($_) } grep { !$seen{$_}++ }
  0         0  
3733             ($self->primary_key_column_names,
3734 0 0       0 keys %{$obj->{MODIFIED_COLUMNS()} || {}})) :
3735 0 0       0 (grep { (!$_->{'lazy'} || $obj->{LAZY_LOADED_KEY()}{$_->{'name'}}) }
  0 0       0  
3736             $self->columns_ordered);
3737              
3738 0         0 @names = map { $_->name_sql($db) } @columns;
  0         0  
3739              
3740 0         0 foreach my $column (@columns)
3741             {
3742 0         0 my $method = $self->column_accessor_method_name($column->{'name'});
3743 0         0 push(@bind, $obj->$method());
3744             }
3745             }
3746             else
3747             {
3748 0         0 my %skip;
3749              
3750 0         0 my @key_columns = $self->primary_key_column_names;
3751 0         0 my @key_methods = $self->primary_key_column_accessor_names;
3752 0         0 my @key_values = grep { defined } map { $obj->$_() } @key_methods;
  0         0  
  0         0  
3753              
3754 0 0       0 unless(@key_values)
3755             {
3756 0         0 @skip{@key_columns} = (1) x @key_columns;
3757             }
3758              
3759 0         0 foreach my $uk ($self->unique_keys)
3760             {
3761 0         0 @key_columns = $uk->columns;
3762 0         0 @key_methods = map { $_->accessor_method_name } @key_columns;
  0         0  
3763 0         0 @key_values = grep { defined } map { $obj->$_() } @key_methods;
  0         0  
  0         0  
3764              
3765 0 0       0 unless(@key_values)
3766             {
3767 0         0 @skip{@key_columns} = (1) x @key_columns;
3768             }
3769             }
3770              
3771             @columns = $changes_only ?
3772 0 0       0 (map { $self->column($_) } grep { !$skip{"$_"} } keys %{$obj->{MODIFIED_COLUMNS()} || {}}) :
  0         0  
  0         0  
3773 0 0       0 (grep { !$skip{"$_"} && (!$_->{'lazy'} ||
3774 0 0 0     0 $obj->{LAZY_LOADED_KEY()}{$_->{'name'}}) } $self->columns_ordered);
3775              
3776 0         0 @names = map { $_->name_sql($db) } @columns;
  0         0  
3777              
3778 0         0 foreach my $column (@columns)
3779             {
3780 0         0 my $method = $self->column_accessor_method_name($column->{'name'});
3781 0         0 push(@bind, $obj->$method());
3782             }
3783             }
3784              
3785 61     61   553 no warnings;
  61         169  
  61         62217  
3786             return
3787             'INSERT INTO ' . $self->fq_table_sql($db) . "\n(\n" .
3788             join(",\n", @names) .
3789             "\n)\nVALUES\n(\n" .
3790 0         0 join(",\n", map { $_->insert_placeholder_sql($db) } @columns) .
3791             "\n)\nON DUPLICATE KEY UPDATE\n" .
3792             join(",\n", map
3793             {
3794 0         0 $_->name_sql($db) . ' = ' . $_->update_placeholder_sql($db)
  0         0  
3795             }
3796             @columns),
3797             [ @bind, @bind ],
3798             [ @columns, @columns ];
3799             }
3800              
3801             sub insert_sql_with_inlining
3802             {
3803 0     0 0 0 my($self, $obj) = @_;
3804              
3805 0 0       0 my $db = $obj->db or Carp::croak "Missing db";
3806              
3807 0         0 my(@bind, @places, @bind_params);
3808              
3809 0         0 my $do_bind_params = $self->dbi_requires_bind_param($db);
3810              
3811 0         0 foreach my $column ($self->columns_ordered)
3812             {
3813 0         0 my $method = $self->column_accessor_method_name($column->name);
3814 0         0 my $value = $obj->$method();
3815              
3816 0 0       0 if($column->should_inline_value($db, $value))
3817             {
3818 0         0 push(@places, " $value");
3819             }
3820             else
3821             {
3822 0         0 push(@places, $column->insert_placeholder_sql($db));
3823 0         0 push(@bind, $value);
3824              
3825 0 0       0 if($do_bind_params)
3826             {
3827 0         0 push(@bind_params, $column->dbi_bind_param_attrs($db));
3828             }
3829             }
3830             }
3831              
3832             return
3833             (
3834 0 0 0     0 ($self->{'insert_sql_with_inlining_start'}{$db->{'id'}} ||
3835             $self->init_insert_sql_with_inlining_start($db)) .
3836             join(",\n", @places) . "\n)",
3837             \@bind,
3838             ($do_bind_params ? \@bind_params : ())
3839             );
3840             }
3841              
3842             sub init_insert_sql_with_inlining_start
3843             {
3844 0     0 0 0 my($self, $db) = @_;
3845             $self->{'insert_sql_with_inlining_start'}{$db->{'id'}} =
3846             'INSERT INTO ' . $self->fq_table_sql($db) . "\n(\n" .
3847 0         0 join(",\n", map { " $_" } $self->column_names_sql($db)) .
  0         0  
3848             "\n)\nVALUES\n(\n";
3849             }
3850              
3851             sub insert_and_on_duplicate_key_update_with_inlining_sql
3852             {
3853 0     0 0 0 my($self, $obj, $db, $changes_only) = @_;
3854              
3855 0         0 my(@columns, @names);
3856              
3857 0         0 my $do_bind_params = $self->dbi_requires_bind_param($db);
3858              
3859 0 0       0 if($obj->{STATE_IN_DB()})
3860             {
3861 0         0 my %seen;
3862              
3863             @columns = $changes_only ?
3864 0         0 (map { $self->column($_) } grep { !$seen{$_}++ }
  0         0  
3865             ($self->primary_key_column_names,
3866 0 0       0 keys %{$obj->{MODIFIED_COLUMNS()} || {}})) :
3867 0 0       0 (grep { (!$_->{'lazy'} || $obj->{LAZY_LOADED_KEY()}{$_->{'name'}}) }
  0 0       0  
3868             $self->columns_ordered);
3869              
3870 0         0 @names = map { $_->name_sql($db) } @columns;
  0         0  
3871             }
3872             else
3873             {
3874 0         0 my %skip;
3875              
3876 0         0 my @key_columns = $self->primary_key_column_names;
3877 0         0 my @key_methods = $self->primary_key_column_accessor_names;
3878 0         0 my @key_values = grep { defined } map { $obj->$_() } @key_methods;
  0         0  
  0         0  
3879              
3880 0 0       0 unless(@key_values)
3881             {
3882 0         0 @skip{@key_columns} = (1) x @key_columns;
3883             }
3884              
3885 0         0 foreach my $uk ($self->unique_keys)
3886             {
3887 0         0 @key_columns = $uk->columns;
3888 0         0 @key_methods = map { $_->accessor_method_name } @key_columns;
  0         0  
3889 0         0 @key_values = grep { defined } map { $obj->$_() } @key_methods;
  0         0  
  0         0  
3890              
3891 0 0       0 unless(@key_values)
3892             {
3893 0         0 @skip{@key_columns} = (1) x @key_columns;
3894             }
3895             }
3896              
3897             @columns = $changes_only ?
3898 0 0       0 (map { $self->column($_) } grep { !$skip{"$_"} } keys %{$obj->{MODIFIED_COLUMNS()} || {}}) :
  0         0  
  0         0  
3899 0 0       0 (grep { !$skip{"$_"} && (!$_->{'lazy'} ||
3900 0 0 0     0 $obj->{LAZY_LOADED_KEY()}{$_->{'name'}}) } $self->columns_ordered);
3901              
3902 0         0 @names = map { $_->name_sql($db) } @columns;
  0         0  
3903             }
3904              
3905 0         0 my(@bind, @places, @bind_params);
3906              
3907 0         0 foreach my $column (@columns)
3908             {
3909 0         0 my $name = $column->{'name'};
3910 0         0 my $method = $self->column_accessor_method_name($name);
3911 0         0 my $value = $obj->$method();
3912              
3913 0 0       0 if($column->should_inline_value($db, $value))
3914             {
3915 0         0 push(@places, [ $name, $column->inline_value_sql($value) ]);
3916             }
3917             else
3918             {
3919 0         0 push(@places, [ $name, $column->insert_placeholder_sql($_) ]);
3920 0         0 push(@bind, $value);
3921              
3922 0 0       0 if($do_bind_params)
3923             {
3924 0         0 push(@bind_params, $column->dbi_bind_param_attrs($db));
3925             }
3926             }
3927             }
3928              
3929 61     61   594 no warnings;
  61         184  
  61         179545  
3930             return
3931             'INSERT INTO ' . $self->fq_table_sql($db) . "\n(\n" .
3932             join(",\n", @names) .
3933 0         0 "\n)\nVALUES\n(\n" . join(",\n", map { $_->[1] } @places) . "\n)\n" .
3934             "ON DUPLICATE KEY UPDATE\n" .
3935 0 0       0 join(",\n", map { "$_->[0] = $_->[1]" } @places),
  0         0  
3936             [ @bind, @bind ],
3937             ($do_bind_params ? \@bind_params : ());
3938             }
3939              
3940             sub insert_changes_only_sql_with_inlining
3941             {
3942 0     0 0 0 my($self, $obj) = @_;
3943              
3944 0 0       0 my $db = $obj->db or Carp::croak "Missing db";
3945              
3946 0   0     0 my $modified = $obj->{MODIFIED_COLUMNS()} || {};
3947 0 0       0 my @modified = grep { $modified->{$_->{'name'}} || $_->default_exists } $self->columns_ordered;
  0         0  
3948              
3949 0 0       0 unless(@modified)
3950             {
3951             # Make a last-ditch attempt to insert with no modified columns
3952             # using the DEFAULT keyword on an arbitrary column. This works
3953             # in MySQL and PostgreSQL.
3954 0 0       0 if($db->supports_arbitrary_defaults_on_insert)
3955             {
3956             return
3957 0         0 'INSERT INTO ' . $self->fq_table_sql($db) . ' (' .
3958             ($self->columns_ordered)[-1]->name_sql($db) . ') VALUES (DEFAULT)',
3959             [];
3960             }
3961             else
3962             {
3963 0         0 Carp::croak "Cannot insert row into table '", $self->table,
3964             "' - No columns have modified or default values";
3965             }
3966             }
3967              
3968 0         0 my(@bind, @places, @bind_params);
3969              
3970 0         0 my $do_bind_params = $self->dbi_requires_bind_param($db);
3971              
3972 0         0 foreach my $column (@modified)
3973             {
3974 0         0 my $method = $self->column_accessor_method_name($column->name);
3975 0         0 my $value = $obj->$method();
3976              
3977 0 0       0 if($column->should_inline_value($db, $value))
3978             {
3979 0         0 push(@places, " $value");
3980             }
3981             else
3982             {
3983 0         0 push(@places, $column->insert_placeholder_sql($db));
3984 0         0 push(@bind, $value);
3985              
3986 0 0       0 if($do_bind_params)
3987             {
3988 0         0 push(@bind_params, $column->dbi_bind_param_attrs($db));
3989             }
3990             }
3991             }
3992              
3993             return
3994             (
3995             'INSERT INTO ' . $self->fq_table_sql($db) . "\n(\n" .
3996 0 0       0 join(",\n", map { $_->name_sql($db) } @modified) .
  0         0  
3997             "\n)\nVALUES\n(\n" . join(",\n", @places) . "\n)",
3998             \@bind,
3999             ($do_bind_params ? \@bind_params : ())
4000             );
4001             }
4002              
4003             sub delete_sql
4004             {
4005 0     0 0 0 my($self, $db) = @_;
4006             return $self->{'delete_sql'}{$db->{'id'}} ||=
4007             'DELETE FROM ' . $self->fq_table_sql($db) . ' WHERE ' .
4008             join(' AND ',
4009 0   0     0 map { $_->name_sql($db) . ' = ' . $_->query_placeholder_sql($db) }
  0         0  
4010             $self->primary_key_columns);
4011             }
4012              
4013             sub get_column_value
4014             {
4015 0     0 0 0 my($self, $object, $column) = @_;
4016              
4017 0 0       0 my $db = $object->db or Carp::confess $object->error;
4018 0 0       0 my $dbh = $db->dbh or Carp::confess $db->error;
4019              
4020 0   0     0 my $sql = $self->{'get_column_sql_tmpl'}{$db->{'id'}} ||
4021             $self->init_get_column_sql_tmpl($db);
4022              
4023 0         0 $sql =~ s/__COLUMN__/$column->name_sql($db)/e;
  0         0  
4024              
4025             my @key_values =
4026 0         0 map { $object->$_() }
4027 0         0 map { $self->column_accessor_method_name($_) }
  0         0  
4028             $self->primary_key_column_names;
4029              
4030 0         0 my($value, $error);
4031              
4032             TRY:
4033             {
4034 0         0 local $@;
  0         0  
4035              
4036             eval
4037 0         0 {
4038 0 0 0     0 ($Debug || $Rose::DB::Object::Debug) && warn "$sql (@key_values)\n";
4039 0         0 my $sth = $dbh->prepare($sql);
4040 0         0 $sth->execute(@key_values);
4041 0         0 $sth->bind_columns(\$value);
4042 0         0 $sth->fetch;
4043             };
4044              
4045 0         0 $error = $@;
4046             }
4047              
4048 0 0       0 if($error)
4049             {
4050 0         0 Carp::croak "Could not lazily-load column value for column '",
4051             $column->name, "' - $error";
4052             }
4053              
4054 0         0 return $value;
4055             }
4056              
4057             sub init_get_column_sql_tmpl
4058             {
4059 0     0 0 0 my($self, $db) = @_;
4060              
4061 0         0 my $key_columns = $self->primary_key_column_names;
4062 0         0 my %key = map { ($_ => 1) } @$key_columns;
  0         0  
4063              
4064             return $self->{'get_column_sql_tmpl'}{$db->{'id'}} =
4065             'SELECT __COLUMN__ FROM ' . $self->fq_table_sql($db) . ' WHERE ' .
4066             join(' AND ', map
4067             {
4068 0         0 my $c = $self->column($_);
  0         0  
4069 0         0 $c->name_sql($db) . ' = ' . $c->query_placeholder_sql($db)
4070             }
4071             @$key_columns);
4072             }
4073              
4074             sub refresh_lazy_column_tracking
4075             {
4076 77     77 0 153 my($self) = shift;
4077              
4078 77         216 $self->_clear_column_generated_values;
4079              
4080             # Initialize method name hashes
4081 77         240 $self->column_accessor_method_names;
4082 77         249 $self->column_mutator_method_names;
4083 77         231 $self->column_rw_method_names;
4084              
4085 77         193 return $self->{'has_lazy_columns'} = grep { $_->lazy } $self->columns_ordered;
  183         1001  
4086             }
4087              
4088             sub has_lazy_columns
4089             {
4090 0     0 0 0 my($self) = shift;
4091 0 0       0 return $self->{'has_lazy_columns'} if(defined $self->{'has_lazy_columns'});
4092 0         0 return $self->{'has_lazy_columns'} = grep { $_->lazy } $self->columns_ordered;
  0         0  
4093             }
4094              
4095             sub prime_all_caches
4096             {
4097 0     0 1 0 my($class) = shift;
4098              
4099 0         0 foreach my $obj_class ($class->registered_classes)
4100             {
4101 0         0 $obj_class->meta->prime_caches(@_);
4102             }
4103             }
4104              
4105             sub prime_caches
4106             {
4107 0     0 1 0 my($self, %args) = @_;
4108              
4109 0         0 my @methods =
4110             qw(column_names num_columns nonlazy_column_names lazy_column_names
4111             column_rw_method_names column_accessor_method_names
4112             nonlazy_column_accessor_method_names column_mutator_method_names
4113             nonlazy_column_mutator_method_names nonlazy_column_db_value_hash_keys
4114             primary_key_column_db_value_hash_keys column_db_value_hash_keys
4115             column_accessor_method_names column_mutator_method_names
4116             column_rw_method_names key_column_accessor_method_names_hash);
4117              
4118 0         0 foreach my $method (@methods)
4119             {
4120 0         0 $self->$method();
4121             }
4122              
4123 0   0     0 my $db = $args{'db'} || $self->class->init_db;
4124              
4125 0         0 $self->method_column('nonesuch');
4126 0         0 $self->fq_primary_key_sequence_names(db => $db);
4127              
4128 0         0 @methods =
4129             qw(dbi_requires_bind_param fq_table fq_table_sql init_get_column_sql_tmpl
4130             delete_sql primary_key_sequence_names insert_sql
4131             init_insert_sql_with_inlining_start
4132             init_insert_changes_only_sql_prefix init_update_sql_prefix
4133             init_update_sql_with_inlining_start column_names_string_sql
4134             nonlazy_column_names_string_sql select_nonlazy_columns_string_sql
4135             select_columns_string_sql select_columns_sql select_nonlazy_columns_sql);
4136              
4137 0         0 foreach my $method (@methods)
4138             {
4139 0         0 $self->$method($db);
4140             }
4141              
4142 0         0 undef @methods; # reclaim memory?
4143              
4144 0         0 foreach my $key ($self->primary_key, $self->unique_keys)
4145             {
4146 0         0 foreach my $method (qw(update_all_sql load_sql load_all_sql))
4147             {
4148 0         0 $self->$method(scalar $key->columns, $db);
4149             }
4150             }
4151             }
4152              
4153             sub _clear_table_generated_values
4154             {
4155 5     5   15 my($self) = shift;
4156              
4157 5         17 $self->{'fq_table'} = undef;
4158 5         15 $self->{'fq_table_sql'} = undef;
4159 5         14 $self->{'get_column_sql_tmpl'} = undef;
4160 5         16 $self->{'load_sql'} = undef;
4161 5         14 $self->{'load_all_sql'} = undef;
4162 5         15 $self->{'delete_sql'} = undef;
4163 5         15 $self->{'fq_primary_key_sequence_names'} = undef;
4164 5         12 $self->{'primary_key_sequence_names'} = undef;
4165 5         13 $self->{'insert_sql'} = undef;
4166 5         15 $self->{'insert_sql_with_inlining_start'} = undef;
4167 5         14 $self->{'insert_changes_only_sql_prefix'} = undef;
4168 5         14 $self->{'update_sql_prefix'} = undef;
4169 5         15 $self->{'update_sql_with_inlining_start'} = undef;
4170 5         15 $self->{'update_all_sql'} = undef;
4171             }
4172              
4173             sub _clear_column_generated_values
4174             {
4175 316     316   513 my($self) = shift;
4176              
4177 316         614 $self->{'fq_table'} = undef;
4178 316         487 $self->{'fq_table_sql'} = undef;
4179 316         693 $self->{'column_names'} = undef;
4180 316         477 $self->{'num_columns'} = undef;
4181 316         475 $self->{'nonlazy_column_names'} = undef;
4182 316         485 $self->{'lazy_column_names'} = undef;
4183 316         502 $self->{'column_names_sql'} = undef;
4184 316         533 $self->{'get_column_sql_tmpl'} = undef;
4185 316         484 $self->{'column_names_string_sql'} = undef;
4186 316         545 $self->{'nonlazy_column_names_string_sql'} = undef;
4187 316         566 $self->{'column_rw_method_names'} = undef;
4188 316         491 $self->{'column_accessor_method_names'} = undef;
4189 316         486 $self->{'nonlazy_column_accessor_method_names'} = undef;
4190 316         520 $self->{'column_mutator_method_names'} = undef;
4191 316         492 $self->{'nonlazy_column_mutator_method_names'} = undef;
4192 316         463 $self->{'nonlazy_column_db_value_hash_keys'} = undef;
4193 316         516 $self->{'primary_key_column_db_value_hash_keys'}= undef;
4194 316         506 $self->{'primary_key_column_names_or_aliases'} = undef;
4195 316         417 $self->{'column_db_value_hash_keys'} = undef;
4196 316         465 $self->{'select_nonlazy_columns_string_sql'} = undef;
4197 316         462 $self->{'select_columns_string_sql'} = undef;
4198 316         623 $self->{'select_columns_sql'} = undef;
4199 316         531 $self->{'select_nonlazy_columns_sql'} = undef;
4200 316         472 $self->{'method_columns'} = undef;
4201 316         557 $self->{'column_accessor_method'} = undef;
4202 316         561 $self->{'key_column_accessor_method'} = undef;
4203 316         588 $self->{'column_rw_method'} = undef;
4204 316         528 $self->{'load_sql'} = undef;
4205 316         425 $self->{'load_all_sql'} = undef;
4206 316         484 $self->{'update_all_sql'} = undef;
4207 316         561 $self->{'update_sql_prefix'} = undef;
4208 316         429 $self->{'insert_sql'} = undef;
4209 316         449 $self->{'insert_sql_with_inlining_start'} = undef;
4210 316         425 $self->{'update_sql_with_inlining_start'} = undef;
4211 316         462 $self->{'insert_changes_only_sql_prefix'} = undef;
4212 316         405 $self->{'delete_sql'} = undef;
4213 316         432 $self->{'insert_columns_placeholders_sql'} = undef;
4214 316         518 $self->{'dbi_requires_bind_param'} = undef;
4215 316         521 $self->{'key_column_names'} = undef;
4216             }
4217              
4218             sub _clear_nonpersistent_column_generated_values
4219             {
4220 76     76   151 my($self) = shift;
4221              
4222 76         156 $self->{'nonpersistent_column_names'} = undef;
4223 76         152 $self->{'nonpersistent_column_accessor_method_names'} = undef;
4224 76         151 $self->{'nonpersistent_column_accessor_method'} = undef;
4225 76         164 $self->{'nonpersistent_column_mutator_method_names'} = undef;
4226 76         148 $self->{'nonpersistent_column_mutator_method'} = undef;
4227             }
4228              
4229             sub _clear_primary_key_column_generated_values
4230             {
4231 84     84   143 my($self) = shift;
4232 84         206 $self->{'primary_key_column_accessor_names'} = undef;
4233 84         199 $self->{'primary_key_column_mutator_names'} = undef;
4234 84         157 $self->{'key_column_accessor_method'} = undef;
4235 84         135 $self->{'primary_key_column_names_or_aliases'} = undef;
4236 84         176 $self->{'key_column_names'} = undef;
4237             }
4238              
4239             sub method_name_is_reserved
4240             {
4241 392     392 1 735 my($self, $name, $class) = @_;
4242              
4243 392 50 33     905 if(!defined $class && UNIVERSAL::isa($self, __PACKAGE__))
4244             {
4245 0 0 0     0 $class ||= $self->class or die "Missing class!";
4246             }
4247              
4248 392 50       702 Carp::confess "Missing method name argument in call to method_name_is_reserved()"
4249             unless(defined $name);
4250              
4251 392 50 33     5134 if(index($name, PRIVATE_PREFIX) == 0)
    100 66        
4252             {
4253 0         0 return "The method prefix '", PRIVATE_PREFIX, "' is reserved."
4254             }
4255             elsif($name =~ /^(?:meta|dbh?|_?init_db|error|not_found|load|save|update|insert|delete|DESTROY)$/ ||
4256             ($class->isa('Rose::DB::Object::Cached') && $name =~ /^(?:remember|forget(?:_all)?)$/))
4257             {
4258 1         6 return "This method name is reserved for use by the $class API."
4259             }
4260              
4261 391         1007 return 0;
4262             }
4263              
4264             sub method_name_from_column_name
4265             {
4266 194     194 1 426 my($self, $column_name, $method_type) = @_;
4267              
4268 194 50 33     501 my $column = $self->column($column_name) || $self->nonpersistent_column($column_name)
4269             or Carp::confess "No such column: $column_name";
4270              
4271 194         518 return $self->method_name_from_column($column, $method_type);
4272             }
4273              
4274             sub method_name_from_column
4275             {
4276 194     194 1 387 my($self, $column, $method_type) = @_;
4277              
4278 194         567 my $default_name = $column->build_method_name_for_type($method_type);
4279              
4280 194   66     559 my $method_name =
4281             $column->method_name($method_type) ||
4282             $self->convention_manager->auto_column_method_name($method_type, $column, $default_name, $self->class) ||
4283             $default_name;
4284              
4285 194 50       578 if(my $code = $self->column_name_to_method_name_mapper)
4286             {
4287 0         0 my $column_name = $column->name;
4288 0         0 local $_ = $method_name;
4289 0         0 $method_name = $code->($self, $column_name, $method_type, $method_name);
4290              
4291 0 0       0 unless(defined $method_name)
4292             {
4293 0         0 Carp::croak "column_name_to_method_name_mapper() returned undef ",
4294             "for column name '$column_name' method type '$method_type'"
4295             }
4296             }
4297              
4298 194         1773 return $method_name;
4299             }
4300              
4301             sub dbi_requires_bind_param
4302             {
4303 0     0 0 0 my($self, $db) = @_;
4304              
4305             return $self->{'dbi_requires_bind_param'}{$db->{'id'}}
4306 0 0       0 if(defined $self->{'dbi_requires_bind_param'}{$db->{'id'}});
4307              
4308 0         0 foreach my $column ($self->columns_ordered)
4309             {
4310 0 0       0 if($column->dbi_requires_bind_param($db))
4311             {
4312 0         0 return $self->{'dbi_requires_bind_param'}{$db->{'id'}} = 1;
4313             }
4314             }
4315              
4316 0         0 return $self->{'dbi_requires_bind_param'}{$db->{'id'}} = 0;
4317             }
4318              
4319             sub make_manager_class
4320             {
4321 2     2 1 5 my($self) = shift;
4322              
4323 2         4 my $error;
4324              
4325             TRY:
4326             {
4327 2         3 local $@;
  2         5  
4328 2     2   5 eval { eval $self->perl_manager_class(@_) };
  2         8  
  2         647  
  2         7  
  2         81  
4329 2         42 $error = $@;
4330             }
4331              
4332 2 100       8 if($error)
4333             {
4334 1         5 Carp::croak "Could not make manager class - $error\nThe Perl code used was:\n\n",
4335             $self->perl_manager_class(@_);
4336             }
4337             }
4338              
4339             sub perl_manager_class
4340             {
4341 4     4 1 11 my($self) = shift;
4342              
4343 3         6 my %args;
4344              
4345 3 50       10 if(@_ == 1)
4346             {
4347 0         0 $args{'base_name'} = shift;
4348             }
4349             else
4350             {
4351 3         8 %args = @_;
4352             }
4353              
4354 3   33     19 $args{'base_name'} ||= $self->convention_manager->auto_manager_base_name;
4355 3   33     38 $args{'class'} ||= $self->convention_manager->auto_manager_class_name;
4356              
4357 3 50       32 unless($args{'class'} =~ /^\w+(?:::\w+)*$/)
4358             {
4359 61     61   768 no warnings;
  61         169  
  61         14382  
4360             Carp::croak "Missing or invalid class",
4361 0 0       0 (length $args{'class'} ? ": '$args{'class'}'" : '');
4362             }
4363              
4364 3 50       7 unless($args{'isa'})
4365             {
4366 3         20 my @def = $self->default_manager_base_class; # may return multiple classes
4367 3 50 33     20 $args{'isa'} = (@def == 1 && ref $def[0]) ? $def[0] : \@def;
4368             }
4369              
4370 3 50       12 $args{'isa'} = [ $args{'isa'} ] unless(ref $args{'isa'});
4371              
4372 3         5 my($isa, $ok);
4373              
4374 3         5 foreach my $class (@{$args{'isa'}})
  3         10  
4375             {
4376 3 50       16 unless($class =~ /^\w+(?:::\w+)*$/)
4377             {
4378 61     61   562 no warnings;
  61         159  
  61         3315  
4379 0         0 Carp::croak "Invalid isa class: '$class'";
4380             }
4381              
4382 61     61   440 no strict 'refs';
  61         158  
  61         10141  
4383 3 100 66     9 $isa .= "use $class;\n" unless($class !~ /^Rose::DB::/ && %{"${class}::"});
  3         25  
4384              
4385 3 100       20 $ok = 1 if(UNIVERSAL::isa($class, 'Rose::DB::Object::Manager'));
4386             }
4387              
4388 3 100       9 unless($ok)
4389             {
4390             Carp::croak
4391             "None of these classes inherit from Rose::DB::Object::Manager: ",
4392 2         4 join(', ', @{$args{'isa'}});
  2         334  
4393             }
4394              
4395 1         3 $isa .= "our \@ISA = qw(@{$args{'isa'}});";
  1         5  
4396              
4397 61     61   532 no strict 'refs';
  61         164  
  61         35173  
4398 1 50       3 if(@{"$args{'class'}::ISA"})
  1         12  
4399             {
4400 0         0 Carp::croak "Can't override class $args{'class'} which already ",
4401             "appears to be defined.";
4402             }
4403              
4404 1         5 my $object_class = $self->class;
4405              
4406 1         169 return<<"EOF";
4407             package $args{'class'};
4408              
4409             use strict;
4410              
4411             $isa
4412              
4413             sub object_class { '$object_class' }
4414              
4415             __PACKAGE__->make_manager_methods('$args{'base_name'}');
4416              
4417             1;
4418             EOF
4419             }
4420              
4421             #
4422             # Automatic metadata setup
4423             #
4424              
4425             our $AUTOLOAD;
4426              
4427       0     sub DESTROY { }
4428              
4429             sub AUTOLOAD
4430             {
4431 0 0   0   0 if($AUTOLOAD =~ /::((?:auto_(?!helper)|(?:default_)?perl_)\w*)$/)
4432             {
4433 0         0 my $method = $1;
4434 0         0 my $self = shift;
4435 0         0 $self->init_auto_helper;
4436              
4437 0 0       0 unless($self->can($method))
4438             {
4439 0         0 Carp::croak "No such method '$method' in class ", ref($self);
4440             }
4441              
4442 0         0 return $self->$method(@_);
4443             }
4444              
4445 0         0 Carp::confess "No such method: $AUTOLOAD";
4446             }
4447              
4448             sub auto_helper_class
4449             {
4450 2     2 0 5 my($self) = shift;
4451              
4452 2 50       6 if(@_)
4453             {
4454 0         0 my $driver = lc shift;
4455 0 0       0 return $self->auto_helper_classes->{$driver} = shift if(@_);
4456 0         0 return $self->auto_helper_classes->{$driver};
4457             }
4458             else
4459             {
4460 2 50       7 my $db = $self->db or die "Missing db";
4461             return $self->auto_helper_classes->{$db->driver} ||
4462 2   0     16 $self->auto_helper_classes->{'generic'} ||
4463             Carp::croak "Don't know how to auto-initialize using driver '",
4464             $db->driver, "'";
4465             }
4466             }
4467              
4468             my %Rebless;
4469              
4470             sub init_auto_helper
4471             {
4472 1     1 0 26 my($self) = shift;
4473              
4474 1 50       7 unless($self->isa($self->auto_helper_class))
4475             {
4476 1   33     62 my $class = ref($self) || $self;
4477              
4478 1         4 my $auto_helper_class = $self->auto_helper_class;
4479              
4480 61     61   594 no strict 'refs';
  61         202  
  61         11658  
4481 1 50       14 unless(@{"${auto_helper_class}::ISA"})
  1         11  
4482             {
4483 1         2 my $error;
4484              
4485             TRY:
4486             {
4487 1         2 local $@;
  1         3  
4488 1         101 eval "use $auto_helper_class";
4489 1         4 $error = $@;
4490             }
4491              
4492 1 50       6 Carp::croak "Could not load '$auto_helper_class' - $error" if($error);
4493             }
4494              
4495 1         8 $self->original_class($class);
4496              
4497             REBLESS: # Do slightly evil re-blessing magic
4498             {
4499             # Check cache
4500 1 50       6 if(my $new_class = $Rebless{$class,$auto_helper_class})
  1         7  
4501             {
4502 0         0 bless $self, $new_class;
4503             }
4504             else
4505             {
4506             # Special, simple case for Rose::DB::Object::Metadata
4507 1 50       3 if($class eq __PACKAGE__)
4508             {
4509 0         0 bless $self, $auto_helper_class;
4510             }
4511             else # Handle Rose::DB::Object::Metadata subclasses
4512             {
4513             # If this is a default Rose::DB driver class
4514 1 50       5 if(index($auto_helper_class, 'Rose::DB::') == 0)
4515             {
4516             # Make a new metadata class based on the current class
4517 1         4 my $new_class = $class . '::__RoseDBObjectMetadataPrivate__::' . $auto_helper_class;
4518              
4519             # Pull all the auto-helper's methods up into the new class,
4520             # unless they're already defined by the original class. This
4521             # is ugly, I know, but remember that it's all an implementation
4522             # detail that could change at any time :)
4523             IMPORT:
4524             {
4525 61     61   543 no strict 'refs';
  61         196  
  61         5959  
  1         2  
4526 1         4 local(*auto_symbol, *existing_symbol);
4527              
4528 1         2 while(my($name, $value) = each(%{"${auto_helper_class}::"}))
  12         59  
4529             {
4530 61     61   470 no warnings;
  61         155  
  61         12076  
4531              
4532 11 100       37 next if($name =~ /^[A-Z]+$/); # skip BEGIN, DESTROY, etc.
4533              
4534 8         17 *auto_symbol = $value;
4535 8         17 *existing_symbol = *{"${class}::$name"};
  8         34  
4536              
4537 8 100 66     29 if(defined &auto_symbol && !defined &existing_symbol)
4538             {
4539 3 50       11 $Debug && warn "IMPORT $name INTO $new_class FROM $auto_helper_class\n";
4540 3         6 *{"${new_class}::$name"} = \&auto_symbol;
  3         27  
4541             }
4542             }
4543             }
4544              
4545 61     61   552 no strict 'refs';
  61         221  
  61         19591  
4546 1         4 @{"${new_class}::ISA"} = ($class, $auto_helper_class);
  1         23  
4547              
4548 1         9 bless $self, $new_class;
4549             }
4550             else
4551             {
4552             # Otherwise use the (apparently custom) metadata class
4553 0         0 bless $self, $auto_helper_class;
4554             }
4555             }
4556              
4557             # Cache value
4558 1         6 $Rebless{$class,$auto_helper_class} = ref $self;
4559             }
4560             }
4561             }
4562              
4563 1         5 return 1;
4564             }
4565              
4566             sub map_record_method_key
4567             {
4568 1     1 0 13 my($self, $method) = (shift, shift);
4569              
4570 1 50       5 if(@_)
4571             {
4572 1         6 return $self->{'map_record_method_key'}{$method} = shift;
4573             }
4574              
4575 0         0 return $self->{'map_record_method_key'}{$method};
4576             }
4577              
4578             sub column_undef_overrides_default
4579             {
4580 297     297 1 456 my($self) = shift;
4581              
4582 297 50       555 if(@_)
4583             {
4584 0 0       0 return $self->{'column_undef_overrides_default'} = $_[0] ? 1 : 0;
4585             }
4586              
4587             return $self->{'column_undef_overrides_default'}
4588 297 50       625 if(defined $self->{'column_undef_overrides_default'});
4589              
4590 297         1064 return $self->{'column_undef_overrides_default'} = ref($self)->default_column_undef_overrides_default;
4591             }
4592              
4593             1;
4594              
4595             __END__
4596              
4597             =head1 NAME
4598              
4599             Rose::DB::Object::Metadata - Database object metadata.
4600              
4601             =head1 SYNOPSIS
4602              
4603             use Rose::DB::Object::Metadata;
4604              
4605             $meta = Rose::DB::Object::Metadata->new(class => 'Product');
4606             # ...or...
4607             $meta = Rose::DB::Object::Metadata->for_class('Product');
4608              
4609             #
4610             # Auto-initialization
4611             #
4612              
4613             $meta->table('products'); # optional if class name ends with "::Product"
4614             $meta->auto_initialize;
4615              
4616             #
4617             # ...or manual setup
4618             #
4619              
4620             $meta->setup
4621             (
4622             table => 'products',
4623              
4624             columns =>
4625             [
4626             id => { type => 'int', primary_key => 1 },
4627             name => { type => 'varchar', length => 255 },
4628             description => { type => 'text' },
4629             category_id => { type => 'int' },
4630              
4631             status =>
4632             {
4633             type => 'varchar',
4634             check_in => [ 'active', 'inactive' ],
4635             default => 'inactive',
4636             },
4637              
4638             start_date => { type => 'datetime' },
4639             end_date => { type => 'datetime' },
4640              
4641             date_created => { type => 'timestamp', default => 'now' },
4642             last_modified => { type => 'timestamp', default => 'now' },
4643             ],
4644              
4645             unique_key => 'name',
4646              
4647             foreign_keys =>
4648             [
4649             category =>
4650             {
4651             class => 'Category',
4652             key_columns =>
4653             {
4654             category_id => 'id',
4655             }
4656             },
4657             ],
4658              
4659             relationships =>
4660             [
4661             prices =>
4662             {
4663             type => 'one to many',
4664             class => 'Price',
4665             column_map => { id => 'id_product' },
4666             },
4667             ],
4668             );
4669              
4670             #
4671             # ...or even more verbose manual setup (old-style, not recommended)
4672             #
4673              
4674             $meta->table('products');
4675              
4676             $meta->columns
4677             (
4678             id => { type => 'int', primary_key => 1 },
4679             name => { type => 'varchar', length => 255 },
4680             description => { type => 'text' },
4681             category_id => { type => 'int' },
4682              
4683             status =>
4684             {
4685             type => 'varchar',
4686             check_in => [ 'active', 'inactive' ],
4687             default => 'inactive',
4688             },
4689              
4690             start_date => { type => 'datetime' },
4691             end_date => { type => 'datetime' },
4692              
4693             date_created => { type => 'timestamp', default => 'now' },
4694             last_modified => { type => 'timestamp', default => 'now' },
4695             );
4696              
4697             $meta->unique_key('name');
4698              
4699             $meta->foreign_keys
4700             (
4701             category =>
4702             {
4703             class => 'Category',
4704             key_columns =>
4705             {
4706             category_id => 'id',
4707             }
4708             },
4709             );
4710              
4711             $meta->relationships
4712             (
4713             prices =>
4714             {
4715             type => 'one to many',
4716             class => 'Price',
4717             column_map => { id => 'id_product' },
4718             },
4719             );
4720              
4721             ...
4722              
4723             =head1 DESCRIPTION
4724              
4725             L<Rose::DB::Object::Metadata> objects store information about a single table in a database: the name of the table, the names and types of columns, any foreign or unique keys, etc. These metadata objects are also responsible for supplying information to, and creating object methods for, the L<Rose::DB::Object>-derived objects to which they belong.
4726              
4727             L<Rose::DB::Object::Metadata> objects also store information about the L<Rose::DB::Object>s that front the database tables they describe. What might normally be thought of as "class data" for the L<Rose::DB::Object> is stored in the metadata object instead, in order to keep the method namespace of the L<Rose::DB::Object>-derived class uncluttered.
4728              
4729             L<Rose::DB::Object::Metadata> objects are per-class singletons; there is one L<Rose::DB::Object::Metadata> object for each L<Rose::DB::Object>-derived class. Metadata objects are almost never explicitly instantiated. Rather, there are automatically created and accessed through L<Rose::DB::Object>-derived objects' L<meta|Rose::DB::Object/meta> method.
4730              
4731             Once created, metadata objects can be populated manually or automatically. Both techniques are shown in the L<synopsis|/SYNOPSIS> above. The automatic mode works by asking the database itself for the information. There are some caveats to this approach. See the L<auto-initialization|/"AUTO-INITIALIZATION"> section for more information.
4732              
4733             L<Rose::DB::Object::Metadata> objects contain three categories of objects that are responsible for creating object methods in L<Rose::DB::Object>-derived classes: columns, foreign keys, and relationships.
4734              
4735             Column objects are subclasses of L<Rose::DB::Object::Metadata::Column>. They are intended to store as much information as possible about each column. The particular class of the column object created for a database column is determined by a L<mapping table|/column_type_classes>. The column class, in turn, is responsible for creating the accessor/mutator method(s) for the column. When it creates these methods, the column class can use (or ignore) any information stored in the column object.
4736              
4737             Foreign key objects are of the class L<Rose::DB::Object::Metadata::ForeignKey>. They store information about columns that refer to columns in other tables that are fronted by their own L<Rose::DB::Object>-derived classes. A foreign key object is responsible for creating accessor method(s) to fetch the foreign object from the foreign table.
4738              
4739             Relationship objects are subclasses of L<Rose::DB::Object::Metadata::Relationship>. They store information about a table's relationship to other tables that are fronted by their own L<Rose::DB::Object>-derived classes. The particular class of the relationship object created for each relationship is determined by a L<mapping table|/relationship_type_classes>. A relationship object is responsible for creating accessor method(s) to fetch the foreign objects from the foreign table.
4740              
4741             =head1 AUTO-INITIALIZATION
4742              
4743             Manual population of metadata objects can be tedious and repetitive. Nearly all of the information stored in a L<Rose::DB::Object::Metadata> object exists in the database in some form. It's reasonable to consider simply extracting this information from the database itself, rather than entering it all manually. This automatic metadata extraction and subsequent L<Rose::DB::Object::Metadata> object population is called "auto-initialization."
4744              
4745             The example of auto-initialization in the L<synopsis|/SYNOPSIS> above is the most succinct variant:
4746              
4747             $meta->auto_initialize;
4748              
4749             As you can read in the documentation for the L<auto_initialize|/auto_initialize> method, that's shorthand for individually auto-initializing each part of the metadata object: columns, the primary key, unique keys, and foreign keys. But this brevity comes at a price. There are many caveats to auto-initialization.
4750              
4751             =head2 Caveats
4752              
4753             =head3 Start-Up Cost
4754              
4755             In order to retrieve the information required for auto-initialization, a database connection must be opened and queries must be run. Sometimes these queries include complex joins. All of these queries must be successfully completed before the L<Rose::DB::Object>-derived objects that the L<Rose::DB::Object::Metadata> is associated with can be used.
4756              
4757             In an environment like L<mod_perl>, server start-up time is precisely when you want to do any expensive operations. But in a command-line script or other short-lived process, the overhead of auto-initializing many metadata objects may become prohibitive.
4758              
4759             Also, don't forget that auto-initialization requires a database connection. L<Rose::DB::Object>-derived objects can sometimes be useful even without a database connection (e.g., to temporarily store information that will never go into the database, or to synthesize data using object methods that have no corresponding database column). When using auto-initialization, this is not possible because the L<Rose::DB::Object>-derived class won't even load if auto-initialization fails because it could not connect to the database.
4760              
4761             =head3 Detail
4762              
4763             First, auto-initialization cannot generate information that exists only in the mind of the programmer. The most common example is a relationship between two database tables that is either ambiguous or totally unexpressed by the database itself.
4764              
4765             For example, if a foreign key constraint does not exist, the relationship between rows in two different tables cannot be extracted from the database, and therefore cannot be auto-initialized.
4766              
4767             Even within the realm of information that, by all rights, should be available in the database, there are limitations. Although there is a handy L<DBI> API for extracting metadata from databases, unfortunately, very few DBI drivers support it fully. Some don't support it at all. In almost all cases, some manual work is required to (often painfully) extract information from the database's "system tables" or "catalog."
4768              
4769             More troublingly, databases do not always provide all the metadata that a human could extract from the series of SQL statement that created the table in the first place. Sometimes, the information just isn't in the database to be extracted, having been lost in the process of table creation. Here's just one example. Consider this MySQL table definition:
4770              
4771             CREATE TABLE mytable
4772             (
4773             id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
4774             code CHAR(6),
4775             flag BOOLEAN NOT NULL DEFAULT 1,
4776             bits BIT(5) NOT NULL DEFAULT '00101',
4777             name VARCHAR(64)
4778             );
4779              
4780             Now look at the metadata that MySQL 4 stores internally for this table:
4781              
4782             mysql> describe mytable;
4783             +-------+------------------+------+-----+---------+----------------+
4784             | Field | Type | Null | Key | Default | Extra |
4785             +-------+------------------+------+-----+---------+----------------+
4786             | id | int(10) unsigned | | PRI | NULL | auto_increment |
4787             | code | varchar(6) | YES | | NULL | |
4788             | flag | tinyint(1) | | | 1 | |
4789             | bits | tinyint(1) | | | 101 | |
4790             | name | varchar(64) | YES | | NULL | |
4791             +-------+------------------+------+-----+---------+----------------+
4792              
4793             Note the following divergences from the "CREATE TABLE" statement.
4794              
4795             =over 4
4796              
4797             =item * B<The "code" column has changed from CHAR(6) to VARCHAR(6).> This is troublesome if you want the traditional semantics of a CHAR type, namely the padding with spaces of values that are less than the column length.
4798              
4799             =item * B<The "flag" column has changed from BOOLEAN to TINYINT(1).> The default accessor method created for boolean columns has value coercion and formatting properties that are important to this data type. The default accessor created for integer columns lacks these constraints. The metadata object has no way of knowing that "flag" was supposed to be a boolean column, and thus makes the wrong kind of accessor method. It is thus possible to store, say, a value of "7" in the "flag" column. Oops.
4800              
4801             =item * B<The "bits" column has changed from BIT(5) to TINYINT(1).> As in the case of the "flag" column above, this type change prevents the correct accessor method from being created. The default bitfield accessor method auto-inflates column values into L<Bit::Vector> objects, which provide convenient methods for bit manipulation. The default accessor created for integer columns does no such thing.
4802              
4803             =back
4804              
4805             Remember that the auto-initialization process can only consider the metadata actually stored in the database. It has no access to the original "create table" statement. Thus, the semantics implied by the original table definition are effectively lost.
4806              
4807             Again, this is just one example of the kind of detail that can be lost in the process of converting your table definition into metadata that is stored in the database. Admittedly, MySQL is perhaps the worst case-scenario, having a well-deserved reputation for disregarding the wishes of table definitions. (The use of implicit default values for "NOT NULL" columns is yet another example.)
4808              
4809             Thankfully, there is a solution to this dilemma. Remember that auto-initialization is actually a multi-step process hiding behind that single call to the L<auto_initialize|/auto_initialize> method. To correct the sins of the database, simply break the auto-initialization process into its components. For example, here's how to correctly auto-initialize the "mytable" example above:
4810              
4811             # Make a first pass at column setup
4812             $meta->auto_init_columns;
4813              
4814             # Account for inaccuracies in DBD::mysql's column info by
4815             # replacing incorrect column definitions with new ones.
4816              
4817             # Fix CHAR(6) column that shows up as VARCHAR(6)
4818             $meta->column(code => { type => 'char', length => 6 });
4819              
4820             # Fix BIT(5) column that shows up as TINYINT(1)
4821             $meta->column(bits => { type => 'bits', bits => 5, default => 101 });
4822              
4823             # Fix BOOLEAN column that shows up as TINYINT(1)
4824             $meta->column(flag => { type => 'boolean', default => 1 });
4825              
4826             # Do everything else
4827             $meta->auto_initialize;
4828              
4829             Note that L<auto_initialize|/auto_initialize> was called at the end. Without the C<replace_existing> parameter, this call will preserve any existing metadata, rather than overwriting it, so our "corrections" are safe.
4830              
4831             =head3 Maintenance
4832              
4833             The price of auto-initialization is eternal vigilance. "What does that mean? Isn't auto-initialization supposed to save time and effort?" Well, yes, but at a cost. In addition to the caveats described above, consider what happens when a table definition changes.
4834              
4835             "Ah ha!" you say, "My existing class will automatically pick up the changes the next time it's loaded! Auto-initialization at its finest!" But is it? What if you added a "NOT NULL" column with no default value? Yes, your existing auto-initialized class will pick up the change, but your existing code will no longer be able to L<save|Rose::DB::Object/save> one these objects. Or what if you're using MySQL and your newly added column is one of the types described above that requires manual tweaking in order to get the desired semantics. Will you always remember to make this change?
4836              
4837             Auto-initialization is not a panacea. Every time you make a change to your database schema, you must also revisit each affected L<Rose::DB::Object>-derived class to at least consider whether or not the metadata needs to be corrected or updated.
4838              
4839             The trade-off may be well worth it, but it's still something to think about. There is, however, a hybrid solution that might be even better. Continue on to the next section to learn more.
4840              
4841             =head2 Code Generation
4842              
4843             As described in the L<section above|/Caveats>, auto-initializing metadata at runtime by querying the database has many caveats. An alternate approach is to query the database for metadata just once, and then generate the equivalent Perl code which can be pasted directly into the class definition in place of the call to L<auto_initialize|/auto_initialize>.
4844              
4845             Like the auto-initialization process itself, perl code generation has a convenient wrapper method as well as separate methods for the individual parts. All of the perl code generation methods begin with "perl_", and they support some rudimentary code formatting options to help the code conform to you preferred style. Examples can be found with the documentation for each perl_* method.
4846              
4847             This hybrid approach to metadata population strikes a good balance between upfront effort and ongoing maintenance. Auto-generating the Perl code for the initial class definition saves a lot of tedious typing. From that point on, manually correcting and maintaining the definition is a small price to pay for the decreased start-up cost, the ability to use the class in the absence of a database connection, and the piece of mind that comes from knowing that your class is stable, and won't change behind your back in response to an "action at a distance" (i.e., a database schema update).
4848              
4849             =head1 CLASS METHODS
4850              
4851             =over 4
4852              
4853             =item B<auto_prime_caches [BOOL]>
4854              
4855             Get or set a boolean value that indicates whether or not the L<prime_caches|/prime_caches> method will be called from within the L<initialize|/initialize> method. The default is true if the C<MOD_PERL> environment variable (C<$ENV{'MOD_PERL'}>) is set to a true value, false otherwise.
4856              
4857             =item B<clear_all_dbs>
4858              
4859             Clears the L<db|/db> attribute of the metadata object for each L<registered class|/registered_classes>.
4860              
4861             =item B<column_type_class TYPE [, CLASS]>
4862              
4863             Given the column type string TYPE, return the name of the L<Rose::DB::Object::Metadata::Column>-derived class used to store metadata and create the accessor method(s) for columns of that type. If a CLASS is passed, the column type TYPE is mapped to CLASS. In both cases, the TYPE argument is automatically converted to lowercase.
4864              
4865             =item B<column_type_classes [MAP]>
4866              
4867             Get or set the hash that maps column type strings to the names of the L<Rose::DB::Object::Metadata::Column>-derived classes used to store metadata and create accessor method(s) for columns of that type.
4868              
4869             This hash is class data. If you want to modify it, I suggest making your own subclass of L<Rose::DB::Object::Metadata> and then setting that as the L<meta_class|Rose::DB::Object/meta_class> of your L<Rose::DB::Object> subclass.
4870              
4871             If passed MAP (a list of type/class pairs or a reference to a hash of the same) then MAP replaces the current column type mapping. Returns a list of type/class pairs (in list context) or a reference to the hash of type/class mappings (in scalar context).
4872              
4873             The default mapping of type names to class names is:
4874              
4875             scalar => Rose::DB::Object::Metadata::Column::Scalar
4876              
4877             char => Rose::DB::Object::Metadata::Column::Character
4878             character => Rose::DB::Object::Metadata::Column::Character
4879             varchar => Rose::DB::Object::Metadata::Column::Varchar
4880             varchar2 => Rose::DB::Object::Metadata::Column::Varchar
4881             nvarchar => Rose::DB::Object::Metadata::Column::Varchar
4882             nvarchar2 => Rose::DB::Object::Metadata::Column::Varchar
4883             string => Rose::DB::Object::Metadata::Column::Varchar
4884              
4885             text => Rose::DB::Object::Metadata::Column::Text
4886             blob => Rose::DB::Object::Metadata::Column::Blob
4887             bytea => Rose::DB::Object::Metadata::Column::Pg::Bytea
4888              
4889             bits => Rose::DB::Object::Metadata::Column::Bitfield
4890             bitfield => Rose::DB::Object::Metadata::Column::Bitfield
4891              
4892             bool => Rose::DB::Object::Metadata::Column::Boolean
4893             boolean => Rose::DB::Object::Metadata::Column::Boolean
4894              
4895             int => Rose::DB::Object::Metadata::Column::Integer
4896             integer => Rose::DB::Object::Metadata::Column::Integer
4897              
4898             tinyint => Rose::DB::Object::Metadata::Column::Integer
4899             smallint => Rose::DB::Object::Metadata::Column::Integer
4900             mediumint => Rose::DB::Object::Metadata::Column::Integer
4901              
4902             bigint => Rose::DB::Object::Metadata::Column::BigInt
4903            
4904             serial => Rose::DB::Object::Metadata::Column::Serial
4905             bigserial => Rose::DB::Object::Metadata::Column::BigSerial
4906              
4907             enum => Rose::DB::Object::Metadata::Column::Enum
4908              
4909             num => Rose::DB::Object::Metadata::Column::Numeric
4910             numeric => Rose::DB::Object::Metadata::Column::Numeric
4911             decimal => Rose::DB::Object::Metadata::Column::Numeric
4912             float => Rose::DB::Object::Metadata::Column::Float
4913             float8 => Rose::DB::Object::Metadata::Column::DoublePrecision
4914              
4915             'double precision' =>
4916             Rose::DB::Object::Metadata::Column::DoublePrecision
4917              
4918             time => Rose::DB::Object::Metadata::Column::Time
4919             interval => Rose::DB::Object::Metadata::Column::Interval
4920              
4921             date => Rose::DB::Object::Metadata::Column::Date
4922             datetime => Rose::DB::Object::Metadata::Column::Datetime
4923             timestamp => Rose::DB::Object::Metadata::Column::Timestamp
4924              
4925             timestamptz =>
4926             Rose::DB::Object::Metadata::Column::TimestampWithTimeZone
4927              
4928             'timestamp with time zone' =>
4929             Rose::DB::Object::Metadata::Column::TimestampWithTimeZone
4930              
4931             'datetime year to fraction' =>
4932             Rose::DB::Object::Metadata::Column::DatetimeYearToFraction
4933              
4934             'datetime year to fraction(1)' =>
4935             Rose::DB::Object::Metadata::Column::DatetimeYearToFraction1
4936              
4937             'datetime year to fraction(2)' =>
4938             Rose::DB::Object::Metadata::Column::DatetimeYearToFraction2
4939              
4940             'datetime year to fraction(3)' =>
4941             Rose::DB::Object::Metadata::Column::DatetimeYearToFraction3
4942              
4943             'datetime year to fraction(4)' =>
4944             Rose::DB::Object::Metadata::Column::DatetimeYearToFraction4
4945              
4946             'datetime year to fraction(5)' =>
4947             Rose::DB::Object::Metadata::Column::DatetimeYearToFraction5
4948              
4949             'timestamp with time zone' =>
4950             Rose::DB::Object::Metadata::Column::Timestamp
4951              
4952             'timestamp without time zone' =>
4953             Rose::DB::Object::Metadata::Column::Timestamp
4954              
4955             'datetime year to second' =>
4956             Rose::DB::Object::Metadata::Column::DatetimeYearToSecond
4957              
4958             'datetime year to minute' =>
4959             Rose::DB::Object::Metadata::Column::DatetimeYearToMinute
4960              
4961             'datetime year to month' =>
4962             Rose::DB::Object::Metadata::Column::DatetimeYearToMonth
4963              
4964             'epoch' => Rose::DB::Object::Metadata::Column::Epoch
4965             'epoch hires' => Rose::DB::Object::Metadata::Column::Epoch::HiRes
4966              
4967             array => Rose::DB::Object::Metadata::Column::Array
4968             set => Rose::DB::Object::Metadata::Column::Set
4969              
4970             chkpass => Rose::DB::Object::Metadata::Column::Pg::Chkpass
4971              
4972             =item B<column_type_names>
4973              
4974             Returns the list (in list context) or reference to an array (in scalar context) of registered column type names.
4975              
4976             =item B<convention_manager_class NAME [, CLASS]>
4977              
4978             Given the string NAME, return the name of the L<Rose::DB::Object::ConventionManager>-derived class L<mapped|/convention_manager_classes> to that name.
4979              
4980             If a CLASS is passed, then NAME is mapped to CLASS.
4981              
4982             =item B<convention_manager_classes [MAP]>
4983              
4984             Get or set the hash that maps names to L<Rose::DB::Object::ConventionManager>-derived class names.
4985              
4986             This hash is class data. If you want to modify it, I suggest making your own subclass of L<Rose::DB::Object::Metadata> and then setting that as the L<meta_class|Rose::DB::Object/meta_class> of your L<Rose::DB::Object> subclass.
4987              
4988             If passed MAP (a list of name/class pairs or a reference to a hash of the same) then MAP replaces the current mapping. Returns a list of name/class pairs (in list context) or a reference to the hash of name/class mappings (in scalar context).
4989              
4990             The default mapping of names to classes is:
4991              
4992             default => Rose::DB::Object::ConventionManager
4993             null => Rose::DB::Object::ConventionManager::Null
4994              
4995             =item B<dbi_prepare_cached [BOOL]>
4996              
4997             Get or set a boolean value that indicates whether or not the L<Rose::DB::Object>-derived L<class|/class> will use L<DBI>'s L<prepare_cached|DBI/prepare_cached> method by default (instead of the L<prepare|DBI/prepare> method) when L<loading|Rose::DB::Object/load>, L<saving|Rose::DB::Object/save>, and L<deleting|Rose::DB::Object/delete> objects. The default value is true.
4998              
4999             =item B<default_column_undef_overrides_default [BOOL]>
5000              
5001             Get or set the default value of the L<column_undef_overrides_default|/column_undef_overrides_default> attribute. Defaults to undef.
5002              
5003             =item B<default_manager_base_class [CLASS]>
5004              
5005             Get or set the default name of the base class used by this metadata class when generating a L<manager|Rose::DB::Object::Manager> classes. The default value is C<Rose::DB::Object::Manager>. See the C<default_manager_base_class()> L<object method|/OBJECT METHODS> to override this value for a specific metadata object.
5006              
5007             =item B<for_class CLASS>
5008              
5009             Returns (or creates, if needed) the single L<Rose::DB::Object::Metadata> object associated with CLASS, where CLASS is the name of a L<Rose::DB::Object>-derived class.
5010              
5011             =item B<init_column_name_to_method_name_mapper>
5012              
5013             This class method should return a reference to a subroutine that maps column names to method names, or false if it does not want to do any custom mapping. The default implementation returns zero (0).
5014              
5015             If defined, the subroutine should take four arguments: the metadata object, the column name, the column method type, and the method name that would be used if the mapper subroutine did not exist. It should return a method name.
5016              
5017             =item B<prime_all_caches [PARAMS]>
5018              
5019             Call L<prime_caches|/prime_caches> on all L<registered_classes|/registered_classes>, passing PARAMS to each call. PARAMS are name/value pairs. Valid parameters are:
5020              
5021             =over 4
5022              
5023             =item B<db DB>
5024              
5025             A L<Rose::DB>-derived object used to determine which data source the cached metadata will be generated on behalf of. (Each data source has its own set of cached metadata.) This parameter is optional. If it is not passed, then the L<Rose::DB>-derived object returned by the L<init_db|Rose::DB::Object/init_db> method for each L<class|/class> will be used instead.
5026              
5027             =back
5028              
5029             =item B<relationship_type_class TYPE>
5030              
5031             Given the relationship type string TYPE, return the name of the L<Rose::DB::Object::Metadata::Relationship>-derived class used to store metadata and create the accessor method(s) for relationships of that type.
5032              
5033             =item B<relationship_type_classes [MAP]>
5034              
5035             Get or set the hash that maps relationship type strings to the names of the L<Rose::DB::Object::Metadata::Relationship>-derived classes used to store metadata and create object methods fetch and/or manipulate objects from foreign tables.
5036              
5037             This hash is class data. If you want to modify it, I suggest making your own subclass of L<Rose::DB::Object::Metadata> and then setting that as the L<meta_class|Rose::DB::Object/meta_class> of your L<Rose::DB::Object> subclass.
5038              
5039             If passed MAP (a list of type/class pairs or a reference to a hash of the same) then MAP replaces the current relationship type mapping. Returns a list of type/class pairs (in list context) or a reference to the hash of type/class mappings (in scalar context).
5040              
5041             The default mapping of type names to class names is:
5042              
5043             'one to one' => Rose::DB::Object::Metadata::Relationship::OneToOne
5044             'one to many' => Rose::DB::Object::Metadata::Relationship::OneToMany
5045             'many to one' => Rose::DB::Object::Metadata::Relationship::ManyToOne
5046             'many to many' => Rose::DB::Object::Metadata::Relationship::ManyToMany
5047              
5048             =item B<registered_classes>
5049              
5050             Return a list (in list context) or reference to an array (in scalar context) of the names of all L<Rose::DB::Object>-derived classes registered under this metadata class's L<registry_key|/registry_key>.
5051              
5052             =item B<registry_key>
5053              
5054             Returns the string used to group L<Rose::DB::Object>-derived class names in the class registry. The default is "Rose::DB::Object::Metadata".
5055              
5056             =back
5057              
5058             =head1 CONSTRUCTOR
5059              
5060             =over 4
5061              
5062             =item B<new PARAMS>
5063              
5064             Returns (or creates, if needed) the single L<Rose::DB::Object::Metadata> associated with a particular L<Rose::DB::Object>-derived class, modifying or initializing it according to PARAMS, where PARAMS are name/value pairs.
5065              
5066             Any object method is a valid parameter name, but PARAMS I<must> include a value for the C<class> parameter, since that's how L<Rose::DB::Object::Metadata> objects are mapped to their corresponding L<Rose::DB::Object>-derived class.
5067              
5068             =back
5069              
5070             =head1 OBJECT METHODS
5071              
5072             =over 4
5073              
5074             =item B<add_column ARGS>
5075              
5076             This is an alias for the L<add_columns|/add_columns> method.
5077              
5078             =item B<add_columns ARGS>
5079              
5080             Add the columns specified by ARGS to the list of columns for the table. Returns the list of columns added in list context, or a reference to an array of columns added in scalar context. Columns can be specified in ARGS in several ways.
5081              
5082             If an argument is a subclass of L<Rose::DB::Object::Metadata::Column>, it is added as-is.
5083              
5084             If an argument is a plain scalar, it is taken as the name of a scalar column. A column object of the class returned by the method call C<$obj-E<gt>column_type_class('scalar')> is constructed and then added.
5085              
5086             Otherwise, only name/value pairs are considered, where the name is taken as the column name and the value must be a reference to a hash.
5087              
5088             If the hash contains the key "primary_key" with a true value, then the column is marked as a L<primary_key_member|Rose::DB::Object::Metadata::Column/is_primary_key_member> and the column name is added to the list of primary key columns by calling the L<add_primary_key_column|/add_primary_key_column> method with the column name as its argument.
5089              
5090             If the hash contains the key "alias", then the value of that key is used as the alias for the column. This is a shorthand equivalent to explicitly calling the L<alias_column|/alias_column> column method.
5091              
5092             If the hash contains the key "temp" and its value is true, then the column is actually added to the list of L<non-persistent columns|/nonpersistent_columns>.
5093              
5094             If the hash contains a key with the same name as a L<column trigger event type|Rose::DB::Object::Metadata::Column/TRIGGERS> (e.g., "on_set", "on_load", "inflate") then the value of that key must be a code reference or a reference to an array of code references, which will be L<added|Rose::DB::Object::Metadata::Column/add_trigger> to the list of the column's L<triggers|Rose::DB::Object::Metadata::Column/TRIGGERS> for the specified event type.
5095              
5096             If the hash contains the key "methods", then its value must be a reference to an array or a reference to a hash. The L<auto_method_types|Rose::DB::Object::Metadata::Column/auto_method_types> of the column are then set to the values of the referenced array, or the keys of the referenced hash. The values of the referenced hash are used to set the L<method_name|Rose::DB::Object::Metadata::Column/method_name> for their corresponding method types.
5097              
5098             If the hash contains the key "add_methods", then its value must be a reference to an array or a reference to a hash. The values of the referenced array or the keys of the referenced hash are added to the column's L<auto_method_types|Rose::DB::Object::Metadata::Column/auto_method_types>. The values of the referenced hash are used to set the L<method_name|Rose::DB::Object::Metadata::Column/method_name> for their corresponding method types.
5099              
5100             If the "methods" and "add_methods" keys are both set, a fatal error will occur.
5101              
5102             Then the L<column_type_class|/column_type_class> method is called with the value of the "type" hash key as its argument (or "scalar" if that key is missing), returning the name of a column class. Finally, a new column object of that class is constructed and is passed all the remaining pairs in the hash reference, along with the name and type of the column. That column object is then added to the list of columns.
5103              
5104             This is done until there are no more arguments to be processed, or until an argument does not conform to one of the required formats, in which case a fatal error occurs.
5105              
5106             Example:
5107              
5108             $meta->add_columns
5109             (
5110             # Add a scalar column
5111             'name',
5112              
5113             # which is roughly equivalent to:
5114             #
5115             # $class = $meta->column_type_class('scalar');
5116             # $col = $class->new(name => 'name');
5117             # (then add $col to the list of columns)
5118              
5119             # Add by name/hashref pair with explicit method types
5120             age => { type => 'int', default => 5, methods => [ 'get', 'set' ] },
5121              
5122             # which is roughly equivalent to:
5123             #
5124             # $class = $meta->column_type_class('int');
5125             # $col = $class->new(name => 'age',
5126             # type => 'int',
5127             # default => 5);
5128             # $col->auto_method_types('get', 'set');
5129             # (then add $col to the list of columns)
5130              
5131             # Add by name/hashref pair with additional method type and name
5132             size => { type => 'int', add_methods => { 'set' => 'set_my_size' } },
5133              
5134             # which is roughly equivalent to:
5135             #
5136             # $class = $meta->column_type_class('int');
5137             # $col = $class->new(name => 'size',
5138             # type => 'int',);
5139             # $col->add_auto_method_types('set');
5140             # $col->method_name(set => 'set_my_size');
5141             # (then add $col to the list of columns)
5142              
5143             # Add a column object directly
5144             Rose::DB::Object::Metadata::Column::Date->new(
5145             name => 'start_date'),
5146             );
5147              
5148             =item B<add_nonpersistent_column ARGS>
5149              
5150             This is an alias for the L<add_nonpersistent_columns|/add_nonpersistent_columns> method.
5151              
5152             =item B<add_nonpersistent_columns ARGS>
5153              
5154             This method behaves like the L<add_columns|/add_columns> method, except that it adds to the list of L<non-persistent columns|/nonpersistent_columns>. See the documentation for the L<nonpersistent_columns|/nonpersistent_columns> method for more information.
5155              
5156             =item B<add_foreign_keys ARGS>
5157              
5158             Add foreign keys as specified by ARGS. Each foreign key must have a L<name|Rose::DB::Object::Metadata::ForeignKey/name> that is unique among all other foreign keys in this L<class|/class>.
5159              
5160             Foreign keys can be specified in ARGS in several ways.
5161              
5162             If an argument is a L<Rose::DB::Object::Metadata::ForeignKey> object (or subclass thereof), it is added as-is.
5163              
5164             Otherwise, only name/value pairs are considered, where the name is taken as the foreign key name and the value must be a reference to a hash.
5165              
5166             If the hash contains the key "methods", then its value must be a reference to an array or a reference to a hash. The L<auto_method_types|Rose::DB::Object::Metadata::ForeignKey/auto_method_types> of the foreign key are then set to the values of the referenced array, or the keys of the referenced hash. The values of the referenced hash are used to set the L<method_name|Rose::DB::Object::Metadata::ForeignKey/method_name> for their corresponding method types.
5167              
5168             If the hash contains the key "add_methods", then its value must be a reference to an array or a reference to a hash. The values of the referenced array or the keys of the referenced hash are added to the foreign key's L<auto_method_types|Rose::DB::Object::Metadata::ForeignKey/auto_method_types>. The values of the referenced hash are used to set the L<method_name|Rose::DB::Object::Metadata::ForeignKey/method_name> for their corresponding method types.
5169              
5170             If the "methods" and "add_methods" keys are both set, a fatal error will occur.
5171              
5172             A new L<Rose::DB::Object::Metadata::ForeignKey> object is constructed and is passed all the remaining pairs in the hash reference, along with the name of the foreign key as the value of the "name" parameter. That foreign key object is then added to the list of foreign keys.
5173              
5174             This is done until there are no more arguments to be processed, or until an argument does not conform to one of the required formats, in which case a fatal error occurs.
5175              
5176             Example:
5177              
5178             $meta->add_foreign_keys
5179             (
5180             # Add by name/hashref pair with explicit method type
5181             category =>
5182             {
5183             class => 'Category',
5184             key_columns => { category_id => 'id' },
5185             methods => [ 'get' ],
5186             },
5187              
5188             # which is roughly equivalent to:
5189             #
5190             # $fk = Rose::DB::Object::Metadata::ForeignKey->new(
5191             # class => 'Category',
5192             # key_columns => { category_id => 'id' },
5193             # name => 'category');
5194             # $fk->auto_method_types('get');
5195             # (then add $fk to the list of foreign keys)
5196              
5197             # Add by name/hashref pair with additional method type and name
5198             color =>
5199             {
5200             class => 'Color',
5201             key_columns => { color_id => 'id' },
5202             add_methods => { set => 'set_my_color' },
5203             },
5204              
5205             # which is roughly equivalent to:
5206             #
5207             # $fk = Rose::DB::Object::Metadata::ForeignKey->new(
5208             # class => 'Color',
5209             # key_columns => { color_id => 'id' },
5210             # name => 'color');
5211             # $fk->add_auto_method_types('set');
5212             # $fk->method_name(set => 'set_my_color');
5213             # (then add $fk to the list of foreign keys)
5214              
5215             # Add a foreign key object directly
5216             Rose::DB::Object::Metadata::ForeignKey->new(...),
5217             );
5218              
5219             For each foreign key added, a corresponding relationship with the same name is added if it does not already exist. The relationship type is determined by the value of the foreign key object's L<relationship|Rose::DB::Object::Metadata::ForeignKey/relationship_type> attribute. The default is "many to one". The class of the relationship is chosen by calling L<relationship_type_class|/relationship_type_class> with the relationship type as an argument.
5220              
5221             =item B<add_primary_key_column COLUMN>
5222              
5223             This method is an alias for L<add_primary_key_columns|/add_primary_key_columns>.
5224              
5225             =item B<add_primary_key_columns COLUMNS>
5226              
5227             Add COLUMNS to the list of columns that make up the primary key. COLUMNS can be a list or reference to an array of column names.
5228              
5229             =item B<add_relationship ARGS>
5230              
5231             This is an alias for the L<add_relationships|/add_relationships> method.
5232              
5233             =item B<add_relationships ARGS>
5234              
5235             Add relationships as specified by ARGS. Each relationship must have a L<name|Rose::DB::Object::Metadata::Relationship/name> that is unique among all other relationships in this L<class|/class>.
5236              
5237             Relationships can be specified in ARGS in several ways.
5238              
5239             If an argument is a subclass of L<Rose::DB::Object::Metadata::Relationship>, it is added as-is.
5240              
5241             Otherwise, only name/value pairs are considered, where the name is taken as the relationship name and the value must be a reference to a hash.
5242              
5243             If the hash contains the key "methods", then its value must be a reference to an array or a reference to a hash. The L<auto_method_types|Rose::DB::Object::Metadata::Relationship/auto_method_types> of the relationship are then set to the values of the referenced array, or the keys of the referenced hash. The values of the referenced hash are used to set the L<method_name|Rose::DB::Object::Metadata::Relationship/method_name> for their corresponding method types.
5244              
5245             If the hash contains the key "add_methods", then its value must be a reference to an array or a reference to a hash. The values of the referenced array or the keys of the referenced hash are added to the relationship's L<auto_method_types|Rose::DB::Object::Metadata::Relationship/auto_method_types>. The values of the referenced hash are used to set the L<method_name|Rose::DB::Object::Metadata::Relationship/method_name> for their corresponding method types.
5246              
5247             If the "methods" and "add_methods" keys are both set, a fatal error will occur.
5248              
5249             Then the L<relationship_type_class|/relationship_type_class> method is called with the value of the C<type> hash key as its argument, returning the name of a relationship class.
5250              
5251             Finally, a new relationship object of that class is constructed and is passed all the remaining pairs in the hash reference, along with the name and type of the relationship. That relationship object is then added to the list of relationships.
5252              
5253             This is done until there are no more arguments to be processed, or until an argument does not conform to one of the required formats, in which case a fatal error occurs.
5254              
5255             Example:
5256              
5257             $meta->add_relationships
5258             (
5259             # Add by name/hashref pair with explicit method type
5260             category =>
5261             {
5262             type => 'many to one',
5263             class => 'Category',
5264             column_map => { category_id => 'id' },
5265             methods => [ 'get' ],
5266             },
5267              
5268             # which is roughly equivalent to:
5269             #
5270             # $class = $meta->relationship_type_class('many to one');
5271             # $rel = $class->new(class => 'Category',
5272             # column_map => { category_id => 'id' },
5273             # name => 'category');
5274             # $rel->auto_method_types('get');
5275             # (then add $rel to the list of relationships)
5276              
5277             # Add by name/hashref pair with additional method type and name
5278             color =>
5279             {
5280             type => 'many to one',
5281             class => 'Color',
5282             column_map => { color_id => 'id' },
5283             add_methods => { set => 'set_my_color' },
5284             },
5285              
5286             # which is roughly equivalent to:
5287             #
5288             # $class = $meta->relationship_type_class('many to one');
5289             # $rel = $class->new(class => 'Color',
5290             # column_map => { color_id => 'id' },
5291             # name => 'color');
5292             # $rel->add_auto_method_types('set');
5293             # $fk->method_name(set => 'set_my_color');
5294             # (rel add $fk to the list of foreign keys)
5295              
5296             # Add a relationship object directly
5297             Rose::DB::Object::Metadata::Relationship::OneToOne->new(...),
5298             );
5299              
5300             =item B<add_unique_key KEY>
5301              
5302             This method is an alias for L<add_unique_keys|/add_unique_keys>.
5303              
5304             =item B<add_unique_keys KEYS>
5305              
5306             Add new unique keys specified by KEYS. Unique keys can be specified in KEYS in two ways.
5307              
5308             If an argument is a L<Rose::DB::Object::Metadata::UniqueKey> object (or subclass thereof), then its L<parent|Rose::DB::Object::Metadata::UniqueKey/parent> is set to the metadata object itself, and it is added.
5309              
5310             Otherwise, an argument must be a single column name or a reference to an array of column names that make up a unique key. A new L<Rose::DB::Object::Metadata::UniqueKey> is created, with its L<parent|Rose::DB::Object::Metadata::UniqueKey/parent> set to the metadata object itself, and then the unique key object is added to this list of unique keys for this L<class|/class>.
5311              
5312             =item B<alias_column NAME, ALIAS>
5313              
5314             Set the L<alias|Rose::DB::Object::Metadata::Column/alias> for the column named NAME to ALIAS. It is sometimes necessary to use an alias for a column because the column name conflicts with an existing L<Rose::DB::Object> method name.
5315              
5316             For example, imagine a column named "save". The L<Rose::DB::Object> API already defines a method named L<save|Rose::DB::Object/save>, so obviously that name can't be used for the accessor method for the "save" column. To solve this, make an alias:
5317              
5318             $meta->alias_column(save => 'save_flag');
5319              
5320             See the L<Rose::DB::Object> documentation or call the L<method_name_is_reserved|/method_name_is_reserved> method to determine if a method name is reserved.
5321              
5322             =item B<allow_inline_column_values [BOOL]>
5323              
5324             Get or set the boolean flag that indicates whether or not the associated L<Rose::DB::Object>-derived class should try to inline column values that L<DBI> does not handle correctly when they are bound to placeholders using L<bind_columns|DBI/bind_columns>. The default value is false.
5325              
5326             Enabling this flag reduces the performance of the L<update|Rose::DB::Object/update> and L<insert|Rose::DB::Object/insert> operations on the L<Rose::DB::Object>-derived object. But it is sometimes necessary to enable the flag because some L<DBI> drivers do not (or cannot) always do the right thing when binding values to placeholders in SQL statements. For example, consider the following SQL for the Informix database:
5327              
5328             CREATE TABLE test (d DATETIME YEAR TO SECOND);
5329             INSERT INTO test (d) VALUES (CURRENT);
5330              
5331             This is valid Informix SQL and will insert a row with the current date and time into the "test" table.
5332              
5333             Now consider the following attempt to do the same thing using L<DBI> placeholders (assume the table was already created as per the CREATE TABLE statement above):
5334              
5335             $sth = $dbh->prepare('INSERT INTO test (d) VALUES (?)');
5336             $sth->execute('CURRENT'); # Error!
5337              
5338             What you'll end up with is an error like this:
5339              
5340             DBD::Informix::st execute failed: SQL: -1262: Non-numeric
5341             character in datetime or interval.
5342              
5343             In other words, L<DBD::Informix> has tried to quote the string "CURRENT", which has special meaning to Informix only when it is not quoted.
5344              
5345             In order to make this work, the value "CURRENT" must be "inlined" rather than bound to a placeholder when it is the value of a "DATETIME YEAR TO SECOND" column in an Informix database.
5346              
5347             =item B<auto_load_related_classes [BOOL]>
5348              
5349             Get or set a flag that indicates whether or not classes related to this L<class|/class> through a L<foreign key|/foreign_keys> or other L<relationship|/relationships> will be automatically loaded when this L<class|/class> is L<initialize|/initialize>d. The default value is true.
5350              
5351             =item B<cached_objects_expire_in [DURATION]>
5352              
5353             This method is only applicable if this metadata object is associated with a L<Rose::DB::Object::Cached>-derived class. It simply calls the class method of the same name that belongs to the L<Rose::DB::Object::Cached>-derived L<class|/class> associated with this metadata object.
5354              
5355             =item B<catalog [CATALOG]>
5356              
5357             Get or set the database catalog for this L<class|/class>. This setting will B<override> any L<setting|Rose::DB/catalog> in the L<db|Rose::DB::Object/db> object. Use this method only if you know that the L<class|/class> will always point to a specific catalog, regardless of what the L<Rose::DB>-derived database handle object specifies.
5358              
5359             =item B<class [CLASS]>
5360              
5361             Get or set the L<Rose::DB::Object>-derived class associated with this metadata object. This is the class where the accessor methods for each column will be created (by L<make_methods|/make_methods>).
5362              
5363             =item B<class_for PARAMS>
5364              
5365             Returns the name of the L<Rose::DB::Object>-derived class associated with the C<catalog>, C<schema>, and C<table> specified by the name/value paris in PARAMS. Catalog and/or schema maybe omitted if unknown or inapplicable, and the "best" match will be returned. Returns undef if there is no class name registered under the specified PARAMS.
5366              
5367             Note: This method may also be called as a class method, but may require explicit C<catalog> and/or C<schema> arguments when dealing with databases that support these concepts I<and> have default implicit values for them.
5368              
5369             =item B<clear_object_cache>
5370              
5371             This method is only applicable if this metadata object is associated with a L<Rose::DB::Object::Cached>-derived class. It simply calls the class method of the same name that belongs to the L<Rose::DB::Object::Cached>-derived L<class|/class> associated with this metadata object.
5372              
5373             =item B<column NAME [, COLUMN | HASHREF]>
5374              
5375             Get or set the column named NAME. If just NAME is passed, the L<Rose::DB::Object::Metadata::Column>-derived column object for the column of that name is returned. If no such column exists, undef is returned.
5376              
5377             If both NAME and COLUMN are passed, then COLUMN must be a L<Rose::DB::Object::Metadata::Column>-derived object. COLUMN has its L<name|Rose::DB::Object::Metadata::Column/name> set to NAME, and is then stored as the column metadata object for NAME, replacing any existing column.
5378              
5379             If both NAME and HASHREF are passed, then the combination of NAME and HASHREF must form a name/value pair suitable for passing to the L<add_columns|/add_columns> method. The new column specified by NAME and HASHREF replaces any existing column.
5380              
5381             =item B<columns [ARGS]>
5382              
5383             Get or set the full list of columns. If ARGS are passed, the column list is cleared and then ARGS are passed to the L<add_columns|/add_columns> method.
5384              
5385             Returns a list of column objects in list context, or a reference to an array of column objects in scalar context.
5386              
5387             =item B<column_accessor_method_name NAME>
5388              
5389             Returns the name of the "get" method for the column named NAME. This is just a shortcut for C<$meta-E<gt>column(NAME)-E<gt>accessor_method_name>.
5390              
5391             =item B<column_accessor_method_names>
5392              
5393             Returns a list (in list context) or a reference to the array (in scalar context) of the names of the "set" methods for all the columns, in the order that the columns are returned by L<column_names|/column_names>.
5394              
5395             =item B<column_aliases [MAP]>
5396              
5397             Get or set the hash that maps column names to their aliases. If passed MAP (a list of name/value pairs or a reference to a hash) then MAP replaces the current alias mapping. Returns a reference to the hash that maps column names to their aliases.
5398              
5399             Note that modifying this map has no effect if L<initialize|/initialize>, L<make_methods|/make_methods>, or L<make_column_methods|/make_column_methods> has already been called for the current L<class|/class>.
5400              
5401             =item B<column_mutator_method_name NAME>
5402              
5403             Returns the name of the "set" method for the column named NAME. This is just a shortcut for C<$meta-E<gt>column(NAME)-E<gt>mutator_method_name>.
5404              
5405             =item B<column_mutator_method_names>
5406              
5407             Returns a list (in list context) or a reference to the array (in scalar context) of the names of the "set" methods for all the columns, in the order that the columns are returned by L<column_names|/column_names>.
5408              
5409             =item B<column_names>
5410              
5411             Returns a list (in list context) or a reference to an array (in scalar context) of column names.
5412              
5413             =item B<column_name_to_method_name_mapper [CODEREF]>
5414              
5415             Get or set the code reference to the subroutine used to map column names to method names. If undefined, then the L<init_column_name_to_method_name_mapper|/init_column_name_to_method_name_mapper> class method is called in order to initialize it. If still undefined or false, then the "default" method name is used.
5416              
5417             If defined, the subroutine should take four arguments: the metadata object, the column name, the column method type, and the method name that would be used if the mapper subroutine did not exist. It should return a method name.
5418              
5419             =item B<column_rw_method_name NAME>
5420              
5421             Returns the name of the "get_set" method for the column named NAME. This is just a shortcut for C<$meta-E<gt>column(NAME)-E<gt>rw_method_name>.
5422              
5423             =item B<column_rw_method_names>
5424              
5425             Returns a list (in list context) or a reference to the array (in scalar context) of the names of the "get_set" methods for all the columns, in the order that the columns are returned by L<column_names|/column_names>.
5426              
5427             =item B<column_undef_overrides_default [BOOL]>
5428              
5429             Get or set a boolean value that influences the default value of the L<undef_overrides_default|Rose::DB::Object::Metadata::Column/undef_overrides_default> attribute for each L<column|/columns> in this L<class|/class>. See the documentation for L<Rose::DB::Object::Metadata::Column>'s L<undef_overrides_default|Rose::DB::Object::Metadata::Column/undef_overrides_default> attribute for more information.
5430              
5431             Defaults to the value returned by the L<default_column_undef_overrides_default|/default_column_undef_overrides_default> class method.
5432              
5433             =item B<convention_manager [ OBJECT | CLASS | NAME ]>
5434              
5435             Get or set the convention manager for this L<class|/class>. Defaults to the return value of the L<init_convention_manager|/init_convention_manager> method.
5436              
5437             If undef is passed, then a L<Rose::DB::Object::ConventionManager::Null> object is stored instead.
5438              
5439             If a L<Rose::DB::Object::ConventionManager>-derived object is passed, its L<meta|Rose::DB::Object::ConventionManager/meta> attribute set to this metadata object and then it is used as the convention manager for this L<class|/class>.
5440              
5441             If a L<Rose::DB::Object::ConventionManager>-derived class name is passed, a new object of that class is created with its L<meta|Rose::DB::Object::ConventionManager/meta> attribute set to this metadata object. Then it is used as the convention manager for this L<class|/class>.
5442              
5443             If a convention manager name is passed, then the corresponding class is looked up in the L<convention manager class map|convention_manager_classes>, a new object of that class is constructed, its L<meta|Rose::DB::Object::ConventionManager/meta> attribute set to this metadata object, and it is used as the convention manager for this L<class|/class>. If there is no class mapped to NAME, a fatal error will occur.
5444              
5445             See the L<Rose::DB::Object::ConventionManager> documentation for more information on convention managers.
5446              
5447             =item B<db>
5448              
5449             Returns the L<Rose::DB>-derived object associated with this metadata object's L<class|/class>. A fatal error will occur if L<class|/class> is undefined or if the L<Rose::DB> object could not be created.
5450              
5451             =item B<default_cascade_save [BOOL]>
5452              
5453             Get or set a boolean value that indicates whether or not the L<class|/class> associated with this metadata object will L<save|Rose::DB::Object/save> related objects when the parent object is L<saved|Rose::DB::Object/save>. See the documentation for L<Rose::DB::Object>'s L<save()|Rose::DB::Object/save> method for details. The default value is false.
5454              
5455             =item B<default_load_speculative [BOOL]>
5456              
5457             Get or set a boolean value that indicates whether or not the L<class|/class> associated with this metadata object will L<load|Rose::DB::Object/load> speculatively by default. See the documentation for L<Rose::DB::Object>'s L<load()|Rose::DB::Object/load> method for details. The default value is false.
5458              
5459             =item B<default_update_changes_only [BOOL]>
5460              
5461             Get or set a boolean value that indicates whether or not the L<class|/class> associated with this metadata object will L<update|Rose::DB::Object/update> only an object's modified columns by default (instead of updating all columns). See the documentation for L<Rose::DB::Object>'s L<update()|Rose::DB::Object/update> method for details. The default value is false.
5462              
5463             =item B<delete_column NAME>
5464              
5465             Delete the column named NAME.
5466              
5467             =item B<delete_columns>
5468              
5469             Delete all of the L<columns|/columns>.
5470              
5471             =item B<delete_column_type_class TYPE>
5472              
5473             Delete the type/class L<mapping|/column_type_classes> entry for the column type TYPE.
5474              
5475             =item B<delete_convention_manager_class NAME>
5476              
5477             Delete the name/class L<mapping|/convention_manager_classes> entry for the convention manager class mapped to NAME.
5478              
5479             =item B<delete_nonpersistent_column NAME>
5480              
5481             Delete the L<non-persistent column|/nonpersistent_columns> named NAME.
5482              
5483             =item B<delete_nonpersistent_columns>
5484              
5485             Delete all of the L<nonpersistent_columns|/nonpersistent_columns>.
5486              
5487             =item B<delete_relationship NAME>
5488              
5489             Delete the relationship named NAME.
5490              
5491             =item B<delete_relationships>
5492              
5493             Delete all of the relationships.
5494              
5495             =item B<delete_relationship_type_class TYPE>
5496              
5497             Delete the type/class mapping entry for the relationship type TYPE.
5498              
5499             =item B<delete_unique_keys>
5500              
5501             Delete all of the unique key definitions.
5502              
5503             =item B<error_mode [MODE]>
5504              
5505             Get or set the error mode of the L<Rose::DB::Object> that fronts the table described by this L<Rose::DB::Object::Metadata> object. If the error mode is false, then it defaults to the return value of the C<init_error_mode> method, which is "fatal" by default.
5506              
5507             The error mode determines what happens when a L<Rose::DB::Object> method encounters an error. The "return" error mode causes the methods to behave as described in the L<Rose::DB::Object> documentation. All other error modes cause an action to be performed before (possibly) returning as per the documentation (depending on whether or not the "action" is some variation on "throw an exception.")
5508              
5509             Valid values of MODE are:
5510              
5511             =over 4
5512              
5513             =item carp
5514              
5515             Call L<Carp::carp|Carp/carp> with the value of the object L<error|Rose::DB::Object/error> as an argument.
5516              
5517             =item cluck
5518              
5519             Call L<Carp::cluck|Carp/cluck> with the value of the object L<error|Rose::DB::Object/error> as an argument.
5520              
5521             =item confess
5522              
5523             Call L<Carp::confess|Carp/confess> with the value of the object L<error|Rose::DB::Object/error> as an argument.
5524              
5525             =item croak
5526              
5527             Call L<Carp::croak|Carp/croak> with the value of the object L<error|Rose::DB::Object/error> as an argument.
5528              
5529             =item fatal
5530              
5531             An alias for the "croak" mode.
5532              
5533             =item return
5534              
5535             Return a value that indicates that an error has occurred, as described in the L<documentation|Rose::DB::Object/"OBJECT METHODS"> for each method.
5536              
5537             =back
5538              
5539             In all cases, the object's L<error|Rose::DB::Object/error> attribute will also contain the error message.
5540              
5541             =item B<first_column>
5542              
5543             Returns the first column, determined by the order that columns were L<added|/add_columns>, or undef if there are no columns.
5544              
5545             =item B<foreign_key NAME [, FOREIGNKEY | HASHREF ]>
5546              
5547             Get or set the foreign key named NAME. NAME should be the name of the thing being referenced by the foreign key, I<not> the name of any of the columns that make up the foreign key. If called with just a NAME argument, the foreign key stored under that name is returned. Undef is returned if there is no such foreign key.
5548              
5549             If both NAME and FOREIGNKEY are passed, then FOREIGNKEY must be a L<Rose::DB::Object::Metadata::ForeignKey>-derived object. FOREIGNKEY has its L<name|Rose::DB::Object::Metadata::ForeignKey/name> set to NAME, and is then stored, replacing any existing foreign key with the same name.
5550              
5551             If both NAME and HASHREF are passed, then the combination of NAME and HASHREF must form a name/value pair suitable for passing to the L<add_foreign_keys|/add_foreign_keys> method. The new foreign key specified by NAME and HASHREF replaces any existing foreign key with the same name.
5552              
5553             =item B<foreign_keys [ARGS]>
5554              
5555             Get or set the full list of foreign keys. If ARGS are passed, the foreign key list is cleared and then ARGS are passed to the L<add_foreign_keys|/add_foreign_keys> method.
5556              
5557             Returns a list of foreign key objects in list context, or a reference to an array of foreign key objects in scalar context.
5558              
5559             =item B<generate_primary_key_value DB>
5560              
5561             This method is the same as L<generate_primary_key_values|/generate_primary_key_values> except that it only returns the generated value for the first primary key column, rather than the entire list of values. Use this method only when there is a single primary key column (or not at all).
5562              
5563             =item B<generate_primary_key_values DB>
5564              
5565             Given the L<Rose::DB>-derived object DB, generate and return a list of new primary key column values for the table described by this metadata object.
5566              
5567             If a L<primary_key_generator|/primary_key_generator> is defined, it will be called (passed this metadata object and the DB) and its value returned.
5568              
5569             If no L<primary_key_generator|/primary_key_generator> is defined, new primary key values will be generated, if possible, using the native facilities of the current database. Note that this may not be possible for databases that auto-generate such values only after an insertion. In that case, undef will be returned.
5570              
5571             =item B<include_predicated_unique_indexes [BOOL]>
5572              
5573             Get or set a boolean value that indicates whether or not the L<auto_init_unique_keys|/auto_init_unique_keys> method will create L<unique keys|/add_unique_keys> for unique indexes that have predicates. The default value is false. This feature is currently only supported for PostgreSQL.
5574              
5575             Here's an example of a unique index that has a predicate:
5576              
5577             CREATE UNIQUE INDEX my_idx ON mytable (mycolumn) WHERE mycolumn > 123;
5578              
5579             The predicate in this case is C<WHERE mycolumn E<gt> 123>.
5580              
5581             Predicated unique indexes differ semantically from unpredicated unique indexes in that predicates generally cause the index to only apply to part of a table. L<Rose::DB::Object> expects L<unique indexes|Rose::DB::Object::Metadata::UniqueKey> to uniquely identify a row within a table. Predicated indexes that fail to do so due to their predicates should therefore not have L<Rose::DB::Object::Metadata::UniqueKey> objects created for them, thus the false default for this attribute.
5582              
5583             =item B<init_convention_manager>
5584              
5585             Returns the default L<Rose::DB::Object::ConventionManager>-derived object used as the L<convention manager|/convention_manager> for this L<class|/class>. This object will be of the class returned by L<convention_manager_class('default')|/convention_manager_class>.
5586              
5587             Override this method in your L<Rose::DB::Object::Metadata> subclass, or L<re-map|/convention_manager_class> the "default" convention manager class, in order to use a different convention manager class. See the L<tips and tricks|Rose::DB::Object::ConventionManager/"TIPS AND TRICKS"> section of the L<Rose::DB::Object::ConventionManager> documentation for an example of the subclassing approach.
5588              
5589             =item B<initialize [ARGS]>
5590              
5591             Initialize the L<Rose::DB::Object>-derived class associated with this metadata object by creating accessor methods for each column and foreign key. The L<table|/table> name and the L<primary_key_columns|/primary_key_columns> must be defined or a fatal error will occur.
5592              
5593             If any column name in the primary key or any of the unique keys does not exist in the list of L<columns|/columns>, then that primary or unique key is deleted. (As per the above, this will trigger a fatal error if any column in the primary key is not in the column list.)
5594              
5595             ARGS, if any, are passed to the call to L<make_methods|/make_methods> that actually creates the methods.
5596              
5597             If L<auto_prime_caches|/auto_prime_caches> is true, then the L<prime_caches|/prime_caches> method will be called at the end of the initialization process.
5598              
5599             =item B<is_initialized [BOOL]>
5600              
5601             Get or set a boolean value that indicates whether or not this L<class|/class> was L<initialize|/initialize>d. A successful call to the L<initialize|/initialize> method will automatically set this flag to true.
5602              
5603             =item B<make_manager_class [PARAMS | CLASS]>
5604              
5605             This method creates a L<Rose::DB::Object::Manager>-derived class to manage objects of this L<class|/class>. To do so, it simply calls L<perl_manager_class|/perl_manager_class>, passing all arguments, and then L<eval|perlfunc/eval>uates the result. See the L<perl_manager_class|/perl_manager_class> documentation for more information.
5606              
5607             =item B<make_methods [ARGS]>
5608              
5609             Create object methods in L<class|/class> for each L<column|/columns>, L<foreign key|/foreign_keys>, and L<relationship|/relationship>. This is done by calling L<make_column_methods|/make_column_methods>, L<make_nonpersistent_column_methods|/make_nonpersistent_column_methods>, L<make_foreign_key_methods|/make_foreign_key_methods>, and L<make_relationship_methods|/make_relationship_methods>, in that order.
5610              
5611             ARGS are name/value pairs which are passed on to the other C<make_*_methods> calls. They are all optional. Valid ARGS are:
5612              
5613             =over 4
5614              
5615             =item * C<preserve_existing>
5616              
5617             If set to a true value, a method will not be created if there is already an existing method with the same named.
5618              
5619             =item * C<replace_existing>
5620              
5621             If set to a true value, override any existing method with the same name.
5622              
5623             =back
5624              
5625             In the absence of one of these parameters, any method name that conflicts with an existing method name will cause a fatal error.
5626              
5627             =item B<make_column_methods [ARGS]>
5628              
5629             Create accessor/mutator methods in L<class|/class> for each L<column|/columns>. ARGS are name/value pairs, and are all optional. Valid ARGS are:
5630              
5631             =over 4
5632              
5633             =item * C<preserve_existing>
5634              
5635             If set to a true value, a method will not be created if there is already an existing method with the same named.
5636              
5637             =item * C<replace_existing>
5638              
5639             If set to a true value, override any existing method with the same name.
5640              
5641             =back
5642              
5643             For each L<auto_method_type|Rose::DB::Object::Metadata::Column/auto_method_types> in each column, the method name is determined by passing the column name and the method type to L<method_name_from_column_name|/method_name_from_column_name>. If the resulting method name is reserved (according to L<method_name_is_reserved|/method_name_is_reserved>, a fatal error will occur. The object methods for each column are created by calling the column object's L<make_methods|Rose::DB::Object::Metadata::Column/make_methods> method.
5644              
5645             =item B<make_foreign_key_methods [ARGS]>
5646              
5647             Create object methods in L<class|/class> for each L<foreign key|/foreign_keys>. ARGS are name/value pairs, and are all optional. Valid ARGS are:
5648              
5649             =over 4
5650              
5651             =item * C<preserve_existing>
5652              
5653             If set to a true value, a method will not be created if there is already an existing method with the same named.
5654              
5655             =item * C<replace_existing>
5656              
5657             If set to a true value, override any existing method with the same name.
5658              
5659             =back
5660              
5661             For each L<auto_method_type|Rose::DB::Object::Metadata::ForeignKey/auto_method_types> in each foreign key, the method name is determined by passing the method type to the L<method_name|Rose::DB::Object::Metadata::ForeignKey/method_name> method of the foreign key object, or the L<build_method_name_for_type|Rose::DB::Object::Metadata::ForeignKey/build_method_name_for_type> method if the L<method_name|Rose::DB::Object::Metadata::ForeignKey/method_name> call returns a false value. If the method name is reserved (according to L<method_name_is_reserved|/method_name_is_reserved>), a fatal error will occur. The object methods for each foreign key are created by calling the foreign key object's L<make_methods|Rose::DB::Object::Metadata::ForeignKey/make_methods> method.
5662              
5663             Foreign keys and relationships with the L<type|Rose::DB::Object::Metadata::Relationship/type> "one to one" or "many to one" both encapsulate essentially the same information. They are kept in sync when this method is called by setting the L<foreign_key|Rose::DB::Object::Metadata::Relationship::ManyToOne/foreign_key> attribute of each "L<one to one|Rose::DB::Object::Metadata::Relationship::OneToOne>" or "L<many to one|Rose::DB::Object::Metadata::Relationship::ManyToOne>" relationship object to be the corresponding foreign key object.
5664              
5665             =item B<make_nonpersistent_column_methods [ARGS]>
5666              
5667             This method behaves like the L<make_column_methods|/make_column_methods> method, except that it works with L<non-persistent columns|/nonpersistent_columns>. See the documentation for the L<nonpersistent_columns|/nonpersistent_columns> method for more information on non-persistent columns.
5668              
5669             =item B<make_relationship_methods [ARGS]>
5670              
5671             Create object methods in L<class|/class> for each L<relationship|/relationships>. ARGS are name/value pairs, and are all optional. Valid ARGS are:
5672              
5673             =over 4
5674              
5675             =item * C<preserve_existing>
5676              
5677             If set to a true value, a method will not be created if there is already an existing method with the same named.
5678              
5679             =item * C<replace_existing>
5680              
5681             If set to a true value, override any existing method with the same name.
5682              
5683             =back
5684              
5685             For each L<auto_method_type|Rose::DB::Object::Metadata::Relationship/auto_method_types> in each relationship, the method name is determined by passing the method type to the L<method_name|Rose::DB::Object::Metadata::Relationship/method_name> method of the relationship object, or the L<build_method_name_for_type|Rose::DB::Object::Metadata::Relationship/build_method_name_for_type> method if the L<method_name|Rose::DB::Object::Metadata::Relationship/method_name> call returns a false value. If the method name is reserved (according to L<method_name_is_reserved|/method_name_is_reserved>), a fatal error will occur. The object methods for each relationship are created by calling the relationship object's L<make_methods|Rose::DB::Object::Metadata::Relationship/make_methods> method.
5686              
5687             Foreign keys and relationships with the L<type|Rose::DB::Object::Metadata::Relationship/type> "one to one" or "many to one" both encapsulate essentially the same information. They are kept in sync when this method is called by setting the L<foreign_key|Rose::DB::Object::Metadata::Relationship::ManyToOne/foreign_key> attribute of each "L<one to one|Rose::DB::Object::Metadata::Relationship::OneToOne>" or "L<many to one|Rose::DB::Object::Metadata::Relationship::ManyToOne>" relationship object to be the corresponding foreign key object.
5688              
5689             If a relationship corresponds exactly to a foreign key, and that foreign key already made an object method, then the relationship is not asked to make its own method.
5690              
5691             =item B<default_manager_base_class [CLASS]>
5692              
5693             Get or set the default name of the base class used by this specific metadata object when generating a L<manager|Rose::DB::Object::Manager> class, using either the L<perl_manager_class|/perl_manager_class> or L<make_manager_class|/make_manager_class> methods. The default value is determined by the C<default_manager_base_class|/default_manager_base_class()> L<class method|/CLASS METHODS>.
5694              
5695             =item B<method_column METHOD>
5696              
5697             Returns the name of the column manipulated by the method named METHOD.
5698              
5699             =item B<method_name_from_column_name NAME, TYPE>
5700              
5701             Looks up the column named NAME and calls L<method_name_from_column|/method_name_from_column> with the column and TYPE as argument. If no such column exists, a fatal error will occur.
5702              
5703             =item B<method_name_from_column COLUMN, TYPE>
5704              
5705             Given a L<Rose::DB::Object::Metadata::Column>-derived column object and a column L<type|Rose::DB::Object::Metadata::Column/type> name, return the corresponding method name that should be used for it. Several entities are given an opportunity to determine the name. They are consulted in the following order.
5706              
5707             =over 4
5708              
5709             =item 1. If a custom-defined L<column_name_to_method_name_mapper|/column_name_to_method_name_mapper> exists, then it is used to generate the method name and this name is returned.
5710              
5711             =item 2. If a method name has been L<explicitly set|Rose::DB::Object::Metadata::Column/method_name>, for this type in the column object itself, then this name is returned.
5712              
5713             =item 3. If the L<convention manager|/convention_manager>'s L<auto_column_method_name|Rose::DB::Object::ConventionManager/auto_column_method_name> method returns a defined value, then this name is returned.
5714              
5715             =item 4. Otherwise, the default naming rules as defined in the column class itself are used.
5716              
5717             =back
5718              
5719             =item B<method_name_is_reserved NAME, CLASS>
5720              
5721             Given the method name NAME and the class name CLASS, returns true if the method name is reserved (i.e., is used by the CLASS API), false otherwise.
5722              
5723             =item B<nonpersistent_column NAME [, COLUMN | HASHREF]>
5724              
5725             This method behaves like the L<column|/column> method, except that it works with L<non-persistent columns|/nonpersistent_columns>. See the documentation for the L<nonpersistent_columns|/nonpersistent_columns> method for more information on non-persistent columns.
5726              
5727             =item B<nonpersistent_columns [ARGS]>
5728              
5729             Get or set the full list of non-persistent columns. If ARGS are passed, the non-persistent column list is cleared and then ARGS are passed to the L<add_nonpersistent_columns|/add_nonpersistent_columns> method.
5730              
5731             Returns a list of non-persistent column objects in list context, or a reference to an array of non-persistent column objects in scalar context.
5732              
5733             Non-persistent columns allow the creation of object attributes and associated accessor/mutator methods exactly like those associated with L<columns|/columns>, but I<without> ever sending any of these attributes to (or pulling any these attributes from) the database.
5734              
5735             Non-persistent columns are tracked entirely separately from L<columns|/columns>. L<Adding|/add_nonpersistent_columns>, L<deleting|/delete_nonpersistent_column>, and listing non-persistent columns has no affect on the list of normal (i.e., "persistent") L<columns|/column>.
5736              
5737             You cannot query the database (e.g., using L<Rose::DB::Object::Manager>) and filter on a non-persistent column; non-persistent columns do not exist in the database. This feature exists solely to leverage the method creation abilities of the various column classes.
5738              
5739             =item B<nonpersistent_column_accessor_method_name NAME>
5740              
5741             Returns the name of the "get" method for the L<non-persistent|/nonpersistent_columns> column named NAME. This is just a shortcut for C<$meta-E<gt>nonpersistent_column(NAME)-E<gt>accessor_method_name>.
5742              
5743             =item B<nonpersistent_column_accessor_method_names>
5744              
5745             Returns a list (in list context) or a reference to the array (in scalar context) of the names of the "set" methods for all the L<non-persistent|/nonpersistent_columns> columns, in the order that the columns are returned by L<nonpersistent_column_names|/nonpersistent_column_names>.
5746              
5747             =item B<nonpersistent_column_mutator_method_name NAME>
5748              
5749             Returns the name of the "set" method for the L<non-persistent|/nonpersistent_columns> column named NAME. This is just a shortcut for C<$meta-E<gt>nonpersistent_column(NAME)-E<gt>mutator_method_name>.
5750              
5751             =item B<nonpersistent_column_mutator_method_names>
5752              
5753             Returns a list (in list context) or a reference to the array (in scalar context) of the names of the "set" methods for all the L<non-persistent columns|/nonpersistent_columns>, in the order that the columns are returned by L<nonpersistent_column_names|/nonpersistent_column_names>.
5754              
5755             =item B<nonpersistent_column_names>
5756              
5757             Returns a list (in list context) or a reference to an array (in scalar context) of L<non-persistent|/nonpersistent_columns> column names.
5758              
5759             =item B<pk_columns [COLUMNS]>
5760              
5761             This is an alias for the L<primary_key_columns|/primary_key_columns> method.
5762              
5763             =item B<post_init_hook [ CODEREF | ARRAYREF ]>
5764              
5765             Get or set a reference to a subroutine or a reference to an array of code references that will be called just after the L<initialize|/initialize> method runs. Each referenced subroutine will be passed the metadata object itself and any arguments passed to the call to L<initialize|/initialize>.
5766              
5767             =item B<pre_init_hook [ CODEREF | ARRAYREF ]>
5768              
5769             Get or set a reference to a subroutine or a reference to an array of code references that will be called just before the L<initialize|/initialize> method runs. Each referenced subroutine will be passed the metadata object itself and any arguments passed to the call to L<initialize|/initialize>.
5770              
5771             =item B<primary_key [PK]>
5772              
5773             Get or set the L<Rose::DB::Object::Metadata::PrimaryKey> object that stores the list of column names that make up the primary key for this table.
5774              
5775             =item B<primary_key_columns [COLUMNS]>
5776              
5777             Get or set the list of columns that make up the primary key. COLUMNS should be a list of column names or L<Rose::DB::Object::Metadata::Column>-derived objects.
5778              
5779             Returns all of the columns that make up the primary key. Each column is a L<Rose::DB::Object::Metadata::Column>-derived column object if a L<column|/column> object with the same name exists, or just the column name otherwise. In scalar context, a reference to an array of columns is returned. In list context, a list is returned.
5780              
5781             This method is just a shortcut for the code:
5782              
5783             $meta->primary_key->columns(...);
5784              
5785             See the L<primary_key|/primary_key> method and the L<Rose::DB::Object::Metadata::PrimaryKey> class for more information.
5786              
5787             =item B<primary_key_column_names [NAMES]>
5788              
5789             Get or set the names of the columns that make up the table's primary key. NAMES should be a list or reference to an array of column names.
5790              
5791             Returns the list of column names (in list context) or a reference to the array of column names (in scalar context).
5792              
5793             This method is just a shortcut for the code:
5794              
5795             $meta->primary_key->column_names(...);
5796              
5797             See the L<primary_key|/primary_key> method and the L<Rose::DB::Object::Metadata::PrimaryKey> class for more information.
5798              
5799             =item B<primary_key_generator [CODEREF]>
5800              
5801             Get or set the subroutine used to generate new primary key values for the primary key columns of this table. The subroutine will be passed two arguments: the current metadata object and the L<Rose::DB>-derived object that points to the current database.
5802              
5803             The subroutine is expected to return a list of values, one for each primary key column. The values must be in the same order as the corresponding columns returned by L<primary_key_columns|/primary_key_columns>. (i.e., the first value belongs to the first column returned by L<primary_key_columns|/primary_key_columns>, the second value belongs to the second column, and so on.)
5804              
5805             =item B<primary_key_sequence_names [NAMES]>
5806              
5807             Get or set the list of database sequence names used to populate the primary key columns. The sequence names must be in the same order as the L<primary_key_columns|/primary_key_columns>. NAMES may be a list or reference to an array of sequence names. Returns a list (in list context) or reference to the array (in scalar context) of sequence names.
5808              
5809             If you do not set this value, it will be derived for you based on the name of the primary key columns. In the common case, you do not need to be concerned about this method. If you are using the built-in SERIAL or AUTO_INCREMENT types in your database for your primary key columns, everything should just work.
5810              
5811             =item B<prime_caches [PARAMS]>
5812              
5813             By default, secondary metadata derived from the attributes of this object is created and cached on demand. Call this method to pre-cache this metadata all at once. This method is useful when running in an environment like L<mod_perl> where it's advantageous to load as much data as possible on start-up.
5814              
5815             PARAMS are name/value pairs. Valid parameters are:
5816              
5817             =over 4
5818              
5819             =item B<db DB>
5820              
5821             A L<Rose::DB>-derived object used to determine which data source the cached metadata will be generated on behalf of. (Each data source has its own set of cached metadata.) This parameter is optional. If it is not passed, then the L<Rose::DB>-derived object returned by the L<init_db|Rose::DB::Object/init_db> method for this L<class|/class> will be used instead.
5822              
5823             =back
5824              
5825             =item B<relationship NAME [, RELATIONSHIP | HASHREF]>
5826              
5827             Get or set the relationship named NAME. If just NAME is passed, the L<Rose::DB::Object::Metadata::Relationship>-derived relationship object for that NAME is returned. If no such relationship exists, undef is returned.
5828              
5829             If both NAME and RELATIONSHIP are passed, then RELATIONSHIP must be a L<Rose::DB::Object::Metadata::Relationship>-derived object. RELATIONSHIP has its L<name|Rose::DB::Object::Metadata::Relationship/name> set to NAME, and is then stored as the relationship metadata object for NAME, replacing any existing relationship.
5830              
5831             If both NAME and HASHREF are passed, then the combination of NAME and HASHREF must form a name/value pair suitable for passing to the L<add_relationships|/add_relationships> method. The new relationship specified by NAME and HASHREF replaces any existing relationship.
5832              
5833             =item B<relationships [ARGS]>
5834              
5835             Get or set the full list of relationships. If ARGS are passed, the relationship list is cleared and then ARGS are passed to the L<add_relationships|/add_relationships> method.
5836              
5837             Returns a list of relationship objects in list context, or a reference to an array of relationship objects in scalar context.
5838              
5839             =item B<replace_column NAME, [COLUMN | HASHREF]>
5840              
5841             Replace the column named NAME with a newly constructed column. This method is equivalent to L<deleting|/delete_column> any existing column named NAME and then L<adding|/add_column> a new one. In other words, this:
5842              
5843             $meta->replace_column($name => $value);
5844              
5845             is equivalent to this:
5846              
5847             $meta->delete_column($name);
5848             $meta->add_column($name => $value);
5849              
5850             The value of the new column may be a L<Rose::DB::Object::Metadata::Column>-derived object or a reference to a hash suitable for passing to the L<add_columns|/add_columns> method.
5851              
5852             =item B<schema [SCHEMA]>
5853              
5854             Get or set the database schema for this L<class|/class>. This setting will B<override> any L<setting|Rose::DB/schema> in the L<db|Rose::DB::Object/db> object. Use this method only if you know that the L<class|/class> will always point to a specific schema, regardless of what the L<Rose::DB>-derived database handle object specifies.
5855              
5856             =item B<setup PARAMS>
5857              
5858             Set up all the metadata for this L<class|/class> in a single method call. This method is a convenient shortcut. It does its work by delegating to other methods.
5859              
5860             The L<setup()|/setup> method does nothing if the metadata object is already initialized (according to the L<is_initialized|/is_initialized> method).
5861              
5862             PARAMS are method/arguments pairs. In general, the following transformations apply.
5863              
5864             Given a method/arrayref pair:
5865              
5866             METHOD => [ ARG1, ARG2 ]
5867              
5868             The arguments will be removed from their array reference and passed to METHOD like this:
5869              
5870             $meta->METHOD(ARG1, ARG2);
5871              
5872             Given a method/value pair:
5873              
5874             METHOD => ARG
5875              
5876             The argument will be passed to METHOD as-is:
5877              
5878             $meta->METHOD(ARG);
5879              
5880             There are two exceptions to these transformation rules.
5881              
5882             If METHOD is "L<unique_key|/unique_key>" or "L<add_unique_key|/add_unique_key>" and the argument is a reference to an array containing only non-reference values, then the array reference itself is passed to the method. For example, this pair:
5883              
5884             unique_key => [ 'name', 'status' ]
5885              
5886             will result in this method call:
5887              
5888             $meta->unique_key([ 'name', 'status' ]);
5889              
5890             (Note that these method names are I<singular>. This exception does I<not> apply to the I<plural> variants, "L<unique_keys|/unique_keys>" and "L<add_unique_keys|/add_unique_keys>".)
5891              
5892             If METHOD is "helpers", then the argument is dereferenced (if it's an array reference) and passed on to L<Rose::DB::Object::Helpers>. That is, this:
5893              
5894             helpers => [ 'load_or_save', { load_or_insert => 'find_or_create' } ],
5895              
5896             Is equivalent to having this in your L<class|/class>:
5897              
5898             use Rose::DB::Object::Helpers
5899             'load_or_save', { load_or_insert => 'find_or_create' };
5900              
5901             Method names may appear more than once in PARAMS. The methods are called in the order that they appear in PARAMS, with the exception of the L<initialize|/initialize> (or L<auto_initialize|/auto_initialize>) method, which is always called last.
5902              
5903             If "initialize" is not one of the method names, then it will be called automatically (with no arguments) at the end. If you do not want to pass any arguments to the L<initialize|/initialize> method, standard practice is to omit it.
5904              
5905             If "auto_initialize" is one of the method names, then the L<auto_initialize|/auto_initialize> method will be called instead of the L<initialize|/initialize> method. This is useful if you want to manually set up a few pieces of metadata, but want the auto-initialization system to set up the rest.
5906              
5907             The name "auto" is considered equivalent to "auto_initialize", but any arguments are ignored unless they are encapsulated in a reference to an array. For example, these are equivalent:
5908              
5909             $meta->setup(
5910             table => 'mytable',
5911             # Call auto_initialize() with no arguments
5912             auto_initialize => [],
5913             );
5914              
5915             # This is another way of writing the same thing as the above
5916             $meta->setup(
5917             table => 'mytable',
5918             # The value "1" is ignored because it's not an arrayref,
5919             # so auto_initialize() will be called with no arguments.
5920             auto => 1,
5921             );
5922              
5923             Finally, here's a full example of a L<setup()|/setup> method call followed by the equivalent "long-hand" implementation.
5924              
5925             $meta->setup
5926             (
5927             table => 'colors',
5928              
5929             columns =>
5930             [
5931             code => { type => 'character', length => 3, not_null => 1 },
5932             name => { type => 'varchar', length => 255 },
5933             ],
5934              
5935             primary_key_columns => [ 'code' ],
5936              
5937             unique_key => [ 'name' ],
5938             );
5939              
5940             The L<setup()|/setup> method call above is equivalent to the following code:
5941              
5942             unless($meta->is_initialized)
5943             {
5944             $meta->table('colors');
5945              
5946             $meta->columns(
5947             [
5948             code => { type => 'character', length => 3, not_null => 1 },
5949             name => { type => 'varchar', length => 255 },
5950             ]);
5951              
5952             $meta->primary_key_columns('code');
5953              
5954             $meta->unique_key([ 'name' ]),
5955              
5956             $meta->initialize;
5957             }
5958              
5959             =item B<sql_qualify_column_names_on_load [BOOL]>
5960              
5961             Get or set a boolean value that indicates whether or not to prefix the columns with the table name in the SQL used to L<load()|Rose::DB::Object/load> an object. The default value is false.
5962              
5963             For example, here is some SQL that might be used to L<load|Rose::DB::Object/load> an object, as generated with L<sql_qualify_column_names_on_load|/sql_qualify_column_names_on_load> set to false:
5964              
5965             SELECT id, name FROM dogs WHERE id = 5;
5966              
5967             Now here's how it would look with L<sql_qualify_column_names_on_load|/sql_qualify_column_names_on_load> set to true:
5968              
5969             SELECT dogs.id, dogs.name FROM dogs WHERE dogs.id = 5;
5970              
5971             =item B<table [TABLE]>
5972              
5973             Get or set the name of the database table. The table name should not include any sort of prefix to indicate the L<schema|Rose::DB/schema> or L<catalog|Rose::DB/catalog>.
5974              
5975             =item B<unique_key KEY>
5976              
5977             This method is an alias for L<add_unique_keys|/add_unique_keys>.
5978              
5979             =item B<unique_keys KEYS>
5980              
5981             Get or set the list of unique keys for this table. If KEYS is passed, any existing keys will be deleted and KEYS will be passed to the L<add_unique_keys|/add_unique_keys> method.
5982              
5983             Returns the list (in list context) or reference to an array (in scalar context) of L<Rose::DB::Object::Metadata::UniqueKey> objects.
5984              
5985             =item B<unique_key_by_name NAME>
5986              
5987             Return the unique key L<named|Rose::DB::Object::Metadata::UniqueKey/name> NAME, or undef if no such key exists.
5988              
5989             =item B<unique_keys_column_names>
5990              
5991             Returns a list (in list context) or a reference to an array (in scalar context) or references to arrays of the column names that make up each unique key. That is:
5992              
5993             # Example of a scalar context return value
5994             [ [ 'id', 'name' ], [ 'code' ] ]
5995              
5996             # Example of a list context return value
5997             ([ 'id', 'name' ], [ 'code' ])
5998              
5999             =back
6000              
6001             =head1 AUTO-INITIALIZATION METHODS
6002              
6003             These methods are associated with the L<auto-initialization|/"AUTO-INITIALIZATION"> process. Calling any of them will cause the auto-initialization code to be loaded, which costs memory. This should be considered an implementation detail for now.
6004              
6005             Regardless of the implementation details, you should still avoid calling any of these methods unless you plan to do some auto-initialization. No matter how generic they may seem (e.g., L<default_perl_indent|/default_perl_indent>), rest assured that none of these methods are remotely useful I<unless> you are doing auto-initialization.
6006              
6007             =head2 CLASS METHODS
6008              
6009             =over 4
6010              
6011             =item B<default_perl_braces [STYLE]>
6012              
6013             Get or set the default brace style used in the Perl code generated by the perl_* object methods. STYLE must be either "k&r" or "bsd". The default value is "k&r".
6014              
6015             =item B<default_perl_indent [INT]>
6016              
6017             Get or set the default integer number of spaces used for each level of indenting in the Perl code generated by the perl_* object methods. The default value is 4.
6018              
6019             =item B<default_perl_unique_key_style [STYLE]>
6020              
6021             Get or set the default style of the unique key initialization used in the Perl code generated by the L<perl_unique_keys_definition|/perl_unique_keys_definition> method. STYLE must be "array" or "object". The default value is "array". See the L<perl_unique_keys_definition|/perl_unique_keys_definition> method for examples of the two styles.
6022              
6023             =back
6024              
6025             =head2 OBJECT METHODS
6026              
6027             =over 4
6028              
6029             =item B<auto_generate_columns>
6030              
6031             Auto-generate L<Rose::DB::Object::Metadata::Column>-derived objects for each column in the table. Note that this method does not modify the metadata object's list of L<columns|/columns>. It simply returns a list of column objects. Calling this method in void context will cause a fatal error.
6032              
6033             Returns a list of column objects (in list context) or a reference to a hash of column objects, keyed by column name (in scalar context). The hash reference return value is intended to allow easy modification of the auto-generated column objects. Example:
6034              
6035             $columns = $meta->auto_generate_columns; # hash ref return value
6036              
6037             # Make some changes
6038             $columns->{'name'}->length(10); # set different length
6039             $columns->{'age'}->default(5); # set different default
6040             ...
6041              
6042             # Finally, set the column list
6043             $meta->columns(values %$columns);
6044              
6045             If you do not want to modify the auto-generated columns, you should use the L<auto_init_columns|/auto_init_columns> method instead.
6046              
6047             A fatal error will occur unless at least one column was auto-generated.
6048              
6049             =item B<auto_generate_foreign_keys [PARAMS]>
6050              
6051             Auto-generate L<Rose::DB::Object::Metadata::ForeignKey> objects for each foreign key in the table. Note that this method does not modify the metadata object's list of L<foreign_keys|/foreign_keys>. It simply returns a list of foreign key objects. Calling this method in void context will cause a fatal error. A warning will be issued if a foreign key could not be generated because no L<Rose::DB::Object>-derived class was found for the foreign table.
6052              
6053             PARAMS are optional name/value pairs. If a C<no_warnings> parameter is passed with a true value, then the warning described above will not be issued.
6054              
6055             Returns a list of foreign key objects (in list context) or a reference to an array of foreign key objects (in scalar context).
6056              
6057             If you do not want to inspect or modify the auto-generated foreign keys, but just want them to populate the metadata object's L<foreign_keys|/foreign_keys> list, you should use the L<auto_init_foreign_keys|/auto_init_foreign_keys> method instead.
6058              
6059             B<Note:> This method works with MySQL only when using the InnoDB storage type.
6060              
6061             =item B<auto_generate_unique_keys>
6062              
6063             Auto-generate L<Rose::DB::Object::Metadata::UniqueKey> objects for each unique key in the table. Note that this method does not modify the metadata object's list of L<unique_keys|/unique_keys>. It simply returns a list of unique key objects. Calling this method in void context will cause a fatal error.
6064              
6065             Returns a list of unique key objects (in list context) or a reference to an array of unique key objects (in scalar context).
6066              
6067             If you do not want to inspect or modify the auto-generated unique keys, but just want them to populate the metadata object's L<unique_keys|/unique_keys> list, you should use the L<auto_init_unique_keys|/auto_init_unique_keys> method instead.
6068              
6069             =item B<auto_retrieve_primary_key_column_names>
6070              
6071             Returns a list (in list context) or a reference to an array (in scalar context) of the names of the columns that make up the primary key for this table. Note that this method does not modify the metadata object's L<primary_key|/primary_key>. It simply returns a list of column names. Calling this method in void context will cause a fatal error.
6072              
6073             This method is rarely called explicitly. Usually, you will use the L<auto_init_primary_key_columns|/auto_init_primary_key_columns> method instead.
6074              
6075             A fatal error will occur unless at least one column name can be retrieved.
6076              
6077             (This method uses the word "retrieve" instead of "generate" like its sibling methods above because it does not generate objects; it simply returns column names.)
6078              
6079             =item B<auto_initialize [PARAMS]>
6080              
6081             Auto-initialize the entire metadata object. This is a wrapper for the individual "auto_init_*" methods, and is roughly equivalent to this:
6082              
6083             $meta->auto_init_columns(...);
6084             $meta->auto_init_primary_key_columns;
6085             $meta->auto_init_unique_keys(...);
6086             $meta->auto_init_foreign_keys(...);
6087             $meta->auto_init_relationships(...);
6088             $meta->initialize;
6089              
6090             PARAMS are optional name/value pairs. When applicable, these parameters are passed on to each of the "auto_init_*" methods. Valid parameters are:
6091              
6092             =over 4
6093              
6094             =item B<include_map_class_relationships BOOL>
6095              
6096             By default, if a class is a L<map class|Rose::DB::Object::Metadata::Relationship::ManyToMany/map_class> (according to the L<is_map_class|Rose::DB::Object::ConventionManager/is_map_class> method of the L<convention manager|/convention_manager>), then relationships directly between that class and the current L<class|/class> will not be created. Set this parameter to true to allow such relationships to be created.
6097              
6098             B<Note:> If some classes that are not actually map classes are being skipped, you should not use this parameter to force them to be included. It's more appropriate to make your own custom L<convention manager|Rose::DB::Object::ConventionManager> subclass and then override the L<is_map_class|Rose::DB::Object::ConventionManager/is_map_class> method to make the correct determination.
6099              
6100             =item B<replace_existing BOOL>
6101              
6102             If true, then the auto-generated columns, unique keys, foreign keys, and relationships entirely replace any existing columns, unique keys, foreign keys, and relationships, respectively.
6103              
6104             =item B<stay_connected BOOL>
6105              
6106             If true, then any database connections retained by the metadata objects belonging to the various L<Rose::DB::Object>-derived classes participating in the auto-initialization process will remain connected until an explicit call to the L<clear_all_dbs|/clear_all_dbs> class method.
6107              
6108             =item B<with_foreign_keys BOOL>
6109              
6110             A boolean value indicating whether or not foreign key metadata will be auto-initialized. Defaults to true.
6111              
6112             =item B<with_relationships [ BOOL | ARRAYREF ]>
6113              
6114             A boolean value or a reference to an array of relationship L<type|Rose::DB::Object::Metadata::Relationship/type> names. If set to a simple boolean value, then the all types of relationships will be considered for auto-initialization. If set to a list of relationship type names, then only relationships of those types will be considered. Defaults to true.
6115              
6116             =item B<with_unique_keys BOOL>
6117              
6118             A boolean value indicating whether or not unique key metadata will be auto-initialized. Defaults to true.
6119              
6120             =back
6121              
6122             During initialization, if one of the columns has a method name that clashes with a L<reserved method name|Rose::DB::Object/"RESERVED METHODS">, then the L<column_alias_generator|/column_alias_generator> will be called to remedy the situation by aliasing the column. If the name still conflicts, then a fatal error will occur.
6123              
6124             A fatal error will occur if auto-initialization fails.
6125              
6126             =item B<auto_init_columns [PARAMS]>
6127              
6128             Auto-generate L<Rose::DB::Object::Metadata::Column> objects for this table, then populate the list of L<columns|/columns>. PARAMS are optional name/value pairs. If a C<replace_existing> parameter is passed with a true value, then the auto-generated columns replace any existing columns. Otherwise, any existing columns are left as-is.
6129              
6130             =item B<auto_init_foreign_keys [PARAMS]>
6131              
6132             Auto-generate L<Rose::DB::Object::Metadata::ForeignKey> objects for this table, then populate the list of L<foreign_keys|/foreign_keys>. PARAMS are optional name/value pairs. If a C<replace_existing> parameter is passed with a true value, then the auto-generated foreign keys replace any existing foreign keys. Otherwise, any existing foreign keys are left as-is.
6133              
6134             B<Note:> This method works with MySQL only when using the InnoDB storage type.
6135              
6136             =item B<auto_init_primary_key_columns>
6137              
6138             Auto-retrieve the names of the columns that make up the primary key for this table, then populate the list of L<primary_key_column_names|/primary_key_column_names>. A fatal error will occur unless at least one primary key column name could be retrieved.
6139              
6140             =item B<auto_init_relationships [PARAMS]>
6141              
6142             Auto-populate the list of L<relationships|/relationships> for this L<class|/class>. PARAMS are optional name/value pairs.
6143              
6144             =over 4
6145              
6146             =item B<include_map_class_relationships BOOL>
6147              
6148             By default, if a class is a L<map class|Rose::DB::Object::Metadata::Relationship::ManyToMany/map_class> (according to the L<is_map_class|Rose::DB::Object::ConventionManager/is_map_class> method of the L<convention manager|/convention_manager>), then relationships directly between that class and the current L<class|/class> will not be created. Set this parameter to true to allow such relationships to be created.
6149              
6150             B<Note:> If some classes that are not actually map classes are being skipped, you should not use this parameter to force them to be included. It's more appropriate to make your own custom L<convention manager|Rose::DB::Object::ConventionManager> subclass and then override the L<is_map_class|Rose::DB::Object::ConventionManager/is_map_class> method to make the correct determination.
6151              
6152             =item B<replace_existing BOOL>
6153              
6154             If true, then the auto-generated relationships replace any existing relationships. Otherwise, any existing relationships are left as-is.
6155              
6156             =item B<relationship_types ARRAYREF>
6157              
6158             A reference to an array of relationship L<type|Rose::DB::Object::Metadata::Relationship/type> names. Only relationships of these types will be created. If omitted, relationships of L<all types|/relationship_type_classes> will be created. If passed a reference to an empty array, no relationships will be created.
6159              
6160             =item B<types ARRAYREF>
6161              
6162             This is an alias for the C<relationship_types> parameter.
6163              
6164             =item B<with_relationships [ BOOL | ARRAYREF ]>
6165              
6166             This is the same as the C<relationship_types> parameter except that it also accepts a boolean value. If true, then relationships of L<all types|/relationship_type_classes> will be created. If false, then none will be created.
6167              
6168             =back
6169              
6170             Assume that this L<class|/class> is called C<Local> and any hypothetical foreign class is called C<Remote>. Relationships are auto-generated according to the following rules.
6171              
6172             =over 4
6173              
6174             =item * A L<one-to-many|Rose::DB::Object::Metadata::Relationship::OneToMany> relationship is created between C<Local> and C<Remote> if C<Remote> has a foreign key that points to C<Local>. This is not done, however, if C<Local> has a L<one-to-one|Rose::DB::Object::Metadata::Relationship::OneToOne> relationship pointing to C<Remote> that references the same columns as the foreign key in C<Remote> that points to C<Local>, or if C<Local> is a map class (according to the L<convention manager|/convention_manager>'s L<is_map_class|Rose::DB::Object::ConventionManager/is_map_class> method). The relationship name is generated by the L<convention manager|/convention_manager>'s L<auto_relationship_name_one_to_many|Rose::DB::Object::ConventionManager/auto_relationship_name_one_to_many> method.
6175              
6176             =item * A L<many-to-many|Rose::DB::Object::Metadata::Relationship::ManyToMany> relationship is created between C<Local> and C<Remote> if there exists a L<map class|Rose::DB::Object::Metadata::Relationship::ManyToMany/map_class> (according to the convention manager's L<is_map_class|Rose::DB::Object::ConventionManager/is_map_class> method) with exactly two foreign keys, one pointing to L<Local> and on pointing to C<Remote>. The relationship name is generated by creating a L<plural|Rose::DB::Object::ConventionManager/singular_to_plural> version of the name of the foreign key in the map class that points to C<Remote>.
6177              
6178             =back
6179              
6180             In all cases, if there is an existing, semantically identical relationship, then a new relationship is not auto-generated. Similarly, any existing methods with the same names are not overridden by methods associated with auto-generated relationships.
6181              
6182             =item B<auto_init_unique_keys [PARAMS]>
6183              
6184             Auto-generate L<Rose::DB::Object::Metadata::UniqueKey> objects for this table, then populate the list of L<unique_keys|/unique_keys>. PARAMS are name/value pairs. If a C<replace_existing> parameter is passed with a true value, then the auto-generated unique keys replace any existing unique keys. Otherwise, any existing unique keys are left as-is.
6185              
6186             =item B<column_alias_generator [CODEREF]>
6187              
6188             Get or set the code reference to the subroutine used to alias columns have, or would generate, one or more method names that clash with L<reserved method names|Rose::DB::Object/"RESERVED METHODS">.
6189              
6190             The subroutine should take two arguments: the metadata object and the column name. The C<$_> variable will also be set to the column name at the time of the call. The subroutine should return an L<alias|Rose::DB::Object::Metadata::Column/alias> for the column.
6191              
6192             The default column alias generator simply appends the string "_col" to the end of the column name and returns that as the alias.
6193              
6194             =item B<foreign_key_name_generator [CODEREF]>
6195              
6196             Get or set the code reference to the subroutine used to generate L<foreign key|Rose::DB::Object::Metadata::ForeignKey> names. B<Note:> This code will only be called if the L<convention_manager|/convention_manager>'s L<auto_foreign_key_name|Rose::DB::Object::ConventionManager/auto_foreign_key_name> method fails to (or declines to) produce a defined foreign key name.
6197              
6198             The subroutine should take two arguments: a metadata object and a L<Rose::DB::Object::Metadata::ForeignKey> object. It should return a name for the foreign key.
6199              
6200             Each foreign key must have a name that is unique within the class. By default, this name will also be the name of the method generated to access the object referred to by the foreign key, so it must be unique among method names in the class as well.
6201              
6202             The default foreign key name generator uses the following algorithm:
6203              
6204             If the foreign key has only one column, and if the name of that column ends with an underscore and the name of the referenced column, then that part of the column name is removed and the remaining string is used as the foreign key name. For example, given the following tables:
6205              
6206             CREATE TABLE categories
6207             (
6208             id SERIAL PRIMARY KEY,
6209             ...
6210             );
6211              
6212             CREATE TABLE products
6213             (
6214             category_id INT REFERENCES categories (id),
6215             ...
6216             );
6217              
6218             The foreign key name would be "category", which is the name of the referring column ("category_id") with an underscore and the name of the referenced column ("_id") removed from the end of it.
6219              
6220             If the foreign key has only one column, but it does not meet the criteria described above, then "_object" is appended to the name of the referring column and the resulting string is used as the foreign key name.
6221              
6222             If the foreign key has more than one column, then the foreign key name is generated by replacing double colons and case-transitions in the referenced class name with underscores, and then converting to lowercase. For example, if the referenced table is fronted by the class My::TableOfStuff, then the generated foreign key name would be "my_table_of_stuff".
6223              
6224             In all of the scenarios above, if the generated foreign key name is still not unique within the class, then a number is appended to the end of the name. That number is incremented until the name is unique.
6225              
6226             In practice, rather than setting a custom foreign key name generator, it's usually easier to simply set the foreign key name(s) manually after auto-initializing the foreign keys (but I<before> calling L<initialize|/initialize> or L<auto_initialize|/auto_initialize>, of course).
6227              
6228             =item B<perl_class_definition [PARAMS]>
6229              
6230             Auto-initialize the columns, primary key, foreign keys, and unique keys, then return the Perl source code for a complete L<Rose::DB::Object>-derived class definition. PARAMS are optional name/value pairs that may include the following:
6231              
6232             =over 4
6233              
6234             =item B<braces STYLE>
6235              
6236             The brace style to use in the generated Perl code. STYLE must be either "k&r" or "bsd". The default value is determined by the return value of the L<default_perl_braces|/default_perl_braces> class method.
6237              
6238             =item B<indent INT>
6239              
6240             The integer number of spaces to use for each level of indenting in the generated Perl code. The default value is determined by the return value of the L<default_perl_indent|/default_perl_indent> class method.
6241              
6242             =item B<isa CLASSES>
6243              
6244             The list of base classes to use in the generated class definition. CLASSES should be a single class name, or a reference to an array of class names. The default base class is L<Rose::DB::Object>.
6245              
6246             =item B<use_setup BOOL>
6247              
6248             If true, then the generated class definition will include a call to the L<setup|/setup> method. Otherwise, the generated code will contain individual methods calls. The default value for this parameter is B<true>; the L<setup|/setup> method is the recommended way to initialize a class.
6249              
6250             =back
6251              
6252             This method is simply a wrapper (with some glue) for the following methods: L<perl_columns_definition|/perl_columns_definition>, L<perl_primary_key_columns_definition|/perl_primary_key_columns_definition>, L<perl_unique_keys_definition|/perl_unique_keys_definition>, L<perl_foreign_keys_definition|/perl_foreign_keys_definition>, and L<perl_relationships_definition|/perl_relationships_definition>. The "braces" and "indent" parameters are passed on to these other methods.
6253              
6254             Here's a complete example, which also serves as an example of the individual "perl_*" methods that this method wraps. First, the table definitions.
6255              
6256             CREATE TABLE topics
6257             (
6258             id SERIAL PRIMARY KEY,
6259             name VARCHAR(32)
6260             );
6261              
6262             CREATE TABLE codes
6263             (
6264             k1 INT NOT NULL,
6265             k2 INT NOT NULL,
6266             k3 INT NOT NULL,
6267             name VARCHAR(32),
6268              
6269             PRIMARY KEY(k1, k2, k3)
6270             );
6271              
6272             CREATE TABLE products
6273             (
6274             id SERIAL PRIMARY KEY,
6275             name VARCHAR(32) NOT NULL,
6276             flag BOOLEAN NOT NULL DEFAULT 't',
6277             status VARCHAR(32) DEFAULT 'active',
6278             topic_id INT REFERENCES topics (id),
6279             fk1 INT,
6280             fk2 INT,
6281             fk3 INT,
6282             last_modified TIMESTAMP,
6283             date_created TIMESTAMP,
6284              
6285             FOREIGN KEY (fk1, fk2, fk3) REFERENCES codes (k1, k2, k3)
6286             );
6287              
6288             CREATE TABLE prices
6289             (
6290             id SERIAL PRIMARY KEY,
6291             product_id INT REFERENCES products (id),
6292             price DECIMAL(10,2) NOT NULL DEFAULT 0.00,
6293             region CHAR(2) NOT NULL DEFAULT 'US'
6294             );
6295              
6296             First we'll auto-initialize the classes.
6297              
6298             package Code;
6299             use base qw(Rose::DB::Object);
6300             __PACKAGE__->meta->auto_initialize;
6301              
6302             package Category;
6303             use base qw(Rose::DB::Object);
6304             # Explicit table name required because the class name
6305             # does not match up with the table name in this case.
6306             __PACKAGE__->meta->table('topics');
6307             __PACKAGE__->meta->auto_initialize;
6308              
6309             package Product;
6310             use base qw(Rose::DB::Object);
6311             __PACKAGE__->meta->auto_initialize;
6312              
6313             package Price;
6314             use base qw(Rose::DB::Object);
6315             __PACKAGE__->meta->auto_initialize;
6316              
6317             Now we'll print the C<Product> class definition;
6318              
6319             print Product->meta->perl_class_definition(braces => 'bsd',
6320             indent => 2);
6321              
6322             The output looks like this:
6323              
6324             package Product;
6325              
6326             use strict;
6327              
6328             use base qw(Rose::DB::Object);
6329              
6330             __PACKAGE__->meta->setup
6331             (
6332             table => 'products',
6333              
6334             columns =>
6335             [
6336             id => { type => 'integer', not_null => 1 },
6337             name => { type => 'varchar', length => 32, not_null => 1 },
6338             flag => { type => 'boolean', default => 'true', not_null => 1 },
6339             status => { type => 'varchar', default => 'active', length => 32 },
6340             topic_id => { type => 'integer' },
6341             fk1 => { type => 'integer' },
6342             fk2 => { type => 'integer' },
6343             fk3 => { type => 'integer' },
6344             last_modified => { type => 'timestamp' },
6345             date_created => { type => 'timestamp' },
6346             ],
6347              
6348             primary_key_columns => [ 'id' ],
6349              
6350             foreign_keys =>
6351             [
6352             code =>
6353             {
6354             class => 'Code',
6355             key_columns =>
6356             {
6357             fk1 => 'k1',
6358             fk2 => 'k2',
6359             fk3 => 'k3',
6360             },
6361             },
6362              
6363             topic =>
6364             {
6365             class => 'Category',
6366             key_columns =>
6367             {
6368             topic_id => 'id',
6369             },
6370             },
6371             ],
6372              
6373             relationships =>
6374             [
6375             prices =>
6376             {
6377             class => 'Price',
6378             key_columns => { id => 'product_id' },
6379             type => 'one to many',
6380             },
6381             ],
6382             );
6383              
6384             1;
6385              
6386             Here's the output when the C<use_setup> parameter is explicitly set to false.
6387              
6388             print Product->meta->perl_class_definition(braces => 'bsd',
6389             indent => 2,
6390             use_setup => 0);
6391              
6392             Note that this approach is not recommended, but exists for historical reasons.
6393              
6394             package Product;
6395              
6396             use strict;
6397              
6398             use base qw(Rose::DB::Object);
6399              
6400             __PACKAGE__->meta->table('products');
6401              
6402             __PACKAGE__->meta->columns
6403             (
6404             id => { type => 'integer', not_null => 1 },
6405             name => { type => 'varchar', length => 32, not_null => 1 },
6406             flag => { type => 'boolean', default => 'true', not_null => 1 },
6407             status => { type => 'varchar', default => 'active', length => 32 },
6408             topic_id => { type => 'integer' },
6409             fk1 => { type => 'integer' },
6410             fk2 => { type => 'integer' },
6411             fk3 => { type => 'integer' },
6412             last_modified => { type => 'timestamp' },
6413             date_created => { type => 'timestamp' },
6414             );
6415              
6416             __PACKAGE__->meta->primary_key_columns([ 'id' ]);
6417              
6418             __PACKAGE__->meta->foreign_keys
6419             (
6420             code =>
6421             {
6422             class => 'Code',
6423             key_columns =>
6424             {
6425             fk1 => 'k1',
6426             fk2 => 'k2',
6427             fk3 => 'k3',
6428             },
6429             },
6430              
6431             topic =>
6432             {
6433             class => 'Category',
6434             key_columns =>
6435             {
6436             topic_id => 'id',
6437             },
6438             },
6439             );
6440              
6441             __PACKAGE__->meta->relationships
6442             (
6443             prices =>
6444             {
6445             class => 'Price',
6446             key_columns => { id => 'product_id' },
6447             type => 'one to many',
6448             },
6449             );
6450              
6451             __PACKAGE__->meta->initialize;
6452              
6453             1;
6454              
6455             See the L<auto-initialization|AUTO-INITIALIZATION> section for more discussion of Perl code generation.
6456              
6457             =item B<perl_columns_definition [PARAMS]>
6458              
6459             Auto-initialize the columns (if necessary), then return the Perl source code that is equivalent to the auto-initialization. PARAMS are optional name/value pairs that may include the following:
6460              
6461             =over 4
6462              
6463             =item B<braces STYLE>
6464              
6465             The brace style to use in the generated Perl code. STYLE must be either "k&r" or "bsd". The default value is determined by the return value of the L<default_perl_braces|/default_perl_braces> class method.
6466              
6467             =item B<for_setup BOOL>
6468              
6469             If true, then the generated Perl code will be a method/arguments pair suitable for use as a parameter to L<setup|/setup> method. The default is false.
6470              
6471             =item B<indent INT>
6472              
6473             The integer number of spaces to use for each level of indenting in the generated Perl code. The default value is determined by the return value of the L<default_perl_indent|/default_perl_indent> class method.
6474              
6475             =back
6476              
6477             To see examples of the generated code, look in the documentation for the L<perl_class_definition|/perl_class_definition> method.
6478              
6479             =item B<perl_foreign_keys_definition [PARAMS]>
6480              
6481             Auto-initialize the foreign keys (if necessary), then return the Perl source code that is equivalent to the auto-initialization. PARAMS are optional name/value pairs that may include the following:
6482              
6483             =over 4
6484              
6485             =item B<braces STYLE>
6486              
6487             The brace style to use in the generated Perl code. STYLE must be either "k&r" or "bsd". The default value is determined by the return value of the L<default_perl_braces|/default_perl_braces> class method.
6488              
6489             =item B<for_setup BOOL>
6490              
6491             If true, then the generated Perl code will be a method/arguments pair suitable for use as a parameter to L<setup|/setup> method. The default is false.
6492              
6493             =item B<indent INT>
6494              
6495             The integer number of spaces to use for each level of indenting in the generated Perl code. The default value is determined by the return value of the L<default_perl_indent|/default_perl_indent> class method.
6496              
6497             =back
6498              
6499             To see examples of the generated code, look in the documentation for the L<perl_class_definition|/perl_class_definition> method.
6500              
6501             =item B<perl_manager_class [ PARAMS | BASE_NAME ]>
6502              
6503             Returns a Perl class definition for a L<Rose::DB::Object::Manager>-derived class to manage objects of this L<class|/class>. If a single string is passed, it is taken as the value of the C<base_name> parameter. PARAMS are optional name/value pairs that may include the following:
6504              
6505             =over 4
6506              
6507             =item B<base_name NAME>
6508              
6509             The value of the L<base_name|Rose::DB::Object::Manager/base_name> parameter that will be passed to the call to L<Rose::DB::Object::Manager>'s L<make_manager_methods|Rose::DB::Object::Manager/make_manager_methods> method. Defaults to the return value of the L<convention manager|/convention_manager>'s L<auto_manager_base_name|Rose::DB::Object::ConventionManager/auto_manager_base_name> method.
6510              
6511             =item B<class CLASS>
6512              
6513             The name of the manager class. Defaults to the return value of the L<convention manager|/convention_manager>'s L<auto_manager_class_name|Rose::DB::Object::ConventionManager/auto_manager_class_name> method.
6514              
6515             =item B<isa [ LIST | ARRAYREF ]>
6516              
6517             The name of a single class or a reference to an array of class names to be included in the C<@ISA> array for the manager class. One of these classes must inherit from L<Rose::DB::Object::Manager>. Defaults to the return value of the C<default_manager_base_class()> L<object method|/OBJECT METHODS>.
6518              
6519             =back
6520              
6521             For example, given this class:
6522              
6523             package Product;
6524              
6525             use Rose::DB::Object;
6526             our @ISA = qw(Rose::DB::Object);
6527             ...
6528              
6529             print Product->meta->perl_manager_class(
6530             class => 'Prod::Mgr',
6531             base_name => 'prod');
6532              
6533             The following would be printed:
6534              
6535             package Prod::Mgr;
6536              
6537             use Rose::DB::Object::Manager;
6538             our @ISA = qw(Rose::DB::Object::Manager);
6539              
6540             sub object_class { 'Product' }
6541              
6542             __PACKAGE__->make_manager_methods('prod');
6543              
6544             1;
6545              
6546             =item B<perl_primary_key_columns_definition>
6547              
6548             Auto-initialize the primary key column names (if necessary), then return the Perl source code that is equivalent to the auto-initialization.
6549              
6550             See the larger example in the documentation for the L<perl_class_definition|/perl_class_definition> method to see what the generated Perl code looks like.
6551              
6552             =item B<perl_relationships_definition [PARAMS]>
6553              
6554             Auto-initialize the relationships (if necessary), then return the Perl source code that is equivalent to the auto-initialization. PARAMS are optional name/value pairs that may include the following:
6555              
6556             =over 4
6557              
6558             =item B<braces STYLE>
6559              
6560             The brace style to use in the generated Perl code. STYLE must be either "k&r" or "bsd". The default value is determined by the return value of the L<default_perl_braces|/default_perl_braces> class method.
6561              
6562             =item B<for_setup BOOL>
6563              
6564             If true, then the generated Perl code will be a method/arguments pair suitable for use as a parameter to L<setup|/setup> method. The default is false.
6565              
6566             =item B<indent INT>
6567              
6568             The integer number of spaces to use for each level of indenting in the generated Perl code. The default value is determined by the return value of the L<default_perl_indent|/default_perl_indent> class method.
6569              
6570             =back
6571              
6572             To see examples of the generated code, look in the documentation for the L<perl_class_definition|/perl_class_definition> method.
6573              
6574             =item B<perl_table_definition [PARAMS]>
6575              
6576             Auto-initialize the table name (if necessary), then return the Perl source code that is equivalent to the auto-initialization. PARAMS are optional name/value pairs that may include the following:
6577              
6578             =over 4
6579              
6580             =item B<braces STYLE>
6581              
6582             The brace style to use in the generated Perl code. STYLE must be either "k&r" or "bsd". The default value is determined by the return value of the L<default_perl_braces|/default_perl_braces> class method.
6583              
6584             =item B<for_setup BOOL>
6585              
6586             If true, then the generated Perl code will be a method/arguments pair suitable for use as a parameter to L<setup|/setup> method. The default is false.
6587              
6588             =item B<indent INT>
6589              
6590             The integer number of spaces to use for each level of indenting in the generated Perl code. The default value is determined by the return value of the L<default_perl_indent|/default_perl_indent> class method.
6591              
6592             =back
6593              
6594             To see examples of the generated code, look in the documentation for the L<perl_class_definition|/perl_class_definition> method.
6595              
6596             =item B<perl_unique_keys_definition [PARAMS]>
6597              
6598             Auto-initialize the unique keys, then return the Perl source code that is equivalent to the auto-initialization. PARAMS are optional name/value pairs that may include the following:
6599              
6600             =over 4
6601              
6602             =item B<braces STYLE>
6603              
6604             The brace style to use in the generated Perl code. STYLE must be either "k&r" or "bsd". The default value is determined by the return value of the L<default_perl_braces|/default_perl_braces> class method.
6605              
6606             =item B<for_setup BOOL>
6607              
6608             If true, then the generated Perl code will be a method/arguments pair suitable for use as a parameter to L<setup|/setup> method. The default is false.
6609              
6610             =item B<indent INT>
6611              
6612             The integer number of spaces to use for each level of indenting in the generated Perl code. The default value is determined by the return value of the L<default_perl_indent|/default_perl_indent> class method.
6613              
6614             =item B<style STYLE>
6615              
6616             Determines the style the initialization used in the generated Perl code. STYLE must be "array" or "object". The default is determined by the return value of the class method L<default_perl_unique_key_style|/default_perl_unique_key_style>.
6617              
6618             The "array" style passes references to arrays of column names:
6619              
6620             __PACKAGE__->meta->unique_keys
6621             (
6622             [ 'id', 'name' ],
6623             [ 'flag', 'status' ],
6624             );
6625              
6626             The "object" style sets unique keys using calls to the L<Rose::DB::Object::Metadata::UniqueKey> constructor:
6627              
6628             __PACKAGE__->meta->unique_keys
6629             (
6630             Rose::DB::Object::Metadata::UniqueKey->new(
6631             name => 'products_id_key',
6632             columns => [ 'id', 'name' ]),
6633              
6634             Rose::DB::Object::Metadata::UniqueKey->new(
6635             name => 'products_flag_key',
6636             columns => [ 'flag', 'status' ]),
6637             );
6638              
6639             =back
6640              
6641             =back
6642              
6643             =head1 AUTHOR
6644              
6645             John C. Siracusa (siracusa@gmail.com)
6646              
6647             =head1 LICENSE
6648              
6649             Copyright (c) 2010 by John C. Siracusa. All rights reserved. This program is
6650             free software; you can redistribute it and/or modify it under the same terms
6651             as Perl itself.