1 package DBIx::Class::Schema::Loader::Base;
5 use base qw/Class::Accessor::Grouped 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//;
15 use Lingua::EN::Inflect::Phrase qw//;
18 use Class::Inspector ();
19 use Scalar::Util 'looks_like_number';
20 use File::Slurp 'slurp';
21 use DBIx::Class::Schema::Loader::Utils qw/split_name dumper_squashed/;
22 use DBIx::Class::Schema::Loader::Optional::Dependencies ();
27 our $VERSION = '0.08000';
29 __PACKAGE__->mk_group_ro_accessors('simple', qw/
36 additional_base_classes
51 default_resultset_class
55 overwrite_modifications
74 __PACKAGE__->mk_group_accessors('simple', qw/
76 schema_version_to_dump
78 _upgrading_from_load_classes
79 _downgrading_to_load_classes
80 _rewriting_result_namespace
85 pod_comment_spillover_length
91 DBIx::Class::Schema::Loader::Base - Base DBIx::Class::Schema::Loader Implementation.
95 See L<DBIx::Class::Schema::Loader>
99 This is the base class for the storage-specific C<DBIx::Class::Schema::*>
100 classes, and implements the common functionality between them.
102 =head1 CONSTRUCTOR OPTIONS
104 These constructor options are the base options for
105 L<DBIx::Class::Schema::Loader/loader_options>. Available constructor options are:
107 =head2 skip_relationships
109 Skip setting up relationships. The default is to attempt the loading
112 =head2 skip_load_external
114 Skip loading of other classes in @INC. The default is to merge all other classes
115 with the same name found in @INC into the schema file we are creating.
119 Static schemas (ones dumped to disk) will, by default, use the new-style
120 relationship names and singularized Results, unless you're overwriting an
121 existing dump made by an older version of L<DBIx::Class::Schema::Loader>, in
122 which case the backward compatible RelBuilder will be activated, and the
123 appropriate monikerization used.
129 will disable the backward-compatible RelBuilder and use
130 the new-style relationship names along with singularized Results, even when
131 overwriting a dump made with an earlier version.
133 The option also takes a hashref:
135 naming => { relationships => 'v8', monikers => 'v8' }
143 How to name relationship accessors.
147 How to name Result classes.
149 =item column_accessors
151 How to name column accessors in Result classes.
161 Latest style, whatever that happens to be.
165 Unsingularlized monikers, C<has_many> only relationships with no _id stripping.
169 Monikers singularized as whole words, C<might_have> relationships for FKs on
170 C<UNIQUE> constraints, C<_id> stripping for belongs_to relationships.
172 Some of the C<_id> stripping edge cases in C<0.05003> have been reverted for
177 All monikers and relationships are inflected using
178 L<Lingua::EN::Inflect::Phrase>, and there is more aggressive C<_id> stripping
179 from relationship names.
181 In general, there is very little difference between v5 and v6 schemas.
185 This mode is identical to C<v6> mode, except that monikerization of CamelCase
186 table names is also done correctly.
188 CamelCase column names in case-preserving mode will also be handled correctly
189 for relationship name inflection. See L</preserve_case>.
191 In this mode, CamelCase L</column_accessors> are normalized based on case
192 transition instead of just being lowercased, so C<FooId> becomes C<foo_id>.
194 If you don't have any CamelCase table or column names, you can upgrade without
195 breaking any of your code.
199 This mode tries harder to not have collisions between column accessors and
200 belongs_to relationship accessors.
204 Dynamic schemas will always default to the 0.04XXX relationship names and won't
205 singularize Results for backward compatibility, to activate the new RelBuilder
206 and singularization put this in your C<Schema.pm> file:
208 __PACKAGE__->naming('current');
210 Or if you prefer to use 0.08XXX features but insure that nothing breaks in the
211 next major version upgrade:
213 __PACKAGE__->naming('v8');
217 By default POD will be generated for columns and relationships, using database
218 metadata for the text if available and supported.
220 Reading database metadata (e.g. C<COMMENT ON TABLE some_table ...>) is only
221 supported for Postgres right now.
223 Set this to C<0> to turn off all POD generation.
225 =head2 pod_comment_mode
227 Controls where table comments appear in the generated POD. Smaller table
228 comments are appended to the C<NAME> section of the documentation, and larger
229 ones are inserted into C<DESCRIPTION> instead. You can force a C<DESCRIPTION>
230 section to be generated with the comment always, only use C<NAME>, or choose
231 the length threshold at which the comment is forced into the description.
237 Use C<NAME> section only.
241 Force C<DESCRIPTION> always.
245 Use C<DESCRIPTION> if length > L</pod_comment_spillover_length>, this is the
250 =head2 pod_comment_spillover_length
252 When pod_comment_mode is set to C<auto>, this is the length of the comment at
253 which it will be forced into a separate description section.
257 =head2 relationship_attrs
259 Hashref of attributes to pass to each generated relationship, listed
260 by type. Also supports relationship type 'all', containing options to
261 pass to all generated relationships. Attributes set for more specific
262 relationship types override those set in 'all'.
266 relationship_attrs => {
267 belongs_to => { is_deferrable => 0 },
270 use this to turn off DEFERRABLE on your foreign key constraints.
274 If set to true, each constructive L<DBIx::Class> statement the loader
275 decides to execute will be C<warn>-ed before execution.
279 Set the name of the schema to load (schema in the sense that your database
280 vendor means it). Does not currently support loading more than one schema
285 Only load tables matching regex. Best specified as a qr// regex.
289 Exclude tables matching regex. Best specified as a qr// regex.
293 Overrides the default table name to moniker translation. Can be either
294 a hashref of table keys and moniker values, or a coderef for a translator
295 function taking a single scalar table name argument and returning
296 a scalar moniker. If the hash entry does not exist, or the function
297 returns a false value, the code falls back to default behavior
300 The default behavior is to split on case transition and non-alphanumeric
301 boundaries, singularize the resulting phrase, then join the titlecased words
304 Table Name | Moniker Name
305 ---------------------------------
307 luser_group | LuserGroup
308 luser-opts | LuserOpt
309 stations_visited | StationVisited
310 routeChange | RouteChange
312 =head2 inflect_plural
314 Just like L</moniker_map> above (can be hash/code-ref, falls back to default
315 if hash key does not exist or coderef returns false), but acts as a map
316 for pluralizing relationship names. The default behavior is to utilize
317 L<Lingua::EN::Inflect::Number/to_PL>.
319 =head2 inflect_singular
321 As L</inflect_plural> above, but for singularizing relationship names.
322 Default behavior is to utilize L<Lingua::EN::Inflect::Number/to_S>.
324 =head2 schema_base_class
326 Base class for your schema classes. Defaults to 'DBIx::Class::Schema'.
328 =head2 result_base_class
330 Base class for your table classes (aka result classes). Defaults to
333 =head2 additional_base_classes
335 List of additional base classes all of your table classes will use.
337 =head2 left_base_classes
339 List of additional base classes all of your table classes will use
340 that need to be leftmost.
342 =head2 additional_classes
344 List of additional classes which all of your table classes will use.
348 List of additional components to be loaded into all of your table
349 classes. A good example would be
350 L<InflateColumn::DateTime|DBIx::Class::InflateColumn::DateTime>
352 =head2 resultset_components
354 List of additional ResultSet components to be loaded into your table
355 classes. A good example would be C<AlwaysRS>. Component
356 C<ResultSetManager> will be automatically added to the above
357 C<components> list if this option is set.
359 =head2 use_namespaces
361 This is now the default, to go back to L<DBIx::Class::Schema/load_classes> pass
364 Generate result class names suitable for
365 L<DBIx::Class::Schema/load_namespaces> and call that instead of
366 L<DBIx::Class::Schema/load_classes>. When using this option you can also
367 specify any of the options for C<load_namespaces> (i.e. C<result_namespace>,
368 C<resultset_namespace>, C<default_resultset_class>), and they will be added
369 to the call (and the generated result class names adjusted appropriately).
371 =head2 dump_directory
373 This option is designed to be a tool to help you transition from this
374 loader to a manually-defined schema when you decide it's time to do so.
376 The value of this option is a perl libdir pathname. Within
377 that directory this module will create a baseline manual
378 L<DBIx::Class::Schema> module set, based on what it creates at runtime
381 The created schema class will have the same classname as the one on
382 which you are setting this option (and the ResultSource classes will be
383 based on this name as well).
385 Normally you wouldn't hard-code this setting in your schema class, as it
386 is meant for one-time manual usage.
388 See L<DBIx::Class::Schema::Loader/dump_to_dir> for examples of the
389 recommended way to access this functionality.
391 =head2 dump_overwrite
393 Deprecated. See L</really_erase_my_files> below, which does *not* mean
394 the same thing as the old C<dump_overwrite> setting from previous releases.
396 =head2 really_erase_my_files
398 Default false. If true, Loader will unconditionally delete any existing
399 files before creating the new ones from scratch when dumping a schema to disk.
401 The default behavior is instead to only replace the top portion of the
402 file, up to and including the final stanza which contains
403 C<# DO NOT MODIFY THIS OR ANYTHING ABOVE!>
404 leaving any customizations you placed after that as they were.
406 When C<really_erase_my_files> is not set, if the output file already exists,
407 but the aforementioned final stanza is not found, or the checksum
408 contained there does not match the generated contents, Loader will
409 croak and not touch the file.
411 You should really be using version control on your schema classes (and all
412 of the rest of your code for that matter). Don't blame me if a bug in this
413 code wipes something out when it shouldn't have, you've been warned.
415 =head2 overwrite_modifications
417 Default false. If false, when updating existing files, Loader will
418 refuse to modify any Loader-generated code that has been modified
419 since its last run (as determined by the checksum Loader put in its
422 If true, Loader will discard any manual modifications that have been
423 made to Loader-generated code.
425 Again, you should be using version control on your schema classes. Be
426 careful with this option.
428 =head2 custom_column_info
430 Hook for adding extra attributes to the
431 L<column_info|DBIx::Class::ResultSource/column_info> for a column.
433 Must be a coderef that returns a hashref with the extra attributes.
435 Receives the table name, column name and column_info.
439 custom_column_info => sub {
440 my ($table_name, $column_name, $column_info) = @_;
442 if ($column_name eq 'dog' && $column_info->{default_value} eq 'snoopy') {
443 return { is_snoopy => 1 };
447 This attribute can also be used to set C<inflate_datetime> on a non-datetime
448 column so it also receives the L</datetime_timezone> and/or L</datetime_locale>.
450 =head2 datetime_timezone
452 Sets the timezone attribute for L<DBIx::Class::InflateColumn::DateTime> for all
453 columns with the DATE/DATETIME/TIMESTAMP data_types.
455 =head2 datetime_locale
457 Sets the locale attribute for L<DBIx::Class::InflateColumn::DateTime> for all
458 columns with the DATE/DATETIME/TIMESTAMP data_types.
462 File in Perl format, which should return a HASH reference, from which to read
467 Usually column names are lowercased, to make them easier to work with in
468 L<DBIx::Class>. This option lets you turn this behavior off, if the driver
471 Drivers for case sensitive databases like Sybase ASE or MSSQL with a
472 case-sensitive collation will turn this option on unconditionally.
474 Currently the drivers for SQLite, mysql, MSSQL and Firebird/InterBase support
477 =head2 qualify_objects
479 Set to true to prepend the L</db_schema> to table names for C<<
480 __PACKAGE__->table >> calls, and to some other things like Oracle sequences.
484 Creates Schema and Result classes that use L<Moose>, L<MooseX::NonMoose> and
485 L<namespace::autoclean>. The default content after the md5 sum also makes the
488 It is safe to upgrade your existing Schema to this option.
492 None of these methods are intended for direct invocation by regular
493 users of L<DBIx::Class::Schema::Loader>. Some are proxied via
494 L<DBIx::Class::Schema::Loader>.
498 my $CURRENT_V = 'v8';
501 schema_base_class result_base_class additional_base_classes
502 left_base_classes additional_classes components resultset_components
505 # ensure that a peice of object data is a valid arrayref, creating
506 # an empty one or encapsulating whatever's there.
507 sub _ensure_arrayref {
512 $self->{$_} = [ $self->{$_} ]
513 unless ref $self->{$_} eq 'ARRAY';
519 Constructor for L<DBIx::Class::Schema::Loader::Base>, used internally
520 by L<DBIx::Class::Schema::Loader>.
525 my ( $class, %args ) = @_;
527 my $self = { %args };
529 bless $self => $class;
531 if (my $config_file = $self->config_file) {
532 my $config_opts = do $config_file;
534 croak "Error reading config from $config_file: $@" if $@;
536 croak "Config file $config_file must be a hashref" unless ref($config_opts) eq 'HASH';
538 while (my ($k, $v) = each %$config_opts) {
539 $self->{$k} = $v unless exists $self->{$k};
543 $self->_ensure_arrayref(qw/additional_classes
544 additional_base_classes
550 $self->_validate_class_args;
552 if ($self->use_moose) {
553 if (not DBIx::Class::Schema::Loader::Optional::Dependencies->req_ok_for('use_moose')) {
554 die sprintf "You must install the following CPAN modules to enable the use_moose option: %s.\nYou are missing: %s.\n",
555 "Moose, MooseX::NonMoose and namespace::autoclean",
556 DBIx::Class::Schema::Loader::Optional::Dependencies->req_missing_for('use_moose');
560 push(@{$self->{components}}, 'ResultSetManager')
561 if @{$self->{resultset_components}};
563 $self->{monikers} = {};
564 $self->{classes} = {};
565 $self->{_upgrading_classes} = {};
567 $self->{schema_class} ||= ( ref $self->{schema} || $self->{schema} );
568 $self->{schema} ||= $self->{schema_class};
570 croak "dump_overwrite is deprecated. Please read the"
571 . " DBIx::Class::Schema::Loader::Base documentation"
572 if $self->{dump_overwrite};
574 $self->{dynamic} = ! $self->{dump_directory};
575 $self->{temp_directory} ||= File::Temp::tempdir( 'dbicXXXX',
580 $self->{dump_directory} ||= $self->{temp_directory};
582 $self->version_to_dump($DBIx::Class::Schema::Loader::VERSION);
583 $self->schema_version_to_dump($DBIx::Class::Schema::Loader::VERSION);
585 if ((not ref $self->naming) && defined $self->naming) {
586 my $naming_ver = $self->naming;
588 relationships => $naming_ver,
589 monikers => $naming_ver,
590 column_accessors => $naming_ver,
595 for (values %{ $self->naming }) {
596 $_ = $CURRENT_V if $_ eq 'current';
599 $self->{naming} ||= {};
601 if ($self->custom_column_info && ref $self->custom_column_info ne 'CODE') {
602 croak 'custom_column_info must be a CODE ref';
605 $self->_check_back_compat;
607 $self->use_namespaces(1) unless defined $self->use_namespaces;
608 $self->generate_pod(1) unless defined $self->generate_pod;
609 $self->pod_comment_mode('auto') unless defined $self->pod_comment_mode;
610 $self->pod_comment_spillover_length(60) unless defined $self->pod_comment_spillover_length;
615 sub _check_back_compat {
618 # dynamic schemas will always be in 0.04006 mode, unless overridden
619 if ($self->dynamic) {
620 # just in case, though no one is likely to dump a dynamic schema
621 $self->schema_version_to_dump('0.04006');
623 if (not %{ $self->naming }) {
624 warn <<EOF unless $ENV{SCHEMA_LOADER_BACKCOMPAT};
626 Dynamic schema detected, will run in 0.04006 mode.
628 Set the 'naming' attribute or the SCHEMA_LOADER_BACKCOMPAT environment variable
629 to disable this warning.
631 Also consider setting 'use_namespaces => 1' if/when upgrading.
633 See perldoc DBIx::Class::Schema::Loader::Manual::UpgradingFromV4 for more
638 $self->_upgrading_from('v4');
641 $self->naming->{relationships} ||= 'v4';
642 $self->naming->{monikers} ||= 'v4';
644 if ($self->use_namespaces) {
645 $self->_upgrading_from_load_classes(1);
648 $self->use_namespaces(0);
654 # otherwise check if we need backcompat mode for a static schema
655 my $filename = $self->_get_dump_filename($self->schema_class);
656 return unless -e $filename;
658 open(my $fh, '<', $filename)
659 or croak "Cannot open '$filename' for reading: $!";
661 my $load_classes = 0;
662 my $result_namespace = '';
665 if (/^__PACKAGE__->load_classes;/) {
667 } elsif (/result_namespace => '([^']+)'/) {
668 $result_namespace = $1;
669 } elsif (my ($real_ver) =
670 /^# Created by DBIx::Class::Schema::Loader v(\d+\.\d+)/) {
672 if ($load_classes && (not defined $self->use_namespaces)) {
673 warn <<"EOF" unless $ENV{SCHEMA_LOADER_BACKCOMPAT};
675 'load_classes;' static schema detected, turning off 'use_namespaces'.
677 Set the 'use_namespaces' attribute or the SCHEMA_LOADER_BACKCOMPAT environment
678 variable to disable this warning.
680 See perldoc DBIx::Class::Schema::Loader::Manual::UpgradingFromV4 for more
683 $self->use_namespaces(0);
685 elsif ($load_classes && $self->use_namespaces) {
686 $self->_upgrading_from_load_classes(1);
688 elsif ((not $load_classes) && defined $self->use_namespaces
689 && (not $self->use_namespaces)) {
690 $self->_downgrading_to_load_classes(
691 $result_namespace || 'Result'
694 elsif ((not defined $self->use_namespaces)
695 || $self->use_namespaces) {
696 if (not $self->result_namespace) {
697 $self->result_namespace($result_namespace || 'Result');
699 elsif ($result_namespace ne $self->result_namespace) {
700 $self->_rewriting_result_namespace(
701 $result_namespace || 'Result'
706 # XXX when we go past .0 this will need fixing
707 my ($v) = $real_ver =~ /([1-9])/;
710 last if $v eq $CURRENT_V || $real_ver =~ /^0\.\d\d999/;
712 if (not %{ $self->naming }) {
713 warn <<"EOF" unless $ENV{SCHEMA_LOADER_BACKCOMPAT};
715 Version $real_ver static schema detected, turning on backcompat mode.
717 Set the 'naming' attribute or the SCHEMA_LOADER_BACKCOMPAT environment variable
718 to disable this warning.
720 See: 'naming' in perldoc DBIx::Class::Schema::Loader::Base .
722 See perldoc DBIx::Class::Schema::Loader::Manual::UpgradingFromV4 if upgrading
723 from version 0.04006.
727 $self->_upgrading_from($v);
731 $self->naming->{relationships} ||= $v;
732 $self->naming->{monikers} ||= $v;
733 $self->naming->{column_accessors} ||= $v;
735 $self->schema_version_to_dump($real_ver);
743 sub _validate_class_args {
747 foreach my $k (@CLASS_ARGS) {
748 next unless $self->$k;
750 my @classes = ref $self->$k eq 'ARRAY' ? @{ $self->$k } : $self->$k;
751 foreach my $c (@classes) {
752 # components default to being under the DBIx::Class namespace unless they
753 # are preceeded with a '+'
754 if ( $k =~ m/components$/ && $c !~ s/^\+// ) {
755 $c = 'DBIx::Class::' . $c;
758 # 1 == installed, 0 == not installed, undef == invalid classname
759 my $installed = Class::Inspector->installed($c);
760 if ( defined($installed) ) {
761 if ( $installed == 0 ) {
762 croak qq/$c, as specified in the loader option "$k", is not installed/;
765 croak qq/$c, as specified in the loader option "$k", is an invalid class name/;
771 sub _find_file_in_inc {
772 my ($self, $file) = @_;
774 foreach my $prefix (@INC) {
775 my $fullpath = File::Spec->catfile($prefix, $file);
776 return $fullpath if -f $fullpath
777 # abs_path throws on Windows for nonexistant files
778 and eval { Cwd::abs_path($fullpath) } ne
779 (eval { Cwd::abs_path(File::Spec->catfile($self->dump_directory, $file)) } || '');
786 my ($self, $class) = @_;
788 my $class_path = $class;
789 $class_path =~ s{::}{/}g;
790 $class_path .= '.pm';
795 sub _find_class_in_inc {
796 my ($self, $class) = @_;
798 return $self->_find_file_in_inc($self->_class_path($class));
804 return $self->_upgrading_from
805 || $self->_upgrading_from_load_classes
806 || $self->_downgrading_to_load_classes
807 || $self->_rewriting_result_namespace
811 sub _rewrite_old_classnames {
812 my ($self, $code) = @_;
814 return $code unless $self->_rewriting;
816 my %old_classes = reverse %{ $self->_upgrading_classes };
818 my $re = join '|', keys %old_classes;
821 $code =~ s/$re/$old_classes{$1} || $1/eg;
827 my ($self, $class) = @_;
829 return if $self->{skip_load_external};
831 # so that we don't load our own classes, under any circumstances
832 local *INC = [ grep $_ ne $self->dump_directory, @INC ];
834 my $real_inc_path = $self->_find_class_in_inc($class);
836 my $old_class = $self->_upgrading_classes->{$class}
837 if $self->_rewriting;
839 my $old_real_inc_path = $self->_find_class_in_inc($old_class)
840 if $old_class && $old_class ne $class;
842 return unless $real_inc_path || $old_real_inc_path;
844 if ($real_inc_path) {
845 # If we make it to here, we loaded an external definition
846 warn qq/# Loaded external class definition for '$class'\n/
849 open(my $fh, '<', $real_inc_path)
850 or croak "Failed to open '$real_inc_path' for reading: $!";
851 my $code = do { local $/; <$fh> };
853 or croak "Failed to close $real_inc_path: $!";
854 $code = $self->_rewrite_old_classnames($code);
856 if ($self->dynamic) { # load the class too
857 # kill redefined warnings
858 my $warn_handler = $SIG{__WARN__} || sub { warn @_ };
859 local $SIG{__WARN__} = sub {
861 unless $_[0] =~ /^Subroutine \S+ redefined/;
867 $self->_ext_stmt($class,
868 qq|# These lines were loaded from '$real_inc_path' found in \@INC.\n|
869 .qq|# They are now part of the custom portion of this file\n|
870 .qq|# for you to hand-edit. If you do not either delete\n|
871 .qq|# this section or remove that file from \@INC, this section\n|
872 .qq|# will be repeated redundantly when you re-create this\n|
873 .qq|# file again via Loader! See skip_load_external to disable\n|
874 .qq|# this feature.\n|
877 $self->_ext_stmt($class, $code);
878 $self->_ext_stmt($class,
879 qq|# End of lines loaded from '$real_inc_path' |
883 if ($old_real_inc_path) {
884 my $code = slurp $old_real_inc_path;
886 $self->_ext_stmt($class, <<"EOF");
888 # These lines were loaded from '$old_real_inc_path',
889 # based on the Result class name that would have been created by an older
890 # version of the Loader. For a static schema, this happens only once during
891 # upgrade. See skip_load_external to disable this feature.
894 $code = $self->_rewrite_old_classnames($code);
896 if ($self->dynamic) {
899 Detected external content in '$old_real_inc_path', a class name that would have
900 been used by an older version of the Loader.
902 * PLEASE RENAME THIS CLASS: from '$old_class' to '$class', as that is the
903 new name of the Result.
905 # kill redefined warnings
906 my $warn_handler = $SIG{__WARN__} || sub { warn @_ };
907 local $SIG{__WARN__} = sub {
909 unless $_[0] =~ /^Subroutine \S+ redefined/;
916 $self->_ext_stmt($class, $code);
917 $self->_ext_stmt($class,
918 qq|# End of lines loaded from '$old_real_inc_path' |
925 Does the actual schema-construction work.
933 $self->_tables_list({ constraint => $self->constraint, exclude => $self->exclude })
941 Rescan the database for changes. Returns a list of the newly added table
944 The schema argument should be the schema class or object to be affected. It
945 should probably be derived from the original schema_class used during L</load>.
950 my ($self, $schema) = @_;
952 $self->{schema} = $schema;
953 $self->_relbuilder->{schema} = $schema;
956 my @current = $self->_tables_list({ constraint => $self->constraint, exclude => $self->exclude });
958 foreach my $table (@current) {
959 if(!exists $self->{_tables}->{$table}) {
960 push(@created, $table);
965 @current{@current} = ();
966 foreach my $table (keys %{ $self->{_tables} }) {
967 if (not exists $current{$table}) {
968 $self->_unregister_source_for_table($table);
972 delete $self->{_dump_storage};
973 delete $self->{_relations_started};
975 my $loaded = $self->_load_tables(@current);
977 return map { $self->monikers->{$_} } @created;
981 no warnings 'uninitialized';
984 return if $self->{skip_relationships};
986 if ($self->naming->{relationships} eq 'v4') {
987 require DBIx::Class::Schema::Loader::RelBuilder::Compat::v0_040;
988 return $self->{relbuilder} ||=
989 DBIx::Class::Schema::Loader::RelBuilder::Compat::v0_040->new(
991 $self->inflect_plural,
992 $self->inflect_singular,
993 $self->relationship_attrs,
996 elsif ($self->naming->{relationships} eq 'v5') {
997 require DBIx::Class::Schema::Loader::RelBuilder::Compat::v0_05;
998 return $self->{relbuilder} ||= DBIx::Class::Schema::Loader::RelBuilder::Compat::v0_05->new (
1000 $self->inflect_plural,
1001 $self->inflect_singular,
1002 $self->relationship_attrs,
1005 elsif ($self->naming->{relationships} eq 'v6') {
1006 require DBIx::Class::Schema::Loader::RelBuilder::Compat::v0_06;
1007 return $self->{relbuilder} ||= DBIx::Class::Schema::Loader::RelBuilder::Compat::v0_06->new (
1009 $self->inflect_plural,
1010 $self->inflect_singular,
1011 $self->relationship_attrs,
1014 elsif ($self->naming->{relationships} eq 'v6') {
1015 require DBIx::Class::Schema::Loader::RelBuilder::Compat::v0_07;
1016 return $self->{relbuilder} ||= DBIx::Class::Schema::Loader::RelBuilder::Compat::v0_07->new (
1018 $self->inflect_plural,
1019 $self->inflect_singular,
1020 $self->relationship_attrs,
1024 return $self->{relbuilder} ||= DBIx::Class::Schema::Loader::RelBuilder->new (
1026 $self->inflect_plural,
1027 $self->inflect_singular,
1028 $self->relationship_attrs,
1033 my ($self, @tables) = @_;
1035 # Save the new tables to the tables list
1037 $self->{_tables}->{$_} = 1;
1040 $self->_make_src_class($_) for @tables;
1042 # sanity-check for moniker clashes
1043 my $inverse_moniker_idx;
1044 for (keys %{$self->monikers}) {
1045 push @{$inverse_moniker_idx->{$self->monikers->{$_}}}, $_;
1049 for (keys %$inverse_moniker_idx) {
1050 my $tables = $inverse_moniker_idx->{$_};
1052 push @clashes, sprintf ("tables %s reduced to the same source moniker '%s'",
1053 join (', ', map { "'$_'" } @$tables),
1060 die 'Unable to load schema - chosen moniker/class naming style results in moniker clashes. '
1061 . 'Either change the naming style, or supply an explicit moniker_map: '
1062 . join ('; ', @clashes)
1068 $self->_setup_src_meta($_) for @tables;
1070 if(!$self->skip_relationships) {
1071 # The relationship loader needs a working schema
1073 local $self->{dump_directory} = $self->{temp_directory};
1074 $self->_reload_classes(\@tables);
1075 $self->_load_relationships($_) for @tables;
1078 # Remove that temp dir from INC so it doesn't get reloaded
1079 @INC = grep $_ ne $self->dump_directory, @INC;
1082 $self->_load_external($_)
1083 for map { $self->classes->{$_} } @tables;
1085 # Reload without unloading first to preserve any symbols from external
1087 $self->_reload_classes(\@tables, 0);
1089 # Drop temporary cache
1090 delete $self->{_cache};
1095 sub _reload_classes {
1096 my ($self, $tables, $unload) = @_;
1098 my @tables = @$tables;
1099 $unload = 1 unless defined $unload;
1101 # so that we don't repeat custom sections
1102 @INC = grep $_ ne $self->dump_directory, @INC;
1104 $self->_dump_to_dir(map { $self->classes->{$_} } @tables);
1106 unshift @INC, $self->dump_directory;
1109 my %have_source = map { $_ => $self->schema->source($_) }
1110 $self->schema->sources;
1112 for my $table (@tables) {
1113 my $moniker = $self->monikers->{$table};
1114 my $class = $self->classes->{$table};
1117 no warnings 'redefine';
1118 local *Class::C3::reinitialize = sub {};
1121 if ($class->can('meta') && try { $class->meta->isa('Moose::Meta::Class') }) {
1122 $class->meta->make_mutable;
1124 Class::Unload->unload($class) if $unload;
1125 my ($source, $resultset_class);
1127 ($source = $have_source{$moniker})
1128 && ($resultset_class = $source->resultset_class)
1129 && ($resultset_class ne 'DBIx::Class::ResultSet')
1131 my $has_file = Class::Inspector->loaded_filename($resultset_class);
1132 if ($resultset_class->can('meta') && try { $resultset_class->meta->isa('Moose::Meta::Class') }) {
1133 $resultset_class->meta->make_mutable;
1135 Class::Unload->unload($resultset_class) if $unload;
1136 $self->_reload_class($resultset_class) if $has_file;
1138 $self->_reload_class($class);
1140 push @to_register, [$moniker, $class];
1143 Class::C3->reinitialize;
1144 for (@to_register) {
1145 $self->schema->register_class(@$_);
1149 # We use this instead of ensure_class_loaded when there are package symbols we
1152 my ($self, $class) = @_;
1154 my $class_path = $self->_class_path($class);
1155 delete $INC{ $class_path };
1157 # kill redefined warnings
1158 my $warn_handler = $SIG{__WARN__} || sub { warn @_ };
1159 local $SIG{__WARN__} = sub {
1161 unless $_[0] =~ /^Subroutine \S+ redefined/;
1163 eval "require $class;";
1164 die "Failed to reload class $class: $@" if $@;
1167 sub _get_dump_filename {
1168 my ($self, $class) = (@_);
1170 $class =~ s{::}{/}g;
1171 return $self->dump_directory . q{/} . $class . q{.pm};
1174 sub _ensure_dump_subdirs {
1175 my ($self, $class) = (@_);
1177 my @name_parts = split(/::/, $class);
1178 pop @name_parts; # we don't care about the very last element,
1179 # which is a filename
1181 my $dir = $self->dump_directory;
1184 mkdir($dir) or croak "mkdir('$dir') failed: $!";
1186 last if !@name_parts;
1187 $dir = File::Spec->catdir($dir, shift @name_parts);
1192 my ($self, @classes) = @_;
1194 my $schema_class = $self->schema_class;
1195 my $schema_base_class = $self->schema_base_class || 'DBIx::Class::Schema';
1197 my $target_dir = $self->dump_directory;
1198 warn "Dumping manual schema for $schema_class to directory $target_dir ...\n"
1199 unless $self->{dynamic} or $self->{quiet};
1202 qq|package $schema_class;\n\n|
1203 . qq|# Created by DBIx::Class::Schema::Loader\n|
1204 . qq|# DO NOT MODIFY THE FIRST PART OF THIS FILE\n\n|
1205 . qq|use strict;\nuse warnings;\n\n|;
1206 if ($self->use_moose) {
1207 $schema_text.= qq|use Moose;\nuse MooseX::NonMoose;\nuse namespace::autoclean;\nextends '$schema_base_class';\n\n|;
1210 $schema_text .= qq|use base '$schema_base_class';\n\n|;
1213 if ($self->use_namespaces) {
1214 $schema_text .= qq|__PACKAGE__->load_namespaces|;
1215 my $namespace_options;
1217 my @attr = qw/resultset_namespace default_resultset_class/;
1219 unshift @attr, 'result_namespace' unless (not $self->result_namespace) || $self->result_namespace eq 'Result';
1221 for my $attr (@attr) {
1223 $namespace_options .= qq| $attr => '| . $self->$attr . qq|',\n|
1226 $schema_text .= qq|(\n$namespace_options)| if $namespace_options;
1227 $schema_text .= qq|;\n|;
1230 $schema_text .= qq|__PACKAGE__->load_classes;\n|;
1234 local $self->{version_to_dump} = $self->schema_version_to_dump;
1235 $self->_write_classfile($schema_class, $schema_text, 1);
1238 my $result_base_class = $self->result_base_class || 'DBIx::Class::Core';
1240 foreach my $src_class (@classes) {
1242 qq|package $src_class;\n\n|
1243 . qq|# Created by DBIx::Class::Schema::Loader\n|
1244 . qq|# DO NOT MODIFY THE FIRST PART OF THIS FILE\n\n|
1245 . qq|use strict;\nuse warnings;\n\n|;
1246 if ($self->use_moose) {
1247 $src_text.= qq|use Moose;\nuse MooseX::NonMoose;\nuse namespace::autoclean;|;
1249 # these options 'use base' which is compile time
1250 if (@{ $self->left_base_classes } || @{ $self->additional_base_classes }) {
1251 $src_text .= qq|\nBEGIN { extends '$result_base_class' }\n\n|;
1254 $src_text .= qq|\nextends '$result_base_class';\n\n|;
1258 $src_text .= qq|use base '$result_base_class';\n\n|;
1260 $self->_write_classfile($src_class, $src_text);
1263 # remove Result dir if downgrading from use_namespaces, and there are no
1265 if (my $result_ns = $self->_downgrading_to_load_classes
1266 || $self->_rewriting_result_namespace) {
1267 my $result_namespace = $self->_result_namespace(
1272 (my $result_dir = $result_namespace) =~ s{::}{/}g;
1273 $result_dir = $self->dump_directory . '/' . $result_dir;
1275 unless (my @files = glob "$result_dir/*") {
1280 warn "Schema dump completed.\n" unless $self->{dynamic} or $self->{quiet};
1285 my ($self, $version, $ts) = @_;
1286 return qq|\n\n# Created by DBIx::Class::Schema::Loader|
1289 . qq|\n# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:|;
1292 sub _write_classfile {
1293 my ($self, $class, $text, $is_schema) = @_;
1295 my $filename = $self->_get_dump_filename($class);
1296 $self->_ensure_dump_subdirs($class);
1298 if (-f $filename && $self->really_erase_my_files) {
1299 warn "Deleting existing file '$filename' due to "
1300 . "'really_erase_my_files' setting\n" unless $self->{quiet};
1304 my ($custom_content, $old_md5, $old_ver, $old_ts) = $self->_get_custom_content($class, $filename);
1306 # If upgrading to use_moose=1 replace default custom content with default Moose custom content.
1307 # If there is already custom content, which does not have the Moose content, add it.
1308 if ($self->use_moose) {
1309 local $self->{use_moose} = 0;
1311 if ($custom_content eq $self->_default_custom_content) {
1312 local $self->{use_moose} = 1;
1314 $custom_content = $self->_default_custom_content;
1317 local $self->{use_moose} = 1;
1319 if ($custom_content !~ /\Q@{[$self->_default_moose_custom_content]}\E/) {
1320 $custom_content .= $self->_default_custom_content;
1325 if (my $old_class = $self->_upgrading_classes->{$class}) {
1326 my $old_filename = $self->_get_dump_filename($old_class);
1328 my ($old_custom_content) = $self->_get_custom_content(
1329 $old_class, $old_filename, 0 # do not add default comment
1332 $old_custom_content =~ s/\n\n# You can replace.*\n1;\n//;
1334 if ($old_custom_content) {
1336 "\n" . $old_custom_content . "\n" . $custom_content;
1339 unlink $old_filename;
1342 $custom_content = $self->_rewrite_old_classnames($custom_content);
1345 for @{$self->{_dump_storage}->{$class} || []};
1347 # Check and see if the dump is infact differnt
1351 $compare_to = $text . $self->_sig_comment($old_ver, $old_ts);
1354 if (Digest::MD5::md5_base64($compare_to) eq $old_md5) {
1355 return unless $self->_upgrading_from && $is_schema;
1359 $text .= $self->_sig_comment(
1360 $self->version_to_dump,
1361 POSIX::strftime('%Y-%m-%d %H:%M:%S', localtime)
1364 open(my $fh, '>', $filename)
1365 or croak "Cannot open '$filename' for writing: $!";
1367 # Write the top half and its MD5 sum
1368 print $fh $text . Digest::MD5::md5_base64($text) . "\n";
1370 # Write out anything loaded via external partial class file in @INC
1372 for @{$self->{_ext_storage}->{$class} || []};
1374 # Write out any custom content the user has added
1375 print $fh $custom_content;
1378 or croak "Error closing '$filename': $!";
1381 sub _default_moose_custom_content {
1382 return qq|\n__PACKAGE__->meta->make_immutable;|;
1385 sub _default_custom_content {
1387 my $default = qq|\n\n# You can replace this text with custom|
1388 . qq| content, and it will be preserved on regeneration|;
1389 if ($self->use_moose) {
1390 $default .= $self->_default_moose_custom_content;
1392 $default .= qq|\n1;\n|;
1396 sub _get_custom_content {
1397 my ($self, $class, $filename, $add_default) = @_;
1399 $add_default = 1 unless defined $add_default;
1401 return ($self->_default_custom_content) if ! -f $filename;
1403 open(my $fh, '<', $filename)
1404 or croak "Cannot open '$filename' for reading: $!";
1407 qr{^(# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:)([A-Za-z0-9/+]{22})\n};
1410 my ($md5, $ts, $ver);
1412 if(!$md5 && /$mark_re/) {
1416 # Pull out the previous version and timestamp
1417 ($ver, $ts) = $buffer =~ m/# Created by DBIx::Class::Schema::Loader v(.*?) @ (.*?)$/s;
1420 croak "Checksum mismatch in '$filename', the auto-generated part of the file has been modified outside of this loader. Aborting.\nIf you want to overwrite these modifications, set the 'overwrite_modifications' loader option.\n"
1421 if !$self->overwrite_modifications && Digest::MD5::md5_base64($buffer) ne $md5;
1430 croak "Cannot not overwrite '$filename' without 'really_erase_my_files',"
1431 . " it does not appear to have been generated by Loader"
1434 # Default custom content:
1435 $buffer ||= $self->_default_custom_content if $add_default;
1437 return ($buffer, $md5, $ver, $ts);
1445 warn "$target: use $_;" if $self->debug;
1446 $self->_raw_stmt($target, "use $_;");
1454 my $blist = join(q{ }, @_);
1456 return unless $blist;
1458 warn "$target: use base qw/$blist/;" if $self->debug;
1459 $self->_raw_stmt($target, "use base qw/$blist/;");
1462 sub _result_namespace {
1463 my ($self, $schema_class, $ns) = @_;
1464 my @result_namespace;
1466 if ($ns =~ /^\+(.*)/) {
1467 # Fully qualified namespace
1468 @result_namespace = ($1)
1471 # Relative namespace
1472 @result_namespace = ($schema_class, $ns);
1475 return wantarray ? @result_namespace : join '::', @result_namespace;
1478 # Create class with applicable bases, setup monikers, etc
1479 sub _make_src_class {
1480 my ($self, $table) = @_;
1482 my $schema = $self->schema;
1483 my $schema_class = $self->schema_class;
1485 my $table_moniker = $self->_table2moniker($table);
1486 my @result_namespace = ($schema_class);
1487 if ($self->use_namespaces) {
1488 my $result_namespace = $self->result_namespace || 'Result';
1489 @result_namespace = $self->_result_namespace(
1494 my $table_class = join(q{::}, @result_namespace, $table_moniker);
1496 if ((my $upgrading_v = $self->_upgrading_from)
1497 || $self->_rewriting) {
1498 local $self->naming->{monikers} = $upgrading_v
1501 my @result_namespace = @result_namespace;
1502 if ($self->_upgrading_from_load_classes) {
1503 @result_namespace = ($schema_class);
1505 elsif (my $ns = $self->_downgrading_to_load_classes) {
1506 @result_namespace = $self->_result_namespace(
1511 elsif ($ns = $self->_rewriting_result_namespace) {
1512 @result_namespace = $self->_result_namespace(
1518 my $old_class = join(q{::}, @result_namespace,
1519 $self->_table2moniker($table));
1521 $self->_upgrading_classes->{$table_class} = $old_class
1522 unless $table_class eq $old_class;
1525 # this was a bad idea, should be ok now without it
1526 # my $table_normalized = lc $table;
1527 # $self->classes->{$table_normalized} = $table_class;
1528 # $self->monikers->{$table_normalized} = $table_moniker;
1530 $self->classes->{$table} = $table_class;
1531 $self->monikers->{$table} = $table_moniker;
1533 $self->_use ($table_class, @{$self->additional_classes});
1534 $self->_inject($table_class, @{$self->left_base_classes});
1536 if (my @components = @{ $self->components }) {
1537 $self->_dbic_stmt($table_class, 'load_components', @components);
1540 $self->_dbic_stmt($table_class, 'load_resultset_components', @{$self->resultset_components})
1541 if @{$self->resultset_components};
1542 $self->_inject($table_class, @{$self->additional_base_classes});
1545 sub _resolve_col_accessor_collisions {
1546 my ($self, $col_info) = @_;
1548 my $base = $self->result_base_class || 'DBIx::Class::Core';
1549 my @components = map "DBIx::Class::$_", @{ $self->components || [] };
1553 for my $class ($base, @components, $self->use_moose ? 'Moose::Object' : ()) {
1554 eval "require ${class};";
1557 push @methods, @{ Class::Inspector->methods($class) || [] };
1561 @methods{@methods} = ();
1564 $methods{meta} = undef;
1566 while (my ($col, $info) = each %$col_info) {
1567 my $accessor = $info->{accessor} || $col;
1569 next if $accessor eq 'id'; # special case (very common column)
1571 if (exists $methods{$accessor}) {
1572 $info->{accessor} = undef;
1577 sub _make_column_accessor_name {
1578 my ($self, $column_name) = @_;
1580 return join '_', map lc, split_name $column_name;
1583 # Set up metadata (cols, pks, etc)
1584 sub _setup_src_meta {
1585 my ($self, $table) = @_;
1587 my $schema = $self->schema;
1588 my $schema_class = $self->schema_class;
1590 my $table_class = $self->classes->{$table};
1591 my $table_moniker = $self->monikers->{$table};
1593 my $table_name = $table;
1594 my $name_sep = $self->schema->storage->sql_maker->name_sep;
1596 if ($name_sep && $table_name =~ /\Q$name_sep\E/) {
1597 $table_name = \ $self->_quote_table_name($table_name);
1600 my $full_table_name = ($self->qualify_objects ? ($self->db_schema . '.') : '') . (ref $table_name ? $$table_name : $table_name);
1602 # be careful to not create refs Data::Dump can "optimize"
1603 $full_table_name = \do {"".$full_table_name} if ref $table_name;
1605 $self->_dbic_stmt($table_class, 'table', $full_table_name);
1607 my $cols = $self->_table_columns($table);
1608 my $col_info = $self->__columns_info_for($table);
1610 while (my ($col, $info) = each %$col_info) {
1612 ($info->{accessor} = $col) =~ s/\W+/_/g;
1616 if ($self->preserve_case) {
1617 while (my ($col, $info) = each %$col_info) {
1618 if ($col ne lc($col)) {
1619 if ((not exists $self->naming->{column_accessors}) || (($self->naming->{column_accessors} =~ /(\d+)/)[0] >= 7)) {
1620 $info->{accessor} = $self->_make_column_accessor_name($info->{accessor} || $col);
1623 $info->{accessor} = lc($info->{accessor} || $col);
1629 # XXX this needs to go away
1630 $col_info = { map { lc($_), $col_info->{$_} } keys %$col_info };
1633 $self->_resolve_col_accessor_collisions($col_info);
1635 my $fks = $self->_table_fk_info($table);
1637 foreach my $fkdef (@$fks) {
1638 for my $col (@{ $fkdef->{local_columns} }) {
1639 $col_info->{$col}{is_foreign_key} = 1;
1643 my $pks = $self->_table_pk_info($table) || [];
1645 foreach my $pkcol (@$pks) {
1646 $col_info->{$pkcol}{is_nullable} = 0;
1652 map { $_, ($col_info->{$_}||{}) } @$cols
1655 my %uniq_tag; # used to eliminate duplicate uniqs
1657 @$pks ? $self->_dbic_stmt($table_class,'set_primary_key',@$pks)
1658 : carp("$table has no primary key");
1659 $uniq_tag{ join("\0", @$pks) }++ if @$pks; # pk is a uniq
1661 my $uniqs = $self->_table_uniq_info($table) || [];
1663 my ($name, $cols) = @$_;
1664 next if $uniq_tag{ join("\0", @$cols) }++; # skip duplicates
1665 $self->_dbic_stmt($table_class,'add_unique_constraint', $name, $cols);
1670 sub __columns_info_for {
1671 my ($self, $table) = @_;
1673 my $result = $self->_columns_info_for($table);
1675 while (my ($col, $info) = each %$result) {
1676 $info = { %$info, %{ $self->_custom_column_info ($table, $col, $info) } };
1677 $info = { %$info, %{ $self->_datetime_column_info($table, $col, $info) } };
1679 $result->{$col} = $info;
1687 Returns a sorted list of loaded tables, using the original database table
1695 return keys %{$self->_tables};
1698 # Make a moniker from a table
1699 sub _default_table2moniker {
1700 no warnings 'uninitialized';
1701 my ($self, $table) = @_;
1703 if ($self->naming->{monikers} eq 'v4') {
1704 return join '', map ucfirst, split /[\W_]+/, lc $table;
1706 elsif ($self->naming->{monikers} eq 'v5') {
1707 return join '', map ucfirst, split /[\W_]+/,
1708 Lingua::EN::Inflect::Number::to_S(lc $table);
1710 elsif ($self->naming->{monikers} eq 'v6') {
1711 (my $as_phrase = lc $table) =~ s/_+/ /g;
1712 my $inflected = Lingua::EN::Inflect::Phrase::to_S($as_phrase);
1714 return join '', map ucfirst, split /\W+/, $inflected;
1717 my @words = map lc, split_name $table;
1718 my $as_phrase = join ' ', @words;
1720 my $inflected = Lingua::EN::Inflect::Phrase::to_S($as_phrase);
1722 return join '', map ucfirst, split /\W+/, $inflected;
1725 sub _table2moniker {
1726 my ( $self, $table ) = @_;
1730 if( ref $self->moniker_map eq 'HASH' ) {
1731 $moniker = $self->moniker_map->{$table};
1733 elsif( ref $self->moniker_map eq 'CODE' ) {
1734 $moniker = $self->moniker_map->($table);
1737 $moniker ||= $self->_default_table2moniker($table);
1742 sub _load_relationships {
1743 my ($self, $table) = @_;
1745 my $tbl_fk_info = $self->_table_fk_info($table);
1746 foreach my $fkdef (@$tbl_fk_info) {
1747 $fkdef->{remote_source} =
1748 $self->monikers->{delete $fkdef->{remote_table}};
1750 my $tbl_uniq_info = $self->_table_uniq_info($table);
1752 my $local_moniker = $self->monikers->{$table};
1753 my $rel_stmts = $self->_relbuilder->generate_code($local_moniker, $tbl_fk_info, $tbl_uniq_info);
1755 foreach my $src_class (sort keys %$rel_stmts) {
1756 my $src_stmts = $rel_stmts->{$src_class};
1757 foreach my $stmt (@$src_stmts) {
1758 $self->_dbic_stmt($src_class,$stmt->{method},@{$stmt->{args}});
1763 # Overload these in driver class:
1765 # Returns an arrayref of column names
1766 sub _table_columns { croak "ABSTRACT METHOD" }
1768 # Returns arrayref of pk col names
1769 sub _table_pk_info { croak "ABSTRACT METHOD" }
1771 # Returns an arrayref of uniqs [ [ foo => [ col1, col2 ] ], [ bar => [ ... ] ] ]
1772 sub _table_uniq_info { croak "ABSTRACT METHOD" }
1774 # Returns an arrayref of foreign key constraints, each
1775 # being a hashref with 3 keys:
1776 # local_columns (arrayref), remote_columns (arrayref), remote_table
1777 sub _table_fk_info { croak "ABSTRACT METHOD" }
1779 # Returns an array of lower case table names
1780 sub _tables_list { croak "ABSTRACT METHOD" }
1782 # Execute a constructive DBIC class method, with debug/dump_to_dir hooks.
1788 # generate the pod for this statement, storing it with $self->_pod
1789 $self->_make_pod( $class, $method, @_ ) if $self->generate_pod;
1791 my $args = dump(@_);
1792 $args = '(' . $args . ')' if @_ < 2;
1793 my $stmt = $method . $args . q{;};
1795 warn qq|$class\->$stmt\n| if $self->debug;
1796 $self->_raw_stmt($class, '__PACKAGE__->' . $stmt);
1800 # generates the accompanying pod for a DBIC class method statement,
1801 # storing it with $self->_pod
1807 if ( $method eq 'table' ) {
1809 my $pcm = $self->pod_comment_mode;
1810 my ($comment, $comment_overflows, $comment_in_name, $comment_in_desc);
1811 $comment = $self->__table_comment($table);
1812 $comment_overflows = ($comment and length $comment > $self->pod_comment_spillover_length);
1813 $comment_in_name = ($pcm eq 'name' or ($pcm eq 'auto' and !$comment_overflows));
1814 $comment_in_desc = ($pcm eq 'description' or ($pcm eq 'auto' and $comment_overflows));
1815 $self->_pod( $class, "=head1 NAME" );
1816 my $table_descr = $class;
1817 $table_descr .= " - " . $comment if $comment and $comment_in_name;
1818 $self->{_class2table}{ $class } = $table;
1819 $self->_pod( $class, $table_descr );
1820 if ($comment and $comment_in_desc) {
1821 $self->_pod( $class, "=head1 DESCRIPTION" );
1822 $self->_pod( $class, $comment );
1824 $self->_pod_cut( $class );
1825 } elsif ( $method eq 'add_columns' ) {
1826 $self->_pod( $class, "=head1 ACCESSORS" );
1827 my $col_counter = 0;
1829 while( my ($name,$attrs) = splice @cols,0,2 ) {
1831 $self->_pod( $class, '=head2 ' . $name );
1832 $self->_pod( $class,
1834 my $s = $attrs->{$_};
1835 $s = !defined $s ? 'undef' :
1836 length($s) == 0 ? '(empty string)' :
1837 ref($s) eq 'SCALAR' ? $$s :
1838 ref($s) ? dumper_squashed $s :
1839 looks_like_number($s) ? $s :
1844 } sort keys %$attrs,
1847 if (my $comment = $self->__column_comment($self->{_class2table}{$class}, $col_counter)) {
1848 $self->_pod( $class, $comment );
1851 $self->_pod_cut( $class );
1852 } elsif ( $method =~ /^(belongs_to|has_many|might_have)$/ ) {
1853 $self->_pod( $class, "=head1 RELATIONS" ) unless $self->{_relations_started} { $class } ;
1854 my ( $accessor, $rel_class ) = @_;
1855 $self->_pod( $class, "=head2 $accessor" );
1856 $self->_pod( $class, 'Type: ' . $method );
1857 $self->_pod( $class, "Related object: L<$rel_class>" );
1858 $self->_pod_cut( $class );
1859 $self->{_relations_started} { $class } = 1;
1863 sub _filter_comment {
1864 my ($self, $txt) = @_;
1866 $txt = '' if not defined $txt;
1868 $txt =~ s/(?:\015?\012|\015\012?)/\n/g;
1873 sub __table_comment {
1876 if (my $code = $self->can('_table_comment')) {
1877 return $self->_filter_comment($self->$code(@_));
1883 sub __column_comment {
1886 if (my $code = $self->can('_column_comment')) {
1887 return $self->_filter_comment($self->$code(@_));
1893 # Stores a POD documentation
1895 my ($self, $class, $stmt) = @_;
1896 $self->_raw_stmt( $class, "\n" . $stmt );
1900 my ($self, $class ) = @_;
1901 $self->_raw_stmt( $class, "\n=cut\n" );
1904 # Store a raw source line for a class (for dumping purposes)
1906 my ($self, $class, $stmt) = @_;
1907 push(@{$self->{_dump_storage}->{$class}}, $stmt);
1910 # Like above, but separately for the externally loaded stuff
1912 my ($self, $class, $stmt) = @_;
1913 push(@{$self->{_ext_storage}->{$class}}, $stmt);
1916 sub _quote_table_name {
1917 my ($self, $table) = @_;
1919 my $qt = $self->schema->storage->sql_maker->quote_char;
1921 return $table unless $qt;
1924 return $qt->[0] . $table . $qt->[1];
1927 return $qt . $table . $qt;
1930 sub _custom_column_info {
1931 my ( $self, $table_name, $column_name, $column_info ) = @_;
1933 if (my $code = $self->custom_column_info) {
1934 return $code->($table_name, $column_name, $column_info) || {};
1939 sub _datetime_column_info {
1940 my ( $self, $table_name, $column_name, $column_info ) = @_;
1942 my $type = $column_info->{data_type} || '';
1943 if ((grep $_, @{ $column_info }{map "inflate_$_", qw/date datetime timestamp/})
1944 or ($type =~ /date|timestamp/i)) {
1945 $result->{timezone} = $self->datetime_timezone if $self->datetime_timezone;
1946 $result->{locale} = $self->datetime_locale if $self->datetime_locale;
1952 my ($self, $name) = @_;
1954 return $self->preserve_case ? $name : lc($name);
1958 my ($self, $name) = @_;
1960 return $self->preserve_case ? $name : uc($name);
1963 sub _unregister_source_for_table {
1964 my ($self, $table) = @_;
1968 my $schema = $self->schema;
1969 # in older DBIC it's a private method
1970 my $unregister = $schema->can('unregister_source') || $schema->can('_unregister_source');
1971 $schema->$unregister($self->_table2moniker($table));
1972 delete $self->monikers->{$table};
1973 delete $self->classes->{$table};
1974 delete $self->_upgrading_classes->{$table};
1975 delete $self->{_tables}{$table};
1979 # remove the dump dir from @INC on destruction
1983 @INC = grep $_ ne $self->dump_directory, @INC;
1988 Returns a hashref of loaded table to moniker mappings. There will
1989 be two entries for each table, the original name and the "normalized"
1990 name, in the case that the two are different (such as databases
1991 that like uppercase table names, or preserve your original mixed-case
1992 definitions, or what-have-you).
1996 Returns a hashref of table to class mappings. In some cases it will
1997 contain multiple entries per table for the original and normalized table
1998 names, as above in L</monikers>.
2002 L<DBIx::Class::Schema::Loader>
2006 See L<DBIx::Class::Schema::Loader/AUTHOR> and L<DBIx::Class::Schema::Loader/CONTRIBUTORS>.
2010 This library is free software; you can redistribute it and/or modify it under
2011 the same terms as Perl itself.
2016 # vim:et sts=4 sw=4 tw=0: