1package Rose::DB::Object::Metadata;
2
3use strict;
4
5use Carp();
6
7use Rose::Object;
8our @ISA = qw(Rose::Object);
9
10use Rose::DB::Object::Util qw(lazy_column_values_loaded_key);
11use Rose::DB::Object::Constants
12  qw(PRIVATE_PREFIX STATE_IN_DB MODIFIED_COLUMNS);
13
14use Rose::DB::Object::ConventionManager;
15use Rose::DB::Object::ConventionManager::Null;
16use Rose::DB::Object::Metadata::PrimaryKey;
17use Rose::DB::Object::Metadata::UniqueKey;
18use Rose::DB::Object::Metadata::ForeignKey;
19use Rose::DB::Object::Metadata::Column::Scalar;
20use Rose::DB::Object::Metadata::Relationship::OneToOne;
21
22# Attempt to load Scalar::Util::Clone at runtime and ignore any errors
23# to keep it from being a "hard" requirement.
24eval { local $@; require Scalar::Util::Clone };
25
26use Clone(); # This is the backup clone method
27
28our $VERSION = '0.799';
29
30our $Debug = 0;
31
32#
33# Object data
34#
35
36use Rose::Object::MakeMethods::Generic
37(
38  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);
80
81#
82# Class data
83#
84
85use Rose::Class::MakeMethods::Generic
86(
87  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);
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
225sub init_column_name_to_method_name_mapper() { 0 }
226
227our %Objects;
228
229sub new
230{
231  my($this_class, %args) = @_;
232  my $class = $args{'class'} or Carp::croak "Missing required 'class' parameter";
233  return $Objects{$class} ||= shift->SUPER::new(@_);
234}
235
236sub init
237{
238  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  $self->sql_qualify_column_names_on_load(0);
243
244  $self->SUPER::init(@_);
245}
246
247sub init_original_class { ref shift }
248
249sub init_auto_prime_caches { $ENV{'MOD_PERL'} ? 1 : 0 }
250
251sub default_manager_base_class
252{
253  my($self_or_class) = shift;
254
255  if(ref($self_or_class))
256  {
257    return $self_or_class->_object_default_manager_base_class(@_) ||
258      ref($self_or_class)->_class_default_manager_base_class;
259  }
260
261  return $self_or_class->_class_default_manager_base_class(@_);
262}
263
264sub reset
265{
266  my($self) = shift;
267
268  $self->is_initialized(0);
269  $self->allow_auto_initialization(0);
270  $self->was_auto_initialized(0);
271  $self->initialized_foreign_keys(0);
272
273  return;
274}
275
276sub clone
277{
278  my($self) = shift;
279
280  # The easy way: use Scalar::Util::Clone
281  if(defined $Scalar::Util::Clone::VERSION)
282  {
283    return Scalar::Util::Clone::clone($self);
284  }
285
286  # The hard way: Clone.pm plus mucking
287  my $meta = Clone::clone($self);
288
289  # Reset all the parent back-links
290  foreach my $item (grep { defined } $meta->columns, $meta->primary_key,
291                    $meta->unique_keys, $meta->foreign_keys,
292                    $meta->relationships)
293  {
294    $item->parent($meta);
295  }
296
297  return $meta;
298}
299
300sub allow_inheritance_from_meta
301{
302  my($class, $meta) = @_;
303  return $meta->num_columns > 0 ? 1 : 0;
304}
305
306sub for_class
307{
308  my($meta_class, $class) = (shift, shift);
309  return $Objects{$class}  if($Objects{$class});
310
311  # Clone an ancestor meta object
312  foreach my $parent_class (__get_parents($class))
313  {
314    if(my $parent_meta = $Objects{$parent_class})
315    {
316      next  unless($meta_class->allow_inheritance_from_meta($parent_meta));
317
318      my $meta = $parent_meta->clone;
319
320      $meta->reset(0);
321      $meta->class($class);
322
323      return $Objects{$class} = $meta;
324    }
325  }
326
327  return $Objects{$class} = $meta_class->new(class => $class);
328}
329
330sub __get_parents
331{
332  my($class) = shift;
333  my @parents;
334
335  no strict 'refs';
336  foreach my $sub_class (@{"${class}::ISA"})
337  {
338    push(@parents, __get_parents($sub_class))  if($sub_class->isa('Rose::DB::Object'));
339  }
340
341  return $class, @parents;
342}
343
344sub clear_all_dbs
345{
346  my($class) = shift;
347
348  foreach my $obj_class ($class->registered_classes)
349  {
350    $obj_class->meta->db(undef);
351  }
352}
353
354sub error_mode
355{
356  return $_[0]->{'error_mode'} ||= $_[0]->init_error_mode
357    unless(@_ > 1);
358
359  my($self, $mode) = @_;
360
361  unless($mode =~ /^(?:return|carp|croak|cluck|confess|fatal)$/)
362  {
363    Carp::croak "Invalid error mode: '$mode'";
364  }
365
366  return $self->{'error_mode'} = $mode;
367}
368
369sub init_error_mode { 'fatal' }
370
371sub handle_error
372{
373  my($self, $object) = @_;
374
375  my $mode = $self->error_mode;
376
377  return  if($mode eq 'return');
378
379  my $level =  $Carp::CarpLevel;
380  local $Carp::CarpLevel = $level + 1;
381
382  if($mode eq 'croak' || $mode eq 'fatal')
383  {
384    Carp::croak $object->error;
385  }
386  elsif($mode eq 'carp')
387  {
388    Carp::carp $object->error;
389  }
390  elsif($mode eq 'cluck')
391  {
392    Carp::cluck $object->error;
393  }
394  elsif($mode eq 'confess')
395  {
396    Carp::confess $object->error;
397  }
398  else
399  {
400    Carp::croak "(Invalid error mode set: '$mode') - ", $object->error;
401  }
402
403  return 1;
404}
405
406sub setup
407{
408  my($self) = shift;
409
410  return 1  if($self->is_initialized);
411
412  my $init_args = [];
413  my $auto_init = 0;
414
415  PAIR: while(@_)
416  {
417    my $method = shift;
418
419    if(ref $method eq 'CODE')
420    {
421      $method->($self);
422      next PAIR;
423    }
424
425    my $args = shift;
426
427    if($method =~ /^((?:auto_(?!helper)|(?:default_)?perl_)\w*)$/)
428    {
429      $self->init_auto_helper;
430    }
431
432    if($method eq 'initialize')
433    {
434      $init_args = ref $args ? $args : [ $args ];
435      next PAIR;
436    }
437    elsif($method eq 'auto_initialize' || $method eq 'auto')
438    {
439      unless($method eq 'auto' && !ref $args)
440      {
441        $init_args = ref $args ? $args : [ $args ];
442      }
443
444      $auto_init = 1;
445      next PAIR;
446    }
447    elsif($method eq 'helpers')
448    {
449      require Rose::DB::Object::Helpers;
450
451      Rose::DB::Object::Helpers->import(
452        '--target-class' => $self->class, (ref $args eq 'ARRAY' ? @$args : $args));
453
454      next PAIR;
455    }
456
457    unless($self->can($method))
458    {
459      Carp::croak "Invalid parameter name: '$method'";
460    }
461
462    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      if(($method eq 'unique_key' || $method eq 'add_unique_key') &&
468         !grep { ref } @$args)
469      {
470        $self->$method($args);
471      }
472      else
473      {
474        $self->$method(@$args);
475      }
476    }
477    else
478    {
479      $self->$method($args);
480    }
481  }
482
483  if($auto_init)
484  {
485    $self->auto_initialize(@$init_args);
486  }
487  else
488  {
489    $self->initialize(@$init_args);
490  }
491
492  return 1;
493}
494
495sub init_db
496{
497  my($self) = shift;
498
499  my $class = $self->class or die "Missing class!";
500
501  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  $self->{'db_id'} = $db->{'id'};
506
507  return $db;
508}
509
510sub init_db_id
511{
512  my($self) = shift;
513  $self->init_db;
514  return $self->{'db_id'};
515}
516
517sub init_convention_manager { shift->convention_manager_class('default')->new }
518
519sub convention_manager
520{
521  my($self) = shift;
522
523  if(@_)
524  {
525    my $mgr = shift;
526
527    # Setting to undef means use the null convention manager
528    if(!defined $mgr)
529    {
530      return $self->{'convention_manager'} =
531        Rose::DB::Object::ConventionManager::Null->new(parent => $self);
532    }
533    elsif(!ref $mgr)
534    {
535      if(UNIVERSAL::isa($mgr, 'Rose::DB::Object::ConventionManager'))
536      {
537        $mgr = $mgr->new;
538      }
539      else
540      {
541        my $class = $self->convention_manager_class($mgr) or
542          Carp::croak "No convention manager class registered under the name '$mgr'";
543
544        $mgr = $class->new;
545      }
546    }
547    elsif(!UNIVERSAL::isa($mgr, 'Rose::DB::Object::ConventionManager'))
548    {
549      Carp::croak "$mgr is not a Rose::DB::Object::ConventionManager-derived object";
550    }
551
552    $mgr->parent($self);
553    return $self->{'convention_manager'} = $mgr;
554  }
555
556  if(defined $self->{'convention_manager'})
557  {
558    return $self->{'convention_manager'};
559  }
560
561  my $mgr = $self->init_convention_manager;
562  $mgr->parent($self);
563  return $self->{'convention_manager'} = $mgr;
564}
565
566sub cached_objects_expire_in { shift->class->cached_objects_expire_in(@_) }
567sub clear_object_cache       { shift->class->clear_object_cache(@_) }
568
569sub prepare_select_options
570{
571  @_ > 1 ? $_[0]->{'prepare_select_options'} = $_[1] :
572           $_[0]->{'prepare_select_options'} ||= {}
573}
574
575sub prepare_insert_options
576{
577  @_ > 1 ? $_[0]->{'prepare_insert_options'} = $_[1] :
578           $_[0]->{'prepare_insert_options'} ||= {}
579}
580
581sub prepare_update_options
582{
583  @_ > 1 ? $_[0]->{'prepare_update_options'} = $_[1] :
584           $_[0]->{'prepare_update_options'} ||= {}
585}
586
587sub prepare_delete_options
588{
589  @_ > 1 ? $_[0]->{'prepare_delete_options'} = $_[1] :
590           $_[0]->{'prepare_delete_options'} ||= {}
591}
592
593sub prepare_bulk_delete_options
594{
595  @_ > 1 ? $_[0]->{'prepare_bulk_delete_options'} = $_[1] :
596           $_[0]->{'prepare_bulk_delete_options'} ||=
597           $_[0]->prepare_delete_options;
598}
599
600sub prepare_bulk_update_options
601{
602  @_ > 1 ? $_[0]->{'prepare_bulk_update_options'} = $_[1] :
603           $_[0]->{'prepare_bulk_update_options'} ||=
604           $_[0]->prepare_update_options;
605}
606
607sub prepare_options
608{
609  my($self, $options) = @_;
610
611  Carp::croak "Missing required hash ref argument to prepare_options()"
612    unless(ref $options eq 'HASH');
613
614  $self->prepare_select_options({ %$options });
615  $self->prepare_insert_options({ %$options });
616  $self->prepare_update_options({ %$options });
617  $self->prepare_delete_options({ %$options });
618}
619
620sub table
621{
622  unless(@_ > 1)
623  {
624    return $_[0]->{'table'} ||= $_[0]->convention_manager->auto_table_name;
625  }
626
627  $_[0]->_clear_table_generated_values;
628  return $_[0]->{'table'} = $_[1];
629}
630
631sub catalog
632{
633  return $_[0]->{'catalog'}  unless(@_ > 1);
634  $_[0]->_clear_table_generated_values;
635  return $_[0]->{'catalog'} = $_[1];
636}
637
638sub select_catalog
639{
640  my($self, $db) = @_;
641  return undef  if($db && !$db->supports_catalog);
642  return $self->{'catalog'} || ($db ? $db->catalog : undef);
643}
644
645sub schema
646{
647  return $_[0]->{'schema'}  unless(@_ > 1);
648  $_[0]->_clear_table_generated_values;
649  return $_[0]->{'schema'} = $_[1];
650}
651
652sub select_schema
653{
654  my($self, $db) = @_;
655  return undef  if($db && !$db->supports_schema);
656  return $self->{'schema'} || ($db ? $db->schema : undef);
657}
658
659sub sql_qualify_column_names_on_load
660{
661  my($self) = shift;
662
663  if(@_)
664  {
665    my $value = $_[0] ? 1 : 0;
666
667    no warnings 'uninitialized';
668    if($value != $self->{'sql_qualify_column_names_on_load'})
669    {
670      $self->{'sql_qualify_column_names_on_load'} = $value;
671      $self->_clear_column_generated_values;
672      $self->prime_caches  if($self->is_initialized);
673    }
674  }
675
676  return $self->{'sql_qualify_column_names_on_load'};
677}
678
679sub key_column_names
680{
681  my($self) = shift;
682
683  $self->{'key_column_names'} ||=
684    [ $self->primary_key_columns, $self->unique_keys_column_names ];
685
686  return wantarray ? @{$self->{'key_column_names'}} : $self->{'key_column_names'};
687}
688
689sub init_primary_key
690{
691  Rose::DB::Object::Metadata::PrimaryKey->new(parent => shift);
692}
693
694sub primary_key_generator    { shift->primary_key->generator(@_)    }
695sub primary_key_columns      { shift->primary_key->columns(@_)      }
696sub primary_key_column_names { shift->primary_key->column_names(@_) }
697sub pk_columns               { shift->primary_key_columns(@_)       }
698
699sub primary_key_column_names_or_aliases
700{
701  my($self) = shift;
702
703  if($self->{'primary_key_column_names_or_aliases'})
704  {
705    return $self->{'primary_key_column_names_or_aliases'};
706  }
707
708  return $self->{'primary_key_column_names_or_aliases'} =
709    [ map { $_->alias || $_->name } $self->primary_key_columns ];
710}
711
712sub init_primary_key_column_info
713{
714  my($self) = shift;
715
716  my $pk_position = 0;
717
718  foreach my $col_name ($self->primary_key_column_names)
719  {
720    $pk_position++;
721    my $column = $self->column($col_name) or next;
722    $column->is_primary_key_member(1);
723    $column->primary_key_position($pk_position);
724  }
725
726  $self->_clear_primary_key_column_generated_values;
727
728  # Init these by asking for them
729  $self->primary_key_column_accessor_names;
730  $self->primary_key_column_mutator_names;
731
732  return;
733}
734
735sub add_primary_key_columns
736{
737  my($self) = shift;
738
739  $self->primary_key->add_columns(@_);
740  $self->init_primary_key_column_info;
741
742  return;
743}
744
745sub add_primary_key_column { shift->add_primary_key_columns(@_) }
746
747sub add_unique_keys
748{
749  my($self) = shift;
750
751  if(@_ == 1 && ref $_[0] eq 'ARRAY')
752  {
753    push @{$self->{'unique_keys'}},
754         Rose::DB::Object::Metadata::UniqueKey->new(parent => $self, columns => $_[0]);
755  }
756  else
757  {
758    push @{$self->{'unique_keys'}}, map
759    {
760      UNIVERSAL::isa($_, 'Rose::DB::Object::Metadata::UniqueKey') ?
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  return;
770}
771
772sub unique_key_by_name
773{
774  my($self, $name) = @_;
775
776  foreach my $uk ($self->unique_keys)
777  {
778    return $uk  if($uk->name eq $name);
779  }
780
781  return undef;
782}
783
784sub add_unique_key { shift->add_unique_keys(@_)  }
785sub unique_key     { \shift->add_unique_keys(@_) }
786
787sub delete_unique_keys { $_[0]->{'unique_keys'} = [] }
788
789sub unique_keys
790{
791  my($self) = shift;
792
793  if(@_)
794  {
795    $self->delete_unique_keys;
796    $self->add_unique_keys(@_);
797  }
798
799  wantarray ? @{$self->{'unique_keys'} ||= []} : ($self->{'unique_keys'} ||= []);
800}
801
802sub unique_keys_column_names
803{
804  wantarray ?   map { scalar $_->column_names } @{shift->{'unique_keys'} ||= []} :
805              [ map { scalar $_->column_names } @{shift->{'unique_keys'} ||= []} ];
806}
807
808sub delete_column
809{
810  my($self, $name) = @_;
811  delete $self->{'columns'}{$name};
812
813  # Remove from ordered list too
814  my $columns = $self->columns_ordered;
815
816  for(my $i = 0; $i < @$columns; $i++)
817  {
818    if($columns->[$i]->name eq $name)
819    {
820      splice(@$columns, $i, 1);
821      last;
822    }
823  }
824
825  return;
826}
827
828sub delete_columns
829{
830  my($self, $name) = @_;
831  $self->{'columns'} = {};
832  $self->{'columns_ordered'} = [];
833  return;
834}
835
836sub delete_nonpersistent_columns
837{
838  my($self, $name) = @_;
839  $self->{'nonpersistent_columns'} = {};
840  $self->{'nonpersistent_columns_ordered'} = [];
841  return;
842}
843
844sub delete_nonpersistent_column
845{
846  my($self, $name) = @_;
847  delete $self->{'nonpersistent_columns'}{$name};
848
849  # Remove from ordered list too
850  my $columns = $self->nonpersistent_columns_ordered;
851
852  for(my $i = 0; $i < @$columns; $i++)
853  {
854    if($columns->[$i]->name eq $name)
855    {
856      splice(@$columns, $i, 1);
857      last;
858    }
859  }
860
861  return;
862}
863
864sub first_column { shift->columns_ordered->[0] }
865
866sub sync_keys_to_columns
867{
868  my($self) = shift;
869
870  $self->_clear_column_generated_values;
871
872  my %columns = map { $_->name => 1 } $self->columns_ordered;
873
874  foreach my $col_name ($self->primary_key_column_names)
875  {
876    unless($columns{$col_name})
877    {
878      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  my @valid_uks;
886
887  UK: foreach my $uk ($self->unique_keys)
888  {
889    foreach my $col_name ($uk->column_names)
890    {
891      unless($columns{$col_name})
892      {
893        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    push(@valid_uks, $uk);
900  }
901
902  $self->unique_keys(@valid_uks);
903
904  return;
905}
906
907sub replace_column
908{
909  my($self) = shift;
910
911  unless(@_ == 2)
912  {
913    Carp::croak "Missing column name and value arguments"        if(@_ < 2);
914    Carp::croak "Too many arguments passed to replace_column()"  if(@_ < 2);
915  }
916
917  return $self->column(@_);
918}
919
920sub column
921{
922  my($self, $name) = (shift, shift);
923
924  if(@_)
925  {
926    $self->delete_column($name);
927    $self->add_column($name => @_);
928  }
929
930  return $self->{'columns'}{$name}  if($self->{'columns'}{$name});
931  return undef;
932}
933
934sub nonpersistent_column
935{
936  my($self, $name) = (shift, shift);
937
938  if(@_)
939  {
940    $self->delete_nonpersistent_column($name);
941    $self->add_nonpersistent_column($name => @_);
942  }
943
944  return $self->{'nonpersistent_columns'}{$name}  if($self->{'nonpersistent_columns'}{$name});
945  return undef;
946}
947
948
949sub columns
950{
951  my($self) = shift;
952
953  if(@_)
954  {
955    $self->delete_columns;
956    $self->add_columns(@_);
957  }
958
959  return $self->columns_ordered;
960}
961
962sub nonpersistent_columns
963{
964  my($self) = shift;
965
966  if(@_)
967  {
968    $self->delete_nonpersistent_columns;
969    $self->add_nonpersistent_columns(@_);
970  }
971
972  return $self->nonpersistent_columns_ordered;
973}
974
975sub num_columns
976{
977  my($self) = shift;
978  return $self->{'num_columns'} ||= scalar(@{$self->columns_ordered});
979}
980
981sub nonlazy_columns
982{
983  my($self) = shift;
984
985  return wantarray ?
986    (grep { !$_->lazy } $self->columns_ordered) :
987    [ grep { !$_->lazy } $self->columns_ordered ];
988}
989
990sub lazy_columns
991{
992  my($self) = shift;
993
994  return wantarray ?
995    (grep { $_->lazy } $self->columns_ordered) :
996    [ grep { $_->lazy } $self->columns_ordered ];
997}
998
999# XXX: Super-lame code sharing via dynamically-scoped flag var
1000our $Nonpersistent;
1001
1002sub add_nonpersistent_columns
1003{
1004  local $Nonpersistent = 1;
1005  shift->_add_columns(@_);
1006}
1007
1008sub add_nonpersistent_column { shift->add_nonpersistent_columns(@_) }
1009
1010sub add_columns
1011{
1012  local $Nonpersistent = 0;
1013  shift->_add_columns(@_);
1014}
1015
1016sub add_column { shift->add_columns(@_) }
1017
1018sub _add_columns
1019{
1020  my($self) = shift;
1021
1022  my $class = ref $self;
1023
1024  my(@columns, @nonpersistent_columns);
1025
1026  ARG: while(@_)
1027  {
1028    my $name = shift;
1029
1030    if(UNIVERSAL::isa($name, 'Rose::DB::Object::Metadata::Column'))
1031    {
1032      my $column = $name;
1033
1034      Carp::croak "Relationship $column lacks a name()"
1035        unless($column->name =~ /\S/);
1036
1037      $column->parent($self);
1038      $column->nonpersistent(1)  if($Nonpersistent);
1039
1040      if($column->nonpersistent)
1041      {
1042        $self->{'nonpersistent_columns'}{$column->name} = $column;
1043        push(@nonpersistent_columns, $column);
1044      }
1045      else
1046      {
1047        $self->{'columns'}{$column->name} = $column;
1048        push(@columns, $column);
1049      }
1050
1051      next;
1052    }
1053
1054    unless(ref $_[0]) # bare column name, persistent only
1055    {
1056      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      $self->{'columns'}{$name} = $column_class->new(name => $name, parent => $self);
1061      push(@columns, $self->{'columns'}{$name});
1062      next;
1063    }
1064
1065    if(UNIVERSAL::isa($_[0], 'Rose::DB::Object::Metadata::Column'))
1066    {
1067      my $column = $_[0];
1068      $column->name($name);
1069      $column->parent($self);
1070
1071      $column->nonpersistent(1)  if($Nonpersistent);
1072
1073      if($column->nonpersistent)
1074      {
1075        $self->{'nonpersistent_columns'}{$column->name} = $column;
1076        push(@nonpersistent_columns, $column);
1077      }
1078      else
1079      {
1080        $self->{'columns'}{$column->name} = $column;
1081        push(@columns, $column);
1082      }
1083    }
1084    elsif(ref $_[0] eq 'HASH')
1085    {
1086      my $info = shift;
1087
1088      my $alias = $info->{'alias'};
1089
1090      if($info->{'primary_key'})
1091      {
1092        #$Debug && warn $self->class, " - adding primary key column $name\n";
1093        $self->add_primary_key_column($name);
1094      }
1095
1096      my $methods     = delete $info->{'methods'};
1097      my $add_methods = delete $info->{'add_methods'};
1098
1099      if($methods && $add_methods)
1100      {
1101        Carp::croak "Cannot specify both 'methods' and 'add_methods' - ",
1102                    "pick one or the other";
1103      }
1104
1105      my $type = $info->{'type'} ||= 'scalar';
1106
1107      my $column_class = $self->original_class->column_type_class($type)
1108        or Carp::croak "No column class set for column type '$type'";
1109
1110      unless($self->column_class_is_loaded($column_class))
1111      {
1112        $self->load_column_class($column_class);
1113      }
1114
1115      my %triggers;
1116
1117      foreach my $event ($column_class->trigger_events)
1118      {
1119        $triggers{$event} = delete $info->{$event}  if(exists $info->{$event});
1120      }
1121
1122      if(delete $info->{'temp'}) # coerce temp to nonpersistent
1123      {
1124        $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      my $column =
1131        $column_class->new(parent => $self, %$info, name => $name);
1132
1133      $column->nonpersistent(1)  if($Nonpersistent);
1134
1135      if($column->nonpersistent)
1136      {
1137        $self->{'nonpersistent_columns'}{$column->name} = $column;
1138        push(@nonpersistent_columns, $column);
1139      }
1140      else
1141      {
1142        $self->{'columns'}{$column->name} = $column;
1143        push(@columns, $column);
1144      }
1145
1146      # Set or add auto-created method names
1147      if($methods || $add_methods)
1148      {
1149        my $auto_method_name =
1150          $methods ? 'auto_method_types' : 'add_auto_method_types';
1151
1152        my $methods_arg = $methods || $add_methods;
1153
1154        if(ref $methods_arg eq 'HASH')
1155        {
1156          $methods = [ keys %$methods_arg ];
1157
1158          while(my($type, $name) = each(%$methods_arg))
1159          {
1160            next  unless(defined $name);
1161            $column->method_name($type => $name);
1162          }
1163        }
1164        else
1165        {
1166          $methods = $methods_arg;
1167        }
1168
1169        $column->$auto_method_name($methods);
1170      }
1171
1172      if(defined $alias)
1173      {
1174        $column->alias($alias);
1175        $self->alias_column($name, $alias);
1176      }
1177
1178      if(%triggers)
1179      {
1180        while(my($event, $value) = each(%triggers))
1181        {
1182          Carp::croak "Missing code reference for $event trigger"
1183            unless($value);
1184
1185          foreach my $code (ref $value eq 'ARRAY' ? @$value : $value)
1186          {
1187            $column->add_trigger(event => $event,
1188                                 code  => $code);
1189          }
1190        }
1191      }
1192    }
1193    else
1194    {
1195      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  foreach my $column (@columns)
1202  {
1203    if($column->can('smart_modification') && !defined $column->{'smart_modification'})
1204    {
1205      $column->smart_modification($self->default_smart_modification);
1206    }
1207  }
1208
1209  if(@columns)
1210  {
1211    push(@{$self->{'columns_ordered'}}, @columns);
1212    $self->_clear_column_generated_values;
1213  }
1214
1215  if(@nonpersistent_columns)
1216  {
1217    push(@{$self->{'nonpersistent_columns_ordered'}}, @nonpersistent_columns);
1218    $self->_clear_nonpersistent_column_generated_values;
1219  }
1220
1221  return wantarray ? (@columns, @nonpersistent_columns) :  [ @columns, @nonpersistent_columns ];
1222}
1223
1224sub relationship
1225{
1226  my($self, $name) = (shift, shift);
1227
1228  if(@_)
1229  {
1230    $self->delete_relationship($name);
1231    $self->add_relationship($name => $_[0]);
1232  }
1233
1234  return $self->{'relationships'}{$name}  if($self->{'relationships'}{$name});
1235  return undef;
1236}
1237
1238sub delete_relationship
1239{
1240  my($self, $name) = @_;
1241  delete $self->{'relationships'}{$name};
1242  return;
1243}
1244
1245sub relationships
1246{
1247  my($self) = shift;
1248
1249  if(@_)
1250  {
1251    $self->delete_relationships;
1252    $self->add_relationships(@_);
1253  }
1254
1255  return wantarray ?
1256    (sort { $a->name cmp $b->name } values %{$self->{'relationships'} ||= {}}) :
1257    [ sort { $a->name cmp $b->name } values %{$self->{'relationships'} ||= {}} ];
1258}
1259
1260sub delete_relationships
1261{
1262  my($self) = shift;
1263
1264  # Delete everything except fk proxy relationships
1265  foreach my $name (keys %{$self->{'relationships'} || {}})
1266  {
1267    delete $self->{'relationships'}{$name}
1268      unless($self->{'relationships'}{$name}->foreign_key);
1269  }
1270
1271  return;
1272}
1273
1274sub add_relationships
1275{
1276  my($self) = shift;
1277
1278  my $class = ref $self;
1279
1280  ARG: while(@_)
1281  {
1282    my $name = shift;
1283
1284    # Relationship object
1285    if(UNIVERSAL::isa($name, 'Rose::DB::Object::Metadata::Relationship'))
1286    {
1287      my $relationship = $name;
1288
1289      Carp::croak "Relationship $relationship lacks a name()"
1290        unless($relationship->name =~ /\S/);
1291
1292      if(defined $self->{'relationships'}{$relationship->name})
1293      {
1294        Carp::croak $self->class, " already has a relationship named '",
1295                    $relationship->name, "'";
1296      }
1297
1298      $relationship->parent($self);
1299      $self->{'relationships'}{$relationship->name} = $relationship;
1300      next;
1301    }
1302
1303    # Name and type only: recurse with hashref arg
1304    if(!ref $_[0])
1305    {
1306      my $type = shift;
1307
1308      $self->add_relationships($name => { type => $type });
1309      next ARG;
1310    }
1311
1312    if(UNIVERSAL::isa($_[0], 'Rose::DB::Object::Metadata::Relationship'))
1313    {
1314      my $relationship = shift;
1315
1316      $relationship->name($name);
1317      $relationship->parent($self);
1318      $self->{'relationships'}{$name} = $relationship;
1319    }
1320    elsif(ref $_[0] eq 'HASH')
1321    {
1322      my $info = shift;
1323
1324      if(defined $self->{'relationships'}{$name})
1325      {
1326        Carp::croak $self->class, " already has a relationship named '$name'";
1327      }
1328
1329      my $methods     = delete $info->{'methods'};
1330      my $add_methods = delete $info->{'add_methods'};
1331
1332      if($methods && $add_methods)
1333      {
1334        Carp::croak "Cannot specify both 'methods' and 'add_methods' - ",
1335                    "pick one or the other";
1336      }
1337
1338      my $type = $info->{'type'} or
1339        Carp::croak "Missing type parameter for relationship '$name'";
1340
1341      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      if($methods || $add_methods)
1348      {
1349        my $auto_method_name =
1350          $methods ? 'auto_method_types' : 'add_auto_method_types';
1351
1352        my $methods_arg = $methods || $add_methods;
1353
1354        if(ref $methods_arg eq 'HASH')
1355        {
1356          $methods = [ keys %$methods_arg ];
1357
1358          while(my($type, $name) = each(%$methods_arg))
1359          {
1360            next  unless(defined $name);
1361            $relationship->method_name($type => $name);
1362          }
1363        }
1364        else
1365        {
1366          $methods = $methods_arg;
1367        }
1368
1369        $relationship->$auto_method_name($methods);
1370      }
1371    }
1372    else
1373    {
1374      Carp::croak "Invalid relationship name or specification: $_[0]";
1375    }
1376  }
1377}
1378
1379sub _build_relationship
1380{
1381  my($self, %args) = @_;
1382
1383  my $class = ref $self;
1384  my $name = $args{'name'} or Carp::croak "Missing name parameter";
1385  my $info = $args{'info'} or Carp::croak "Missing info parameter";
1386  my $type = $args{'type'} or
1387    Carp::croak "Missing type parameter for relationship '$name'";
1388
1389  my $relationship_class = $class->relationship_type_class($type)
1390    or Carp::croak "No relationship class set for relationship type '$type'";
1391
1392  unless($self->relationship_class_is_loaded($relationship_class))
1393  {
1394    $self->load_relationship_class($relationship_class);
1395  }
1396
1397  $Debug && warn $self->class, " - adding $name $relationship_class\n";
1398  my $relationship =
1399    $self->convention_manager->auto_relationship($name, $relationship_class, $info) ||
1400    $relationship_class->new(%$info, name => $name);
1401
1402  unless($relationship)
1403  {
1404    Carp::croak "$class - Incomplete relationship specification could not be ",
1405                "completed by convention manager: $name";
1406  }
1407
1408  $relationship->parent($self);
1409
1410  return $relationship;
1411}
1412
1413sub add_relationship { shift->add_relationships(@_) }
1414
1415my %Class_Loaded;
1416
1417sub load_column_class
1418{
1419  my($self, $column_class) = @_;
1420
1421  unless(UNIVERSAL::isa($column_class, 'Rose::DB::Object::Metadata::Column'))
1422  {
1423    my $error;
1424
1425    TRY:
1426    {
1427      local $@;
1428      eval "require $column_class";
1429      $error = $@;
1430    }
1431
1432    Carp::croak "Could not load column class '$column_class' - $error"
1433      if($error);
1434  }
1435
1436  $Class_Loaded{$column_class}++;
1437}
1438
1439sub column_class_is_loaded { $Class_Loaded{$_[1]} }
1440
1441sub column_type_class
1442{
1443  my($class, $type) = (shift, shift);
1444  return $class->_column_type_class(lc $type, @_)
1445}
1446
1447sub delete_column_type_class
1448{
1449  my($class, $type) = (shift, shift);
1450  return $class->_delete_column_type_class(lc $type, @_)
1451}
1452
1453sub load_relationship_class
1454{
1455  my($self, $relationship_class) = @_;
1456
1457  my $error;
1458
1459  TRY:
1460  {
1461    local $@;
1462    eval "require $relationship_class";
1463    $error = $@;
1464  }
1465
1466  Carp::croak "Could not load relationship class '$relationship_class' - $error"
1467    if($error);
1468
1469  $Class_Loaded{$relationship_class}++;
1470}
1471
1472sub relationship_class_is_loaded { $Class_Loaded{$_[1]} }
1473
1474sub add_foreign_keys
1475{
1476  my($self) = shift;
1477
1478  ARG: while(@_)
1479  {
1480    my $name = shift;
1481
1482    # Foreign key object
1483    if(UNIVERSAL::isa($name, 'Rose::DB::Object::Metadata::ForeignKey'))
1484    {
1485      my $fk = $name;
1486
1487      Carp::croak "Foreign key $fk lacks a name()"
1488        unless($fk->name =~ /\S/);
1489
1490      if(defined $self->{'foreign_keys'}{$fk->name})
1491      {
1492        Carp::croak $self->class, " already has a foreign key named '",
1493                    $fk->name, "'";
1494      }
1495
1496      $fk->parent($self);
1497
1498      $self->{'foreign_keys'}{$fk->name} = $fk;
1499
1500      unless(defined $self->relationship($fk->name))
1501      {
1502        $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      next ARG;
1511    }
1512
1513    # Name only: try to get all the other info by convention
1514    if(!ref $_[0])
1515    {
1516      if(my $fk = $self->convention_manager->auto_foreign_key($name))
1517      {
1518        $self->add_foreign_keys($fk);
1519        next ARG;
1520      }
1521      else
1522      {
1523        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    if(ref $_[0] eq 'HASH')
1531    {
1532      my $info = shift;
1533
1534      if(defined $self->{'foreign_keys'}{$name})
1535      {
1536        Carp::croak $self->class, " already has a foreign key named '$name'";
1537      }
1538
1539      my $methods     = delete $info->{'methods'};
1540      my $add_methods = delete $info->{'add_methods'};
1541
1542      if($methods && $add_methods)
1543      {
1544        Carp::croak "Cannot specify both 'methods' and 'add_methods' - ",
1545                    "pick one or the other";
1546      }
1547
1548      $Debug && warn $self->class, " - adding $name foreign key\n";
1549      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      $fk->parent($self);
1554
1555      # Set or add auto-created method names
1556      if($methods || $add_methods)
1557      {
1558        my $auto_method_name =
1559          $methods ? 'auto_method_types' : 'add_auto_method_types';
1560
1561        my $methods_arg = $methods || $add_methods;
1562
1563        if(ref $methods_arg eq 'HASH')
1564        {
1565          $methods = [ keys %$methods_arg ];
1566
1567          while(my($type, $name) = each(%$methods_arg))
1568          {
1569            next  unless(defined $name);
1570            $fk->method_name($type => $name);
1571          }
1572        }
1573        else
1574        {
1575          $methods = $methods_arg;
1576        }
1577
1578        $fk->$auto_method_name($methods);
1579      }
1580
1581      unless(defined $self->relationship($name))
1582      {
1583        $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      Carp::croak "Invalid foreign key specification: $_[0]";
1593    }
1594  }
1595}
1596
1597sub add_foreign_key { shift->add_foreign_keys(@_) }
1598
1599sub foreign_key
1600{
1601  my($self, $name) = (shift, shift);
1602
1603  if(@_)
1604  {
1605    $self->delete_foreign_key($name);
1606    $self->add_foreign_key($name => @_);
1607  }
1608
1609  return $self->{'foreign_keys'}{$name}  if($self->{'foreign_keys'}{$name});
1610  return undef;
1611}
1612
1613sub delete_foreign_key
1614{
1615  my($self, $name) = @_;
1616  delete $self->{'foreign_keys'}{$name};
1617  return;
1618}
1619
1620sub delete_foreign_keys
1621{
1622  my($self) = shift;
1623
1624  # Delete fk proxy relationship
1625  foreach my $fk (values %{$self->{'foreign_keys'}})
1626  {
1627    foreach my $rel ($self->relationships)
1628    {
1629      no warnings 'uninitialized';
1630      if($rel->foreign_key eq $fk)
1631      {
1632        $self->delete_relationship($rel->name);
1633      }
1634    }
1635  }
1636
1637  # Delete fks
1638  $self->{'foreign_keys'} = {};
1639
1640  return;
1641}
1642
1643sub foreign_keys
1644{
1645  my($self) = shift;
1646
1647  if(@_)
1648  {
1649    $self->delete_foreign_keys;
1650    $self->add_foreign_keys(@_);
1651  }
1652
1653  return wantarray ?
1654    (sort { $a->name cmp $b->name } values %{$self->{'foreign_keys'} ||= {}}) :
1655    [ sort { $a->name cmp $b->name } values %{$self->{'foreign_keys'} ||= {}} ];
1656}
1657
1658sub initialize
1659{
1660  my($self) = shift;
1661  my(%args) = @_;
1662
1663  $Debug && warn $self->class, " - initialize\n";
1664
1665  if(my $code = $self->pre_init_hook)
1666  {
1667    foreach my $sub (ref $code eq 'ARRAY' ? @$code : $code)
1668    {
1669      $sub->($self, @_);
1670    }
1671  }
1672
1673  my $class = $self->class
1674    or Carp::croak "Missing class for metadata object $self";
1675
1676  $self->sync_keys_to_columns;
1677
1678  my $table = $self->table;
1679  Carp::croak "$class - Missing table name"
1680    unless(defined $table && $table =~ /\S/);
1681
1682  my @pk = $self->primary_key_column_names;
1683  Carp::croak "$class - Missing primary key for table '$table'"  unless(@pk);
1684
1685  $self->init_primary_key_column_info;
1686
1687  my @column_names = $self->column_names;
1688  Carp::croak "$class - No columns defined for for table '$table'"
1689    unless(@column_names);
1690
1691  foreach my $name ($self->primary_key_column_names)
1692  {
1693    my $column = $self->column($name) or
1694      Carp::croak "Could not find column for primary key column name '$name'";
1695
1696    if($column->is_lazy)
1697    {
1698      Carp::croak "Column '$name' cannot be lazy: cannot load primary key ",
1699                  "columns on demand";
1700    }
1701  }
1702
1703  $self->make_methods(@_);
1704
1705  $self->register_class;
1706
1707  unless($args{'passive'})
1708  {
1709    # Retry deferred stuff
1710    $self->retry_deferred_tasks;
1711    $self->retry_deferred_foreign_keys;
1712    $self->retry_deferred_relationships;
1713  }
1714
1715  $self->refresh_lazy_column_tracking;
1716
1717  unless($args{'stay_connected'})
1718  {
1719    $self->db(undef); # make sure to ditch any db we may have retained
1720  }
1721
1722  $self->is_initialized(1);
1723
1724  $Debug && warn $self->class, " - initialized\n";
1725
1726  if(my $code = $self->post_init_hook)
1727  {
1728    foreach my $sub (ref $code eq 'ARRAY' ? @$code : $code)
1729    {
1730      $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  $self->key_column_accessor_method_names_hash;
1737
1738  $self->prime_caches  if($self->auto_prime_caches);
1739
1740  return;
1741}
1742
1743use constant NULL_CATALOG => "\0";
1744use constant NULL_SCHEMA  => "\0";
1745
1746sub register_class
1747{
1748  my($self) = shift;
1749
1750  my $class = $self->class
1751    or Carp::croak "Missing class for metadata object $self";
1752
1753  my $db = $self->db;
1754
1755  my $catalog = $self->select_catalog($db);
1756  my $schema  = $db ? ($db->registration_schema || $self->select_schema($db)) :
1757                $self->select_schema($db);;
1758
1759  $catalog  = NULL_CATALOG  unless(defined $catalog);
1760  $schema   = NULL_SCHEMA   unless(defined $schema);
1761
1762  my $default_schema = $db ? $db->default_implicit_schema : undef;
1763
1764  my $table = $self->table
1765    or Carp::croak "Missing table for metadata object $self";
1766
1767  $table = lc $table  if($db->likes_lowercase_table_names);
1768
1769  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  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    $reg->{'lc-table',lc $table} = $class;
1784
1785  $reg->{'catalog-schema-table',$catalog,$default_schema,$table} = $class
1786    if(defined $default_schema);
1787
1788  push(@{$reg->{'classes'}}, $class);
1789
1790  return;
1791}
1792
1793sub registry_key { __PACKAGE__ }
1794
1795sub registered_classes
1796{
1797  my($self) = shift;
1798  my $reg = $self->registry_key->class_registry;
1799  return wantarray ? @{$reg->{'classes'} ||= []} : $reg->{'classes'};
1800}
1801
1802sub unregister_all_classes
1803{
1804  my($self) = shift;
1805  $self->registry_key->class_registry({});
1806  return;
1807}
1808
1809sub class_for
1810{
1811  my($self_or_class, %args) = @_;
1812
1813  my $self  = ref($self_or_class) ? $self_or_class : undef;
1814  my $class = ref($self) || $self_or_class;
1815
1816  my $db = $self ? $self->db : undef;
1817
1818  my $catalog = $args{'catalog'};
1819  my $schema  = $args{'schema'};
1820
1821  $catalog = NULL_CATALOG  unless(defined $catalog);
1822  $schema  = NULL_SCHEMA   unless(defined $schema);
1823
1824  my $default_schema = $db ? $db->default_implicit_schema : undef;
1825  $default_schema = NULL_SCHEMA   unless(defined $default_schema);
1826
1827  my $table = $args{'table'}
1828    or Carp::croak "Missing required table parameter";
1829
1830  $table = lc $table  if($db && $db->likes_lowercase_table_names);
1831
1832  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  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    ($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  unless($f_class)
1848  {
1849    $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      ($schema eq NULL_SCHEMA && $default_schema eq NULL_SCHEMA ? $reg->{'lc-table',$table} : undef);
1855  }
1856
1857  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
1866sub make_column_methods
1867{
1868  my($self) = shift;
1869  my(%args) = @_;
1870
1871  my $class = $self->class;
1872
1873  $args{'target_class'} = $class;
1874
1875  my $aliases = $self->column_aliases;
1876
1877  while(my($column_name, $alias) = each(%$aliases))
1878  {
1879    $self->column($column_name)->alias($alias);
1880  }
1881
1882  foreach my $column ($self->columns_ordered)
1883  {
1884    unless($column->validate_specification)
1885    {
1886      Carp::croak "Column specification for column '", $column->name,
1887                  "' in class ", $self->class, " is invalid: ",
1888                  $column->error;
1889    }
1890
1891    my $name = $column->name;
1892    my $method;
1893
1894    foreach my $type ($column->auto_method_types)
1895    {
1896      $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      if(my $reason = $self->method_name_is_reserved($method, $class))
1901      {
1902        Carp::croak "Cannot create method '$method' - $reason  ",
1903                    "Use alias_column() to map it to another name."
1904      }
1905
1906      $column->method_name($type => $method);
1907    }
1908
1909    #$Debug && warn $self->class, " - make methods for column $name\n";
1910
1911    $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  $self->_clear_column_generated_values;
1945
1946  # Initialize method name hashes
1947  $self->column_accessor_method_names;
1948  $self->column_mutator_method_names;
1949  $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  return;
1965}
1966
1967sub make_nonpersistent_column_methods
1968{
1969  my($self) = shift;
1970  my(%args) = @_;
1971
1972  my $class = $self->class;
1973
1974  $args{'target_class'} = $class;
1975
1976  foreach my $column ($self->nonpersistent_columns_ordered)
1977  {
1978    unless($column->validate_specification)
1979    {
1980      Carp::croak "Column specification for column '", $column->name,
1981                  "' in class ", $self->class, " is invalid: ",
1982                  $column->error;
1983    }
1984
1985    my $name = $column->name;
1986    my $method;
1987
1988    foreach my $type ($column->auto_method_types)
1989    {
1990      $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      if(my $reason = $self->method_name_is_reserved($method, $class))
1995      {
1996        Carp::croak "Cannot create method '$method' - $reason  ",
1997                    "Use alias_column() to map it to another name."
1998      }
1999
2000      $column->method_name($type => $method);
2001    }
2002
2003    #$Debug && warn $self->class, " - make methods for column $name\n";
2004
2005    $column->make_methods(%args);
2006  }
2007
2008  $self->_clear_nonpersistent_column_generated_values;
2009
2010  # Initialize method name hashes
2011  $self->nonpersistent_column_accessor_method_names;
2012
2013  return;
2014}
2015
2016sub make_foreign_key_methods
2017{
2018  my($self) = shift;
2019  my(%args) = @_;
2020
2021  #$self->retry_deferred_foreign_keys;
2022
2023  my $class = $self->class;
2024  my $meta_class = ref $self;
2025
2026  $args{'target_class'} = $class;
2027
2028  foreach my $foreign_key ($self->foreign_keys)
2029  {
2030    #next  unless($foreign_key->is_ready_to_make_methods);
2031
2032    foreach my $type ($foreign_key->auto_method_types)
2033    {
2034      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      if(my $reason = $self->method_name_is_reserved($method, $class))
2041      {
2042        Carp::croak "Cannot create method '$method' - $reason  ",
2043                    "Choose a different foreign key name."
2044      }
2045
2046      $foreign_key->method_name($type => $method);
2047    }
2048
2049    if($self->auto_load_related_classes && (my $fclass = $foreign_key->class))
2050    {
2051      unless($fclass->isa('Rose::DB::Object'))
2052      {
2053        my $error;
2054
2055        TRY:
2056        {
2057          local $@;
2058          eval "require $fclass";
2059          $error = $@;
2060        }
2061
2062        $Debug && print STDERR "FK REQUIRES $fclass - $error\n";
2063
2064        if($error)
2065        {
2066          # XXX: Need to distinguish recoverable errors from unrecoverable errors
2067          if($error !~ /\.pm in \@INC/ && !UNIVERSAL::isa($error, 'Rose::DB::Object::Exception::ClassNotReady'))
2068          {
2069            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    if($foreign_key->is_ready_to_make_methods)
2078    {
2079      if($Debug && !$args{'preserve_existing'})
2080      {
2081        warn $self->class, " - make methods for foreign key ",
2082             $foreign_key->name, "\n";
2083      }
2084
2085      $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      $foreign_key->sanity_check;
2092
2093      $Debug && warn $self->class, " - defer foreign key ", $foreign_key->name, "\n";
2094
2095      $foreign_key->deferred_make_method_args(\%args);
2096      $meta_class->add_deferred_foreign_key($foreign_key);
2097    }
2098
2099    # Keep foreign keys and their corresponding relationships in sync.
2100    my $fk_id       = $foreign_key->id;
2101    my $fk_rel_type = $foreign_key->relationship_type;
2102
2103    foreach my $relationship ($self->relationships)
2104    {
2105      next  unless($relationship->type eq $fk_rel_type);
2106
2107      if($fk_id eq $relationship->id)
2108      {
2109        $relationship->foreign_key($foreign_key);
2110      }
2111    }
2112  }
2113
2114  $self->retry_deferred_foreign_keys;
2115
2116  return;
2117}
2118
2119our @Deferred_Tasks;
2120
2121sub deferred_tasks
2122{
2123  return wantarray ? @Deferred_Tasks : \@Deferred_Tasks;
2124}
2125
2126sub add_deferred_tasks
2127{
2128  my($class) = shift;
2129
2130  ARG: foreach my $arg (@_)
2131  {
2132    foreach my $task (@Deferred_Tasks)
2133    {
2134      next  ARG if($arg->{'class'}  eq $task->{'class'} &&
2135                   $arg->{'method'} eq $task->{'method'});
2136    }
2137
2138    push(@Deferred_Tasks, $arg);
2139  }
2140}
2141
2142sub add_deferred_task { shift->add_deferred_tasks(@_) }
2143
2144sub has_deferred_tasks
2145{
2146  my($self) = shift;
2147
2148  my $class = $self->class;
2149  my $meta_class = ref $self;
2150
2151  # Search among the deferred tasks too (icky)
2152  foreach my $task ($meta_class->deferred_tasks)
2153  {
2154    if($task->{'class'} eq $class)
2155    {
2156      return 1;
2157    }
2158  }
2159
2160  return 0;
2161}
2162
2163sub retry_deferred_tasks
2164{
2165  my($self) = shift;
2166
2167  my @tasks;
2168
2169  foreach my $task (@Deferred_Tasks)
2170  {
2171    my $code  = $task->{'code'};
2172    my $check = $task->{'check'};
2173
2174    $code->();
2175
2176    unless($check->())
2177    {
2178      push(@tasks, $task);
2179    }
2180  }
2181
2182  if(join(',', sort @Deferred_Tasks) ne join(',', sort @tasks))
2183  {
2184    @Deferred_Tasks = @tasks;
2185  }
2186}
2187
2188our @Deferred_Foreign_Keys;
2189
2190sub deferred_foreign_keys
2191{
2192  return wantarray ? @Deferred_Foreign_Keys : \@Deferred_Foreign_Keys;
2193}
2194
2195sub has_deferred_foreign_keys
2196{
2197  my($self) = shift;
2198
2199  my $class = $self->class;
2200  my $meta_class = ref $self;
2201
2202  foreach my $fk ($meta_class->deferred_foreign_keys)
2203  {
2204    return 1  if($fk->class eq $class);
2205  }
2206
2207  # Search among the deferred tasks too (icky)
2208  foreach my $task ($meta_class->deferred_tasks)
2209  {
2210    if($task->{'class'} eq $class && $task->{'method'} eq 'auto_init_foreign_keys')
2211    {
2212      return 1;
2213    }
2214  }
2215
2216  return 0;
2217}
2218
2219sub has_outstanding_metadata_tasks
2220{
2221  my($self) = shift;
2222
2223  return $self->{'has_outstanding_metadata_tasks'} = shift  if(@_);
2224
2225  if(defined $self->{'has_outstanding_metadata_tasks'})
2226  {
2227    return $self->{'has_outstanding_metadata_tasks'};
2228  }
2229
2230  if($self->has_deferred_foreign_keys  ||
2231     $self->has_deferred_relationships ||
2232     $self->has_deferred_tasks)
2233  {
2234    return $self->{'has_outstanding_metadata_tasks'} = 1;
2235  }
2236
2237  return $self->{'has_outstanding_metadata_tasks'} = 0;
2238}
2239
2240sub add_deferred_foreign_keys
2241{
2242  my($class) = shift;
2243
2244my $check = 0;
2245
2246  ARG: foreach my $arg (@_)
2247  {
2248    foreach my $fk (@Deferred_Foreign_Keys)
2249    {
2250      next ARG  if($fk->id eq $arg->id);
2251    }
2252
2253    $arg->parent->has_outstanding_metadata_tasks(1);
2254    push(@Deferred_Foreign_Keys, $arg);
2255  }
2256}
2257
2258sub add_deferred_foreign_key { shift->add_deferred_foreign_keys(@_) }
2259
2260sub retry_deferred_foreign_keys
2261{
2262  my($self) = shift;
2263
2264  my $meta_class = ref $self;
2265
2266  my @foreign_keys;
2267
2268  # Check to see if any deferred foreign keys are ready now
2269  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    if($foreign_key->is_ready_to_make_methods)
2280    {
2281      $Debug && warn $foreign_key->parent->class,
2282                     " - (Retry) make methods for foreign key ",
2283                     $foreign_key->name, "\n";
2284
2285      my $args = $foreign_key->deferred_make_method_args || {};
2286      $foreign_key->make_methods(%$args); #, preserve_existing => 1);
2287    }
2288    else
2289    {
2290      push(@foreign_keys, $foreign_key);
2291    }
2292  }
2293
2294  if(join(',', sort @Deferred_Foreign_Keys) ne join(',', sort @foreign_keys))
2295  {
2296    @Deferred_Foreign_Keys = @foreign_keys;
2297  }
2298
2299  # Retry relationship auto-init for all other classes
2300  foreach my $class ($self->registered_classes)
2301  {
2302    my $meta = $class->meta;
2303    next  unless($meta->allow_auto_initialization && $meta->has_outstanding_metadata_tasks);
2304    $meta->auto_init_relationships(%{ $meta->auto_init_args || {} },
2305                                   restore_types => 1);
2306  }
2307}
2308
2309sub make_relationship_methods
2310{
2311  my($self) = shift;
2312  my(%args) = @_;
2313
2314  #$self->retry_deferred_relationships;
2315
2316  my $meta_class = ref $self;
2317  my $class = $self->class;
2318
2319  $args{'target_class'} = $class;
2320
2321  my $preserve_existing_arg = $args{'preserve_existing'};
2322
2323  REL: foreach my $relationship ($self->relationships)
2324  {
2325    next  if($args{'name'} && $relationship->name ne $args{'name'});
2326    #next  unless($relationship->is_ready_to_make_methods);
2327
2328    foreach my $type ($relationship->auto_method_types)
2329    {
2330      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      if(my $reason = $self->method_name_is_reserved($method, $class))
2337      {
2338        Carp::croak "Cannot create method '$method' - $reason  ",
2339                    "Choose a different relationship name."
2340      }
2341
2342      $relationship->method_name($type => $method);
2343
2344      # Initialize/reset preserve_existing flag
2345      if($self->is_auto_initializating)
2346      {
2347        $args{'preserve_existing'} = $preserve_existing_arg || $self->allow_auto_initialization;
2348      }
2349
2350      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      if($relationship->can('id'))
2357      {
2358        my $rel_id = $relationship->id;
2359
2360        FK: foreach my $fk ($self->foreign_keys)
2361        {
2362          if($rel_id eq $fk->id)
2363          {
2364            $args{'preserve_existing'} = 1;
2365            delete $args{'replace_existing'};
2366            last FK;
2367          }
2368        }
2369      }
2370    }
2371
2372    if($self->auto_load_related_classes)
2373    {
2374      if($relationship->can('class'))
2375      {
2376        my $fclass = $relationship->class;
2377
2378        unless($fclass->isa('Rose::DB::Object') && $fclass->meta->is_initialized)
2379        {
2380          my $error;
2381
2382          TRY:
2383          {
2384            local $@;
2385            eval "require $fclass";
2386            $error = $@;
2387          }
2388
2389          $Debug && print STDERR "REL ",  $relationship->name,
2390                                 " REQUIRES $fclass - $error\n";
2391
2392          if($error)
2393          {
2394            # XXX: Need to distinguish recoverable errors from unrecoverable errors
2395            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              Carp::confess "Could not load $fclass - $error";
2399            }
2400          }
2401        }
2402      }
2403
2404      if($relationship->can('map_class'))
2405      {
2406        my $map_class = $relationship->map_class;
2407
2408        unless($map_class->isa('Rose::DB::Object') && $map_class->meta->is_initialized)
2409        {
2410          my $error;
2411
2412          TRY:
2413          {
2414            local $@;
2415            eval "require $map_class";
2416            $error = $@;
2417          }
2418
2419          $Debug && print STDERR "REL ",  $relationship->name,
2420                                 " REQUIRES $map_class - $error\n";
2421
2422          if($error)
2423          {
2424            # XXX: Need to distinguish recoverable errors from unrecoverable errors
2425            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              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    if($relationship->is_ready_to_make_methods)
2438    {
2439      if($Debug && !$args{'preserve_existing'})
2440      {
2441        warn $self->class, " - make methods for relationship ",
2442             $relationship->name, "\n";
2443      }
2444
2445      $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      $relationship->sanity_check;
2452
2453      $Debug && warn $self->class, " - defer relationship ", $relationship->name, "\n";
2454
2455      $relationship->deferred_make_method_args(\%args);
2456      $meta_class->add_deferred_relationship($relationship);
2457    }
2458  }
2459
2460  #$self->retry_deferred_relationships;
2461
2462  return;
2463}
2464
2465our @Deferred_Relationships;
2466
2467sub deferred_relationships
2468{
2469  return wantarray ? @Deferred_Relationships : \@Deferred_Relationships;
2470}
2471
2472sub has_deferred_relationships
2473{
2474  my($self) = shift;
2475
2476  my $class = $self->class;
2477  my $meta_class = ref $self;
2478
2479  foreach my $rel ($meta_class->deferred_relationships)
2480  {
2481    if(($rel->can('class') && $rel->class eq $class) ||
2482       ($rel->can('map_class') && $rel->map_class eq $class))
2483    {
2484      return 1;
2485    }
2486  }
2487
2488  # Search among the deferred tasks too (icky)
2489  foreach my $task ($meta_class->deferred_tasks)
2490  {
2491    if($task->{'class'} eq $class && $task->{'method'} eq 'auto_init_relationships')
2492    {
2493      return 1;
2494    }
2495  }
2496
2497  return 0;
2498}
2499
2500sub add_deferred_relationships
2501{
2502  my($class) = shift;
2503
2504  ARG: foreach my $arg (@_)
2505  {
2506    foreach my $rel (@Deferred_Relationships)
2507    {
2508      next ARG  if($rel->id eq $arg->id);
2509    }
2510
2511    push(@Deferred_Relationships, $arg);
2512  }
2513}
2514
2515sub add_deferred_relationship { shift->add_deferred_relationships(@_) }
2516
2517sub retry_deferred_relationships
2518{
2519  my($self) = shift;
2520
2521  my $meta_class = ref $self;
2522
2523  my @relationships;
2524
2525  # Check to see if any deferred relationships are ready now
2526  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    my $rebuild_rel =
2531      $self->convention_manager->auto_relationship(
2532        $relationship->name, ref $relationship,
2533          scalar $relationship->spec_hash);
2534
2535    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      %$relationship = %$rebuild_rel;
2540    }
2541
2542    if($relationship->is_ready_to_make_methods)
2543    {
2544      $Debug && warn $relationship->parent->class,
2545                     " - (Retry) make methods for relationship ",
2546                     $relationship->name, "\n";
2547
2548      my $args = $relationship->deferred_make_method_args || {};
2549      $args->{'preserve_existing'} = 1;
2550      delete $args->{'replace_existing'};
2551
2552      $relationship->make_methods(%$args);
2553
2554      # Reassign to list in case we rebuild above
2555      $relationship->parent->relationship($relationship->name => $relationship);
2556    }
2557    else
2558    {
2559      push(@relationships, $relationship);
2560    }
2561  }
2562
2563  if(join(',', sort @Deferred_Relationships) ne join(',', sort @relationships))
2564  {
2565    @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
2576sub make_methods
2577{
2578  my($self) = shift;
2579
2580  $self->make_column_methods(@_);
2581  $self->make_nonpersistent_column_methods(@_);
2582  $self->make_foreign_key_methods(@_);
2583  $self->make_relationship_methods(@_);
2584}
2585
2586sub generate_primary_key_values
2587{
2588  my($self, $db) = @_;
2589
2590  if(my $code = $self->primary_key_generator)
2591  {
2592    return $code->($self, $db);
2593  }
2594
2595  my @ids;
2596
2597  my $seqs = $self->fq_primary_key_sequence_names(db => $db);
2598
2599  if($seqs && @$seqs)
2600  {
2601    my $i = 0;
2602
2603    foreach my $seq (@$seqs)
2604    {
2605      $i++;
2606
2607      unless(defined $seq)
2608      {
2609        push(@ids, undef);
2610        next;
2611      }
2612
2613      my $id = $db->next_value_in_sequence($seq);
2614
2615      unless($id)
2616      {
2617        $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        return undef;
2622      }
2623
2624      push(@ids, $id);
2625    }
2626
2627    return @ids;
2628  }
2629  else
2630  {
2631    return $db->generate_primary_key_values(scalar @{$self->primary_key_column_names});
2632  }
2633}
2634
2635sub generate_primary_key_value
2636{
2637  my @ids = shift->generate_primary_key_values(@_);
2638  return $ids[0];
2639}
2640
2641sub generate_primary_key_placeholders
2642{
2643  my($self, $db) = @_;
2644  return $db->generate_primary_key_placeholders(scalar @{$self->primary_key_column_names});
2645}
2646
2647sub primary_key_column_accessor_names
2648{
2649  my($self) = shift;
2650
2651  if($self->{'primary_key_column_accessor_names'})
2652  {
2653    return @{$self->{'primary_key_column_accessor_names'}};
2654  }
2655
2656  my @column_names = $self->primary_key_column_names;
2657  my @columns      = grep { defined } map { $self->column($_) } @column_names;
2658
2659  return  unless(@column_names == @columns); # not ready yet
2660
2661  my @methods = grep { defined } map { $self->column_accessor_method_name($_) }
2662                @column_names;
2663
2664  return  unless(@methods);
2665
2666  $self->{'primary_key_column_accessor_names'} = \@methods;
2667  return @methods;
2668}
2669
2670sub primary_key_column_mutator_names
2671{
2672  my($self) = shift;
2673
2674  if($self->{'primary_key_column_mutator_names'})
2675  {
2676    return @{$self->{'primary_key_column_mutator_names'}};
2677  }
2678
2679  my @column_names = $self->primary_key_column_names;
2680  my @columns      = grep { defined } map { $self->column($_) } @column_names;
2681
2682  return  unless(@column_names == @columns); # not ready yet
2683
2684  my @methods = grep { defined } map { $self->column_mutator_method_name($_) }
2685                @column_names;
2686
2687  return  unless(@methods);
2688
2689  $self->{'primary_key_column_mutator_names'} = \@methods;
2690  return @methods;
2691}
2692
2693sub fq_primary_key_sequence_names
2694{
2695  my($self, %args) = @_;
2696
2697  my $db_id = $args{'db'}{'id'} || ($self->{'db_id'} ||= $self->init_db_id);
2698
2699  if(defined $self->{'fq_primary_key_sequence_names'}{$db_id})
2700  {
2701    my $seqs = $self->{'fq_primary_key_sequence_names'}{$db_id} or return;
2702    return wantarray ? @$seqs : $seqs;
2703  }
2704
2705  my $db = $args{'db'} or
2706    die "Cannot generate fully-qualified primary key sequence name without db argument";
2707
2708  my @seqs = $self->primary_key_sequence_names($db);
2709
2710  if(@seqs)
2711  {
2712    $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    foreach my $seq (@seqs)
2717    {
2718      if(defined $seq && index($seq, '.') < 0)
2719      {
2720        $seq = $db->quote_identifier_for_sequence($self->select_catalog($db),
2721                                                  $self->select_schema($db), $seq);
2722      }
2723    }
2724
2725    $self->{'fq_primary_key_sequence_names'}{$db->{'id'}} = \@seqs;
2726    return wantarray ? @seqs : \@seqs;
2727  }
2728
2729  return;
2730}
2731
2732sub refresh_primary_key_sequence_names
2733{
2734  my($self, $db) = @_;
2735  my $db_id = UNIVERSAL::isa($db, 'Rose::DB') ? $db->id : $db;
2736  $self->{'fq_primary_key_sequence_names'}{$db_id} = undef;
2737  $self->{'primary_key_sequence_names'}{$db_id} = undef;
2738  return;
2739}
2740
2741sub primary_key_sequence_names
2742{
2743  my($self) = shift;
2744
2745  my($db, $db_id);
2746
2747  $db = shift  if(UNIVERSAL::isa($_[0], 'Rose::DB'));
2748  $db_id = $db ? $db->{'id'} : $self->init_db_id;
2749
2750  # Set pk sequence names
2751  if(@_)
2752  {
2753    # Clear fully-qualified pk values
2754    $self->{'fq_primary_key_sequence_names'}{$db_id} = undef;
2755
2756    my $ret = $self->{'primary_key_sequence_names'}{$db_id} =
2757      (@_ == 1 && ref $_[0]) ? $_[0] : [ @_ ];
2758
2759    # Push down into pk metadata object too
2760    $self->primary_key->sequence_names(($db ? $db : ()), @$ret);
2761
2762    return wantarray ? @$ret : $ret;
2763  }
2764
2765  if($self->{'primary_key_sequence_names'}{$db_id})
2766  {
2767    my $ret = $self->{'primary_key_sequence_names'}{$db_id};
2768    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  my @pks  = $self->primary_key_column_names;
2776  my $seqs = $self->primary_key->sequence_names($db);
2777  my @seqs;
2778
2779  if($seqs)
2780  {
2781    # If each pk column has a defined sequence name, accept them as-is
2782    if(@pks == grep { defined } @$seqs)
2783    {
2784      $self->{'primary_key_sequence_names'}{$db_id} = $seqs;
2785      return wantarray ? @$seqs : $seqs;
2786    }
2787    else # otherwise, use them as a starting point
2788    {
2789      @seqs = @$seqs;
2790    }
2791  }
2792
2793  unless($db)
2794  {
2795    die "Cannot generate primary key sequence name without db argument";
2796  }
2797
2798
2799  my $cm = $self->convention_manager;
2800  my $table = $self->table or
2801    Carp::croak "Cannot generate primary key sequence name without table name";
2802
2803  my $i = 0;
2804
2805  foreach my $column ($self->primary_key_columns)
2806  {
2807    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    if($column->type eq 'scalar')
2814    {
2815      $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      $seq = $cm->auto_column_sequence_name($table, $column, $db);
2825    }
2826
2827    unless(exists $seqs[$i] && defined $seqs[$i])
2828    {
2829      $seqs[$i] = $seq  if(defined $seq);
2830    }
2831
2832    $i++;
2833  }
2834
2835  # Only save if it looks like the class setup is finished
2836  if($self->is_initialized)
2837  {
2838    $self->{'primary_key_sequence_names'}{$db->{'id'}} = \@seqs;
2839  }
2840
2841  return wantarray ? @seqs : \@seqs;
2842}
2843
2844sub _sequence_name
2845{
2846  my($self, $db, $catalog, $schema, $table, $column) = @_;
2847
2848  # XXX: This is only beneficial in PostgreSQL right now
2849  return  unless($db->driver eq 'pg');
2850
2851  $table = lc $table  if($db->likes_lowercase_table_names);
2852
2853  my($col_info, $error);
2854
2855  TRY:
2856  {
2857    local $@;
2858
2859    eval
2860    {
2861      my $dbh = $db->dbh;
2862
2863      local $dbh->{'RaiseError'} = 0;
2864      local $dbh->{'PrintError'} = 0;
2865
2866      my $sth = $dbh->column_info($catalog, $schema, $table, $column) or return;
2867
2868      $sth->execute;
2869      $col_info = $sth->fetchrow_hashref;
2870      $sth->finish;
2871    };
2872
2873    $error = $@;
2874  }
2875
2876  return  if($error || !$col_info);
2877
2878  $db->refine_dbi_column_info($col_info, $self);
2879
2880  my $seq = $col_info->{'rdbo_default_value_sequence_name'};
2881
2882  my $implicit_schema = $db->default_implicit_schema;
2883
2884  # Strip off default implicit schema unless a schema is explicitly specified
2885  if(defined $seq && defined $implicit_schema && !defined $schema)
2886  {
2887    $seq =~ s/^$implicit_schema\.//;
2888  }
2889
2890  return $seq;
2891}
2892
2893sub column_names
2894{
2895  my($self) = shift;
2896  $self->{'column_names'} ||= [ map { $_->name } $self->columns_ordered ];
2897  return wantarray ? @{$self->{'column_names'}} : $self->{'column_names'};
2898}
2899
2900sub nonpersistent_column_names
2901{
2902  my($self) = shift;
2903  $self->{'nonpersistent_column_names'} ||= [ map { $_->name } $self->nonpersistent_columns_ordered ];
2904  return wantarray ? @{$self->{'nonpersistent_column_names'}} : $self->{'nonpersistent_column_names'};
2905}
2906
2907sub nonlazy_column_names
2908{
2909  my($self) = shift;
2910  $self->{'nonlazy_column_names'} ||= [ map { $_->name } $self->nonlazy_columns ];
2911  return wantarray ? @{$self->{'nonlazy_column_names'}} : $self->{'nonlazy_column_names'};
2912}
2913
2914sub lazy_column_names
2915{
2916  my($self) = shift;
2917  $self->{'lazy_column_names'} ||= [ map { $_->name } $self->lazy_columns ];
2918  return wantarray ? @{$self->{'lazy_column_names'}} : $self->{'lazy_column_names'};
2919}
2920
2921sub nonlazy_column_names_string_sql
2922{
2923  my($self, $db) = @_;
2924
2925  return $self->{'nonlazy_column_names_string_sql'}{$db->{'id'}} ||=
2926    join(', ', map { $_->name_sql($db) } $self->nonlazy_columns);
2927}
2928
2929sub column_names_string_sql
2930{
2931  my($self, $db) = @_;
2932
2933  return $self->{'column_names_string_sql'}{$db->{'id'}} ||=
2934    join(', ', map { $_->name_sql($db) } $self->columns_ordered);
2935}
2936
2937sub column_names_sql
2938{
2939  my($self, $db) = @_;
2940
2941  my $list = $self->{'column_names_sql'}{$db->{'id'}} ||=
2942    [ map { $_->name_sql($db) } $self->columns_ordered ];
2943
2944  return wantarray ? @$list : $list;
2945}
2946
2947sub select_nonlazy_columns_string_sql
2948{
2949  my($self, $db) = @_;
2950
2951  return $self->{'select_nonlazy_columns_string_sql'}{$db->{'id'}} ||=
2952    join(', ', @{ scalar $self->select_nonlazy_columns_sql($db) });
2953}
2954
2955sub select_columns_string_sql
2956{
2957  my($self, $db) = @_;
2958
2959  return $self->{'select_columns_string_sql'}{$db->{'id'}} ||=
2960    join(', ', @{ scalar $self->select_columns_sql($db) });
2961}
2962
2963sub select_columns_sql
2964{
2965  my($self, $db) = @_;
2966
2967  my $list = $self->{'select_columns_sql'}{$db->{'id'}};
2968
2969  unless($list)
2970  {
2971    my $table = $self->table;
2972
2973    if($self->sql_qualify_column_names_on_load)
2974    {
2975      $list = [ map { $_->select_sql($db, $table) } $self->columns_ordered ];
2976    }
2977    else
2978    {
2979      $list = [ map { $_->select_sql($db) } $self->columns_ordered ];
2980    }
2981
2982    $self->{'select_columns_sql'}{$db->{'id'}} = $list;
2983  }
2984
2985  return wantarray ? @$list : $list;
2986}
2987
2988sub select_nonlazy_columns_sql
2989{
2990  my($self, $db) = @_;
2991
2992  my $list = $self->{'select_nonlazy_columns_sql'}{$db->{'id'}};
2993
2994  unless($list)
2995  {
2996    my $table = $self->table;
2997
2998    if($self->sql_qualify_column_names_on_load)
2999    {
3000      $list = [ map { $_->select_sql($db, $table) } $self->nonlazy_columns ];
3001    }
3002    else
3003    {
3004      $list = [ map { $_->select_sql($db) } $self->nonlazy_columns ];
3005    }
3006
3007    $self->{'select_nonlazy_columns_sql'}{$db->{'id'}} = $list;
3008  }
3009
3010  return wantarray ? @$list : $list;
3011}
3012
3013sub method_column
3014{
3015  my($self, $method) = @_;
3016
3017  unless(defined $self->{'method_columns'})
3018  {
3019    foreach my $column ($self->columns_ordered)
3020    {
3021      foreach my $type ($column->defined_method_types)
3022      {
3023        if(my $method = $column->method_name($type))
3024        {
3025          $self->{'method_column'}{$method} = $column;
3026        }
3027      }
3028    }
3029  }
3030
3031  return $self->{'method_column'}{$method};
3032}
3033
3034sub column_rw_method_names
3035{
3036  my($self) = shift;
3037
3038  $self->{'column_rw_method_names'} ||=
3039    [ map { $self->column_rw_method_name($_) } $self->column_names ];
3040
3041  return wantarray ? @{$self->{'column_rw_method_names'}} :
3042                     $self->{'column_rw_method_names'};
3043}
3044
3045sub column_accessor_method_names
3046{
3047  my($self) = shift;
3048
3049  $self->{'column_accessor_method_names'} ||=
3050    [ map { $self->column_accessor_method_name($_) } $self->column_names ];
3051
3052  return wantarray ? @{$self->{'column_accessor_method_names'}} :
3053                     $self->{'column_accessor_method_names'};
3054}
3055
3056sub nonpersistent_column_accessor_method_names
3057{
3058  my($self) = shift;
3059
3060  $self->{'nonpersistent_column_accessor_method_names'} ||=
3061    [ map { $self->nonpersistent_column_accessor_method_name($_) } $self->nonpersistent_column_names ];
3062
3063  return wantarray ? @{$self->{'nonpersistent_column_accessor_method_names'}} :
3064                     $self->{'nonpersistent_column_accessor_method_names'};
3065}
3066
3067sub nonlazy_column_accessor_method_names
3068{
3069  my($self) = shift;
3070
3071  $self->{'nonlazy_column_accessor_method_names'} ||=
3072    [ map { $self->column_accessor_method_name($_) } $self->nonlazy_column_names ];
3073
3074  return wantarray ? @{$self->{'nonlazy_column_accessor_method_names'}} :
3075                     $self->{'nonlazy_column_accessor_method_names'};
3076}
3077
3078sub column_mutator_method_names
3079{
3080  my($self) = shift;
3081
3082  $self->{'column_mutator_method_names'} ||=
3083    [ map { $self->column_mutator_method_name($_) } $self->column_names ];
3084
3085  return wantarray ? @{$self->{'column_mutator_method_names'}} :
3086                     $self->{'column_mutator_method_names'};
3087}
3088
3089sub nonpersistent_column_mutator_method_names
3090{
3091  my($self) = shift;
3092
3093  $self->{'nonpersistent_column_mutator_method_names'} ||=
3094    [ map { $self->nonpersistent_column_mutator_method_name($_) } $self->nonpersistent_column_names ];
3095
3096  return wantarray ? @{$self->{'nonpersistent_column_mutator_method_names'}} :
3097                     $self->{'nonpersistent_column_mutator_method_names'};
3098}
3099
3100sub nonlazy_column_mutator_method_names
3101{
3102  my($self) = shift;
3103
3104  $self->{'nonlazy_column_mutator_method_names'} ||=
3105    [ map { $self->column_mutator_method_name($_) } $self->nonlazy_column_names ];
3106
3107  return wantarray ? @{$self->{'nonlazy_column_mutator_method_names'}} :
3108                     $self->{'nonlazy_column_mutator_method_names'};
3109}
3110
3111sub column_db_value_hash_keys
3112{
3113  my($self) = shift;
3114
3115  $self->{'column_db_value_hash_keys'} ||=
3116    { map { $_->mutator_method_name => $_->db_value_hash_key } $self->columns_ordered };
3117
3118  return wantarray ? %{$self->{'column_db_value_hash_keys'}} :
3119                     $self->{'column_db_value_hash_keys'};
3120}
3121
3122sub nonlazy_column_db_value_hash_keys
3123{
3124  my($self) = shift;
3125
3126  $self->{'nonlazy_column_db_value_hash_keys'} ||=
3127    { map { $_->mutator_method_name => $_->db_value_hash_key } $self->nonlazy_columns };
3128
3129  return wantarray ? %{$self->{'nonlazy_column_db_value_hash_keys'}} :
3130                     $self->{'nonlazy_column_db_value_hash_keys'};
3131}
3132
3133sub primary_key_column_db_value_hash_keys
3134{
3135  my($self) = shift;
3136
3137  $self->{'primary_key_column_db_value_hash_keys'} ||=
3138    [ map { $_->db_value_hash_key } $self->primary_key_columns ];
3139
3140  return wantarray ? @{$self->{'primary_key_column_db_value_hash_keys'}} :
3141                     $self->{'primary_key_column_db_value_hash_keys'};
3142}
3143
3144sub alias_column
3145{
3146  my($self, $name, $new_name) = @_;
3147
3148  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    unless($self->{'columns'}{$name});
3153
3154  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  $self->_clear_column_generated_values;
3168
3169  if(my $column = $self->column($name))
3170  {
3171    $column->method_name($new_name);
3172  }
3173
3174  $self->{'column_aliases'}{$name} = $new_name;
3175}
3176
3177sub column_aliases
3178{
3179  return $_[0]->{'column_aliases'}  unless(@_ > 1);
3180  return $_[0]->{'column_aliases'} = (ref $_[1] eq 'HASH') ? $_[1] : { @_[1 .. $#_] };
3181}
3182
3183sub column_accessor_method_name
3184{
3185  $_[0]->{'column_accessor_method'}{$_[1]} ||=
3186    ($_[0]->column($_[1]) ? $_[0]->column($_[1])->accessor_method_name : undef);
3187}
3188
3189sub nonpersistent_column_accessor_method_name
3190{
3191  $_[0]->{'nonpersistent_column_accessor_method'}{$_[1]} ||=
3192    ($_[0]->nonpersistent_column($_[1]) ? $_[0]->nonpersistent_column($_[1])->accessor_method_name : undef);
3193}
3194
3195sub column_accessor_method_names_hash { shift->{'column_accessor_method'} }
3196
3197sub nonpersistent_column_accessor_method_names_hash { shift->{'nonpersistent_column_accessor_method'} }
3198
3199sub key_column_accessor_method_names_hash
3200{
3201  my($self) = shift;
3202
3203  return $self->{'key_column_accessor_method'}  if($self->{'key_column_accessor_method'});
3204
3205  foreach my $column (grep { ref } $self->primary_key_columns)
3206  {
3207    $self->{'key_column_accessor_method'}{$column->name} = $column->accessor_method_name;
3208  }
3209
3210  foreach my $uk ($self->unique_keys)
3211  {
3212    foreach my $column (grep { ref } $uk->columns)
3213    {
3214      $self->{'key_column_accessor_method'}{$column->name} = $column->accessor_method_name;
3215    }
3216  }
3217
3218  return $self->{'key_column_accessor_method'};
3219}
3220
3221sub column_mutator_method_name
3222{
3223  $_[0]->{'column_mutator_method'}{$_[1]} ||=
3224    ($_[0]->column($_[1]) ? $_[0]->column($_[1])->mutator_method_name : undef);
3225}
3226
3227sub nonpersistent_column_mutator_method_name
3228{
3229  $_[0]->{'nonpersistent_column_mutator_method'}{$_[1]} ||=
3230    ($_[0]->nonpersistent_column($_[1]) ? $_[0]->nonpersistent_column($_[1])->mutator_method_name : undef);
3231}
3232
3233sub column_mutator_method_names_hash { shift->{'column_mutator_method'} }
3234
3235sub column_rw_method_name
3236{
3237  $_[0]->{'column_rw_method'}{$_[1]} ||=
3238    $_[0]->column($_[1])->rw_method_name;
3239}
3240
3241sub column_rw_method_names_hash { shift->{'column_rw_method'} }
3242
3243sub fq_table_sql
3244{
3245  my($self, $db) = @_;
3246  return $self->{'fq_table_sql'}{$db->{'id'}} ||=
3247    join('.', grep { defined } ($self->select_catalog($db),
3248                                $self->select_schema($db),
3249                                $db->auto_quote_table_name($self->table)));
3250}
3251
3252sub fqq_table_sql
3253{
3254  my($self, $db) = @_;
3255  return $self->{'fq_table_sql'}{$db->{'id'}} ||=
3256    join('.', grep { defined } ($self->select_catalog($db),
3257                                $self->select_schema($db),
3258                                $db->quote_table_name($self->table)));
3259}
3260
3261sub fq_table
3262{
3263  my($self, $db) = @_;
3264  return $self->{'fq_table'}{$db->{'id'}} ||=
3265    join('.', grep { defined } ($self->select_catalog($db),
3266                                $self->select_schema($db),
3267                                $self->table));
3268}
3269
3270sub load_all_sql
3271{
3272  my($self, $key_columns, $db) = @_;
3273
3274  $key_columns ||= $self->primary_key_column_names;
3275
3276  no warnings;
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      my $c = $self->column($_);
3283
3284      ($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
3291sub load_sql
3292{
3293  my($self, $key_columns, $db) = @_;
3294
3295  $key_columns ||= $self->primary_key_column_names;
3296
3297  no warnings;
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      my $c = $self->column($_);
3304      ($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
3311sub load_all_sql_with_null_key
3312{
3313  my($self, $key_columns, $key_values, $db) = @_;
3314
3315  my $i = 0;
3316
3317  my $fq    = $self->sql_qualify_column_names_on_load;
3318  my $table = $self->table;
3319
3320  no warnings;
3321  return
3322    'SELECT ' . $self->select_columns_string_sql($db) . ' FROM ' .
3323    $self->fq_table_sql($db) . ' WHERE ' .
3324    join(' AND ', map
3325    {
3326      my $c = $self->column($_);
3327      ($fq ? $db->auto_quote_column_with_table($c->name_sql, $table) : $c->name_sql($db)) .
3328      (defined $key_values->[$i++] ? ' = ' . $c->query_placeholder_sql : ' IS NULL')
3329    }
3330    @$key_columns);
3331}
3332
3333sub load_sql_with_null_key
3334{
3335  my($self, $key_columns, $key_values, $db) = @_;
3336
3337  my $i = 0;
3338
3339  my $fq    = $self->sql_qualify_column_names_on_load;
3340  my $table = $self->table;
3341
3342  no warnings;
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      my $c = $self->column($_);
3349      ($fq ? $db->auto_quote_column_with_table($c->name_sql, $table) : $c->name_sql($db)) .
3350      (defined $key_values->[$i++] ? ' = ' . $c->query_placeholder_sql : ' IS NULL')
3351    }
3352    @$key_columns);
3353}
3354
3355sub update_all_sql
3356{
3357  my($self, $key_columns, $db) = @_;
3358
3359  $key_columns ||= $self->primary_key_column_names;
3360
3361  my $cache_key = "$db->{'id'}:" . join("\0", @$key_columns);
3362
3363  return $self->{'update_all_sql'}{$cache_key}
3364    if($self->{'update_all_sql'}{$cache_key});
3365
3366  my %key = map { ($_ => 1) } @$key_columns;
3367
3368  no warnings;
3369  return $self->{'update_all_sql'}{$cache_key} =
3370    'UPDATE ' . $self->fq_table_sql($db) . " SET \n" .
3371    join(",\n", map
3372    {
3373      '    ' . $_->name_sql($db) . ' = ' . $_->update_placeholder_sql($db)
3374    }
3375    grep { !$key{$_->name} } $self->columns_ordered) .
3376    "\nWHERE " .
3377    join(' AND ', map
3378    {
3379      my $c = $self->column($_);
3380      $c->name_sql($db) . ' = ' . $c->query_placeholder_sql
3381    }
3382    @$key_columns);
3383}
3384
3385use constant LAZY_LOADED_KEY => lazy_column_values_loaded_key();
3386
3387sub update_sql
3388{
3389  my($self, $obj, $key_columns, $db) = @_;
3390
3391  $key_columns ||= $self->primary_key_column_names;
3392
3393  my %key = map { ($_ => 1) } @$key_columns;
3394
3395  no warnings 'uninitialized';
3396
3397  my @columns =
3398    grep { !$key{$_->name} && (!$_->lazy || $obj->{LAZY_LOADED_KEY()}{$_->name}) }
3399    $self->columns_ordered;
3400
3401  my @exec;
3402
3403  unless($self->dbi_requires_bind_param($db))
3404  {
3405    my $method_name = $self->column_accessor_method_names_hash;
3406
3407    foreach my $column (@columns)
3408    {
3409      my $method = $method_name->{$column->{'name'}};
3410      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      '    ' . $_->name_sql($db) . ' = ' . $_->update_placeholder_sql($db)
3419    }
3420    @columns) .
3421    "\nWHERE " .
3422    join(' AND ', map
3423    {
3424      my $c = $self->column($_);
3425      $c->name_sql($db) . ' = ' . $c->query_placeholder_sql($db)
3426    }
3427    @$key_columns),
3428    \@exec,
3429    \@columns);
3430}
3431
3432sub init_update_sql_prefix
3433{
3434  my($self, $db) = @_;
3435  return $self->{'update_sql_prefix'}{$db->{'id'}} =
3436         'UPDATE ' . $self->fq_table_sql($db) . " SET \n";
3437}
3438
3439sub update_changes_only_sql
3440{
3441  my($self, $obj, $key_columns, $db) = @_;
3442
3443  $key_columns ||= $self->primary_key_column_names;
3444
3445  my %key = map { ($_ => 1) } @$key_columns;
3446
3447  my @modified = map { $self->column($_) } grep { !$key{$_} } keys %{$obj->{MODIFIED_COLUMNS()} || {}};
3448
3449  return  unless(@modified);
3450
3451  no warnings;
3452  return ($self->{'update_sql_prefix'}{$db->{'id'}} ||=
3453    'UPDATE ' . $self->fq_table_sql($db) . " SET \n") .
3454    join(",\n", map
3455    {
3456      '    ' . $_->name_sql($db) . ' = ' . $_->update_placeholder_sql($db)
3457    }
3458    @modified) .
3459    "\nWHERE " .
3460    join(' AND ', map
3461    {
3462      my $c = $self->column($_);
3463      $c->name_sql($db) . ' = ' . $c->query_placeholder_sql($db)
3464    }
3465    @$key_columns),
3466    [ map { my $m = $_->accessor_method_name; $obj->$m() } @modified ],
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
3535sub update_sql_with_inlining
3536{
3537  my($self, $obj, $key_columns) = @_;
3538
3539  my $db = $obj->db or Carp::croak "Missing db";
3540
3541  $key_columns ||= $self->primary_key_column_names;
3542
3543  my %key = map { ($_ => 1) } @$key_columns;
3544
3545  my(@bind, @updates, @bind_params);
3546
3547  my $do_bind_params = $self->dbi_requires_bind_param($db);
3548
3549  foreach my $column (grep { !$key{$_} && (!$_->{'lazy'} ||
3550                             $obj->{LAZY_LOADED_KEY()}{$_->{'name'}}) }
3551                      $self->columns_ordered)
3552  {
3553    my $method = $self->column_accessor_method_name($column->name);
3554    my $value  = $obj->$method();
3555
3556    if($column->should_inline_value($db, $value))
3557    {
3558      push(@updates, $column->name_sql($db) . " = $value");
3559    }
3560    else
3561    {
3562      push(@updates, $column->name_sql($db) . ' = ' .
3563                     $column->update_placeholder_sql($db));
3564      push(@bind, $value);
3565
3566      if($do_bind_params)
3567      {
3568        push(@bind_params, $column->dbi_bind_param_attrs($db));
3569      }
3570    }
3571  }
3572
3573  my $i = 0;
3574
3575  no warnings;
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      my $c = $self->column($_);
3584      $c->name_sql($db) . ' = ' . $c->query_placeholder_sql($db)
3585    }
3586    @$key_columns),
3587    \@bind,
3588    ($do_bind_params ? \@bind_params : ())
3589  );
3590}
3591
3592sub init_update_sql_with_inlining_start
3593{
3594  my($self, $db) = @_;
3595  return $self->{'update_sql_with_inlining_start'}{$db->{'id'}} =
3596         'UPDATE ' . $self->fq_table_sql($db) . " SET \n";
3597}
3598
3599sub update_changes_only_sql_with_inlining
3600{
3601  my($self, $obj, $key_columns) = @_;
3602
3603  my $db = $obj->db or Carp::croak "Missing db";
3604
3605  $key_columns ||= $self->primary_key_column_names;
3606
3607  my %key = map { ($_ => 1) } @$key_columns;
3608
3609  my $modified = $obj->{MODIFIED_COLUMNS()};
3610
3611  my(@bind, @updates, @bind_params);
3612
3613  my $do_bind_params = $self->dbi_requires_bind_param($db);
3614
3615  foreach my $column (grep { !$key{$_->{'name'}} && $modified->{$_->{'name'}} } $self->columns_ordered)
3616  {
3617    my $method = $self->column_accessor_method_name($column->name);
3618    my $value  = $obj->$method();
3619
3620    if($column->should_inline_value($db, $value))
3621    {
3622      push(@updates, '  ' . $column->name_sql($db) . " = $value");
3623    }
3624    else
3625    {
3626      push(@updates, $column->name_sql($db) . ' = ' .
3627                     $column->update_placeholder_sql($db));
3628      push(@bind, $value);
3629
3630      if($do_bind_params)
3631      {
3632        push(@bind_params, $column->dbi_bind_param_attrs($db));
3633      }
3634    }
3635  }
3636
3637  return  unless(@updates);
3638
3639  my $i = 0;
3640
3641  no warnings;
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      my $c = $self->column($_);
3650      $c->name_sql($db) . ' = ' . $c->query_placeholder_sql($db)
3651    }
3652    @$key_columns),
3653    \@bind,
3654    ($do_bind_params ? \@bind_params : ())
3655  );
3656}
3657
3658sub insert_sql
3659{
3660  my($self, $db) = @_;
3661
3662  no warnings;
3663  return $self->{'insert_sql'}{$db->{'id'}} ||=
3664    'INSERT INTO ' . $self->fq_table_sql($db) . "\n(\n" .
3665    join(",\n", map { "  $_" } $self->column_names_sql($db)) .
3666    "\n)\nVALUES\n(\n" . $self->insert_columns_placeholders_sql($db) .
3667    "\n)";
3668}
3669
3670sub insert_changes_only_sql
3671{
3672  my($self, $obj, $db) = @_;
3673
3674  my $modified = $obj->{MODIFIED_COLUMNS()} || {};
3675  my @modified = grep { $modified->{$_->{'name'}} || $_->default_exists } $self->columns_ordered;
3676
3677  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    if($db->supports_arbitrary_defaults_on_insert)
3683    {
3684      return
3685        'INSERT INTO ' . $self->fq_table_sql($db) . ' (' .
3686        ($self->columns_ordered)[-1]->name_sql($db) . ') VALUES (DEFAULT)',
3687        [];
3688    }
3689    else
3690    {
3691      Carp::croak "Cannot insert row into table '", $self->table,
3692                  "' - No columns have modified or default values";
3693    }
3694  }
3695
3696  no warnings;
3697  return ($self->{'insert_changes_only_sql_prefix'}{$db->{'id'}} ||
3698          $self->init_insert_changes_only_sql_prefix($db)) .
3699    join(",\n", map { $_->name_sql($db) } @modified) .
3700    "\n)\nVALUES\n(\n" .
3701    join(",\n", map { $_->insert_placeholder_sql($db) } @modified) . "\n)",
3702    [ map { my $m = $_->accessor_method_name; $obj->$m() } @modified ],
3703    \@modified;
3704}
3705
3706sub init_insert_changes_only_sql_prefix
3707{
3708  my($self, $db) = @_;
3709  return $self->{'insert_changes_only_sql_prefix'}{$db->{'id'}} =
3710         'INSERT INTO ' . $self->fq_table_sql($db) . "\n(\n";
3711;
3712}
3713
3714sub insert_columns_placeholders_sql
3715{
3716  my($self, $db) = @_;
3717  return $self->{'insert_columns_placeholders_sql'}{$db->{'id'}} ||=
3718    join(",\n", map { '  ' . $_->insert_placeholder_sql($db) } $self->columns_ordered)
3719}
3720
3721sub insert_and_on_duplicate_key_update_sql
3722{
3723  my($self, $obj, $db, $changes_only) = @_;
3724
3725  my(@columns, @names, @bind);
3726
3727  if($obj->{STATE_IN_DB()})
3728  {
3729    my %seen;
3730
3731    @columns = $changes_only ?
3732      (map { $self->column($_) } grep { !$seen{$_}++ }
3733       ($self->primary_key_column_names,
3734        keys %{$obj->{MODIFIED_COLUMNS()} || {}})) :
3735      (grep { (!$_->{'lazy'} || $obj->{LAZY_LOADED_KEY()}{$_->{'name'}}) }
3736       $self->columns_ordered);
3737
3738    @names = map { $_->name_sql($db) } @columns;
3739
3740    foreach my $column (@columns)
3741    {
3742      my $method = $self->column_accessor_method_name($column->{'name'});
3743      push(@bind, $obj->$method());
3744    }
3745  }
3746  else
3747  {
3748    my %skip;
3749
3750    my @key_columns = $self->primary_key_column_names;
3751    my @key_methods = $self->primary_key_column_accessor_names;
3752    my @key_values  = grep { defined } map { $obj->$_() } @key_methods;
3753
3754    unless(@key_values)
3755    {
3756      @skip{@key_columns} = (1) x @key_columns;
3757    }
3758
3759    foreach my $uk ($self->unique_keys)
3760    {
3761      @key_columns = $uk->columns;
3762      @key_methods = map { $_->accessor_method_name } @key_columns;
3763      @key_values  = grep { defined } map { $obj->$_() } @key_methods;
3764
3765      unless(@key_values)
3766      {
3767        @skip{@key_columns} = (1) x @key_columns;
3768      }
3769    }
3770
3771    @columns = $changes_only ?
3772      (map { $self->column($_) } grep { !$skip{"$_"} } keys %{$obj->{MODIFIED_COLUMNS()} || {}}) :
3773      (grep { !$skip{"$_"} && (!$_->{'lazy'} ||
3774              $obj->{LAZY_LOADED_KEY()}{$_->{'name'}}) } $self->columns_ordered);
3775
3776    @names = map { $_->name_sql($db) } @columns;
3777
3778    foreach my $column (@columns)
3779    {
3780      my $method = $self->column_accessor_method_name($column->{'name'});
3781      push(@bind, $obj->$method());
3782    }
3783  }
3784
3785  no warnings;
3786  return
3787    'INSERT INTO ' . $self->fq_table_sql($db) . "\n(\n" .
3788    join(",\n", @names) .
3789    "\n)\nVALUES\n(\n" .
3790    join(",\n", map { $_->insert_placeholder_sql($db) } @columns) .
3791    "\n)\nON DUPLICATE KEY UPDATE\n" .
3792    join(",\n", map
3793    {
3794      $_->name_sql($db) . ' = ' . $_->update_placeholder_sql($db)
3795    }
3796    @columns),
3797    [ @bind, @bind ],
3798    [ @columns, @columns ];
3799}
3800
3801sub insert_sql_with_inlining
3802{
3803  my($self, $obj) = @_;
3804
3805  my $db = $obj->db or Carp::croak "Missing db";
3806
3807  my(@bind, @places, @bind_params);
3808
3809  my $do_bind_params = $self->dbi_requires_bind_param($db);
3810
3811  foreach my $column ($self->columns_ordered)
3812  {
3813    my $method = $self->column_accessor_method_name($column->name);
3814    my $value  = $obj->$method();
3815
3816    if($column->should_inline_value($db, $value))
3817    {
3818      push(@places, "  $value");
3819    }
3820    else
3821    {
3822      push(@places, $column->insert_placeholder_sql($db));
3823      push(@bind, $value);
3824
3825      if($do_bind_params)
3826      {
3827        push(@bind_params, $column->dbi_bind_param_attrs($db));
3828      }
3829    }
3830  }
3831
3832  return
3833  (
3834    ($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
3842sub init_insert_sql_with_inlining_start
3843{
3844  my($self, $db) = @_;
3845  $self->{'insert_sql_with_inlining_start'}{$db->{'id'}} =
3846    'INSERT INTO ' . $self->fq_table_sql($db) . "\n(\n" .
3847    join(",\n", map { "  $_" } $self->column_names_sql($db)) .
3848    "\n)\nVALUES\n(\n";
3849}
3850
3851sub insert_and_on_duplicate_key_update_with_inlining_sql
3852{
3853  my($self, $obj, $db, $changes_only) = @_;
3854
3855  my(@columns, @names);
3856
3857  my $do_bind_params = $self->dbi_requires_bind_param($db);
3858
3859  if($obj->{STATE_IN_DB()})
3860  {
3861    my %seen;
3862
3863    @columns = $changes_only ?
3864      (map { $self->column($_) } grep { !$seen{$_}++ }
3865       ($self->primary_key_column_names,
3866        keys %{$obj->{MODIFIED_COLUMNS()} || {}})) :
3867      (grep { (!$_->{'lazy'} || $obj->{LAZY_LOADED_KEY()}{$_->{'name'}}) }
3868       $self->columns_ordered);
3869
3870    @names = map { $_->name_sql($db) } @columns;
3871  }
3872  else
3873  {
3874    my %skip;
3875
3876    my @key_columns = $self->primary_key_column_names;
3877    my @key_methods = $self->primary_key_column_accessor_names;
3878    my @key_values  = grep { defined } map { $obj->$_() } @key_methods;
3879
3880    unless(@key_values)
3881    {
3882      @skip{@key_columns} = (1) x @key_columns;
3883    }
3884
3885    foreach my $uk ($self->unique_keys)
3886    {
3887      @key_columns = $uk->columns;
3888      @key_methods = map { $_->accessor_method_name } @key_columns;
3889      @key_values  = grep { defined } map { $obj->$_() } @key_methods;
3890
3891      unless(@key_values)
3892      {
3893        @skip{@key_columns} = (1) x @key_columns;
3894      }
3895    }
3896
3897    @columns = $changes_only ?
3898      (map { $self->column($_) } grep { !$skip{"$_"} } keys %{$obj->{MODIFIED_COLUMNS()} || {}}) :
3899      (grep { !$skip{"$_"} && (!$_->{'lazy'} ||
3900              $obj->{LAZY_LOADED_KEY()}{$_->{'name'}}) } $self->columns_ordered);
3901
3902    @names = map { $_->name_sql($db) } @columns;
3903  }
3904
3905  my(@bind, @places, @bind_params);
3906
3907  foreach my $column (@columns)
3908  {
3909    my $name   = $column->{'name'};
3910    my $method = $self->column_accessor_method_name($name);
3911    my $value  = $obj->$method();
3912
3913    if($column->should_inline_value($db, $value))
3914    {
3915      push(@places, [ $name, $column->inline_value_sql($value) ]);
3916    }
3917    else
3918    {
3919      push(@places, [ $name, $column->insert_placeholder_sql($_) ]);
3920      push(@bind, $value);
3921
3922      if($do_bind_params)
3923      {
3924        push(@bind_params, $column->dbi_bind_param_attrs($db));
3925      }
3926    }
3927  }
3928
3929  no warnings;
3930  return
3931    'INSERT INTO ' . $self->fq_table_sql($db) . "\n(\n" .
3932    join(",\n", @names) .
3933    "\n)\nVALUES\n(\n" . join(",\n", map { $_->[1] } @places) . "\n)\n" .
3934    "ON DUPLICATE KEY UPDATE\n" .
3935    join(",\n", map { "$_->[0] = $_->[1]" } @places),
3936    [ @bind, @bind ],
3937    ($do_bind_params ? \@bind_params : ());
3938}
3939
3940sub insert_changes_only_sql_with_inlining
3941{
3942  my($self, $obj) = @_;
3943
3944  my $db = $obj->db or Carp::croak "Missing db";
3945
3946  my $modified = $obj->{MODIFIED_COLUMNS()} || {};
3947  my @modified = grep { $modified->{$_->{'name'}} || $_->default_exists } $self->columns_ordered;
3948
3949  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    if($db->supports_arbitrary_defaults_on_insert)
3955    {
3956      return
3957        'INSERT INTO ' . $self->fq_table_sql($db) . ' (' .
3958        ($self->columns_ordered)[-1]->name_sql($db) . ') VALUES (DEFAULT)',
3959        [];
3960    }
3961    else
3962    {
3963      Carp::croak "Cannot insert row into table '", $self->table,
3964                  "' - No columns have modified or default values";
3965    }
3966  }
3967
3968  my(@bind, @places, @bind_params);
3969
3970  my $do_bind_params = $self->dbi_requires_bind_param($db);
3971
3972  foreach my $column (@modified)
3973  {
3974    my $method = $self->column_accessor_method_name($column->name);
3975    my $value  = $obj->$method();
3976
3977    if($column->should_inline_value($db, $value))
3978    {
3979      push(@places, "  $value");
3980    }
3981    else
3982    {
3983      push(@places, $column->insert_placeholder_sql($db));
3984      push(@bind, $value);
3985
3986      if($do_bind_params)
3987      {
3988        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    join(",\n", map { $_->name_sql($db) } @modified) .
3997    "\n)\nVALUES\n(\n" . join(",\n", @places) . "\n)",
3998    \@bind,
3999    ($do_bind_params ? \@bind_params : ())
4000  );
4001}
4002
4003sub delete_sql
4004{
4005  my($self, $db) = @_;
4006  return $self->{'delete_sql'}{$db->{'id'}} ||=
4007    'DELETE FROM ' . $self->fq_table_sql($db) . ' WHERE ' .
4008    join(' AND ',
4009      map {  $_->name_sql($db) . ' = ' . $_->query_placeholder_sql($db) }
4010      $self->primary_key_columns);
4011}
4012
4013sub get_column_value
4014{
4015  my($self, $object, $column) = @_;
4016
4017  my $db  = $object->db or Carp::confess $object->error;
4018  my $dbh = $db->dbh or Carp::confess $db->error;
4019
4020  my $sql = $self->{'get_column_sql_tmpl'}{$db->{'id'}} ||
4021            $self->init_get_column_sql_tmpl($db);
4022
4023  $sql =~ s/__COLUMN__/$column->name_sql($db)/e;
4024
4025  my @key_values =
4026    map { $object->$_() }
4027    map { $self->column_accessor_method_name($_) }
4028    $self->primary_key_column_names;
4029
4030  my($value, $error);
4031
4032  TRY:
4033  {
4034    local $@;
4035
4036    eval
4037    {
4038      ($Debug || $Rose::DB::Object::Debug) && warn "$sql (@key_values)\n";
4039      my $sth = $dbh->prepare($sql);
4040      $sth->execute(@key_values);
4041      $sth->bind_columns(\$value);
4042      $sth->fetch;
4043    };
4044
4045    $error = $@;
4046  }
4047
4048  if($error)
4049  {
4050    Carp::croak "Could not lazily-load column value for column '",
4051                $column->name, "' - $error";
4052  }
4053
4054  return $value;
4055}
4056
4057sub init_get_column_sql_tmpl
4058{
4059  my($self, $db) = @_;
4060
4061  my $key_columns = $self->primary_key_column_names;
4062  my %key = map { ($_ => 1) } @$key_columns;
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      my $c = $self->column($_);
4069      $c->name_sql($db) . ' = ' . $c->query_placeholder_sql($db)
4070    }
4071    @$key_columns);
4072}
4073
4074sub refresh_lazy_column_tracking
4075{
4076  my($self) = shift;
4077
4078  $self->_clear_column_generated_values;
4079
4080  # Initialize method name hashes
4081  $self->column_accessor_method_names;
4082  $self->column_mutator_method_names;
4083  $self->column_rw_method_names;
4084
4085  return $self->{'has_lazy_columns'} = grep { $_->lazy } $self->columns_ordered;
4086}
4087
4088sub has_lazy_columns
4089{
4090  my($self) = shift;
4091  return $self->{'has_lazy_columns'}  if(defined $self->{'has_lazy_columns'});
4092  return $self->{'has_lazy_columns'} = grep { $_->lazy } $self->columns_ordered;
4093}
4094
4095sub prime_all_caches
4096{
4097  my($class) = shift;
4098
4099  foreach my $obj_class ($class->registered_classes)
4100  {
4101    $obj_class->meta->prime_caches(@_);
4102  }
4103}
4104
4105sub prime_caches
4106{
4107  my($self, %args) = @_;
4108
4109  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  foreach my $method (@methods)
4119  {
4120    $self->$method();
4121  }
4122
4123  my $db = $args{'db'} || $self->class->init_db;
4124
4125  $self->method_column('nonesuch');
4126  $self->fq_primary_key_sequence_names(db => $db);
4127
4128  @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  foreach my $method (@methods)
4138  {
4139    $self->$method($db);
4140  }
4141
4142  undef @methods; # reclaim memory?
4143
4144  foreach my $key ($self->primary_key, $self->unique_keys)
4145  {
4146    foreach my $method (qw(update_all_sql load_sql load_all_sql))
4147    {
4148      $self->$method(scalar $key->columns, $db);
4149    }
4150  }
4151}
4152
4153sub _clear_table_generated_values
4154{
4155  my($self) = shift;
4156
4157  $self->{'fq_table'}                       = undef;
4158  $self->{'fq_table_sql'}                   = undef;
4159  $self->{'get_column_sql_tmpl'}            = undef;
4160  $self->{'load_sql'}                       = undef;
4161  $self->{'load_all_sql'}                   = undef;
4162  $self->{'delete_sql'}                     = undef;
4163  $self->{'fq_primary_key_sequence_names'}  = undef;
4164  $self->{'primary_key_sequence_names'}     = undef;
4165  $self->{'insert_sql'}                     = undef;
4166  $self->{'insert_sql_with_inlining_start'} = undef;
4167  $self->{'insert_changes_only_sql_prefix'} = undef;
4168  $self->{'update_sql_prefix'}              = undef;
4169  $self->{'update_sql_with_inlining_start'} = undef;
4170  $self->{'update_all_sql'}                 = undef;
4171}
4172
4173sub _clear_column_generated_values
4174{
4175  my($self) = shift;
4176
4177  $self->{'fq_table'}                             = undef;
4178  $self->{'fq_table_sql'}                         = undef;
4179  $self->{'column_names'}                         = undef;
4180  $self->{'num_columns'}                          = undef;
4181  $self->{'nonlazy_column_names'}                 = undef;
4182  $self->{'lazy_column_names'}                    = undef;
4183  $self->{'column_names_sql'}                     = undef;
4184  $self->{'get_column_sql_tmpl'}                  = undef;
4185  $self->{'column_names_string_sql'}              = undef;
4186  $self->{'nonlazy_column_names_string_sql'}      = undef;
4187  $self->{'column_rw_method_names'}               = undef;
4188  $self->{'column_accessor_method_names'}         = undef;
4189  $self->{'nonlazy_column_accessor_method_names'} = undef;
4190  $self->{'column_mutator_method_names'}          = undef;
4191  $self->{'nonlazy_column_mutator_method_names'}  = undef;
4192  $self->{'nonlazy_column_db_value_hash_keys'}    = undef;
4193  $self->{'primary_key_column_db_value_hash_keys'}= undef;
4194  $self->{'primary_key_column_names_or_aliases'}  = undef
4195  $self->{'column_db_value_hash_keys'}            = undef;
4196  $self->{'select_nonlazy_columns_string_sql'}    = undef;
4197  $self->{'select_columns_string_sql'}            = undef;
4198  $self->{'select_columns_sql'}                   = undef;
4199  $self->{'select_nonlazy_columns_sql'}           = undef;
4200  $self->{'method_columns'}                       = undef;
4201  $self->{'column_accessor_method'}               = undef;
4202  $self->{'key_column_accessor_method'}           = undef;
4203  $self->{'column_rw_method'}                     = undef;
4204  $self->{'load_sql'}                             = undef;
4205  $self->{'load_all_sql'}                         = undef;
4206  $self->{'update_all_sql'}                       = undef;
4207  $self->{'update_sql_prefix'}                    = undef;
4208  $self->{'insert_sql'}                           = undef;
4209  $self->{'insert_sql_with_inlining_start'}       = undef;
4210  $self->{'update_sql_with_inlining_start'}       = undef;
4211  $self->{'insert_changes_only_sql_prefix'}       = undef;
4212  $self->{'delete_sql'}                           = undef;
4213  $self->{'insert_columns_placeholders_sql'}      = undef;
4214  $self->{'dbi_requires_bind_param'}              = undef;
4215  $self->{'key_column_names'}                     = undef;
4216}
4217
4218sub _clear_nonpersistent_column_generated_values
4219{
4220  my($self) = shift;
4221
4222  $self->{'nonpersistent_column_names'}                 = undef;
4223  $self->{'nonpersistent_column_accessor_method_names'} = undef;
4224  $self->{'nonpersistent_column_accessor_method'}       = undef;
4225  $self->{'nonpersistent_column_mutator_method_names'}  = undef;
4226  $self->{'nonpersistent_column_mutator_method'}        = undef;
4227}
4228
4229sub _clear_primary_key_column_generated_values
4230{
4231  my($self) = shift;
4232  $self->{'primary_key_column_accessor_names'}   = undef;
4233  $self->{'primary_key_column_mutator_names'}    = undef;
4234  $self->{'key_column_accessor_method'}          = undef;
4235  $self->{'primary_key_column_names_or_aliases'} = undef;
4236  $self->{'key_column_names'} = undef;
4237}
4238
4239sub method_name_is_reserved
4240{
4241  my($self, $name, $class) = @_;
4242
4243  if(!defined $class && UNIVERSAL::isa($self, __PACKAGE__))
4244  {
4245    $class ||= $self->class or die "Missing class!";
4246  }
4247
4248  Carp::confess "Missing method name argument in call to method_name_is_reserved()"
4249    unless(defined $name);
4250
4251  if(index($name, PRIVATE_PREFIX) == 0)
4252  {
4253    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    return "This method name is reserved for use by the $class API."
4259  }
4260
4261  return 0;
4262}
4263
4264sub method_name_from_column_name
4265{
4266  my($self, $column_name, $method_type) = @_;
4267
4268  my $column = $self->column($column_name) || $self->nonpersistent_column($column_name)
4269    or Carp::confess "No such column: $column_name";
4270
4271  return $self->method_name_from_column($column, $method_type);
4272}
4273
4274sub method_name_from_column
4275{
4276  my($self, $column, $method_type) = @_;
4277
4278  my $default_name = $column->build_method_name_for_type($method_type);
4279
4280  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  if(my $code = $self->column_name_to_method_name_mapper)
4286  {
4287    my $column_name = $column->name;
4288    local $_ = $method_name;
4289    $method_name = $code->($self, $column_name, $method_type, $method_name);
4290
4291    unless(defined $method_name)
4292    {
4293      Carp::croak "column_name_to_method_name_mapper() returned undef ",
4294                  "for column name '$column_name' method type '$method_type'"
4295    }
4296  }
4297
4298  return $method_name;
4299}
4300
4301sub dbi_requires_bind_param
4302{
4303  my($self, $db) = @_;
4304
4305  return $self->{'dbi_requires_bind_param'}{$db->{'id'}}
4306    if(defined $self->{'dbi_requires_bind_param'}{$db->{'id'}});
4307
4308  foreach my $column ($self->columns_ordered)
4309  {
4310    if($column->dbi_requires_bind_param($db))
4311    {
4312      return $self->{'dbi_requires_bind_param'}{$db->{'id'}} = 1;
4313    }
4314  }
4315
4316  return $self->{'dbi_requires_bind_param'}{$db->{'id'}} = 0;
4317}
4318
4319sub make_manager_class
4320{
4321  my($self) = shift;
4322
4323  my $error;
4324
4325  TRY:
4326  {
4327    local $@;
4328    eval { eval $self->perl_manager_class(@_) };
4329    $error = $@;
4330  }
4331
4332  if($error)
4333  {
4334    Carp::croak "Could not make manager class - $error\nThe Perl code used was:\n\n",
4335                $self->perl_manager_class(@_);
4336  }
4337}
4338
4339sub perl_manager_class
4340{
4341  my($self) = shift;
4342
4343  my %args;
4344
4345  if(@_ == 1)
4346  {
4347    $args{'base_name'} = shift;
4348  }
4349  else
4350  {
4351    %args = @_;
4352  }
4353
4354  $args{'base_name'} ||= $self->convention_manager->auto_manager_base_name;
4355  $args{'class'}     ||= $self->convention_manager->auto_manager_class_name;
4356
4357  unless($args{'class'} =~ /^\w+(?:::\w+)*$/)
4358  {
4359    no warnings;
4360    Carp::croak "Missing or invalid class",
4361                (length $args{'class'} ? ": '$args{'class'}'" : '');
4362  }
4363
4364  unless($args{'isa'})
4365  {
4366    my @def = $self->default_manager_base_class; # may return multiple classes
4367    $args{'isa'} = (@def == 1 && ref $def[0]) ? $def[0] : \@def;
4368  }
4369
4370  $args{'isa'} = [ $args{'isa'} ]  unless(ref $args{'isa'});
4371
4372  my($isa, $ok);
4373
4374  foreach my $class (@{$args{'isa'}})
4375  {
4376    unless($class =~ /^\w+(?:::\w+)*$/)
4377    {
4378      no warnings;
4379      Carp::croak "Invalid isa class: '$class'";
4380    }
4381
4382    no strict 'refs';
4383    $isa .= "use $class;\n"  unless($class !~ /^Rose::DB::/ && %{"${class}::"});
4384
4385    $ok = 1  if(UNIVERSAL::isa($class, 'Rose::DB::Object::Manager'));
4386  }
4387
4388  unless($ok)
4389  {
4390    Carp::croak
4391      "None of these classes inherit from Rose::DB::Object::Manager: ",
4392      join(', ', @{$args{'isa'}});
4393  }
4394
4395  $isa .= "our \@ISA = qw(@{$args{'isa'}});";
4396
4397  no strict 'refs';
4398  if(@{"$args{'class'}::ISA"})
4399  {
4400    Carp::croak "Can't override class $args{'class'} which already ",
4401                "appears to be defined.";
4402  }
4403
4404  my $object_class = $self->class;
4405
4406  return<<"EOF";
4407package $args{'class'};
4408
4409use strict;
4410
4411$isa
4412
4413sub object_class { '$object_class' }
4414
4415__PACKAGE__->make_manager_methods('$args{'base_name'}');
4416
44171;
4418EOF
4419}
4420
4421#
4422# Automatic metadata setup
4423#
4424
4425our $AUTOLOAD;
4426
4427sub DESTROY { }
4428
4429sub AUTOLOAD
4430{
4431  if($AUTOLOAD =~ /::((?:auto_(?!helper)|(?:default_)?perl_)\w*)$/)
4432  {
4433    my $method = $1;
4434    my $self = shift;
4435    $self->init_auto_helper;
4436
4437    unless($self->can($method))
4438    {
4439      Carp::croak "No such method '$method' in class ", ref($self);
4440    }
4441
4442    return $self->$method(@_);
4443  }
4444
4445  Carp::confess "No such method: $AUTOLOAD";
4446}
4447
4448sub auto_helper_class
4449{
4450  my($self) = shift;
4451
4452  if(@_)
4453  {
4454    my $driver = lc shift;
4455    return $self->auto_helper_classes->{$driver} = shift  if(@_);
4456    return $self->auto_helper_classes->{$driver};
4457  }
4458  else
4459  {
4460    my $db = $self->db or die "Missing db";
4461    return $self->auto_helper_classes->{$db->driver} ||
4462      $self->auto_helper_classes->{'generic'} ||
4463      Carp::croak "Don't know how to auto-initialize using driver '",
4464                  $db->driver, "'";
4465  }
4466}
4467
4468my %Rebless;
4469
4470sub init_auto_helper
4471{
4472  my($self) = shift;
4473
4474  unless($self->isa($self->auto_helper_class))
4475  {
4476    my $class = ref($self) || $self;
4477
4478    my $auto_helper_class = $self->auto_helper_class;
4479
4480    no strict 'refs';
4481    unless(@{"${auto_helper_class}::ISA"})
4482    {
4483      my $error;
4484
4485      TRY:
4486      {
4487        local $@;
4488        eval "use $auto_helper_class";
4489        $error = $@;
4490      }
4491
4492      Carp::croak "Could not load '$auto_helper_class' - $error"  if($error);
4493    }
4494
4495    $self->original_class($class);
4496
4497    REBLESS: # Do slightly evil re-blessing magic
4498    {
4499      # Check cache
4500      if(my $new_class = $Rebless{$class,$auto_helper_class})
4501      {
4502        bless $self, $new_class;
4503      }
4504      else
4505      {
4506        # Special, simple case for Rose::DB::Object::Metadata
4507        if($class eq __PACKAGE__)
4508        {
4509          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          if(index($auto_helper_class, 'Rose::DB::') == 0)
4515          {
4516            # Make a new metadata class based on the current class
4517            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              no strict 'refs';
4526              local(*auto_symbol, *existing_symbol);
4527
4528              while(my($name, $value) = each(%{"${auto_helper_class}::"}))
4529              {
4530                no warnings;
4531
4532                next  if($name =~ /^[A-Z]+$/); # skip BEGIN, DESTROY, etc.
4533
4534                *auto_symbol     = $value;
4535                *existing_symbol = *{"${class}::$name"};
4536
4537                if(defined &auto_symbol && !defined &existing_symbol)
4538                {
4539                  $Debug && warn "IMPORT $name INTO $new_class FROM $auto_helper_class\n";
4540                  *{"${new_class}::$name"} = \&auto_symbol;
4541                }
4542              }
4543            }
4544
4545            no strict 'refs';
4546            @{"${new_class}::ISA"} = ($class, $auto_helper_class);
4547
4548            bless $self, $new_class;
4549          }
4550          else
4551          {
4552            # Otherwise use the (apparently custom) metadata class
4553            bless $self, $auto_helper_class;
4554          }
4555        }
4556
4557        # Cache value
4558        $Rebless{$class,$auto_helper_class} = ref $self;
4559      }
4560    }
4561  }
4562
4563  return 1;
4564}
4565
4566sub map_record_method_key
4567{
4568  my($self, $method) = (shift, shift);
4569
4570  if(@_)
4571  {
4572    return $self->{'map_record_method_key'}{$method} = shift;
4573  }
4574
4575  return $self->{'map_record_method_key'}{$method};
4576}
4577
4578sub column_undef_overrides_default
4579{
4580  my($self) = shift;
4581
4582  if(@_)
4583  {
4584    return $self->{'column_undef_overrides_default'} = $_[0] ? 1 : 0;
4585  }
4586
4587  return $self->{'column_undef_overrides_default'}
4588    if(defined $self->{'column_undef_overrides_default'});
4589
4590  return $self->{'column_undef_overrides_default'} = ref($self)->default_column_undef_overrides_default;
4591}
4592
45931;
4594
4595__END__
4596
4597=head1 NAME
4598
4599Rose::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
4725L<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
4727L<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
4729L<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
4731Once 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
4733L<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
4735Column 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
4737Foreign 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
4739Relationship 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
4743Manual 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
4745The example of auto-initialization in the L<synopsis|/SYNOPSIS> above is the most succinct variant:
4746
4747    $meta->auto_initialize;
4748
4749As 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
4755In 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
4757In 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
4759Also, 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
4763First, 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
4765For 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
4767Even 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
4769More 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
4780Now 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
4793Note 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
4805Remember 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
4807Again, 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
4809Thankfully, 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
4829Note 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
4833The 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
4837Auto-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
4839The 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
4843As 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
4845Like 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
4847This 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
4855Get 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
4859Clears 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
4863Given 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
4867Get 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
4869This 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
4871If 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
4873The 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
4974Returns 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
4978Given the string NAME, return the name of the L<Rose::DB::Object::ConventionManager>-derived class L<mapped|/convention_manager_classes> to that name.
4979
4980If a CLASS is passed, then NAME is mapped to CLASS.
4981
4982=item B<convention_manager_classes [MAP]>
4983
4984Get or set the hash that maps names to L<Rose::DB::Object::ConventionManager>-derived class names.
4985
4986This 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
4988If 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
4990The 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
4997Get 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
5001Get 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
5005Get 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
5009Returns (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
5013This 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
5015If 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
5019Call 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
5025A 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
5031Given 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
5035Get 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
5037This 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
5039If 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
5041The 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
5050Return 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
5054Returns 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
5064Returns (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
5066Any 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
5076This is an alias for the L<add_columns|/add_columns> method.
5077
5078=item B<add_columns ARGS>
5079
5080Add 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
5082If an argument is a subclass of L<Rose::DB::Object::Metadata::Column>, it is added as-is.
5083
5084If 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
5086Otherwise, 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
5088If 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
5090If 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
5092If 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
5094If 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
5096If 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
5098If 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
5100If the "methods" and "add_methods" keys are both set, a fatal error will occur.
5101
5102Then 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
5104This 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
5106Example:
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
5150This is an alias for the L<add_nonpersistent_columns|/add_nonpersistent_columns> method.
5151
5152=item B<add_nonpersistent_columns ARGS>
5153
5154This 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
5158Add 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
5160Foreign keys can be specified in ARGS in several ways.
5161
5162If an argument is a L<Rose::DB::Object::Metadata::ForeignKey> object (or subclass thereof), it is added as-is.
5163
5164Otherwise, 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
5166If 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
5168If 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
5170If the "methods" and "add_methods" keys are both set, a fatal error will occur.
5171
5172A 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
5174This 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
5176Example:
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
5219For 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
5223This method is an alias for L<add_primary_key_columns|/add_primary_key_columns>.
5224
5225=item B<add_primary_key_columns COLUMNS>
5226
5227Add 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
5231This is an alias for the L<add_relationships|/add_relationships> method.
5232
5233=item B<add_relationships ARGS>
5234
5235Add 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
5237Relationships can be specified in ARGS in several ways.
5238
5239If an argument is a subclass of L<Rose::DB::Object::Metadata::Relationship>, it is added as-is.
5240
5241Otherwise, 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
5243If 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
5245If 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
5247If the "methods" and "add_methods" keys are both set, a fatal error will occur.
5248
5249Then 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
5251Finally, 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
5253This 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
5255Example:
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
5302This method is an alias for L<add_unique_keys|/add_unique_keys>.
5303
5304=item B<add_unique_keys KEYS>
5305
5306Add new unique keys specified by KEYS.  Unique keys can be specified in KEYS in two ways.
5307
5308If 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
5310Otherwise, 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
5314Set 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
5316For 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
5320See 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
5324Get 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
5326Enabling 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
5331This is valid Informix SQL and will insert a row with the current date and time into the "test" table.
5332
5333Now 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
5338What 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
5343In 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
5345In 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
5349Get 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
5353This 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
5357Get 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
5361Get 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
5365Returns 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
5367Note: 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
5371This 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
5375Get 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
5377If 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
5379If 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
5383Get 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
5385Returns 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
5389Returns 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
5393Returns 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
5397Get 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
5399Note 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
5403Returns 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
5407Returns 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
5411Returns 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
5415Get 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
5417If 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
5421Returns 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
5425Returns 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
5429Get 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
5431Defaults 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
5435Get 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
5437If undef is passed, then a L<Rose::DB::Object::ConventionManager::Null> object is stored instead.
5438
5439If 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
5441If 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
5443If 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
5445See the L<Rose::DB::Object::ConventionManager> documentation for more information on convention managers.
5446
5447=item B<db>
5448
5449Returns 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
5453Get 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
5457Get 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
5461Get 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
5465Delete the column named NAME.
5466
5467=item B<delete_columns>
5468
5469Delete all of the L<columns|/columns>.
5470
5471=item B<delete_column_type_class TYPE>
5472
5473Delete the type/class L<mapping|/column_type_classes> entry for the column type TYPE.
5474
5475=item B<delete_convention_manager_class NAME>
5476
5477Delete 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
5481Delete the L<non-persistent column|/nonpersistent_columns> named NAME.
5482
5483=item B<delete_nonpersistent_columns>
5484
5485Delete all of the L<nonpersistent_columns|/nonpersistent_columns>.
5486
5487=item B<delete_relationship NAME>
5488
5489Delete the relationship named NAME.
5490
5491=item B<delete_relationships>
5492
5493Delete all of the relationships.
5494
5495=item B<delete_relationship_type_class TYPE>
5496
5497Delete the type/class mapping entry for the relationship type TYPE.
5498
5499=item B<delete_unique_keys>
5500
5501Delete all of the unique key definitions.
5502
5503=item B<error_mode [MODE]>
5504
5505Get 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
5507The 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
5509Valid values of MODE are:
5510
5511=over 4
5512
5513=item carp
5514
5515Call 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
5519Call 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
5523Call 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
5527Call 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
5531An alias for the "croak" mode.
5532
5533=item return
5534
5535Return 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
5539In 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
5543Returns 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
5547Get 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
5549If 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
5551If 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
5555Get 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
5557Returns 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
5561This 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
5565Given 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
5567If 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
5569If 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
5573Get 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
5575Here'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
5579The predicate in this case is C<WHERE mycolumn E<gt> 123>.
5580
5581Predicated 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
5585Returns 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
5587Override 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
5591Initialize 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
5593If 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
5595ARGS, if any, are passed to the call to L<make_methods|/make_methods> that actually creates the methods.
5596
5597If 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
5601Get 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
5605This 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
5609Create 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
5611ARGS 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
5617If 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
5621If set to a true value, override any existing method with the same name.
5622
5623=back
5624
5625In 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
5629Create 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
5635If 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
5639If set to a true value, override any existing method with the same name.
5640
5641=back
5642
5643For 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
5647Create 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
5653If 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
5657If set to a true value, override any existing method with the same name.
5658
5659=back
5660
5661For 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
5663Foreign 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
5667This 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
5671Create 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
5677If 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
5681If set to a true value, override any existing method with the same name.
5682
5683=back
5684
5685For 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
5687Foreign 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
5689If 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
5693Get 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
5697Returns the name of the column manipulated by the method named METHOD.
5698
5699=item B<method_name_from_column_name NAME, TYPE>
5700
5701Looks 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
5705Given 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
5721Given 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
5725This 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
5729Get 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
5731Returns 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
5733Non-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
5735Non-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
5737You 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
5741Returns 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
5745Returns 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
5749Returns 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
5753Returns 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
5757Returns 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
5761This is an alias for the L<primary_key_columns|/primary_key_columns> method.
5762
5763=item B<post_init_hook [ CODEREF | ARRAYREF ]>
5764
5765Get 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
5769Get 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
5773Get 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
5777Get 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
5779Returns 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
5781This method is just a shortcut for the code:
5782
5783    $meta->primary_key->columns(...);
5784
5785See 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
5789Get 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
5791Returns the list of column names (in list context) or a reference to the array of column names (in scalar context).
5792
5793This method is just a shortcut for the code:
5794
5795    $meta->primary_key->column_names(...);
5796
5797See 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
5801Get 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
5803The 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
5807Get 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
5809If 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
5813By 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
5815PARAMS are name/value pairs.  Valid parameters are:
5816
5817=over 4
5818
5819=item B<db DB>
5820
5821A 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
5827Get 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
5829If 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
5831If 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
5835Get 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
5837Returns 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
5841Replace 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
5845is equivalent to this:
5846
5847    $meta->delete_column($name);
5848    $meta->add_column($name => $value);
5849
5850The 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
5854Get 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
5858Set 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
5860The L<setup()|/setup> method does nothing if the metadata object is already initialized (according to the L<is_initialized|/is_initialized> method).
5861
5862PARAMS are method/arguments pairs.  In general, the following transformations apply.
5863
5864Given a method/arrayref pair:
5865
5866    METHOD => [ ARG1, ARG2 ]
5867
5868The arguments will be removed from their array reference and passed to METHOD like this:
5869
5870    $meta->METHOD(ARG1, ARG2);
5871
5872Given a method/value pair:
5873
5874    METHOD => ARG
5875
5876The argument will be passed to METHOD as-is:
5877
5878    $meta->METHOD(ARG);
5879
5880There are two exceptions to these transformation rules.
5881
5882If 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
5886will 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
5892If 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
5896Is 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
5901Method 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
5903If "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
5905If "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
5907The 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
5923Finally, 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
5940The 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
5961Get 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
5963For 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
5967Now 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
5973Get 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
5977This method is an alias for L<add_unique_keys|/add_unique_keys>.
5978
5979=item B<unique_keys KEYS>
5980
5981Get 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
5983Returns 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
5987Return 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
5991Returns 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
6003These 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
6005Regardless 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
6013Get 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
6017Get 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
6021Get 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
6031Auto-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
6033Returns 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
6045If you do not want to modify the auto-generated columns, you should use the L<auto_init_columns|/auto_init_columns> method instead.
6046
6047A fatal error will occur unless at least one column was auto-generated.
6048
6049=item B<auto_generate_foreign_keys [PARAMS]>
6050
6051Auto-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
6053PARAMS 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
6055Returns a list of foreign key objects (in list context) or a reference to an array of foreign key objects (in scalar context).
6056
6057If 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
6059B<Note:> This method works with MySQL only when using the InnoDB storage type.
6060
6061=item B<auto_generate_unique_keys>
6062
6063Auto-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
6065Returns a list of unique key objects (in list context) or a reference to an array of unique key objects (in scalar context).
6066
6067If 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
6071Returns 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
6073This method is rarely called explicitly.  Usually, you will use the L<auto_init_primary_key_columns|/auto_init_primary_key_columns> method instead.
6074
6075A 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
6081Auto-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
6090PARAMS 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
6096By 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
6098B<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
6102If 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
6106If 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
6110A 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
6114A 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
6118A boolean value indicating whether or not unique key metadata will be auto-initialized.  Defaults to true.
6119
6120=back
6121
6122During 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
6124A fatal error will occur if auto-initialization fails.
6125
6126=item B<auto_init_columns [PARAMS]>
6127
6128Auto-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
6132Auto-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
6134B<Note:> This method works with MySQL only when using the InnoDB storage type.
6135
6136=item B<auto_init_primary_key_columns>
6137
6138Auto-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
6142Auto-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
6148By 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
6150B<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
6154If 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
6158A 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
6162This is an alias for the C<relationship_types> parameter.
6163
6164=item B<with_relationships [ BOOL | ARRAYREF ]>
6165
6166This 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
6170Assume 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
6180In 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
6184Auto-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
6188Get 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
6190The 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
6192The 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
6196Get 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
6198The 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
6200Each 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
6202The default foreign key name generator uses the following algorithm:
6203
6204If 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
6218The 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
6220If 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
6222If 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
6224In 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
6226In 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
6230Auto-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
6236The 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
6240The 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
6244The 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
6248If 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
6252This 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
6254Here'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
6296First 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
6317Now we'll print the C<Product> class definition;
6318
6319    print Product->meta->perl_class_definition(braces => 'bsd',
6320                                               indent => 2);
6321
6322The 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
6386Here'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
6392Note 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
6455See the L<auto-initialization|AUTO-INITIALIZATION> section for more discussion of Perl code generation.
6456
6457=item B<perl_columns_definition [PARAMS]>
6458
6459Auto-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
6465The 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
6469If 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
6473The 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
6477To 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
6481Auto-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
6487The 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
6491If 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
6495The 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
6499To 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
6503Returns 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
6509The 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
6513The 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
6517The 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
6521For 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
6533The 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
6548Auto-initialize the primary key column names (if necessary), then return the Perl source code that is equivalent to the auto-initialization.
6549
6550See 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
6554Auto-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
6560The 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
6564If 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
6568The 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
6572To 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
6576Auto-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
6582The 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
6586If 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
6590The 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
6594To 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
6598Auto-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
6604The 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
6608If 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
6612The 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
6616Determines 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
6618The "array" style passes references to arrays of column names:
6619
6620  __PACKAGE__->meta->unique_keys
6621  (
6622    [ 'id', 'name' ],
6623    [ 'flag', 'status' ],
6624  );
6625
6626The "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
6645John C. Siracusa (siracusa@gmail.com)
6646
6647=head1 LICENSE
6648
6649Copyright (c) 2010 by John C. Siracusa.  All rights reserved.  This program is
6650free software; you can redistribute it and/or modify it under the same terms
6651as Perl itself.
6652