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 DBIx::Class::Schema::Loader::Utils qw/split_name dumper_squashed eval_package_without_redefine_warnings class_path slurp_file/;
21 use DBIx::Class::Schema::Loader::Optional::Dependencies ();
24 use Encode qw/encode decode/;
25 use List::MoreUtils qw/all firstidx/;
30 our $VERSION = '0.07010';
32 __PACKAGE__->mk_group_ro_accessors('simple', qw/
39 additional_base_classes
55 default_resultset_class
60 overwrite_modifications
83 __PACKAGE__->mk_group_accessors('simple', qw/
85 schema_version_to_dump
87 _upgrading_from_load_classes
88 _downgrading_to_load_classes
89 _rewriting_result_namespace
94 pod_comment_spillover_length
100 result_components_map
102 datetime_undef_if_invalid
103 _result_class_methods
105 filter_generated_code
111 my $CURRENT_V = 'v7';
114 schema_components schema_base_class result_base_class
115 additional_base_classes left_base_classes additional_classes components
121 my $CRLF = "\x0d\x0a";
125 DBIx::Class::Schema::Loader::Base - Base DBIx::Class::Schema::Loader Implementation.
129 See L<DBIx::Class::Schema::Loader>
133 This is the base class for the storage-specific C<DBIx::Class::Schema::*>
134 classes, and implements the common functionality between them.
136 =head1 CONSTRUCTOR OPTIONS
138 These constructor options are the base options for
139 L<DBIx::Class::Schema::Loader/loader_options>. Available constructor options are:
141 =head2 skip_relationships
143 Skip setting up relationships. The default is to attempt the loading
146 =head2 skip_load_external
148 Skip loading of other classes in @INC. The default is to merge all other classes
149 with the same name found in @INC into the schema file we are creating.
153 Static schemas (ones dumped to disk) will, by default, use the new-style
154 relationship names and singularized Results, unless you're overwriting an
155 existing dump made by an older version of L<DBIx::Class::Schema::Loader>, in
156 which case the backward compatible RelBuilder will be activated, and the
157 appropriate monikerization used.
163 will disable the backward-compatible RelBuilder and use
164 the new-style relationship names along with singularized Results, even when
165 overwriting a dump made with an earlier version.
167 The option also takes a hashref:
169 naming => { relationships => 'v7', monikers => 'v7' }
177 How to name relationship accessors.
181 How to name Result classes.
183 =item column_accessors
185 How to name column accessors in Result classes.
195 Latest style, whatever that happens to be.
199 Unsingularlized monikers, C<has_many> only relationships with no _id stripping.
203 Monikers singularized as whole words, C<might_have> relationships for FKs on
204 C<UNIQUE> constraints, C<_id> stripping for belongs_to relationships.
206 Some of the C<_id> stripping edge cases in C<0.05003> have been reverted for
211 All monikers and relationships are inflected using
212 L<Lingua::EN::Inflect::Phrase>, and there is more aggressive C<_id> stripping
213 from relationship names.
215 In general, there is very little difference between v5 and v6 schemas.
219 This mode is identical to C<v6> mode, except that monikerization of CamelCase
220 table names is also done correctly.
222 CamelCase column names in case-preserving mode will also be handled correctly
223 for relationship name inflection. See L</preserve_case>.
225 In this mode, CamelCase L</column_accessors> are normalized based on case
226 transition instead of just being lowercased, so C<FooId> becomes C<foo_id>.
228 If you don't have any CamelCase table or column names, you can upgrade without
229 breaking any of your code.
233 For L</monikers>, this option does not inflect the table names but makes
234 monikers based on the actual name. For L</column_accessors> this option does
235 not normalize CamelCase column names to lowercase column accessors, but makes
236 accessors that are the same names as the columns (with any non-\w chars
237 replaced with underscores.)
241 For L</monikers>, singularizes the names using the most current inflector. This
242 is the same as setting the option to L</current>.
246 For L</monikers>, pluralizes the names, using the most current inflector.
250 Dynamic schemas will always default to the 0.04XXX relationship names and won't
251 singularize Results for backward compatibility, to activate the new RelBuilder
252 and singularization put this in your C<Schema.pm> file:
254 __PACKAGE__->naming('current');
256 Or if you prefer to use 0.07XXX features but insure that nothing breaks in the
257 next major version upgrade:
259 __PACKAGE__->naming('v7');
263 If true, will not print the usual C<Dumping manual schema ... Schema dump
264 completed.> messages. Does not affect warnings (except for warnings related to
265 L</really_erase_my_files>.)
269 By default POD will be generated for columns and relationships, using database
270 metadata for the text if available and supported.
272 Comment metadata can be stored in two ways.
274 The first is that you can create two tables named C<table_comments> and
275 C<column_comments> respectively. They both need to have columns named
276 C<table_name> and C<comment_text>. The second one needs to have a column
277 named C<column_name>. Then data stored in these tables will be used as a
278 source of metadata about tables and comments.
280 (If you wish you can change the name of these tables with the parameters
281 L</table_comments_table> and L</column_comments_table>.)
283 As a fallback you can use built-in commenting mechanisms. Currently this is
284 only supported for PostgreSQL, Oracle and MySQL. To create comments in
285 PostgreSQL you add statements of the form C<COMMENT ON TABLE some_table IS
286 '...'>, the same syntax is used in Oracle. To create comments in MySQL you add
287 C<COMMENT '...'> to the end of the column or table definition. Note that MySQL
288 restricts the length of comments, and also does not handle complex Unicode
291 Set this to C<0> to turn off all POD generation.
293 =head2 pod_comment_mode
295 Controls where table comments appear in the generated POD. Smaller table
296 comments are appended to the C<NAME> section of the documentation, and larger
297 ones are inserted into C<DESCRIPTION> instead. You can force a C<DESCRIPTION>
298 section to be generated with the comment always, only use C<NAME>, or choose
299 the length threshold at which the comment is forced into the description.
305 Use C<NAME> section only.
309 Force C<DESCRIPTION> always.
313 Use C<DESCRIPTION> if length > L</pod_comment_spillover_length>, this is the
318 =head2 pod_comment_spillover_length
320 When pod_comment_mode is set to C<auto>, this is the length of the comment at
321 which it will be forced into a separate description section.
325 =head2 table_comments_table
327 The table to look for comments about tables in. By default C<table_comments>.
328 See L</generate_pod> for details.
330 =head2 column_comments_table
332 The table to look for comments about columns in. By default C<column_comments>.
333 See L</generate_pod> for details.
335 =head2 relationship_attrs
337 Hashref of attributes to pass to each generated relationship, listed
338 by type. Also supports relationship type 'all', containing options to
339 pass to all generated relationships. Attributes set for more specific
340 relationship types override those set in 'all'.
344 relationship_attrs => {
345 belongs_to => { is_deferrable => 0 },
348 use this to turn off DEFERRABLE on your foreign key constraints.
352 If set to true, each constructive L<DBIx::Class> statement the loader
353 decides to execute will be C<warn>-ed before execution.
357 Set the name of the schema to load (schema in the sense that your database
360 Can be set to an arrayref of schema names for multiple schemas, or the special
361 value C<%> for all schemas.
363 For MSSQL, Sybase ASE, and Informix can be set to a hashref of databases as
364 keys and arrays of owners as values, set to the value:
368 for all owners in all databases.
370 You may need to control naming of monikers with L</moniker_parts> if you have
371 name clashes for tables in different schemas/databases.
375 The database table names are represented by the
376 L<DBIx::Class::Schema::Loader::Table> class in the loader, the
377 L<DBIx::Class::Schema::Loader::Table::Sybase> class for Sybase ASE and
378 L<DBIx::Class::Schema::Loader::Table::Informix> for Informix.
380 Monikers are created normally based on just the
381 L<name|DBIx::Class::Schema::Loader::DBObject/name> property, corresponding to
382 the table name, but can consist of other parts of the fully qualified name of
385 The L</moniker_parts> option is an arrayref of methods on the table class
386 corresponding to parts of the fully qualified table name, defaulting to
387 C<['name']>, in the order those parts are used to create the moniker name.
389 The C<'name'> entry B<must> be present.
391 Below is a table of supported databases and possible L</moniker_parts>.
395 =item * DB2, Firebird, mysql, Oracle, Pg, SQLAnywhere, SQLite, MS Access
399 =item * Informix, MSSQL, Sybase ASE
401 C<database>, C<schema>, C<name>
407 Only load tables matching regex. Best specified as a qr// regex.
411 Exclude tables matching regex. Best specified as a qr// regex.
415 Overrides the default table name to moniker translation. Can be either
416 a hashref of table keys and moniker values, or a coderef for a translator
417 function taking a single scalar table name argument and returning
418 a scalar moniker. If the hash entry does not exist, or the function
419 returns a false value, the code falls back to default behavior
422 The default behavior is to split on case transition and non-alphanumeric
423 boundaries, singularize the resulting phrase, then join the titlecased words
426 Table Name | Moniker Name
427 ---------------------------------
429 luser_group | LuserGroup
430 luser-opts | LuserOpt
431 stations_visited | StationVisited
432 routeChange | RouteChange
434 =head2 col_accessor_map
436 Same as moniker_map, but for column accessor names. If a coderef is
437 passed, the code is called with arguments of
439 the name of the column in the underlying database,
440 default accessor name that DBICSL would ordinarily give this column,
442 table_class => name of the DBIC class we are building,
443 table_moniker => calculated moniker for this table (after moniker_map if present),
444 table_name => name of the database table,
445 full_table_name => schema-qualified name of the database table (RDBMS specific),
446 schema_class => name of the schema class we are building,
447 column_info => hashref of column info (data_type, is_nullable, etc),
452 Similar in idea to moniker_map, but different in the details. It can be
453 a hashref or a code ref.
455 If it is a hashref, keys can be either the default relationship name, or the
456 moniker. The keys that are the default relationship name should map to the
457 name you want to change the relationship to. Keys that are monikers should map
458 to hashes mapping relationship names to their translation. You can do both at
459 once, and the more specific moniker version will be picked up first. So, for
460 instance, you could have
469 and relationships that would have been named C<bar> will now be named C<baz>
470 except that in the table whose moniker is C<Foo> it will be named C<blat>.
472 If it is a coderef, the argument passed will be a hashref of this form:
475 name => default relationship name,
476 type => the relationship type eg: C<has_many>,
477 local_class => name of the DBIC class we are building,
478 local_moniker => moniker of the DBIC class we are building,
479 local_columns => columns in this table in the relationship,
480 remote_class => name of the DBIC class we are related to,
481 remote_moniker => moniker of the DBIC class we are related to,
482 remote_columns => columns in the other table in the relationship,
485 DBICSL will try to use the value returned as the relationship name.
487 =head2 inflect_plural
489 Just like L</moniker_map> above (can be hash/code-ref, falls back to default
490 if hash key does not exist or coderef returns false), but acts as a map
491 for pluralizing relationship names. The default behavior is to utilize
492 L<Lingua::EN::Inflect::Phrase/to_PL>.
494 =head2 inflect_singular
496 As L</inflect_plural> above, but for singularizing relationship names.
497 Default behavior is to utilize L<Lingua::EN::Inflect::Phrase/to_S>.
499 =head2 schema_base_class
501 Base class for your schema classes. Defaults to 'DBIx::Class::Schema'.
503 =head2 result_base_class
505 Base class for your table classes (aka result classes). Defaults to
508 =head2 additional_base_classes
510 List of additional base classes all of your table classes will use.
512 =head2 left_base_classes
514 List of additional base classes all of your table classes will use
515 that need to be leftmost.
517 =head2 additional_classes
519 List of additional classes which all of your table classes will use.
521 =head2 schema_components
523 List of components to load into the Schema class.
527 List of additional components to be loaded into all of your Result
528 classes. A good example would be
529 L<InflateColumn::DateTime|DBIx::Class::InflateColumn::DateTime>
531 =head2 result_components_map
533 A hashref of moniker keys and component values. Unlike L</components>, which
534 loads the given components into every Result class, this option allows you to
535 load certain components for specified Result classes. For example:
537 result_components_map => {
538 StationVisited => '+YourApp::Schema::Component::StationVisited',
540 '+YourApp::Schema::Component::RouteChange',
541 'InflateColumn::DateTime',
545 You may use this in conjunction with L</components>.
549 List of L<Moose> roles to be applied to all of your Result classes.
551 =head2 result_roles_map
553 A hashref of moniker keys and role values. Unlike L</result_roles>, which
554 applies the given roles to every Result class, this option allows you to apply
555 certain roles for specified Result classes. For example:
557 result_roles_map => {
559 'YourApp::Role::Building',
560 'YourApp::Role::Destination',
562 RouteChange => 'YourApp::Role::TripEvent',
565 You may use this in conjunction with L</result_roles>.
567 =head2 use_namespaces
569 This is now the default, to go back to L<DBIx::Class::Schema/load_classes> pass
572 Generate result class names suitable for
573 L<DBIx::Class::Schema/load_namespaces> and call that instead of
574 L<DBIx::Class::Schema/load_classes>. When using this option you can also
575 specify any of the options for C<load_namespaces> (i.e. C<result_namespace>,
576 C<resultset_namespace>, C<default_resultset_class>), and they will be added
577 to the call (and the generated result class names adjusted appropriately).
579 =head2 dump_directory
581 The value of this option is a perl libdir pathname. Within
582 that directory this module will create a baseline manual
583 L<DBIx::Class::Schema> module set, based on what it creates at runtime.
585 The created schema class will have the same classname as the one on
586 which you are setting this option (and the ResultSource classes will be
587 based on this name as well).
589 Normally you wouldn't hard-code this setting in your schema class, as it
590 is meant for one-time manual usage.
592 See L<DBIx::Class::Schema::Loader/dump_to_dir> for examples of the
593 recommended way to access this functionality.
595 =head2 dump_overwrite
597 Deprecated. See L</really_erase_my_files> below, which does *not* mean
598 the same thing as the old C<dump_overwrite> setting from previous releases.
600 =head2 really_erase_my_files
602 Default false. If true, Loader will unconditionally delete any existing
603 files before creating the new ones from scratch when dumping a schema to disk.
605 The default behavior is instead to only replace the top portion of the
606 file, up to and including the final stanza which contains
607 C<# DO NOT MODIFY THE FIRST PART OF THIS FILE>
608 leaving any customizations you placed after that as they were.
610 When C<really_erase_my_files> is not set, if the output file already exists,
611 but the aforementioned final stanza is not found, or the checksum
612 contained there does not match the generated contents, Loader will
613 croak and not touch the file.
615 You should really be using version control on your schema classes (and all
616 of the rest of your code for that matter). Don't blame me if a bug in this
617 code wipes something out when it shouldn't have, you've been warned.
619 =head2 overwrite_modifications
621 Default false. If false, when updating existing files, Loader will
622 refuse to modify any Loader-generated code that has been modified
623 since its last run (as determined by the checksum Loader put in its
626 If true, Loader will discard any manual modifications that have been
627 made to Loader-generated code.
629 Again, you should be using version control on your schema classes. Be
630 careful with this option.
632 =head2 custom_column_info
634 Hook for adding extra attributes to the
635 L<column_info|DBIx::Class::ResultSource/column_info> for a column.
637 Must be a coderef that returns a hashref with the extra attributes.
639 Receives the table name, column name and column_info.
643 custom_column_info => sub {
644 my ($table_name, $column_name, $column_info) = @_;
646 if ($column_name eq 'dog' && $column_info->{default_value} eq 'snoopy') {
647 return { is_snoopy => 1 };
651 This attribute can also be used to set C<inflate_datetime> on a non-datetime
652 column so it also receives the L</datetime_timezone> and/or L</datetime_locale>.
654 =head2 datetime_timezone
656 Sets the timezone attribute for L<DBIx::Class::InflateColumn::DateTime> for all
657 columns with the DATE/DATETIME/TIMESTAMP data_types.
659 =head2 datetime_locale
661 Sets the locale attribute for L<DBIx::Class::InflateColumn::DateTime> for all
662 columns with the DATE/DATETIME/TIMESTAMP data_types.
664 =head2 datetime_undef_if_invalid
666 Pass a C<0> for this option when using MySQL if you B<DON'T> want C<<
667 datetime_undef_if_invalid => 1 >> in your column info for DATE, DATETIME and
670 The default is recommended to deal with data such as C<00/00/00> which
671 sometimes ends up in such columns in MySQL.
675 File in Perl format, which should return a HASH reference, from which to read
680 Usually column names are lowercased, to make them easier to work with in
681 L<DBIx::Class>. This option lets you turn this behavior off, if the driver
684 Drivers for case sensitive databases like Sybase ASE or MSSQL with a
685 case-sensitive collation will turn this option on unconditionally.
687 Currently the drivers for SQLite, mysql, MSSQL and Firebird/InterBase support
690 =head2 qualify_objects
692 Set to true to prepend the L</db_schema> to table names for C<<
693 __PACKAGE__->table >> calls, and to some other things like Oracle sequences.
697 Creates Schema and Result classes that use L<Moose>, L<MooseX::NonMoose> and
698 L<namespace::autoclean>. The default content after the md5 sum also makes the
701 It is safe to upgrade your existing Schema to this option.
703 =head2 col_collision_map
705 This option controls how accessors for column names which collide with perl
706 methods are named. See L</COLUMN ACCESSOR COLLISIONS> for more information.
708 This option takes either a single L<sprintf|perlfunc/sprintf> format or a hashref of
709 strings which are compiled to regular expressions that map to
710 L<sprintf|perlfunc/sprintf> formats.
714 col_collision_map => 'column_%s'
716 col_collision_map => { '(.*)' => 'column_%s' }
718 col_collision_map => { '(foo).*(bar)' => 'column_%s_%s' }
720 =head2 rel_collision_map
722 Works just like L</col_collision_map>, but for relationship names/accessors
723 rather than column names/accessors.
725 The default is to just append C<_rel> to the relationship name, see
726 L</RELATIONSHIP NAME COLLISIONS>.
728 =head2 uniq_to_primary
730 Automatically promotes the largest unique constraints with non-nullable columns
731 on tables to primary keys, assuming there is only one largest unique
734 =head2 filter_generated_code
736 An optional hook that lets you filter the generated text for various classes
737 through a function that change it in any way that you want. The function will
738 receive the type of file, C<schema> or C<result>, class and code; and returns
739 the new code to use instead. For instance you could add custom comments, or do
740 anything else that you want.
742 The option can also be set to a string, which is then used as a filter program,
745 If this exists but fails to return text matching C</\bpackage\b/>, no file will
748 filter_generated_code => sub {
749 my ($type, $class, $text) = @_;
756 None of these methods are intended for direct invocation by regular
757 users of L<DBIx::Class::Schema::Loader>. Some are proxied via
758 L<DBIx::Class::Schema::Loader>.
762 # ensure that a peice of object data is a valid arrayref, creating
763 # an empty one or encapsulating whatever's there.
764 sub _ensure_arrayref {
769 $self->{$_} = [ $self->{$_} ]
770 unless ref $self->{$_} eq 'ARRAY';
776 Constructor for L<DBIx::Class::Schema::Loader::Base>, used internally
777 by L<DBIx::Class::Schema::Loader>.
782 my ( $class, %args ) = @_;
784 if (exists $args{column_accessor_map}) {
785 $args{col_accessor_map} = delete $args{column_accessor_map};
788 my $self = { %args };
790 # don't lose undef options
791 for (values %$self) {
792 $_ = 0 unless defined $_;
795 bless $self => $class;
797 if (my $config_file = $self->config_file) {
798 my $config_opts = do $config_file;
800 croak "Error reading config from $config_file: $@" if $@;
802 croak "Config file $config_file must be a hashref" unless ref($config_opts) eq 'HASH';
804 while (my ($k, $v) = each %$config_opts) {
805 $self->{$k} = $v unless exists $self->{$k};
809 if (defined $self->{result_component_map}) {
810 if (defined $self->result_components_map) {
811 croak "Specify only one of result_components_map or result_component_map";
813 $self->result_components_map($self->{result_component_map})
816 if (defined $self->{result_role_map}) {
817 if (defined $self->result_roles_map) {
818 croak "Specify only one of result_roles_map or result_role_map";
820 $self->result_roles_map($self->{result_role_map})
823 croak "the result_roles and result_roles_map options may only be used in conjunction with use_moose=1"
824 if ((not defined $self->use_moose) || (not $self->use_moose))
825 && ((defined $self->result_roles) || (defined $self->result_roles_map));
827 $self->_ensure_arrayref(qw/schema_components
829 additional_base_classes
835 $self->_validate_class_args;
837 croak "result_components_map must be a hash"
838 if defined $self->result_components_map
839 && ref $self->result_components_map ne 'HASH';
841 if ($self->result_components_map) {
842 my %rc_map = %{ $self->result_components_map };
843 foreach my $moniker (keys %rc_map) {
844 $rc_map{$moniker} = [ $rc_map{$moniker} ] unless ref $rc_map{$moniker};
846 $self->result_components_map(\%rc_map);
849 $self->result_components_map({});
851 $self->_validate_result_components_map;
853 croak "result_roles_map must be a hash"
854 if defined $self->result_roles_map
855 && ref $self->result_roles_map ne 'HASH';
857 if ($self->result_roles_map) {
858 my %rr_map = %{ $self->result_roles_map };
859 foreach my $moniker (keys %rr_map) {
860 $rr_map{$moniker} = [ $rr_map{$moniker} ] unless ref $rr_map{$moniker};
862 $self->result_roles_map(\%rr_map);
864 $self->result_roles_map({});
866 $self->_validate_result_roles_map;
868 if ($self->use_moose) {
869 if (not DBIx::Class::Schema::Loader::Optional::Dependencies->req_ok_for('use_moose')) {
870 die sprintf "You must install the following CPAN modules to enable the use_moose option: %s.\n",
871 DBIx::Class::Schema::Loader::Optional::Dependencies->req_missing_for('use_moose');
875 $self->{_tables} = {};
876 $self->{monikers} = {};
877 $self->{moniker_to_table} = {};
878 $self->{class_to_table} = {};
879 $self->{classes} = {};
880 $self->{_upgrading_classes} = {};
882 $self->{schema_class} ||= ( ref $self->{schema} || $self->{schema} );
883 $self->{schema} ||= $self->{schema_class};
884 $self->{table_comments_table} ||= 'table_comments';
885 $self->{column_comments_table} ||= 'column_comments';
887 croak "dump_overwrite is deprecated. Please read the"
888 . " DBIx::Class::Schema::Loader::Base documentation"
889 if $self->{dump_overwrite};
891 $self->{dynamic} = ! $self->{dump_directory};
892 $self->{temp_directory} ||= File::Temp::tempdir( 'dbicXXXX',
897 $self->{dump_directory} ||= $self->{temp_directory};
899 $self->real_dump_directory($self->{dump_directory});
901 $self->version_to_dump($DBIx::Class::Schema::Loader::VERSION);
902 $self->schema_version_to_dump($DBIx::Class::Schema::Loader::VERSION);
904 if (not defined $self->naming) {
905 $self->naming_set(0);
908 $self->naming_set(1);
911 if ((not ref $self->naming) && defined $self->naming) {
912 my $naming_ver = $self->naming;
914 relationships => $naming_ver,
915 monikers => $naming_ver,
916 column_accessors => $naming_ver,
921 for (values %{ $self->naming }) {
922 $_ = $CURRENT_V if $_ eq 'current';
925 $self->{naming} ||= {};
927 if ($self->custom_column_info && ref $self->custom_column_info ne 'CODE') {
928 croak 'custom_column_info must be a CODE ref';
931 $self->_check_back_compat;
933 $self->use_namespaces(1) unless defined $self->use_namespaces;
934 $self->generate_pod(1) unless defined $self->generate_pod;
935 $self->pod_comment_mode('auto') unless defined $self->pod_comment_mode;
936 $self->pod_comment_spillover_length(60) unless defined $self->pod_comment_spillover_length;
938 if (my $col_collision_map = $self->col_collision_map) {
939 if (my $reftype = ref $col_collision_map) {
940 if ($reftype ne 'HASH') {
941 croak "Invalid type $reftype for option 'col_collision_map'";
945 $self->col_collision_map({ '(.*)' => $col_collision_map });
949 if (my $rel_collision_map = $self->rel_collision_map) {
950 if (my $reftype = ref $rel_collision_map) {
951 if ($reftype ne 'HASH') {
952 croak "Invalid type $reftype for option 'rel_collision_map'";
956 $self->rel_collision_map({ '(.*)' => $rel_collision_map });
960 if (defined(my $rel_name_map = $self->rel_name_map)) {
961 my $reftype = ref $rel_name_map;
962 if ($reftype ne 'HASH' && $reftype ne 'CODE') {
963 croak "Invalid type $reftype for option 'rel_name_map', must be HASH or CODE";
967 if (defined(my $filter = $self->filter_generated_code)) {
968 my $reftype = ref $filter;
969 if ($reftype && $reftype ne 'CODE') {
970 croak "Invalid type $reftype for option 'filter_generated_code, must be a scalar or a CODE reference";
974 if (defined $self->db_schema) {
975 if (ref $self->db_schema eq 'ARRAY') {
976 if (@{ $self->db_schema } > 1) {
977 $self->{qualify_objects} = 1;
979 elsif (@{ $self->db_schema } == 0) {
980 $self->{db_schema} = undef;
983 elsif (not ref $self->db_schema) {
984 if ($self->db_schema eq '%') {
985 $self->{qualify_objects} = 1;
988 $self->{db_schema} = [ $self->db_schema ];
992 if (not $self->moniker_parts) {
993 $self->moniker_parts(['name']);
996 if (not ref $self->moniker_parts) {
997 $self->moniker_parts([ $self->moniker_parts ]);
999 if (ref $self->moniker_parts ne 'ARRAY') {
1000 croak 'moniker_parts must be an arrayref';
1002 if ((firstidx { $_ eq 'name' } @{ $self->moniker_parts }) == -1) {
1003 croak "moniker_parts option *must* contain 'name'";
1010 sub _check_back_compat {
1013 # dynamic schemas will always be in 0.04006 mode, unless overridden
1014 if ($self->dynamic) {
1015 # just in case, though no one is likely to dump a dynamic schema
1016 $self->schema_version_to_dump('0.04006');
1018 if (not $self->naming_set) {
1019 warn <<EOF unless $ENV{SCHEMA_LOADER_BACKCOMPAT};
1021 Dynamic schema detected, will run in 0.04006 mode.
1023 Set the 'naming' attribute or the SCHEMA_LOADER_BACKCOMPAT environment variable
1024 to disable this warning.
1026 See perldoc DBIx::Class::Schema::Loader::Manual::UpgradingFromV4 for more
1031 $self->_upgrading_from('v4');
1034 if ((not defined $self->use_namespaces) && ($self->naming_set)) {
1035 $self->use_namespaces(1);
1038 $self->naming->{relationships} ||= 'v4';
1039 $self->naming->{monikers} ||= 'v4';
1041 if ($self->use_namespaces) {
1042 $self->_upgrading_from_load_classes(1);
1045 $self->use_namespaces(0);
1051 # otherwise check if we need backcompat mode for a static schema
1052 my $filename = $self->get_dump_filename($self->schema_class);
1053 return unless -e $filename;
1055 my ($old_gen, $old_md5, $old_ver, $old_ts, $old_custom) =
1056 $self->_parse_generated_file($filename);
1058 return unless $old_ver;
1060 # determine if the existing schema was dumped with use_moose => 1
1061 if (! defined $self->use_moose) {
1062 $self->{use_moose} = 1 if $old_gen =~ /^ (?!\s*\#) use \s+ Moose/xm;
1065 my $load_classes = ($old_gen =~ /^__PACKAGE__->load_classes;/m) ? 1 : 0;
1067 my $result_namespace = do { ($old_gen =~ /result_namespace => (.+)/) ? $1 : '' };
1068 my $ds = eval $result_namespace;
1070 Could not eval expression '$result_namespace' for result_namespace from
1073 $result_namespace = $ds || '';
1075 if ($load_classes && (not defined $self->use_namespaces)) {
1076 warn <<"EOF" unless $ENV{SCHEMA_LOADER_BACKCOMPAT};
1078 'load_classes;' static schema detected, turning off 'use_namespaces'.
1080 Set the 'use_namespaces' attribute or the SCHEMA_LOADER_BACKCOMPAT environment
1081 variable to disable this warning.
1083 See perldoc DBIx::Class::Schema::Loader::Manual::UpgradingFromV4 for more
1086 $self->use_namespaces(0);
1088 elsif ($load_classes && $self->use_namespaces) {
1089 $self->_upgrading_from_load_classes(1);
1091 elsif ((not $load_classes) && defined $self->use_namespaces && ! $self->use_namespaces) {
1092 $self->_downgrading_to_load_classes(
1093 $result_namespace || 'Result'
1096 elsif ((not defined $self->use_namespaces) || $self->use_namespaces) {
1097 if (not $self->result_namespace) {
1098 $self->result_namespace($result_namespace || 'Result');
1100 elsif ($result_namespace ne $self->result_namespace) {
1101 $self->_rewriting_result_namespace(
1102 $result_namespace || 'Result'
1107 # XXX when we go past .0 this will need fixing
1108 my ($v) = $old_ver =~ /([1-9])/;
1111 return if ($v eq $CURRENT_V || $old_ver =~ /^0\.\d\d999/);
1113 if (not %{ $self->naming }) {
1114 warn <<"EOF" unless $ENV{SCHEMA_LOADER_BACKCOMPAT};
1116 Version $old_ver static schema detected, turning on backcompat mode.
1118 Set the 'naming' attribute or the SCHEMA_LOADER_BACKCOMPAT environment variable
1119 to disable this warning.
1121 See: 'naming' in perldoc DBIx::Class::Schema::Loader::Base .
1123 See perldoc DBIx::Class::Schema::Loader::Manual::UpgradingFromV4 if upgrading
1124 from version 0.04006.
1127 $self->naming->{relationships} ||= $v;
1128 $self->naming->{monikers} ||= $v;
1129 $self->naming->{column_accessors} ||= $v;
1131 $self->schema_version_to_dump($old_ver);
1134 $self->_upgrading_from($v);
1138 sub _validate_class_args {
1141 foreach my $k (@CLASS_ARGS) {
1142 next unless $self->$k;
1144 my @classes = ref $self->$k eq 'ARRAY' ? @{ $self->$k } : $self->$k;
1145 $self->_validate_classes($k, \@classes);
1149 sub _validate_result_components_map {
1152 foreach my $classes (values %{ $self->result_components_map }) {
1153 $self->_validate_classes('result_components_map', $classes);
1157 sub _validate_result_roles_map {
1160 foreach my $classes (values %{ $self->result_roles_map }) {
1161 $self->_validate_classes('result_roles_map', $classes);
1165 sub _validate_classes {
1168 my $classes = shift;
1170 # make a copy to not destroy original
1171 my @classes = @$classes;
1173 foreach my $c (@classes) {
1174 # components default to being under the DBIx::Class namespace unless they
1175 # are preceeded with a '+'
1176 if ( $key =~ m/component/ && $c !~ s/^\+// ) {
1177 $c = 'DBIx::Class::' . $c;
1180 # 1 == installed, 0 == not installed, undef == invalid classname
1181 my $installed = Class::Inspector->installed($c);
1182 if ( defined($installed) ) {
1183 if ( $installed == 0 ) {
1184 croak qq/$c, as specified in the loader option "$key", is not installed/;
1187 croak qq/$c, as specified in the loader option "$key", is an invalid class name/;
1193 sub _find_file_in_inc {
1194 my ($self, $file) = @_;
1196 foreach my $prefix (@INC) {
1197 my $fullpath = File::Spec->catfile($prefix, $file);
1198 return $fullpath if -f $fullpath
1199 # abs_path throws on Windows for nonexistant files
1200 and (try { Cwd::abs_path($fullpath) }) ne
1201 ((try { Cwd::abs_path(File::Spec->catfile($self->dump_directory, $file)) }) || '');
1207 sub _find_class_in_inc {
1208 my ($self, $class) = @_;
1210 return $self->_find_file_in_inc(class_path($class));
1216 return $self->_upgrading_from
1217 || $self->_upgrading_from_load_classes
1218 || $self->_downgrading_to_load_classes
1219 || $self->_rewriting_result_namespace
1223 sub _rewrite_old_classnames {
1224 my ($self, $code) = @_;
1226 return $code unless $self->_rewriting;
1228 my %old_classes = reverse %{ $self->_upgrading_classes };
1230 my $re = join '|', keys %old_classes;
1231 $re = qr/\b($re)\b/;
1233 $code =~ s/$re/$old_classes{$1} || $1/eg;
1238 sub _load_external {
1239 my ($self, $class) = @_;
1241 return if $self->{skip_load_external};
1243 # so that we don't load our own classes, under any circumstances
1244 local *INC = [ grep $_ ne $self->dump_directory, @INC ];
1246 my $real_inc_path = $self->_find_class_in_inc($class);
1248 my $old_class = $self->_upgrading_classes->{$class}
1249 if $self->_rewriting;
1251 my $old_real_inc_path = $self->_find_class_in_inc($old_class)
1252 if $old_class && $old_class ne $class;
1254 return unless $real_inc_path || $old_real_inc_path;
1256 if ($real_inc_path) {
1257 # If we make it to here, we loaded an external definition
1258 warn qq/# Loaded external class definition for '$class'\n/
1261 my $code = $self->_rewrite_old_classnames(slurp_file $real_inc_path);
1263 if ($self->dynamic) { # load the class too
1264 eval_package_without_redefine_warnings($class, $code);
1267 $self->_ext_stmt($class,
1268 qq|# These lines were loaded from '$real_inc_path' found in \@INC.\n|
1269 .qq|# They are now part of the custom portion of this file\n|
1270 .qq|# for you to hand-edit. If you do not either delete\n|
1271 .qq|# this section or remove that file from \@INC, this section\n|
1272 .qq|# will be repeated redundantly when you re-create this\n|
1273 .qq|# file again via Loader! See skip_load_external to disable\n|
1274 .qq|# this feature.\n|
1277 $self->_ext_stmt($class, $code);
1278 $self->_ext_stmt($class,
1279 qq|# End of lines loaded from '$real_inc_path' |
1283 if ($old_real_inc_path) {
1284 my $code = slurp_file $old_real_inc_path;
1286 $self->_ext_stmt($class, <<"EOF");
1288 # These lines were loaded from '$old_real_inc_path',
1289 # based on the Result class name that would have been created by an older
1290 # version of the Loader. For a static schema, this happens only once during
1291 # upgrade. See skip_load_external to disable this feature.
1294 $code = $self->_rewrite_old_classnames($code);
1296 if ($self->dynamic) {
1299 Detected external content in '$old_real_inc_path', a class name that would have
1300 been used by an older version of the Loader.
1302 * PLEASE RENAME THIS CLASS: from '$old_class' to '$class', as that is the
1303 new name of the Result.
1305 eval_package_without_redefine_warnings($class, $code);
1309 $self->_ext_stmt($class, $code);
1310 $self->_ext_stmt($class,
1311 qq|# End of lines loaded from '$old_real_inc_path' |
1318 Does the actual schema-construction work.
1325 $self->_load_tables(
1326 $self->_tables_list({ constraint => $self->constraint, exclude => $self->exclude })
1334 Rescan the database for changes. Returns a list of the newly added table
1337 The schema argument should be the schema class or object to be affected. It
1338 should probably be derived from the original schema_class used during L</load>.
1343 my ($self, $schema) = @_;
1345 $self->{schema} = $schema;
1346 $self->_relbuilder->{schema} = $schema;
1349 my @current = $self->_tables_list({ constraint => $self->constraint, exclude => $self->exclude });
1351 foreach my $table (@current) {
1352 if(!exists $self->_tables->{$table->sql_name}) {
1353 push(@created, $table);
1358 @current{map $_->sql_name, @current} = ();
1359 foreach my $table (values %{ $self->_tables }) {
1360 if (not exists $current{$table->sql_name}) {
1361 $self->_remove_table($table);
1365 delete @$self{qw/_dump_storage _relations_started _uniqs_started/};
1367 my $loaded = $self->_load_tables(@current);
1369 foreach my $table (@created) {
1370 $self->monikers->{$table->sql_name} = $self->_table2moniker($table);
1373 return map { $self->monikers->{$_->sql_name} } @created;
1379 return if $self->{skip_relationships};
1381 return $self->{relbuilder} ||= do {
1383 no warnings 'uninitialized';
1384 my $relbuilder_suff =
1390 ->{ $self->naming->{relationships}};
1392 my $relbuilder_class = 'DBIx::Class::Schema::Loader::RelBuilder'.$relbuilder_suff;
1393 $self->ensure_class_loaded($relbuilder_class);
1394 $relbuilder_class->new( $self );
1400 my ($self, @tables) = @_;
1402 # Save the new tables to the tables list
1404 $self->_tables->{$_->sql_name} = $_;
1407 $self->_make_src_class($_) for @tables;
1409 # sanity-check for moniker clashes
1410 my $inverse_moniker_idx;
1411 foreach my $table (values %{ $self->_tables }) {
1412 push @{ $inverse_moniker_idx->{$self->monikers->{$table->sql_name}} }, $table;
1416 foreach my $moniker (keys %$inverse_moniker_idx) {
1417 my $tables = $inverse_moniker_idx->{$moniker};
1419 push @clashes, sprintf ("tables %s reduced to the same source moniker '%s'",
1420 join (', ', map $_->sql_name, @$tables),
1427 die 'Unable to load schema - chosen moniker/class naming style results in moniker clashes. '
1428 . 'Either change the naming style, or supply an explicit moniker_map: '
1429 . join ('; ', @clashes)
1434 $self->_setup_src_meta($_) for @tables;
1436 if(!$self->skip_relationships) {
1437 # The relationship loader needs a working schema
1438 local $self->{quiet} = 1;
1439 local $self->{dump_directory} = $self->{temp_directory};
1440 $self->_reload_classes(\@tables);
1441 $self->_load_relationships(\@tables);
1443 # Remove that temp dir from INC so it doesn't get reloaded
1444 @INC = grep $_ ne $self->dump_directory, @INC;
1447 $self->_load_roles($_) for @tables;
1449 $self->_load_external($_)
1450 for map { $self->classes->{$_->sql_name} } @tables;
1452 # Reload without unloading first to preserve any symbols from external
1454 $self->_reload_classes(\@tables, { unload => 0 });
1456 # Drop temporary cache
1457 delete $self->{_cache};
1462 sub _reload_classes {
1463 my ($self, $tables, $opts) = @_;
1465 my @tables = @$tables;
1467 my $unload = $opts->{unload};
1468 $unload = 1 unless defined $unload;
1470 # so that we don't repeat custom sections
1471 @INC = grep $_ ne $self->dump_directory, @INC;
1473 $self->_dump_to_dir(map { $self->classes->{$_->sql_name} } @tables);
1475 unshift @INC, $self->dump_directory;
1478 my %have_source = map { $_ => $self->schema->source($_) }
1479 $self->schema->sources;
1481 for my $table (@tables) {
1482 my $moniker = $self->monikers->{$table->sql_name};
1483 my $class = $self->classes->{$table->sql_name};
1486 no warnings 'redefine';
1487 local *Class::C3::reinitialize = sub {}; # to speed things up, reinitialized below
1490 if (my $mc = $self->_moose_metaclass($class)) {
1493 Class::Unload->unload($class) if $unload;
1494 my ($source, $resultset_class);
1496 ($source = $have_source{$moniker})
1497 && ($resultset_class = $source->resultset_class)
1498 && ($resultset_class ne 'DBIx::Class::ResultSet')
1500 my $has_file = Class::Inspector->loaded_filename($resultset_class);
1501 if (my $mc = $self->_moose_metaclass($resultset_class)) {
1504 Class::Unload->unload($resultset_class) if $unload;
1505 $self->_reload_class($resultset_class) if $has_file;
1507 $self->_reload_class($class);
1509 push @to_register, [$moniker, $class];
1512 Class::C3->reinitialize;
1513 for (@to_register) {
1514 $self->schema->register_class(@$_);
1518 sub _moose_metaclass {
1519 return undef unless $INC{'Class/MOP.pm'}; # if CMOP is not loaded the class could not have loaded in the 1st place
1523 my $mc = try { Class::MOP::class_of($class) }
1526 return $mc->isa('Moose::Meta::Class') ? $mc : undef;
1529 # We use this instead of ensure_class_loaded when there are package symbols we
1532 my ($self, $class) = @_;
1534 delete $INC{ +class_path($class) };
1537 eval_package_without_redefine_warnings ($class, "require $class");
1540 my $source = slurp_file $self->_get_dump_filename($class);
1541 die "Failed to reload class $class: $_.\n\nCLASS SOURCE:\n\n$source";
1545 sub _get_dump_filename {
1546 my ($self, $class) = (@_);
1548 $class =~ s{::}{/}g;
1549 return $self->dump_directory . q{/} . $class . q{.pm};
1552 =head2 get_dump_filename
1556 Returns the full path to the file for a class that the class has been or will
1557 be dumped to. This is a file in a temp dir for a dynamic schema.
1561 sub get_dump_filename {
1562 my ($self, $class) = (@_);
1564 local $self->{dump_directory} = $self->real_dump_directory;
1566 return $self->_get_dump_filename($class);
1569 sub _ensure_dump_subdirs {
1570 my ($self, $class) = (@_);
1572 my @name_parts = split(/::/, $class);
1573 pop @name_parts; # we don't care about the very last element,
1574 # which is a filename
1576 my $dir = $self->dump_directory;
1579 mkdir($dir) or croak "mkdir('$dir') failed: $!";
1581 last if !@name_parts;
1582 $dir = File::Spec->catdir($dir, shift @name_parts);
1587 my ($self, @classes) = @_;
1589 my $schema_class = $self->schema_class;
1590 my $schema_base_class = $self->schema_base_class || 'DBIx::Class::Schema';
1592 my $target_dir = $self->dump_directory;
1593 warn "Dumping manual schema for $schema_class to directory $target_dir ...\n"
1594 unless $self->dynamic or $self->quiet;
1597 qq|package $schema_class;\n\n|
1598 . qq|# Created by DBIx::Class::Schema::Loader\n|
1599 . qq|# DO NOT MODIFY THE FIRST PART OF THIS FILE\n\n|;
1601 if ($self->use_moose) {
1602 $schema_text.= qq|use Moose;\nuse namespace::autoclean;\nextends '$schema_base_class';\n\n|;
1605 $schema_text .= qq|use strict;\nuse warnings;\n\nuse base '$schema_base_class';\n\n|;
1608 my @schema_components = @{ $self->schema_components || [] };
1610 if (@schema_components) {
1611 my $schema_components = dump @schema_components;
1612 $schema_components = "($schema_components)" if @schema_components == 1;
1614 $schema_text .= "__PACKAGE__->load_components${schema_components};\n\n";
1617 if ($self->use_namespaces) {
1618 $schema_text .= qq|__PACKAGE__->load_namespaces|;
1619 my $namespace_options;
1621 my @attr = qw/resultset_namespace default_resultset_class/;
1623 unshift @attr, 'result_namespace' unless (not $self->result_namespace) || $self->result_namespace eq 'Result';
1625 for my $attr (@attr) {
1627 my $code = dumper_squashed $self->$attr;
1628 $namespace_options .= qq| $attr => $code,\n|
1631 $schema_text .= qq|(\n$namespace_options)| if $namespace_options;
1632 $schema_text .= qq|;\n|;
1635 $schema_text .= qq|__PACKAGE__->load_classes;\n|;
1639 local $self->{version_to_dump} = $self->schema_version_to_dump;
1640 $self->_write_classfile($schema_class, $schema_text, 1);
1643 my $result_base_class = $self->result_base_class || 'DBIx::Class::Core';
1645 foreach my $src_class (@classes) {
1647 qq|package $src_class;\n\n|
1648 . qq|# Created by DBIx::Class::Schema::Loader\n|
1649 . qq|# DO NOT MODIFY THE FIRST PART OF THIS FILE\n\n|;
1651 $src_text .= $self->_make_pod_heading($src_class);
1653 $src_text .= qq|use strict;\nuse warnings;\n\n|;
1655 $src_text .= $self->_base_class_pod($result_base_class)
1656 unless $result_base_class eq 'DBIx::Class::Core';
1658 if ($self->use_moose) {
1659 $src_text.= qq|use Moose;\nuse MooseX::NonMoose;\nuse namespace::autoclean;|;
1661 # these options 'use base' which is compile time
1662 if (@{ $self->left_base_classes } || @{ $self->additional_base_classes }) {
1663 $src_text .= qq|\nBEGIN { extends '$result_base_class' }\n|;
1666 $src_text .= qq|\nextends '$result_base_class';\n|;
1670 $src_text .= qq|use base '$result_base_class';\n|;
1673 $self->_write_classfile($src_class, $src_text);
1676 # remove Result dir if downgrading from use_namespaces, and there are no
1678 if (my $result_ns = $self->_downgrading_to_load_classes
1679 || $self->_rewriting_result_namespace) {
1680 my $result_namespace = $self->_result_namespace(
1685 (my $result_dir = $result_namespace) =~ s{::}{/}g;
1686 $result_dir = $self->dump_directory . '/' . $result_dir;
1688 unless (my @files = glob "$result_dir/*") {
1693 warn "Schema dump completed.\n" unless $self->dynamic or $self->quiet;
1697 my ($self, $version, $ts) = @_;
1698 return qq|\n\n# Created by DBIx::Class::Schema::Loader|
1701 . qq|\n# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:|;
1704 sub _write_classfile {
1705 my ($self, $class, $text, $is_schema) = @_;
1707 my $filename = $self->_get_dump_filename($class);
1708 $self->_ensure_dump_subdirs($class);
1710 if (-f $filename && $self->really_erase_my_files) {
1711 warn "Deleting existing file '$filename' due to "
1712 . "'really_erase_my_files' setting\n" unless $self->quiet;
1716 my ($old_gen, $old_md5, $old_ver, $old_ts, $old_custom)
1717 = $self->_parse_generated_file($filename);
1719 if (! $old_gen && -f $filename) {
1720 croak "Cannot overwrite '$filename' without 'really_erase_my_files',"
1721 . " it does not appear to have been generated by Loader"
1724 my $custom_content = $old_custom || '';
1726 # prepend extra custom content from a *renamed* class (singularization effect)
1727 if (my $renamed_class = $self->_upgrading_classes->{$class}) {
1728 my $old_filename = $self->_get_dump_filename($renamed_class);
1730 if (-f $old_filename) {
1731 my $extra_custom = ($self->_parse_generated_file ($old_filename))[4];
1733 $extra_custom =~ s/\n\n# You can replace.*\n1;\n//;
1735 $custom_content = join ("\n", '', $extra_custom, $custom_content)
1738 unlink $old_filename;
1742 $custom_content ||= $self->_default_custom_content($is_schema);
1744 # If upgrading to use_moose=1 replace default custom content with default Moose custom content.
1745 # If there is already custom content, which does not have the Moose content, add it.
1746 if ($self->use_moose) {
1748 my $non_moose_custom_content = do {
1749 local $self->{use_moose} = 0;
1750 $self->_default_custom_content;
1753 if ($custom_content eq $non_moose_custom_content) {
1754 $custom_content = $self->_default_custom_content($is_schema);
1756 elsif ($custom_content !~ /\Q@{[$self->_default_moose_custom_content($is_schema)]}\E/) {
1757 $custom_content .= $self->_default_custom_content($is_schema);
1760 elsif (defined $self->use_moose && $old_gen) {
1761 croak 'It is not possible to "downgrade" a schema that was loaded with use_moose => 1 to use_moose => 0, due to differing custom content'
1762 if $old_gen =~ /use \s+ MooseX?\b/x;
1765 $custom_content = $self->_rewrite_old_classnames($custom_content);
1768 for @{$self->{_dump_storage}->{$class} || []};
1770 if ($self->filter_generated_code) {
1771 my $filter = $self->filter_generated_code;
1773 if (ref $filter eq 'CODE') {
1775 ($is_schema ? 'schema' : 'result'),
1781 my ($out, $in) = (gensym, gensym);
1783 my $pid = open2($out, $in, $filter)
1784 or croak "Could not open pipe to $filter: $!";
1790 $text = decode('UTF-8', do { local $/; <$out> });
1792 $text =~ s/$CR?$LF/\n/g;
1796 my $exit_code = $? >> 8;
1798 if ($exit_code != 0) {
1799 croak "filter '$filter' exited non-zero: $exit_code";
1802 if (not $text or not $text =~ /\bpackage\b/) {
1803 warn("$class skipped due to filter") if $self->debug;
1808 # Check and see if the dump is in fact different
1812 $compare_to = $text . $self->_sig_comment($old_ver, $old_ts);
1813 if (Digest::MD5::md5_base64(encode 'UTF-8', $compare_to) eq $old_md5) {
1814 return unless $self->_upgrading_from && $is_schema;
1818 $text .= $self->_sig_comment(
1819 $self->version_to_dump,
1820 POSIX::strftime('%Y-%m-%d %H:%M:%S', localtime)
1823 open(my $fh, '>:encoding(UTF-8)', $filename)
1824 or croak "Cannot open '$filename' for writing: $!";
1826 # Write the top half and its MD5 sum
1827 print $fh $text . Digest::MD5::md5_base64(encode 'UTF-8', $text) . "\n";
1829 # Write out anything loaded via external partial class file in @INC
1831 for @{$self->{_ext_storage}->{$class} || []};
1833 # Write out any custom content the user has added
1834 print $fh $custom_content;
1837 or croak "Error closing '$filename': $!";
1840 sub _default_moose_custom_content {
1841 my ($self, $is_schema) = @_;
1843 if (not $is_schema) {
1844 return qq|\n__PACKAGE__->meta->make_immutable;|;
1847 return qq|\n__PACKAGE__->meta->make_immutable(inline_constructor => 0);|;
1850 sub _default_custom_content {
1851 my ($self, $is_schema) = @_;
1852 my $default = qq|\n\n# You can replace this text with custom|
1853 . qq| code or comments, and it will be preserved on regeneration|;
1854 if ($self->use_moose) {
1855 $default .= $self->_default_moose_custom_content($is_schema);
1857 $default .= qq|\n1;\n|;
1861 sub _parse_generated_file {
1862 my ($self, $fn) = @_;
1864 return unless -f $fn;
1866 open(my $fh, '<:encoding(UTF-8)', $fn)
1867 or croak "Cannot open '$fn' for reading: $!";
1870 qr{^(# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:)([A-Za-z0-9/+]{22})\r?\n};
1872 my ($md5, $ts, $ver, $gen);
1878 # Pull out the version and timestamp from the line above
1879 ($ver, $ts) = $gen =~ m/^# Created by DBIx::Class::Schema::Loader v(.*?) @ (.*?)\r?\Z/m;
1882 croak "Checksum mismatch in '$fn', 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"
1883 if !$self->overwrite_modifications && Digest::MD5::md5_base64(encode 'UTF-8', $gen) ne $md5;
1892 my $custom = do { local $/; <$fh> }
1896 $custom =~ s/$CRLF|$LF/\n/g;
1900 return ($gen, $md5, $ver, $ts, $custom);
1908 warn "$target: use $_;" if $self->debug;
1909 $self->_raw_stmt($target, "use $_;");
1917 my $blist = join(q{ }, @_);
1919 return unless $blist;
1921 warn "$target: use base qw/$blist/;" if $self->debug;
1922 $self->_raw_stmt($target, "use base qw/$blist/;");
1929 my $rlist = join(q{, }, map { qq{'$_'} } @_);
1931 return unless $rlist;
1933 warn "$target: with $rlist;" if $self->debug;
1934 $self->_raw_stmt($target, "\nwith $rlist;");
1937 sub _result_namespace {
1938 my ($self, $schema_class, $ns) = @_;
1939 my @result_namespace;
1941 $ns = $ns->[0] if ref $ns;
1943 if ($ns =~ /^\+(.*)/) {
1944 # Fully qualified namespace
1945 @result_namespace = ($1)
1948 # Relative namespace
1949 @result_namespace = ($schema_class, $ns);
1952 return wantarray ? @result_namespace : join '::', @result_namespace;
1955 # Create class with applicable bases, setup monikers, etc
1956 sub _make_src_class {
1957 my ($self, $table) = @_;
1959 my $schema = $self->schema;
1960 my $schema_class = $self->schema_class;
1962 my $table_moniker = $self->_table2moniker($table);
1963 my @result_namespace = ($schema_class);
1964 if ($self->use_namespaces) {
1965 my $result_namespace = $self->result_namespace || 'Result';
1966 @result_namespace = $self->_result_namespace(
1971 my $table_class = join(q{::}, @result_namespace, $table_moniker);
1973 if ((my $upgrading_v = $self->_upgrading_from)
1974 || $self->_rewriting) {
1975 local $self->naming->{monikers} = $upgrading_v
1978 my @result_namespace = @result_namespace;
1979 if ($self->_upgrading_from_load_classes) {
1980 @result_namespace = ($schema_class);
1982 elsif (my $ns = $self->_downgrading_to_load_classes) {
1983 @result_namespace = $self->_result_namespace(
1988 elsif ($ns = $self->_rewriting_result_namespace) {
1989 @result_namespace = $self->_result_namespace(
1995 my $old_table_moniker = do {
1996 local $self->naming->{monikers} = $upgrading_v;
1997 $self->_table2moniker($table);
2000 my $old_class = join(q{::}, @result_namespace, $old_table_moniker);
2002 $self->_upgrading_classes->{$table_class} = $old_class
2003 unless $table_class eq $old_class;
2006 $self->classes->{$table->sql_name} = $table_class;
2007 $self->monikers->{$table->sql_name} = $table_moniker;
2008 $self->moniker_to_table->{$table_moniker} = $table;
2009 $self->class_to_table->{$table_class} = $table;
2011 $self->_pod_class_list($table_class, 'ADDITIONAL CLASSES USED', @{$self->additional_classes});
2013 $self->_use ($table_class, @{$self->additional_classes});
2015 $self->_pod_class_list($table_class, 'LEFT BASE CLASSES', @{$self->left_base_classes});
2017 $self->_inject($table_class, @{$self->left_base_classes});
2019 my @components = @{ $self->components || [] };
2021 push @components, @{ $self->result_components_map->{$table_moniker} }
2022 if exists $self->result_components_map->{$table_moniker};
2024 my @fq_components = @components;
2025 foreach my $component (@fq_components) {
2026 if ($component !~ s/^\+//) {
2027 $component = "DBIx::Class::$component";
2031 $self->_pod_class_list($table_class, 'COMPONENTS LOADED', @fq_components);
2033 $self->_dbic_stmt($table_class, 'load_components', @components) if @components;
2035 $self->_pod_class_list($table_class, 'ADDITIONAL BASE CLASSES', @{$self->additional_base_classes});
2037 $self->_inject($table_class, @{$self->additional_base_classes});
2040 sub _is_result_class_method {
2041 my ($self, $name, $table) = @_;
2043 my $table_moniker = $table ? $self->monikers->{$table->sql_name} : '';
2045 $self->_result_class_methods({})
2046 if not defined $self->_result_class_methods;
2048 if (not exists $self->_result_class_methods->{$table_moniker}) {
2049 my (@methods, %methods);
2050 my $base = $self->result_base_class || 'DBIx::Class::Core';
2052 my @components = @{ $self->components || [] };
2054 push @components, @{ $self->result_components_map->{$table_moniker} }
2055 if exists $self->result_components_map->{$table_moniker};
2057 for my $c (@components) {
2058 $c = $c =~ /^\+/ ? substr($c,1) : "DBIx::Class::$c";
2061 my @roles = @{ $self->result_roles || [] };
2063 push @roles, @{ $self->result_roles_map->{$table_moniker} }
2064 if exists $self->result_roles_map->{$table_moniker};
2066 for my $class ($base, @components,
2067 ($self->use_moose ? 'Moose::Object' : ()), @roles) {
2068 $self->ensure_class_loaded($class);
2070 push @methods, @{ Class::Inspector->methods($class) || [] };
2073 push @methods, @{ Class::Inspector->methods('UNIVERSAL') };
2075 @methods{@methods} = ();
2077 $self->_result_class_methods->{$table_moniker} = \%methods;
2079 my $result_methods = $self->_result_class_methods->{$table_moniker};
2081 return exists $result_methods->{$name};
2084 sub _resolve_col_accessor_collisions {
2085 my ($self, $table, $col_info) = @_;
2087 while (my ($col, $info) = each %$col_info) {
2088 my $accessor = $info->{accessor} || $col;
2090 next if $accessor eq 'id'; # special case (very common column)
2092 if ($self->_is_result_class_method($accessor, $table)) {
2095 if (my $map = $self->col_collision_map) {
2096 for my $re (keys %$map) {
2097 if (my @matches = $col =~ /$re/) {
2098 $info->{accessor} = sprintf $map->{$re}, @matches;
2106 Column '$col' in table '$table' collides with an inherited method.
2107 See "COLUMN ACCESSOR COLLISIONS" in perldoc DBIx::Class::Schema::Loader::Base .
2109 $info->{accessor} = undef;
2115 # use the same logic to run moniker_map, col_accessor_map
2117 my ( $self, $map, $default_code, $ident, @extra ) = @_;
2119 my $default_ident = $default_code->( $ident, @extra );
2121 if( $map && ref $map eq 'HASH' ) {
2122 $new_ident = $map->{ $ident };
2124 elsif( $map && ref $map eq 'CODE' ) {
2125 $new_ident = $map->( $ident, $default_ident, @extra );
2128 $new_ident ||= $default_ident;
2133 sub _default_column_accessor_name {
2134 my ( $self, $column_name ) = @_;
2136 my $accessor_name = $column_name;
2137 $accessor_name =~ s/\W+/_/g;
2139 if ((($self->naming->{column_accessors}||'') =~ /(\d+)/ && $1 < 7) || (not $self->preserve_case)) {
2140 # older naming just lc'd the col accessor and that's all.
2141 return lc $accessor_name;
2143 elsif (($self->naming->{column_accessors}||'') eq 'preserve') {
2144 return $accessor_name;
2147 return join '_', map lc, split_name $column_name;
2150 sub _make_column_accessor_name {
2151 my ($self, $column_name, $column_context_info ) = @_;
2153 my $accessor = $self->_run_user_map(
2154 $self->col_accessor_map,
2155 sub { $self->_default_column_accessor_name( shift ) },
2157 $column_context_info,
2163 # Set up metadata (cols, pks, etc)
2164 sub _setup_src_meta {
2165 my ($self, $table) = @_;
2167 my $schema = $self->schema;
2168 my $schema_class = $self->schema_class;
2170 my $table_class = $self->classes->{$table->sql_name};
2171 my $table_moniker = $self->monikers->{$table->sql_name};
2173 $self->_dbic_stmt($table_class, 'table', $table->dbic_name);
2175 my $cols = $self->_table_columns($table);
2176 my $col_info = $self->__columns_info_for($table);
2178 ### generate all the column accessor names
2179 while (my ($col, $info) = each %$col_info) {
2180 # hashref of other info that could be used by
2181 # user-defined accessor map functions
2183 table_class => $table_class,
2184 table_moniker => $table_moniker,
2185 table_name => $table,
2186 full_table_name => $table->dbic_name,
2187 schema_class => $schema_class,
2188 column_info => $info,
2191 $info->{accessor} = $self->_make_column_accessor_name( $col, $context );
2194 $self->_resolve_col_accessor_collisions($table, $col_info);
2196 # prune any redundant accessor names
2197 while (my ($col, $info) = each %$col_info) {
2198 no warnings 'uninitialized';
2199 delete $info->{accessor} if $info->{accessor} eq $col;
2202 my $fks = $self->_table_fk_info($table);
2204 foreach my $fkdef (@$fks) {
2205 for my $col (@{ $fkdef->{local_columns} }) {
2206 $col_info->{$col}{is_foreign_key} = 1;
2210 my $pks = $self->_table_pk_info($table) || [];
2212 my %uniq_tag; # used to eliminate duplicate uniqs
2214 $uniq_tag{ join("\0", @$pks) }++ if @$pks; # pk is a uniq
2216 my $uniqs = $self->_table_uniq_info($table) || [];
2219 foreach my $uniq (@$uniqs) {
2220 my ($name, $cols) = @$uniq;
2221 next if $uniq_tag{ join("\0", @$cols) }++; # skip duplicates
2222 push @uniqs, [$name, $cols];
2225 my @non_nullable_uniqs = grep {
2226 all { $col_info->{$_}{is_nullable} == 0 } @{ $_->[1] }
2229 if ($self->uniq_to_primary && (not @$pks) && @non_nullable_uniqs) {
2230 my @by_colnum = sort { $b->[0] <=> $a->[0] }
2231 map [ scalar @{ $_->[1] }, $_ ], @non_nullable_uniqs;
2233 if (not (@by_colnum > 1 && $by_colnum[0][0] == $by_colnum[1][0])) {
2234 my @keys = map $_->[1], @by_colnum;
2238 # remove the uniq from list
2239 @uniqs = grep { $_->[0] ne $pk->[0] } @uniqs;
2245 foreach my $pkcol (@$pks) {
2246 $col_info->{$pkcol}{is_nullable} = 0;
2252 map { $_, ($col_info->{$_}||{}) } @$cols
2255 $self->_dbic_stmt($table_class, 'set_primary_key', @$pks)
2258 # Sort unique constraints by constraint name for repeatable results (rels
2259 # are sorted as well elsewhere.)
2260 @uniqs = sort { $a->[0] cmp $b->[0] } @uniqs;
2262 foreach my $uniq (@uniqs) {
2263 my ($name, $cols) = @$uniq;
2264 $self->_dbic_stmt($table_class,'add_unique_constraint', $name, $cols);
2268 sub __columns_info_for {
2269 my ($self, $table) = @_;
2271 my $result = $self->_columns_info_for($table);
2273 while (my ($col, $info) = each %$result) {
2274 $info = { %$info, %{ $self->_custom_column_info ($table, $col, $info) } };
2275 $info = { %$info, %{ $self->_datetime_column_info($table, $col, $info) } };
2277 $result->{$col} = $info;
2285 Returns a sorted list of loaded tables, using the original database table
2293 return values %{$self->_tables};
2296 # Make a moniker from a table
2297 sub _default_table2moniker {
2298 no warnings 'uninitialized';
2299 my ($self, $table) = @_;
2301 my @name_parts = map $table->$_, @{ $self->moniker_parts };
2303 my $name_idx = firstidx { $_ eq 'name' } @{ $self->moniker_parts };
2305 if ($self->naming->{monikers} eq 'v4') {
2306 return join '', map ucfirst, map split(/[\W_]+/, lc $_), @name_parts;
2308 elsif ($self->naming->{monikers} eq 'v5') {
2309 my @parts = map lc, @name_parts;
2310 $parts[$name_idx] = Lingua::EN::Inflect::Number::to_S($parts[$name_idx]);
2312 return join '', map ucfirst, map split(/[\W_]+/, $_), @parts;
2314 elsif ($self->naming->{monikers} eq 'v6') {
2315 (my $as_phrase = join '', map lc, @name_parts) =~ s/_+/ /g;
2316 my $inflected = Lingua::EN::Inflect::Phrase::to_S($as_phrase);
2318 return join '', map ucfirst, split /\W+/, $inflected;
2321 my @words = map lc, map split_name $_, @name_parts;
2322 my $as_phrase = join ' ', @words;
2324 my $inflected = $self->naming->{monikers} eq 'plural' ?
2325 Lingua::EN::Inflect::Phrase::to_PL($as_phrase)
2327 $self->naming->{monikers} eq 'preserve' ?
2330 Lingua::EN::Inflect::Phrase::to_S($as_phrase);
2332 return join '', map ucfirst, split /\W+/, $inflected;
2335 sub _table2moniker {
2336 my ( $self, $table ) = @_;
2338 $self->_run_user_map(
2340 sub { $self->_default_table2moniker( shift ) },
2345 sub _load_relationships {
2346 my ($self, $tables) = @_;
2350 foreach my $table (@$tables) {
2351 my $local_moniker = $self->monikers->{$table->sql_name};
2353 my $tbl_fk_info = $self->_table_fk_info($table);
2355 foreach my $fkdef (@$tbl_fk_info) {
2356 $fkdef->{local_table} = $table;
2357 $fkdef->{local_moniker} = $local_moniker;
2358 $fkdef->{remote_source} =
2359 $self->monikers->{$fkdef->{remote_table}->sql_name};
2361 my $tbl_uniq_info = $self->_table_uniq_info($table);
2363 push @tables, [ $local_moniker, $tbl_fk_info, $tbl_uniq_info ];
2366 my $rel_stmts = $self->_relbuilder->generate_code(\@tables);
2368 foreach my $src_class (sort keys %$rel_stmts) {
2370 my @src_stmts = map $_->[1],
2371 sort { $a->[0] cmp $b->[0] }
2372 map [ $_->{args}[0], $_ ], @{ $rel_stmts->{$src_class} };
2374 foreach my $stmt (@src_stmts) {
2375 $self->_dbic_stmt($src_class,$stmt->{method}, @{$stmt->{args}});
2381 my ($self, $table) = @_;
2383 my $table_moniker = $self->monikers->{$table->sql_name};
2384 my $table_class = $self->classes->{$table->sql_name};
2386 my @roles = @{ $self->result_roles || [] };
2387 push @roles, @{ $self->result_roles_map->{$table_moniker} }
2388 if exists $self->result_roles_map->{$table_moniker};
2391 $self->_pod_class_list($table_class, 'L<Moose> ROLES APPLIED', @roles);
2393 $self->_with($table_class, @roles);
2397 # Overload these in driver class:
2399 # Returns an arrayref of column names
2400 sub _table_columns { croak "ABSTRACT METHOD" }
2402 # Returns arrayref of pk col names
2403 sub _table_pk_info { croak "ABSTRACT METHOD" }
2405 # Returns an arrayref of uniqs [ [ foo => [ col1, col2 ] ], [ bar => [ ... ] ] ]
2406 sub _table_uniq_info { croak "ABSTRACT METHOD" }
2408 # Returns an arrayref of foreign key constraints, each
2409 # being a hashref with 3 keys:
2410 # local_columns (arrayref), remote_columns (arrayref), remote_table
2411 sub _table_fk_info { croak "ABSTRACT METHOD" }
2413 # Returns an array of lower case table names
2414 sub _tables_list { croak "ABSTRACT METHOD" }
2416 # Execute a constructive DBIC class method, with debug/dump_to_dir hooks.
2422 # generate the pod for this statement, storing it with $self->_pod
2423 $self->_make_pod( $class, $method, @_ ) if $self->generate_pod;
2425 my $args = dump(@_);
2426 $args = '(' . $args . ')' if @_ < 2;
2427 my $stmt = $method . $args . q{;};
2429 warn qq|$class\->$stmt\n| if $self->debug;
2430 $self->_raw_stmt($class, '__PACKAGE__->' . $stmt);
2434 sub _make_pod_heading {
2435 my ($self, $class) = @_;
2437 return '' if not $self->generate_pod;
2439 my $table = $self->class_to_table->{$class};
2442 my $pcm = $self->pod_comment_mode;
2443 my ($comment, $comment_overflows, $comment_in_name, $comment_in_desc);
2444 $comment = $self->__table_comment($table);
2445 $comment_overflows = ($comment and length $comment > $self->pod_comment_spillover_length);
2446 $comment_in_name = ($pcm eq 'name' or ($pcm eq 'auto' and !$comment_overflows));
2447 $comment_in_desc = ($pcm eq 'description' or ($pcm eq 'auto' and $comment_overflows));
2449 $pod .= "=head1 NAME\n\n";
2451 my $table_descr = $class;
2452 $table_descr .= " - " . $comment if $comment and $comment_in_name;
2454 $pod .= "$table_descr\n\n";
2456 if ($comment and $comment_in_desc) {
2457 $pod .= "=head1 DESCRIPTION\n\n${comment}\n\n";
2464 # generates the accompanying pod for a DBIC class method statement,
2465 # storing it with $self->_pod
2471 if ($method eq 'table') {
2473 $table = $$table if ref $table eq 'SCALAR';
2474 $self->_pod($class, "=head1 TABLE: C<$table>");
2475 $self->_pod_cut($class);
2477 elsif ( $method eq 'add_columns' ) {
2478 $self->_pod( $class, "=head1 ACCESSORS" );
2479 my $col_counter = 0;
2481 while( my ($name,$attrs) = splice @cols,0,2 ) {
2483 $self->_pod( $class, '=head2 ' . $name );
2484 $self->_pod( $class,
2486 my $s = $attrs->{$_};
2487 $s = !defined $s ? 'undef' :
2488 length($s) == 0 ? '(empty string)' :
2489 ref($s) eq 'SCALAR' ? $$s :
2490 ref($s) ? dumper_squashed $s :
2491 looks_like_number($s) ? $s : qq{'$s'};
2494 } sort keys %$attrs,
2496 if (my $comment = $self->__column_comment($self->class_to_table->{$class}, $col_counter, $name)) {
2497 $self->_pod( $class, $comment );
2500 $self->_pod_cut( $class );
2501 } elsif ( $method =~ /^(belongs_to|has_many|might_have)$/ ) {
2502 $self->_pod( $class, "=head1 RELATIONS" ) unless $self->{_relations_started} { $class } ;
2503 my ( $accessor, $rel_class ) = @_;
2504 $self->_pod( $class, "=head2 $accessor" );
2505 $self->_pod( $class, 'Type: ' . $method );
2506 $self->_pod( $class, "Related object: L<$rel_class>" );
2507 $self->_pod_cut( $class );
2508 $self->{_relations_started} { $class } = 1;
2510 elsif ($method eq 'add_unique_constraint') {
2511 $self->_pod($class, '=head1 UNIQUE CONSTRAINTS')
2512 unless $self->{_uniqs_started}{$class};
2514 my ($name, $cols) = @_;
2516 $self->_pod($class, "=head2 C<$name>");
2517 $self->_pod($class, '=over 4');
2519 foreach my $col (@$cols) {
2520 $self->_pod($class, "=item \* L</$col>");
2523 $self->_pod($class, '=back');
2524 $self->_pod_cut($class);
2526 $self->{_uniqs_started}{$class} = 1;
2528 elsif ($method eq 'set_primary_key') {
2529 $self->_pod($class, "=head1 PRIMARY KEY");
2530 $self->_pod($class, '=over 4');
2532 foreach my $col (@_) {
2533 $self->_pod($class, "=item \* L</$col>");
2536 $self->_pod($class, '=back');
2537 $self->_pod_cut($class);
2541 sub _pod_class_list {
2542 my ($self, $class, $title, @classes) = @_;
2544 return unless @classes && $self->generate_pod;
2546 $self->_pod($class, "=head1 $title");
2547 $self->_pod($class, '=over 4');
2549 foreach my $link (@classes) {
2550 $self->_pod($class, "=item * L<$link>");
2553 $self->_pod($class, '=back');
2554 $self->_pod_cut($class);
2557 sub _base_class_pod {
2558 my ($self, $base_class) = @_;
2560 return '' unless $self->generate_pod;
2563 =head1 BASE CLASS: L<$base_class>
2570 sub _filter_comment {
2571 my ($self, $txt) = @_;
2573 $txt = '' if not defined $txt;
2575 $txt =~ s/(?:\015?\012|\015\012?)/\n/g;
2580 sub __table_comment {
2583 if (my $code = $self->can('_table_comment')) {
2584 return $self->_filter_comment($self->$code(@_));
2590 sub __column_comment {
2593 if (my $code = $self->can('_column_comment')) {
2594 return $self->_filter_comment($self->$code(@_));
2600 # Stores a POD documentation
2602 my ($self, $class, $stmt) = @_;
2603 $self->_raw_stmt( $class, "\n" . $stmt );
2607 my ($self, $class ) = @_;
2608 $self->_raw_stmt( $class, "\n=cut\n" );
2611 # Store a raw source line for a class (for dumping purposes)
2613 my ($self, $class, $stmt) = @_;
2614 push(@{$self->{_dump_storage}->{$class}}, $stmt);
2617 # Like above, but separately for the externally loaded stuff
2619 my ($self, $class, $stmt) = @_;
2620 push(@{$self->{_ext_storage}->{$class}}, $stmt);
2623 sub _custom_column_info {
2624 my ( $self, $table_name, $column_name, $column_info ) = @_;
2626 if (my $code = $self->custom_column_info) {
2627 return $code->($table_name, $column_name, $column_info) || {};
2632 sub _datetime_column_info {
2633 my ( $self, $table_name, $column_name, $column_info ) = @_;
2635 my $type = $column_info->{data_type} || '';
2636 if ((grep $_, @{ $column_info }{map "inflate_$_", qw/date datetime timestamp/})
2637 or ($type =~ /date|timestamp/i)) {
2638 $result->{timezone} = $self->datetime_timezone if $self->datetime_timezone;
2639 $result->{locale} = $self->datetime_locale if $self->datetime_locale;
2645 my ($self, $name) = @_;
2647 return $self->preserve_case ? $name : lc($name);
2651 my ($self, $name) = @_;
2653 return $self->preserve_case ? $name : uc($name);
2657 my ($self, $table) = @_;
2660 my $schema = $self->schema;
2661 # in older DBIC it's a private method
2662 my $unregister = $schema->can('unregister_source') || $schema->can('_unregister_source');
2663 $schema->$unregister(delete $self->monikers->{$table->sql_name});
2664 delete $self->_upgrading_classes->{delete $self->classes->{$table->sql_name}};
2665 delete $self->_tables->{$table->sql_name};
2669 # remove the dump dir from @INC on destruction
2673 @INC = grep $_ ne $self->dump_directory, @INC;
2678 Returns a hashref of loaded table to moniker mappings. There will
2679 be two entries for each table, the original name and the "normalized"
2680 name, in the case that the two are different (such as databases
2681 that like uppercase table names, or preserve your original mixed-case
2682 definitions, or what-have-you).
2686 Returns a hashref of table to class mappings. In some cases it will
2687 contain multiple entries per table for the original and normalized table
2688 names, as above in L</monikers>.
2690 =head1 COLUMN ACCESSOR COLLISIONS
2692 Occasionally you may have a column name that collides with a perl method, such
2693 as C<can>. In such cases, the default action is to set the C<accessor> of the
2694 column spec to C<undef>.
2696 You can then name the accessor yourself by placing code such as the following
2699 __PACKAGE__->add_column('+can' => { accessor => 'my_can' });
2701 Another option is to use the L</col_collision_map> option.
2703 =head1 RELATIONSHIP NAME COLLISIONS
2705 In very rare cases, you may get a collision between a generated relationship
2706 name and a method in your Result class, for example if you have a foreign key
2707 called C<belongs_to>.
2709 This is a problem because relationship names are also relationship accessor
2710 methods in L<DBIx::Class>.
2712 The default behavior is to append C<_rel> to the relationship name and print
2713 out a warning that refers to this text.
2715 You can also control the renaming with the L</rel_collision_map> option.
2719 L<DBIx::Class::Schema::Loader>
2723 See L<DBIx::Class::Schema::Loader/AUTHOR> and L<DBIx::Class::Schema::Loader/CONTRIBUTORS>.
2727 This library is free software; you can redistribute it and/or modify it under
2728 the same terms as Perl itself.
2733 # vim:et sts=4 sw=4 tw=0: