1 package DBIx::Class::Schema::Loader::Base;
5 use base qw/Class::Accessor::Fast Class::C3::Componentised/;
7 use Carp::Clan qw/^DBIx::Class/;
8 use DBIx::Class::Schema::Loader::RelBuilder;
9 use Data::Dump qw/ dump /;
14 use Lingua::EN::Inflect::Number qw//;
19 our $VERSION = '0.04999_11';
21 __PACKAGE__->mk_ro_accessors(qw/
28 additional_base_classes
43 default_resultset_class
54 __PACKAGE__->mk_accessors(qw/
56 schema_version_to_dump
61 DBIx::Class::Schema::Loader::Base - Base DBIx::Class::Schema::Loader Implementation.
65 See L<DBIx::Class::Schema::Loader>
69 This is the base class for the storage-specific C<DBIx::Class::Schema::*>
70 classes, and implements the common functionality between them.
72 =head1 CONSTRUCTOR OPTIONS
74 These constructor options are the base options for
75 L<DBIx::Class::Schema::Loader/loader_options>. Available constructor options are:
77 =head2 skip_relationships
79 Skip setting up relationships. The default is to attempt the loading
84 Static schemas (ones dumped to disk) will, by default, use the new-style 0.05XXX
85 relationship names and singularized Results, unless you're overwriting an
86 existing dump made by a 0.04XXX version of L<DBIx::Class::Schema::Loader>, in
87 which case the backward compatible RelBuilder will be activated, and
88 singularization will be turned off.
94 will disable the backward-compatible RelBuilder and use
95 the new-style relationship names along with singularized Results, even when
96 overwriting a dump made with an earlier version.
98 The option also takes a hashref:
100 naming => { relationships => 'v5', results => 'v4' }
108 Latest default style, whatever that happens to be.
112 Version 0.05XXX style.
116 Version 0.04XXX style.
120 Dynamic schemas will always default to the 0.04XXX relationship names and won't
121 singularize Results for backward compatibility, to activate the new RelBuilder
122 and singularization put this in your C<Schema.pm> file:
124 __PACKAGE__->naming('current');
126 Or if you prefer to use 0.05XXX features but insure that nothing breaks in the
127 next major version upgrade:
129 __PACKAGE__->naming('v5');
133 If set to true, each constructive L<DBIx::Class> statement the loader
134 decides to execute will be C<warn>-ed before execution.
138 Set the name of the schema to load (schema in the sense that your database
139 vendor means it). Does not currently support loading more than one schema
144 Only load tables matching regex. Best specified as a qr// regex.
148 Exclude tables matching regex. Best specified as a qr// regex.
152 Overrides the default table name to moniker translation. Can be either
153 a hashref of table keys and moniker values, or a coderef for a translator
154 function taking a single scalar table name argument and returning
155 a scalar moniker. If the hash entry does not exist, or the function
156 returns a false value, the code falls back to default behavior
159 The default behavior is: C<join '', map ucfirst, split /[\W_]+/, lc $table>,
160 which is to say: lowercase everything, split up the table name into chunks
161 anywhere a non-alpha-numeric character occurs, change the case of first letter
162 of each chunk to upper case, and put the chunks back together. Examples:
164 Table Name | Moniker Name
165 ---------------------------
167 luser_group | LuserGroup
168 luser-opts | LuserOpts
170 =head2 inflect_plural
172 Just like L</moniker_map> above (can be hash/code-ref, falls back to default
173 if hash key does not exist or coderef returns false), but acts as a map
174 for pluralizing relationship names. The default behavior is to utilize
175 L<Lingua::EN::Inflect::Number/to_PL>.
177 =head2 inflect_singular
179 As L</inflect_plural> above, but for singularizing relationship names.
180 Default behavior is to utilize L<Lingua::EN::Inflect::Number/to_S>.
182 =head2 schema_base_class
184 Base class for your schema classes. Defaults to 'DBIx::Class::Schema'.
186 =head2 result_base_class
188 Base class for your table classes (aka result classes). Defaults to 'DBIx::Class'.
190 =head2 additional_base_classes
192 List of additional base classes all of your table classes will use.
194 =head2 left_base_classes
196 List of additional base classes all of your table classes will use
197 that need to be leftmost.
199 =head2 additional_classes
201 List of additional classes which all of your table classes will use.
205 List of additional components to be loaded into all of your table
206 classes. A good example would be C<ResultSetManager>.
208 =head2 resultset_components
210 List of additional ResultSet components to be loaded into your table
211 classes. A good example would be C<AlwaysRS>. Component
212 C<ResultSetManager> will be automatically added to the above
213 C<components> list if this option is set.
215 =head2 use_namespaces
217 Generate result class names suitable for
218 L<DBIx::Class::Schema/load_namespaces> and call that instead of
219 L<DBIx::Class::Schema/load_classes>. When using this option you can also
220 specify any of the options for C<load_namespaces> (i.e. C<result_namespace>,
221 C<resultset_namespace>, C<default_resultset_class>), and they will be added
222 to the call (and the generated result class names adjusted appropriately).
224 =head2 dump_directory
226 This option is designed to be a tool to help you transition from this
227 loader to a manually-defined schema when you decide it's time to do so.
229 The value of this option is a perl libdir pathname. Within
230 that directory this module will create a baseline manual
231 L<DBIx::Class::Schema> module set, based on what it creates at runtime
234 The created schema class will have the same classname as the one on
235 which you are setting this option (and the ResultSource classes will be
236 based on this name as well).
238 Normally you wouldn't hard-code this setting in your schema class, as it
239 is meant for one-time manual usage.
241 See L<DBIx::Class::Schema::Loader/dump_to_dir> for examples of the
242 recommended way to access this functionality.
244 =head2 dump_overwrite
246 Deprecated. See L</really_erase_my_files> below, which does *not* mean
247 the same thing as the old C<dump_overwrite> setting from previous releases.
249 =head2 really_erase_my_files
251 Default false. If true, Loader will unconditionally delete any existing
252 files before creating the new ones from scratch when dumping a schema to disk.
254 The default behavior is instead to only replace the top portion of the
255 file, up to and including the final stanza which contains
256 C<# DO NOT MODIFY THIS OR ANYTHING ABOVE!>
257 leaving any customizations you placed after that as they were.
259 When C<really_erase_my_files> is not set, if the output file already exists,
260 but the aforementioned final stanza is not found, or the checksum
261 contained there does not match the generated contents, Loader will
262 croak and not touch the file.
264 You should really be using version control on your schema classes (and all
265 of the rest of your code for that matter). Don't blame me if a bug in this
266 code wipes something out when it shouldn't have, you've been warned.
270 None of these methods are intended for direct invocation by regular
271 users of L<DBIx::Class::Schema::Loader>. Anything you can find here
272 can also be found via standard L<DBIx::Class::Schema> methods somehow.
276 # ensure that a peice of object data is a valid arrayref, creating
277 # an empty one or encapsulating whatever's there.
278 sub _ensure_arrayref {
283 $self->{$_} = [ $self->{$_} ]
284 unless ref $self->{$_} eq 'ARRAY';
290 Constructor for L<DBIx::Class::Schema::Loader::Base>, used internally
291 by L<DBIx::Class::Schema::Loader>.
296 my ( $class, %args ) = @_;
298 my $self = { %args };
300 bless $self => $class;
302 $self->_ensure_arrayref(qw/additional_classes
303 additional_base_classes
309 push(@{$self->{components}}, 'ResultSetManager')
310 if @{$self->{resultset_components}};
312 $self->{monikers} = {};
313 $self->{classes} = {};
315 $self->{schema_class} ||= ( ref $self->{schema} || $self->{schema} );
316 $self->{schema} ||= $self->{schema_class};
318 croak "dump_overwrite is deprecated. Please read the"
319 . " DBIx::Class::Schema::Loader::Base documentation"
320 if $self->{dump_overwrite};
322 $self->{dynamic} = ! $self->{dump_directory};
323 $self->{temp_directory} ||= File::Temp::tempdir( 'dbicXXXX',
328 $self->{dump_directory} ||= $self->{temp_directory};
330 $self->version_to_dump($DBIx::Class::Schema::Loader::VERSION);
331 $self->schema_version_to_dump($DBIx::Class::Schema::Loader::VERSION);
333 $self->_check_back_compat;
338 sub _check_back_compat {
341 # dynamic schemas will always be in 0.04006 mode
342 if ($self->dynamic) {
344 my $class = ref $self || $self;
345 require DBIx::Class::Schema::Loader::Compat::v0_040;
346 unshift @{"${class}::ISA"},
347 'DBIx::Class::Schema::Loader::Compat::v0_040';
348 Class::C3::reinitialize;
349 # just in case, though no one is likely to dump a dynamic schema
350 $self->schema_version_to_dump('0.04006');
354 # otherwise check if we need backcompat mode for a static schema
355 my $filename = $self->_get_dump_filename($self->schema_class);
356 return unless -e $filename;
358 open(my $fh, '<', $filename)
359 or croak "Cannot open '$filename' for reading: $!";
362 if (/^# Created by DBIx::Class::Schema::Loader v((\d+)\.(\d+))/) {
364 my $ver = "v${2}_${3}";
366 my $compat_class = "DBIx::Class::Schema::Loader::Compat::${ver}";
367 if ($self->load_optional_class($compat_class)) {
369 my $class = ref $self || $self;
370 unshift @{"${class}::ISA"}, $compat_class;
371 Class::C3::reinitialize;
372 $self->schema_version_to_dump($real_ver);
375 $ver =~ s/\d\z// or last;
383 sub _find_file_in_inc {
384 my ($self, $file) = @_;
386 foreach my $prefix (@INC) {
387 my $fullpath = File::Spec->catfile($prefix, $file);
388 return $fullpath if -f $fullpath
389 and Cwd::abs_path($fullpath) ne
390 Cwd::abs_path(File::Spec->catfile($self->dump_directory, $file)) || '';
397 my ($self, $class) = @_;
399 my $class_path = $class;
400 $class_path =~ s{::}{/}g;
401 $class_path .= '.pm';
406 sub _find_class_in_inc {
407 my ($self, $class) = @_;
409 return $self->_find_file_in_inc($self->_class_path($class));
413 my ($self, $class) = @_;
415 my $real_inc_path = $self->_find_class_in_inc($class);
417 return if !$real_inc_path;
419 # If we make it to here, we loaded an external definition
420 warn qq/# Loaded external class definition for '$class'\n/
423 open(my $fh, '<', $real_inc_path)
424 or croak "Failed to open '$real_inc_path' for reading: $!";
425 $self->_ext_stmt($class,
426 qq|# These lines were loaded from '$real_inc_path' found in \@INC.\n|
427 .qq|# They are now part of the custom portion of this file\n|
428 .qq|# for you to hand-edit. If you do not either delete\n|
429 .qq|# this section or remove that file from \@INC, this section\n|
430 .qq|# will be repeated redundantly when you re-create this\n|
431 .qq|# file again via Loader!\n|
435 $self->_ext_stmt($class, $_);
437 $self->_ext_stmt($class,
438 qq|# End of lines loaded from '$real_inc_path' |
441 or croak "Failed to close $real_inc_path: $!";
443 if ($self->dynamic) { # load the class too
444 # turn off redefined warnings
445 local $SIG{__WARN__} = sub {};
453 Does the actual schema-construction work.
460 $self->_load_tables($self->_tables_list);
467 Rescan the database for newly added tables. Does
468 not process drops or changes. Returns a list of
469 the newly added table monikers.
471 The schema argument should be the schema class
472 or object to be affected. It should probably
473 be derived from the original schema_class used
479 my ($self, $schema) = @_;
481 $self->{schema} = $schema;
482 $self->_relbuilder->{schema} = $schema;
485 my @current = $self->_tables_list;
486 foreach my $table ($self->_tables_list) {
487 if(!exists $self->{_tables}->{$table}) {
488 push(@created, $table);
492 my $loaded = $self->_load_tables(@created);
494 return map { $self->monikers->{$_} } @$loaded;
500 return if $self->{skip_relationships};
502 $self->{relbuilder} ||= DBIx::Class::Schema::Loader::RelBuilder->new(
503 $self->schema, $self->inflect_plural, $self->inflect_singular
508 my ($self, @tables) = @_;
510 # First, use _tables_list with constraint and exclude
511 # to get a list of tables to operate on
513 my $constraint = $self->constraint;
514 my $exclude = $self->exclude;
516 @tables = grep { /$constraint/ } @tables if $constraint;
517 @tables = grep { ! /$exclude/ } @tables if $exclude;
519 # Save the new tables to the tables list
521 $self->{_tables}->{$_} = 1;
524 $self->_make_src_class($_) for @tables;
525 $self->_setup_src_meta($_) for @tables;
527 if(!$self->skip_relationships) {
528 # The relationship loader needs a working schema
530 local $self->{dump_directory} = $self->{temp_directory};
531 $self->_reload_classes(\@tables);
532 $self->_load_relationships($_) for @tables;
535 # Remove that temp dir from INC so it doesn't get reloaded
536 @INC = grep { $_ ne $self->{dump_directory} } @INC;
539 $self->_load_external($_)
540 for map { $self->classes->{$_} } @tables;
542 # Reload without unloading first to preserve any symbols from external
544 $self->_reload_classes(\@tables, 0);
546 # Drop temporary cache
547 delete $self->{_cache};
552 sub _reload_classes {
553 my ($self, $tables, $unload) = @_;
555 my @tables = @$tables;
556 $unload = 1 unless defined $unload;
558 # so that we don't repeat custom sections
559 @INC = grep $_ ne $self->dump_directory, @INC;
561 $self->_dump_to_dir(map { $self->classes->{$_} } @tables);
563 unshift @INC, $self->dump_directory;
566 my %have_source = map { $_ => $self->schema->source($_) }
567 $self->schema->sources;
569 for my $table (@tables) {
570 my $moniker = $self->monikers->{$table};
571 my $class = $self->classes->{$table};
574 no warnings 'redefine';
575 local *Class::C3::reinitialize = sub {};
578 Class::Unload->unload($class) if $unload;
579 my ($source, $resultset_class);
581 ($source = $have_source{$moniker})
582 && ($resultset_class = $source->resultset_class)
583 && ($resultset_class ne 'DBIx::Class::ResultSet')
585 my $has_file = Class::Inspector->loaded_filename($resultset_class);
586 Class::Unload->unload($resultset_class) if $unload;
587 $self->_reload_class($resultset_class) if $has_file;
589 $self->_reload_class($class);
591 push @to_register, [$moniker, $class];
594 Class::C3->reinitialize;
596 $self->schema->register_class(@$_);
600 # We use this instead of ensure_class_loaded when there are package symbols we
603 my ($self, $class) = @_;
605 my $class_path = $self->_class_path($class);
606 delete $INC{ $class_path };
607 eval "require $class;";
610 sub _get_dump_filename {
611 my ($self, $class) = (@_);
614 return $self->dump_directory . q{/} . $class . q{.pm};
617 sub _ensure_dump_subdirs {
618 my ($self, $class) = (@_);
620 my @name_parts = split(/::/, $class);
621 pop @name_parts; # we don't care about the very last element,
622 # which is a filename
624 my $dir = $self->dump_directory;
627 mkdir($dir) or croak "mkdir('$dir') failed: $!";
629 last if !@name_parts;
630 $dir = File::Spec->catdir($dir, shift @name_parts);
635 my ($self, @classes) = @_;
637 my $schema_class = $self->schema_class;
638 my $schema_base_class = $self->schema_base_class || 'DBIx::Class::Schema';
640 my $target_dir = $self->dump_directory;
641 warn "Dumping manual schema for $schema_class to directory $target_dir ...\n"
642 unless $self->{dynamic} or $self->{quiet};
645 qq|package $schema_class;\n\n|
646 . qq|# Created by DBIx::Class::Schema::Loader\n|
647 . qq|# DO NOT MODIFY THE FIRST PART OF THIS FILE\n\n|
648 . qq|use strict;\nuse warnings;\n\n|
649 . qq|use base '$schema_base_class';\n\n|;
651 if ($self->use_namespaces) {
652 $schema_text .= qq|__PACKAGE__->load_namespaces|;
653 my $namespace_options;
654 for my $attr (qw(result_namespace
656 default_resultset_class)) {
658 $namespace_options .= qq| $attr => '| . $self->$attr . qq|',\n|
661 $schema_text .= qq|(\n$namespace_options)| if $namespace_options;
662 $schema_text .= qq|;\n|;
665 $schema_text .= qq|__PACKAGE__->load_classes;\n|;
669 local $self->{version_to_dump} = $self->schema_version_to_dump;
670 $self->_write_classfile($schema_class, $schema_text);
673 my $result_base_class = $self->result_base_class || 'DBIx::Class';
675 foreach my $src_class (@classes) {
677 qq|package $src_class;\n\n|
678 . qq|# Created by DBIx::Class::Schema::Loader\n|
679 . qq|# DO NOT MODIFY THE FIRST PART OF THIS FILE\n\n|
680 . qq|use strict;\nuse warnings;\n\n|
681 . qq|use base '$result_base_class';\n\n|;
683 $self->_write_classfile($src_class, $src_text);
686 warn "Schema dump completed.\n" unless $self->{dynamic} or $self->{quiet};
691 my ($self, $version, $ts) = @_;
692 return qq|\n\n# Created by DBIx::Class::Schema::Loader|
695 . qq|\n# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:|;
698 sub _write_classfile {
699 my ($self, $class, $text) = @_;
701 my $filename = $self->_get_dump_filename($class);
702 $self->_ensure_dump_subdirs($class);
704 if (-f $filename && $self->really_erase_my_files) {
705 warn "Deleting existing file '$filename' due to "
706 . "'really_erase_my_files' setting\n" unless $self->{quiet};
710 my ($custom_content, $old_md5, $old_ver, $old_ts) = $self->_get_custom_content($class, $filename);
713 for @{$self->{_dump_storage}->{$class} || []};
715 # Check and see if the dump is infact differnt
719 $compare_to = $text . $self->_sig_comment($old_ver, $old_ts);
722 if (Digest::MD5::md5_base64($compare_to) eq $old_md5) {
727 $text .= $self->_sig_comment(
728 $self->version_to_dump,
729 POSIX::strftime('%Y-%m-%d %H:%M:%S', localtime)
732 open(my $fh, '>', $filename)
733 or croak "Cannot open '$filename' for writing: $!";
735 # Write the top half and its MD5 sum
736 print $fh $text . Digest::MD5::md5_base64($text) . "\n";
738 # Write out anything loaded via external partial class file in @INC
740 for @{$self->{_ext_storage}->{$class} || []};
742 # Write out any custom content the user has added
743 print $fh $custom_content;
746 or croak "Error closing '$filename': $!";
749 sub _default_custom_content {
750 return qq|\n\n# You can replace this text with custom|
751 . qq| content, and it will be preserved on regeneration|
755 sub _get_custom_content {
756 my ($self, $class, $filename) = @_;
758 return ($self->_default_custom_content) if ! -f $filename;
760 open(my $fh, '<', $filename)
761 or croak "Cannot open '$filename' for reading: $!";
764 qr{^(# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:)([A-Za-z0-9/+]{22})\n};
767 my ($md5, $ts, $ver);
769 if(!$md5 && /$mark_re/) {
773 # Pull out the previous version and timestamp
774 ($ver, $ts) = $buffer =~ m/# Created by DBIx::Class::Schema::Loader v(.*?) @ (.*?)$/s;
777 croak "Checksum mismatch in '$filename'"
778 if Digest::MD5::md5_base64($buffer) ne $md5;
787 croak "Cannot not overwrite '$filename' without 'really_erase_my_files',"
788 . " it does not appear to have been generated by Loader"
791 # Default custom content:
792 $buffer ||= $self->_default_custom_content;
794 return ($buffer, $md5, $ver, $ts);
802 warn "$target: use $_;" if $self->debug;
803 $self->_raw_stmt($target, "use $_;");
810 my $schema_class = $self->schema_class;
812 my $blist = join(q{ }, @_);
813 warn "$target: use base qw/ $blist /;" if $self->debug && @_;
814 $self->_raw_stmt($target, "use base qw/ $blist /;") if @_;
817 # Create class with applicable bases, setup monikers, etc
818 sub _make_src_class {
819 my ($self, $table) = @_;
821 my $schema = $self->schema;
822 my $schema_class = $self->schema_class;
824 my $table_moniker = $self->_table2moniker($table);
825 my @result_namespace = ($schema_class);
826 if ($self->use_namespaces) {
827 my $result_namespace = $self->result_namespace || 'Result';
828 if ($result_namespace =~ /^\+(.*)/) {
829 # Fully qualified namespace
830 @result_namespace = ($1)
834 push @result_namespace, $result_namespace;
837 my $table_class = join(q{::}, @result_namespace, $table_moniker);
839 my $table_normalized = lc $table;
840 $self->classes->{$table} = $table_class;
841 $self->classes->{$table_normalized} = $table_class;
842 $self->monikers->{$table} = $table_moniker;
843 $self->monikers->{$table_normalized} = $table_moniker;
845 $self->_use ($table_class, @{$self->additional_classes});
846 $self->_inject($table_class, @{$self->left_base_classes});
848 $self->_dbic_stmt($table_class, 'load_components', @{$self->components}, 'Core');
850 $self->_dbic_stmt($table_class, 'load_resultset_components', @{$self->resultset_components})
851 if @{$self->resultset_components};
852 $self->_inject($table_class, @{$self->additional_base_classes});
855 # Set up metadata (cols, pks, etc)
856 sub _setup_src_meta {
857 my ($self, $table) = @_;
859 my $schema = $self->schema;
860 my $schema_class = $self->schema_class;
862 my $table_class = $self->classes->{$table};
863 my $table_moniker = $self->monikers->{$table};
865 my $table_name = $table;
866 my $name_sep = $self->schema->storage->sql_maker->name_sep;
868 if ($name_sep && $table_name =~ /\Q$name_sep\E/) {
869 $table_name = \ $self->_quote_table_name($table_name);
872 $self->_dbic_stmt($table_class,'table',$table_name);
874 my $cols = $self->_table_columns($table);
876 eval { $col_info = $self->_columns_info_for($table) };
878 $self->_dbic_stmt($table_class,'add_columns',@$cols);
881 if ($self->_is_case_sensitive) {
882 for my $col (keys %$col_info) {
883 $col_info->{$col}{accessor} = lc $col
887 $col_info = { map { lc($_), $col_info->{$_} } keys %$col_info };
890 my $fks = $self->_table_fk_info($table);
892 for my $fkdef (@$fks) {
893 for my $col (@{ $fkdef->{local_columns} }) {
894 $col_info->{$col}{is_foreign_key} = 1;
900 map { $_, ($col_info->{$_}||{}) } @$cols
904 my %uniq_tag; # used to eliminate duplicate uniqs
906 my $pks = $self->_table_pk_info($table) || [];
907 @$pks ? $self->_dbic_stmt($table_class,'set_primary_key',@$pks)
908 : carp("$table has no primary key");
909 $uniq_tag{ join("\0", @$pks) }++ if @$pks; # pk is a uniq
911 my $uniqs = $self->_table_uniq_info($table) || [];
913 my ($name, $cols) = @$_;
914 next if $uniq_tag{ join("\0", @$cols) }++; # skip duplicates
915 $self->_dbic_stmt($table_class,'add_unique_constraint', $name, $cols);
922 Returns a sorted list of loaded tables, using the original database table
930 return keys %{$self->_tables};
933 # Make a moniker from a table
934 sub _default_table2moniker {
935 my ($self, $table) = @_;
937 return join '', map ucfirst, split /[\W_]+/,
938 Lingua::EN::Inflect::Number::to_S(lc $table);
942 my ( $self, $table ) = @_;
946 if( ref $self->moniker_map eq 'HASH' ) {
947 $moniker = $self->moniker_map->{$table};
949 elsif( ref $self->moniker_map eq 'CODE' ) {
950 $moniker = $self->moniker_map->($table);
953 $moniker ||= $self->_default_table2moniker($table);
958 sub _load_relationships {
959 my ($self, $table) = @_;
961 my $tbl_fk_info = $self->_table_fk_info($table);
962 foreach my $fkdef (@$tbl_fk_info) {
963 $fkdef->{remote_source} =
964 $self->monikers->{delete $fkdef->{remote_table}};
966 my $tbl_uniq_info = $self->_table_uniq_info($table);
968 my $local_moniker = $self->monikers->{$table};
969 my $rel_stmts = $self->_relbuilder->generate_code($local_moniker, $tbl_fk_info, $tbl_uniq_info);
971 foreach my $src_class (sort keys %$rel_stmts) {
972 my $src_stmts = $rel_stmts->{$src_class};
973 foreach my $stmt (@$src_stmts) {
974 $self->_dbic_stmt($src_class,$stmt->{method},@{$stmt->{args}});
979 # Overload these in driver class:
981 # Returns an arrayref of column names
982 sub _table_columns { croak "ABSTRACT METHOD" }
984 # Returns arrayref of pk col names
985 sub _table_pk_info { croak "ABSTRACT METHOD" }
987 # Returns an arrayref of uniqs [ [ foo => [ col1, col2 ] ], [ bar => [ ... ] ] ]
988 sub _table_uniq_info { croak "ABSTRACT METHOD" }
990 # Returns an arrayref of foreign key constraints, each
991 # being a hashref with 3 keys:
992 # local_columns (arrayref), remote_columns (arrayref), remote_table
993 sub _table_fk_info { croak "ABSTRACT METHOD" }
995 # Returns an array of lower case table names
996 sub _tables_list { croak "ABSTRACT METHOD" }
998 # Execute a constructive DBIC class method, with debug/dump_to_dir hooks.
1003 if ( $method eq 'table' ) {
1005 $self->_pod( $class, "=head1 NAME" );
1006 my $table_descr = $class;
1007 if ( $self->can('_table_comment') ) {
1008 my $comment = $self->_table_comment($table);
1009 $table_descr .= " - " . $comment if $comment;
1011 $self->{_class2table}{ $class } = $table;
1012 $self->_pod( $class, $table_descr );
1013 $self->_pod_cut( $class );
1014 } elsif ( $method eq 'add_columns' ) {
1015 $self->_pod( $class, "=head1 ACCESSORS" );
1020 $self->_pod( $class, '=head2 ' . $_ );
1022 $comment = $self->_column_comment( $self->{_class2table}{$class}, ($i - 1) / 2 + 1 ) if $self->can('_column_comment');
1023 $self->_pod( $class, $comment ) if $comment;
1025 $self->_pod_cut( $class );
1026 } elsif ( $method =~ /^(belongs_to|has_many|might_have)$/ ) {
1027 $self->_pod( $class, "=head1 RELATIONS" ) unless $self->{_relations_started} { $class } ;
1028 my ( $accessor, $rel_class ) = @_;
1029 $self->_pod( $class, "=head2 $accessor" );
1030 $self->_pod( $class, 'Type: ' . $method );
1031 $self->_pod( $class, "Related object: L<$rel_class>" );
1032 $self->_pod_cut( $class );
1033 $self->{_relations_started} { $class } = 1;
1035 my $args = dump(@_);
1036 $args = '(' . $args . ')' if @_ < 2;
1037 my $stmt = $method . $args . q{;};
1039 warn qq|$class\->$stmt\n| if $self->debug;
1040 $self->_raw_stmt($class, '__PACKAGE__->' . $stmt);
1044 # Stores a POD documentation
1046 my ($self, $class, $stmt) = @_;
1047 $self->_raw_stmt( $class, "\n" . $stmt );
1051 my ($self, $class ) = @_;
1052 $self->_raw_stmt( $class, "\n=cut\n" );
1056 # Store a raw source line for a class (for dumping purposes)
1058 my ($self, $class, $stmt) = @_;
1059 push(@{$self->{_dump_storage}->{$class}}, $stmt);
1062 # Like above, but separately for the externally loaded stuff
1064 my ($self, $class, $stmt) = @_;
1065 push(@{$self->{_ext_storage}->{$class}}, $stmt);
1068 sub _quote_table_name {
1069 my ($self, $table) = @_;
1071 my $qt = $self->schema->storage->sql_maker->quote_char;
1073 return $table unless $qt;
1076 return $qt->[0] . $table . $qt->[1];
1079 return $qt . $table . $qt;
1082 sub _is_case_sensitive { 0 }
1086 Returns a hashref of loaded table to moniker mappings. There will
1087 be two entries for each table, the original name and the "normalized"
1088 name, in the case that the two are different (such as databases
1089 that like uppercase table names, or preserve your original mixed-case
1090 definitions, or what-have-you).
1094 Returns a hashref of table to class mappings. In some cases it will
1095 contain multiple entries per table for the original and normalized table
1096 names, as above in L</monikers>.
1100 L<DBIx::Class::Schema::Loader>
1104 See L<DBIx::Class::Schema::Loader/CONTRIBUTORS>.
1108 This library is free software; you can redistribute it and/or modify it under
1109 the same terms as Perl itself.