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