1 package DBIx::Class::Schema::Loader::Base;
5 use base qw/Class::Accessor::Grouped Class::C3::Componentised/;
8 use Carp::Clan qw/^DBIx::Class/;
9 use DBIx::Class::Schema::Loader::RelBuilder ();
10 use Data::Dump 'dump';
15 use Lingua::EN::Inflect::Number ();
16 use Lingua::EN::Inflect::Phrase ();
17 use String::ToIdentifier::EN ();
18 use String::ToIdentifier::EN::Unicode ();
21 use Class::Inspector ();
22 use Scalar::Util 'looks_like_number';
23 use DBIx::Class::Schema::Loader::Utils qw/split_name dumper_squashed eval_package_without_redefine_warnings class_path slurp_file sigwarn_silencer firstidx uniq/;
24 use DBIx::Class::Schema::Loader::Optional::Dependencies ();
27 use Encode qw/encode decode/;
28 use List::Util qw/all any none/;
29 use File::Temp 'tempfile';
32 our $VERSION = '0.07043';
34 __PACKAGE__->mk_group_ro_accessors('simple', qw/
41 additional_base_classes
57 default_resultset_class
63 overwrite_modifications
91 __PACKAGE__->mk_group_accessors('simple', qw/
93 schema_version_to_dump
95 _upgrading_from_load_classes
96 _downgrading_to_load_classes
97 _rewriting_result_namespace
102 pod_comment_spillover_length
108 result_components_map
110 datetime_undef_if_invalid
111 _result_class_methods
113 filter_generated_code
117 moniker_part_separator
121 my $CURRENT_V = 'v7';
124 schema_components schema_base_class result_base_class
125 additional_base_classes left_base_classes additional_classes components
131 my $CRLF = "\x0d\x0a";
135 DBIx::Class::Schema::Loader::Base - Base DBIx::Class::Schema::Loader Implementation.
139 See L<DBIx::Class::Schema::Loader>.
143 This is the base class for the storage-specific C<DBIx::Class::Schema::*>
144 classes, and implements the common functionality between them.
146 =head1 CONSTRUCTOR OPTIONS
148 These constructor options are the base options for
149 L<DBIx::Class::Schema::Loader/loader_options>. Available constructor options are:
151 =head2 skip_relationships
153 Skip setting up relationships. The default is to attempt the loading
156 =head2 skip_load_external
158 Skip loading of other classes in @INC. The default is to merge all other classes
159 with the same name found in @INC into the schema file we are creating.
161 Even if this is not set, code generated by this module and not
162 subsequently modified is never included.
166 Static schemas (ones dumped to disk) will, by default, use the new-style
167 relationship names and singularized Results, unless you're overwriting an
168 existing dump made by an older version of L<DBIx::Class::Schema::Loader>, in
169 which case the backward compatible RelBuilder will be activated, and the
170 appropriate monikerization used.
176 will disable the backward-compatible RelBuilder and use
177 the new-style relationship names along with singularized Results, even when
178 overwriting a dump made with an earlier version.
180 The option also takes a hashref:
183 relationships => 'v8',
185 column_accessors => 'v8',
191 naming => { ALL => 'v8', force_ascii => 1 }
199 Set L</relationships>, L</monikers> and L</column_accessors> to the specified
204 How to name relationship accessors.
208 How to name Result classes.
210 =item column_accessors
212 How to name column accessors in Result classes.
216 For L</v8> mode and later, uses L<String::ToIdentifier::EN> instead of
217 L<String::ToIdentifier::EN::Unicode> to force monikers and other identifiers to
228 Latest style, whatever that happens to be.
232 Unsingularlized monikers, C<has_many> only relationships with no _id stripping.
236 Monikers singularized as whole words, C<might_have> relationships for FKs on
237 C<UNIQUE> constraints, C<_id> stripping for belongs_to relationships.
239 Some of the C<_id> stripping edge cases in C<0.05003> have been reverted for
244 All monikers and relationships are inflected using
245 L<Lingua::EN::Inflect::Phrase>, and there is more aggressive C<_id> stripping
246 from relationship names.
248 In general, there is very little difference between v5 and v6 schemas.
252 This mode is identical to C<v6> mode, except that monikerization of CamelCase
253 table names is also done better (but best in v8.)
255 CamelCase column names in case-preserving mode will also be handled better
256 for relationship name inflection (but best in v8.) See L</preserve_case>.
258 In this mode, CamelCase L</column_accessors> are normalized based on case
259 transition instead of just being lowercased, so C<FooId> becomes C<foo_id>.
265 The default mode is L</v7>, to get L</v8> mode, you have to specify it in
266 L</naming> explicitly until C<0.08> comes out.
268 L</monikers> and L</column_accessors> are created using
269 L<String::ToIdentifier::EN::Unicode> or L<String::ToIdentifier::EN> if
270 L</force_ascii> is set; this is only significant for names with non-C<\w>
271 characters such as C<.>.
273 CamelCase identifiers with words in all caps, e.g. C<VLANValidID> are supported
274 correctly in this mode.
276 For relationships, belongs_to accessors are made from column names by stripping
277 postfixes other than C<_id> as well, for example just C<Id>, C<_?ref>, C<_?cd>,
278 C<_?code> and C<_?num>, case insensitively.
282 For L</monikers>, this option does not inflect the table names but makes
283 monikers based on the actual name. For L</column_accessors> this option does
284 not normalize CamelCase column names to lowercase column accessors, but makes
285 accessors that are the same names as the columns (with any non-\w chars
286 replaced with underscores.)
290 For L</monikers>, singularizes the names using the most current inflector. This
291 is the same as setting the option to L</current>.
295 For L</monikers>, pluralizes the names, using the most current inflector.
299 Dynamic schemas will always default to the 0.04XXX relationship names and won't
300 singularize Results for backward compatibility, to activate the new RelBuilder
301 and singularization put this in your C<Schema.pm> file:
303 __PACKAGE__->naming('current');
305 Or if you prefer to use 0.07XXX features but insure that nothing breaks in the
306 next major version upgrade:
308 __PACKAGE__->naming('v7');
312 If true, will not print the usual C<Dumping manual schema ... Schema dump
313 completed.> messages. Does not affect warnings (except for warnings related to
314 L</really_erase_my_files>.)
318 If true, don't actually write out the generated files. This can only be
319 used with static schema generation.
323 By default POD will be generated for columns and relationships, using database
324 metadata for the text if available and supported.
326 Comment metadata can be stored in two ways.
328 The first is that you can create two tables named C<table_comments> and
329 C<column_comments> respectively. These tables must exist in the same database
330 and schema as the tables they describe. They both need to have columns named
331 C<table_name> and C<comment_text>. The second one needs to have a column named
332 C<column_name>. Then data stored in these tables will be used as a source of
333 metadata about tables and comments.
335 (If you wish you can change the name of these tables with the parameters
336 L</table_comments_table> and L</column_comments_table>.)
338 As a fallback you can use built-in commenting mechanisms. Currently this is
339 only supported for PostgreSQL, Oracle and MySQL. To create comments in
340 PostgreSQL you add statements of the form C<COMMENT ON TABLE some_table IS
341 '...'>, the same syntax is used in Oracle. To create comments in MySQL you add
342 C<COMMENT '...'> to the end of the column or table definition. Note that MySQL
343 restricts the length of comments, and also does not handle complex Unicode
346 Set this to C<0> to turn off all POD generation.
348 =head2 pod_comment_mode
350 Controls where table comments appear in the generated POD. Smaller table
351 comments are appended to the C<NAME> section of the documentation, and larger
352 ones are inserted into C<DESCRIPTION> instead. You can force a C<DESCRIPTION>
353 section to be generated with the comment always, only use C<NAME>, or choose
354 the length threshold at which the comment is forced into the description.
360 Use C<NAME> section only.
364 Force C<DESCRIPTION> always.
368 Use C<DESCRIPTION> if length > L</pod_comment_spillover_length>, this is the
373 =head2 pod_comment_spillover_length
375 When pod_comment_mode is set to C<auto>, this is the length of the comment at
376 which it will be forced into a separate description section.
380 =head2 table_comments_table
382 The table to look for comments about tables in. By default C<table_comments>.
383 See L</generate_pod> for details.
385 This must not be a fully qualified name, the table will be looked for in the
386 same database and schema as the table whose comment is being retrieved.
388 =head2 column_comments_table
390 The table to look for comments about columns in. By default C<column_comments>.
391 See L</generate_pod> for details.
393 This must not be a fully qualified name, the table will be looked for in the
394 same database and schema as the table/column whose comment is being retrieved.
396 =head2 relationship_attrs
398 Hashref of attributes to pass to each generated relationship, listed by type.
399 Also supports relationship type 'all', containing options to pass to all
400 generated relationships. Attributes set for more specific relationship types
401 override those set in 'all', and any attributes specified by this option
402 override the introspected attributes of the foreign key if any.
406 relationship_attrs => {
407 has_many => { cascade_delete => 1, cascade_copy => 1 },
408 might_have => { cascade_delete => 1, cascade_copy => 1 },
411 use this to turn L<DBIx::Class> cascades to on on your
412 L<has_many|DBIx::Class::Relationship/has_many> and
413 L<might_have|DBIx::Class::Relationship/might_have> relationships, they default
416 Can also be a coderef, for more precise control, in which case the coderef gets
417 this hash of parameters (as a list:)
419 rel_name # the name of the relationship
420 rel_type # the type of the relationship: 'belongs_to', 'has_many' or 'might_have'
421 local_source # the DBIx::Class::ResultSource object for the source the rel is *from*
422 remote_source # the DBIx::Class::ResultSource object for the source the rel is *to*
423 local_table # a DBIx::Class::Schema::Loader::Table object for the table of the source the rel is from
424 local_cols # an arrayref of column names of columns used in the rel in the source it is from
425 remote_table # a DBIx::Class::Schema::Loader::Table object for the table of the source the rel is to
426 remote_cols # an arrayref of column names of columns used in the rel in the source it is to
427 attrs # the attributes that would be set
429 it should return the new hashref of attributes, or nothing for no changes.
433 relationship_attrs => sub {
436 say "the relationship name is: $p{rel_name}";
437 say "the relationship is a: $p{rel_type}";
438 say "the local class is: ", $p{local_source}->result_class;
439 say "the remote class is: ", $p{remote_source}->result_class;
440 say "the local table is: ", $p{local_table}->sql_name;
441 say "the rel columns in the local table are: ", (join ", ", @{$p{local_cols}});
442 say "the remote table is: ", $p{remote_table}->sql_name;
443 say "the rel columns in the remote table are: ", (join ", ", @{$p{remote_cols}});
445 if ($p{local_table} eq 'dogs' && @{$p{local_cols}} == 1 && $p{local_cols}[0] eq 'name') {
446 $p{attrs}{could_be_snoopy} = 1;
452 These are the default attributes:
463 on_delete => 'CASCADE',
464 on_update => 'CASCADE',
468 For L<belongs_to|DBIx::Class::Relationship/belongs_to> relationships, these
469 defaults are overridden by the attributes introspected from the foreign key in
470 the database, if this information is available (and the driver is capable of
473 This information overrides the defaults mentioned above, and is then itself
474 overridden by the user's L</relationship_attrs> for C<belongs_to> if any are
477 In general, for most databases, for a plain foreign key with no rules, the
478 values for a L<belongs_to|DBIx::Class::Relationship/belongs_to> relationship
481 on_delete => 'NO ACTION',
482 on_update => 'NO ACTION',
485 In the cases where an attribute is not supported by the DB, a value matching
486 the actual behavior is used, for example Oracle does not support C<ON UPDATE>
487 rules, so C<on_update> is set to C<NO ACTION>. This is done so that the
488 behavior of the schema is preserved when cross deploying to a different RDBMS
489 such as SQLite for testing.
491 In the cases where the DB does not support C<DEFERRABLE> foreign keys, the
492 value is set to C<1> if L<DBIx::Class> has a working C<<
493 $storage->with_deferred_fk_checks >>. This is done so that the same
494 L<DBIx::Class> code can be used, and cross deployed from and to such databases.
498 If set to true, each constructive L<DBIx::Class> statement the loader
499 decides to execute will be C<warn>-ed before execution.
503 Set the name of the schema to load (schema in the sense that your database
506 Can be set to an arrayref of schema names for multiple schemas, or the special
507 value C<%> for all schemas.
509 For MSSQL, Sybase ASE, and Informix can be set to a hashref of databases as
510 keys and arrays of owners as values, set to the value:
514 for all owners in all databases.
516 Name clashes resulting from the same table name in different databases/schemas
517 will be resolved automatically by prefixing the moniker with the database
520 To prefix/suffix all monikers with the database and/or schema, see
525 The database table names are represented by the
526 L<DBIx::Class::Schema::Loader::Table> class in the loader, the
527 L<DBIx::Class::Schema::Loader::Table::Sybase> class for Sybase ASE and
528 L<DBIx::Class::Schema::Loader::Table::Informix> for Informix.
530 Monikers are created normally based on just the
531 L<name|DBIx::Class::Schema::Loader::DBObject/name> property, corresponding to
532 the table name, but can consist of other parts of the fully qualified name of
535 The L</moniker_parts> option is an arrayref of methods on the table class
536 corresponding to parts of the fully qualified table name, defaulting to
537 C<['name']>, in the order those parts are used to create the moniker name.
538 The parts are joined together using L</moniker_part_separator>.
540 The C<'name'> entry B<must> be present.
542 Below is a table of supported databases and possible L</moniker_parts>.
546 =item * DB2, Firebird, mysql, Oracle, Pg, SQLAnywhere, SQLite, MS Access
550 =item * Informix, MSSQL, Sybase ASE
552 C<database>, C<schema>, C<name>
556 =head2 moniker_part_separator
558 String used to join L</moniker_parts> when creating the moniker.
559 Defaults to the empty string. Use C<::> to get a separate namespace per
560 database and/or schema.
564 Only load matching tables.
568 Exclude matching tables.
570 These can be specified either as a regex (preferrably on the C<qr//>
571 form), or as an arrayref of arrayrefs. Regexes are matched against
572 the (unqualified) table name, while arrayrefs are matched according to
577 db_schema => [qw(some_schema other_schema)],
578 moniker_parts => [qw(schema name)],
580 [ qr/\Asome_schema\z/ => qr/\A(?:foo|bar)\z/ ],
581 [ qr/\Aother_schema\z/ => qr/\Abaz\z/ ],
584 In this case only the tables C<foo> and C<bar> in C<some_schema> and
585 C<baz> in C<other_schema> will be dumped.
589 Overrides the default table name to moniker translation. Either
595 a nested hashref, which will be traversed according to L</moniker_parts>
599 moniker_parts => [qw(schema name)],
606 In which case the table C<bar> in the C<foo> schema would get the moniker
611 a hashref of unqualified table name keys and moniker values
615 a coderef for a translator function taking a L<table
616 object|DBIx::Class::Schema::Loader::Table> argument (which stringifies to the
617 unqualified table name) and returning a scalar moniker
619 The function is also passed a coderef that can be called with either
620 of the hashref forms to get the moniker mapped accordingly. This is
621 useful if you need to handle some monikers specially, but want to use
622 the hashref form for the rest.
626 If the hash entry does not exist, or the function returns a false
627 value, the code falls back to default behavior for that table name.
629 The default behavior is to split on case transition and non-alphanumeric
630 boundaries, singularize the resulting phrase, then join the titlecased words
633 Table Name | Moniker Name
634 ---------------------------------
636 luser_group | LuserGroup
637 luser-opts | LuserOpt
638 stations_visited | StationVisited
639 routeChange | RouteChange
641 =head2 moniker_part_map
643 Map for overriding the monikerization of individual L</moniker_parts>.
644 The keys are the moniker part to override, the value is either a
645 hashref of coderef for mapping the corresponding part of the
646 moniker. If a coderef is used, it gets called with the moniker part
647 and the hash key the code ref was found under.
651 moniker_part_map => {
652 schema => sub { ... },
655 Given the table C<foo.bar>, the code ref would be called with the
656 arguments C<foo> and C<schema>, plus a coderef similar to the one
657 described in L</moniker_map>.
659 L</moniker_map> takes precedence over this.
661 =head2 col_accessor_map
663 Same as moniker_map, but for column accessor names. If a coderef is
664 passed, the code is called with arguments of
666 the name of the column in the underlying database,
667 default accessor name that DBICSL would ordinarily give this column,
669 table_class => name of the DBIC class we are building,
670 table_moniker => calculated moniker for this table (after moniker_map if present),
671 table => table object of interface DBIx::Class::Schema::Loader::Table,
672 full_table_name => schema-qualified name of the database table (RDBMS specific),
673 schema_class => name of the schema class we are building,
674 column_info => hashref of column info (data_type, is_nullable, etc),
676 coderef ref that can be called with a hashref map
678 the L<table object|DBIx::Class::Schema::Loader::Table> stringifies to the
679 unqualified table name.
683 Similar in idea to moniker_map, but different in the details. It can be
684 a hashref or a code ref.
686 If it is a hashref, keys can be either the default relationship name, or the
687 moniker. The keys that are the default relationship name should map to the
688 name you want to change the relationship to. Keys that are monikers should map
689 to hashes mapping relationship names to their translation. You can do both at
690 once, and the more specific moniker version will be picked up first. So, for
691 instance, you could have
700 and relationships that would have been named C<bar> will now be named C<baz>
701 except that in the table whose moniker is C<Foo> it will be named C<blat>.
703 If it is a coderef, it will be passed a hashref of this form:
706 name => default relationship name,
707 type => the relationship type eg: C<has_many>,
708 local_class => name of the DBIC class we are building,
709 local_moniker => moniker of the DBIC class we are building,
710 local_columns => columns in this table in the relationship,
711 remote_class => name of the DBIC class we are related to,
712 remote_moniker => moniker of the DBIC class we are related to,
713 remote_columns => columns in the other table in the relationship,
714 # for type => "many_to_many" only:
715 link_class => name of the DBIC class for the link table
716 link_moniker => moniker of the DBIC class for the link table
717 link_rel_name => name of the relationship to the link table
720 In addition it is passed a coderef that can be called with a hashref map.
722 DBICSL will try to use the value returned as the relationship name.
724 =head2 inflect_plural
726 Just like L</moniker_map> above (can be hash/code-ref, falls back to default
727 if hash key does not exist or coderef returns false), but acts as a map
728 for pluralizing relationship names. The default behavior is to utilize
729 L<Lingua::EN::Inflect::Phrase/to_PL>.
731 =head2 inflect_singular
733 As L</inflect_plural> above, but for singularizing relationship names.
734 Default behavior is to utilize L<Lingua::EN::Inflect::Phrase/to_S>.
736 =head2 schema_base_class
738 Base class for your schema classes. Defaults to 'DBIx::Class::Schema'.
740 =head2 schema_components
742 List of components to load into the Schema class.
744 =head2 result_base_class
746 Base class for your table classes (aka result classes). Defaults to
749 =head2 additional_base_classes
751 List of additional base classes all of your table classes will use.
753 =head2 left_base_classes
755 List of additional base classes all of your table classes will use
756 that need to be leftmost.
758 =head2 additional_classes
760 List of additional classes which all of your table classes will use.
764 List of additional components to be loaded into all of your Result
765 classes. A good example would be
766 L<InflateColumn::DateTime|DBIx::Class::InflateColumn::DateTime>
768 =head2 result_components_map
770 A hashref of moniker keys and component values. Unlike L</components>, which
771 loads the given components into every Result class, this option allows you to
772 load certain components for specified Result classes. For example:
774 result_components_map => {
775 StationVisited => '+YourApp::Schema::Component::StationVisited',
777 '+YourApp::Schema::Component::RouteChange',
778 'InflateColumn::DateTime',
782 You may use this in conjunction with L</components>.
786 List of L<Moose> roles to be applied to all of your Result classes.
788 =head2 result_roles_map
790 A hashref of moniker keys and role values. Unlike L</result_roles>, which
791 applies the given roles to every Result class, this option allows you to apply
792 certain roles for specified Result classes. For example:
794 result_roles_map => {
796 'YourApp::Role::Building',
797 'YourApp::Role::Destination',
799 RouteChange => 'YourApp::Role::TripEvent',
802 You may use this in conjunction with L</result_roles>.
804 =head2 use_namespaces
806 This is now the default, to go back to L<DBIx::Class::Schema/load_classes> pass
809 Generate result class names suitable for
810 L<DBIx::Class::Schema/load_namespaces> and call that instead of
811 L<DBIx::Class::Schema/load_classes>. When using this option you can also
812 specify any of the options for C<load_namespaces> (i.e. C<result_namespace>,
813 C<resultset_namespace>, C<default_resultset_class>), and they will be added
814 to the call (and the generated result class names adjusted appropriately).
816 =head2 dump_directory
818 The value of this option is a perl libdir pathname. Within
819 that directory this module will create a baseline manual
820 L<DBIx::Class::Schema> module set, based on what it creates at runtime.
822 The created schema class will have the same classname as the one on
823 which you are setting this option (and the ResultSource classes will be
824 based on this name as well).
826 Normally you wouldn't hard-code this setting in your schema class, as it
827 is meant for one-time manual usage.
829 See L<DBIx::Class::Schema::Loader/dump_to_dir> for examples of the
830 recommended way to access this functionality.
832 =head2 dump_overwrite
834 Deprecated. See L</really_erase_my_files> below, which does *not* mean
835 the same thing as the old C<dump_overwrite> setting from previous releases.
837 =head2 really_erase_my_files
839 Default false. If true, Loader will unconditionally delete any existing
840 files before creating the new ones from scratch when dumping a schema to disk.
842 The default behavior is instead to only replace the top portion of the
843 file, up to and including the final stanza which contains
844 C<# DO NOT MODIFY THE FIRST PART OF THIS FILE>
845 leaving any customizations you placed after that as they were.
847 When C<really_erase_my_files> is not set, if the output file already exists,
848 but the aforementioned final stanza is not found, or the checksum
849 contained there does not match the generated contents, Loader will
850 croak and not touch the file.
852 You should really be using version control on your schema classes (and all
853 of the rest of your code for that matter). Don't blame me if a bug in this
854 code wipes something out when it shouldn't have, you've been warned.
856 =head2 overwrite_modifications
858 Default false. If false, when updating existing files, Loader will
859 refuse to modify any Loader-generated code that has been modified
860 since its last run (as determined by the checksum Loader put in its
863 If true, Loader will discard any manual modifications that have been
864 made to Loader-generated code.
866 Again, you should be using version control on your schema classes. Be
867 careful with this option.
871 Omit the package version from the signature comment.
873 =head2 omit_timestamp
875 Omit the creation timestamp from the signature comment.
877 =head2 custom_column_info
879 Hook for adding extra attributes to the
880 L<column_info|DBIx::Class::ResultSource/column_info> for a column.
882 Must be a coderef that returns a hashref with the extra attributes.
884 Receives the L<table object|DBIx::Class::Schema::Loader::Table> (which
885 stringifies to the unqualified table name), column name and column_info.
889 custom_column_info => sub {
890 my ($table, $column_name, $column_info) = @_;
892 if ($column_name eq 'dog' && $column_info->{default_value} eq 'snoopy') {
893 return { is_snoopy => 1 };
897 This attribute can also be used to set C<inflate_datetime> on a non-datetime
898 column so it also receives the L</datetime_timezone> and/or L</datetime_locale>.
900 =head2 datetime_timezone
902 Sets the timezone attribute for L<DBIx::Class::InflateColumn::DateTime> for all
903 columns with the DATE/DATETIME/TIMESTAMP data_types.
905 =head2 datetime_locale
907 Sets the locale attribute for L<DBIx::Class::InflateColumn::DateTime> for all
908 columns with the DATE/DATETIME/TIMESTAMP data_types.
910 =head2 datetime_undef_if_invalid
912 Pass a C<0> for this option when using MySQL if you B<DON'T> want C<<
913 datetime_undef_if_invalid => 1 >> in your column info for DATE, DATETIME and
916 The default is recommended to deal with data such as C<00/00/00> which
917 sometimes ends up in such columns in MySQL.
921 File in Perl format, which should return a HASH reference, from which to read
926 Normally database names are lowercased and split by underscore, use this option
927 if you have CamelCase database names.
929 Drivers for case sensitive databases like Sybase ASE or MSSQL with a
930 case-sensitive collation will turn this option on unconditionally.
932 B<NOTE:> L</naming> = C<v8> is highly recommended with this option as the
933 semantics of this mode are much improved for CamelCase database names.
935 L</naming> = C<v7> or greater is required with this option.
937 =head2 qualify_objects
939 Set to true to prepend the L</db_schema> to table names for C<<
940 __PACKAGE__->table >> calls, and to some other things like Oracle sequences.
942 This attribute is automatically set to true for multi db_schema configurations,
943 unless explicitly set to false by the user.
947 Creates Schema and Result classes that use L<Moose>, L<MooseX::NonMoose> and
948 L<MooseX::MarkAsMethods> (or L<namespace::autoclean>, see below). The default
949 content after the md5 sum also makes the classes immutable.
951 It is safe to upgrade your existing Schema to this option.
953 =head2 only_autoclean
955 By default, we use L<MooseX::MarkAsMethods> to remove imported functions from
956 your generated classes. It uses L<namespace::autoclean> to do this, after
957 telling your object's metaclass that any operator L<overload>s in your class
958 are methods, which will cause namespace::autoclean to spare them from removal.
960 This prevents the "Hey, where'd my overloads go?!" effect.
962 If you don't care about operator overloads, enabling this option falls back to
963 just using L<namespace::autoclean> itself.
965 If none of the above made any sense, or you don't have some pressing need to
966 only use L<namespace::autoclean>, leaving this set to the default is
969 =head2 col_collision_map
971 This option controls how accessors for column names which collide with perl
972 methods are named. See L</COLUMN ACCESSOR COLLISIONS> for more information.
974 This option takes either a single L<sprintf|perlfunc/sprintf> format or a hashref of
975 strings which are compiled to regular expressions that map to
976 L<sprintf|perlfunc/sprintf> formats.
980 col_collision_map => 'column_%s'
982 col_collision_map => { '(.*)' => 'column_%s' }
984 col_collision_map => { '(foo).*(bar)' => 'column_%s_%s' }
986 =head2 rel_collision_map
988 Works just like L</col_collision_map>, but for relationship names/accessors
989 rather than column names/accessors.
991 The default is to just append C<_rel> to the relationship name, see
992 L</RELATIONSHIP NAME COLLISIONS>.
994 =head2 uniq_to_primary
996 Automatically promotes the largest unique constraints with non-nullable columns
997 on tables to primary keys, assuming there is only one largest unique
1000 =head2 allow_extra_m2m_cols
1002 Generate C<many_to_many> relationship bridges even if the link table has
1003 extra columns other than the foreign keys. The primary key must still
1004 equal the union of the foreign keys.
1007 =head2 filter_generated_code
1009 An optional hook that lets you filter the generated text for various classes
1010 through a function that change it in any way that you want. The function will
1011 receive the type of file, C<schema> or C<result>, class and code; and returns
1012 the new code to use instead. For instance you could add custom comments, or do
1013 anything else that you want.
1015 The option can also be set to a string, which is then used as a filter program,
1018 If this exists but fails to return text matching C</\bpackage\b/>, no file will
1021 filter_generated_code => sub {
1022 my ($type, $class, $text) = @_;
1027 You can also use this option to set L<perltidy markers|perltidy/Skipping
1028 Selected Sections of Code> in your generated classes. This will leave
1029 the generated code in the default format, but will allow you to tidy
1030 your classes at any point in future, without worrying about changing the
1031 portions of the file which are checksummed, since C<perltidy> will just
1032 ignore all text between the markers.
1034 filter_generated_code => sub {
1035 return "#<<<\n$_[2]\n#>>>";
1040 None of these methods are intended for direct invocation by regular
1041 users of L<DBIx::Class::Schema::Loader>. Some are proxied via
1042 L<DBIx::Class::Schema::Loader>.
1046 # ensure that a piece of object data is a valid arrayref, creating
1047 # an empty one or encapsulating whatever's there.
1048 sub _ensure_arrayref {
1053 $self->{$_} = [ $self->{$_} ]
1054 unless ref $self->{$_} eq 'ARRAY';
1060 Constructor for L<DBIx::Class::Schema::Loader::Base>, used internally
1061 by L<DBIx::Class::Schema::Loader>.
1066 my ( $class, %args ) = @_;
1068 if (exists $args{column_accessor_map}) {
1069 $args{col_accessor_map} = delete $args{column_accessor_map};
1072 my $self = { %args };
1074 # don't lose undef options
1075 for (values %$self) {
1076 $_ = 0 unless defined $_;
1079 bless $self => $class;
1081 if (my $config_file = $self->config_file) {
1082 my $config_opts = do $config_file;
1084 croak "Error reading config from $config_file: $@" if $@;
1086 croak "Config file $config_file must be a hashref" unless ref($config_opts) eq 'HASH';
1088 while (my ($k, $v) = each %$config_opts) {
1089 $self->{$k} = $v unless exists $self->{$k};
1093 if (defined $self->{result_component_map}) {
1094 if (defined $self->result_components_map) {
1095 croak "Specify only one of result_components_map or result_component_map";
1097 $self->result_components_map($self->{result_component_map})
1100 if (defined $self->{result_role_map}) {
1101 if (defined $self->result_roles_map) {
1102 croak "Specify only one of result_roles_map or result_role_map";
1104 $self->result_roles_map($self->{result_role_map})
1107 croak "the result_roles and result_roles_map options may only be used in conjunction with use_moose=1"
1108 if ((not defined $self->use_moose) || (not $self->use_moose))
1109 && ((defined $self->result_roles) || (defined $self->result_roles_map));
1111 $self->_ensure_arrayref(qw/schema_components
1113 additional_base_classes
1119 $self->_validate_class_args;
1121 croak "result_components_map must be a hash"
1122 if defined $self->result_components_map
1123 && ref $self->result_components_map ne 'HASH';
1125 if ($self->result_components_map) {
1126 my %rc_map = %{ $self->result_components_map };
1127 foreach my $moniker (keys %rc_map) {
1128 $rc_map{$moniker} = [ $rc_map{$moniker} ] unless ref $rc_map{$moniker};
1130 $self->result_components_map(\%rc_map);
1133 $self->result_components_map({});
1135 $self->_validate_result_components_map;
1137 croak "result_roles_map must be a hash"
1138 if defined $self->result_roles_map
1139 && ref $self->result_roles_map ne 'HASH';
1141 if ($self->result_roles_map) {
1142 my %rr_map = %{ $self->result_roles_map };
1143 foreach my $moniker (keys %rr_map) {
1144 $rr_map{$moniker} = [ $rr_map{$moniker} ] unless ref $rr_map{$moniker};
1146 $self->result_roles_map(\%rr_map);
1148 $self->result_roles_map({});
1150 $self->_validate_result_roles_map;
1152 if ($self->use_moose) {
1153 if (not DBIx::Class::Schema::Loader::Optional::Dependencies->req_ok_for('use_moose')) {
1154 die sprintf "You must install the following CPAN modules to enable the use_moose option: %s.\n",
1155 DBIx::Class::Schema::Loader::Optional::Dependencies->req_missing_for('use_moose');
1159 $self->{_tables} = {};
1160 $self->{monikers} = {};
1161 $self->{moniker_to_table} = {};
1162 $self->{class_to_table} = {};
1163 $self->{classes} = {};
1164 $self->{_upgrading_classes} = {};
1165 $self->{generated_classes} = [];
1167 $self->{schema_class} ||= ( ref $self->{schema} || $self->{schema} );
1168 $self->{schema} ||= $self->{schema_class};
1169 $self->{table_comments_table} ||= 'table_comments';
1170 $self->{column_comments_table} ||= 'column_comments';
1172 croak "dump_overwrite is deprecated. Please read the"
1173 . " DBIx::Class::Schema::Loader::Base documentation"
1174 if $self->{dump_overwrite};
1176 $self->{dynamic} = ! $self->{dump_directory};
1178 croak "dry_run can only be used with static schema generation"
1179 if $self->dynamic and $self->dry_run;
1181 $self->{temp_directory} ||= File::Temp::tempdir( 'dbicXXXX',
1186 $self->{dump_directory} ||= $self->{temp_directory};
1188 $self->real_dump_directory($self->{dump_directory});
1190 $self->version_to_dump($DBIx::Class::Schema::Loader::VERSION);
1191 $self->schema_version_to_dump($DBIx::Class::Schema::Loader::VERSION);
1193 if (not defined $self->naming) {
1194 $self->naming_set(0);
1197 $self->naming_set(1);
1200 if ((not ref $self->naming) && defined $self->naming) {
1201 my $naming_ver = $self->naming;
1203 relationships => $naming_ver,
1204 monikers => $naming_ver,
1205 column_accessors => $naming_ver,
1208 elsif (ref $self->naming eq 'HASH' && exists $self->naming->{ALL}) {
1209 my $val = delete $self->naming->{ALL};
1211 $self->naming->{$_} = $val
1212 foreach qw/relationships monikers column_accessors/;
1215 if ($self->naming) {
1216 foreach my $key (qw/relationships monikers column_accessors/) {
1217 $self->naming->{$key} = $CURRENT_V if ($self->naming->{$key}||'') eq 'current';
1220 $self->{naming} ||= {};
1222 if ($self->custom_column_info && ref $self->custom_column_info ne 'CODE') {
1223 croak 'custom_column_info must be a CODE ref';
1226 $self->_check_back_compat;
1228 $self->use_namespaces(1) unless defined $self->use_namespaces;
1229 $self->generate_pod(1) unless defined $self->generate_pod;
1230 $self->pod_comment_mode('auto') unless defined $self->pod_comment_mode;
1231 $self->pod_comment_spillover_length(60) unless defined $self->pod_comment_spillover_length;
1233 if (my $col_collision_map = $self->col_collision_map) {
1234 if (my $reftype = ref $col_collision_map) {
1235 if ($reftype ne 'HASH') {
1236 croak "Invalid type $reftype for option 'col_collision_map'";
1240 $self->col_collision_map({ '(.*)' => $col_collision_map });
1244 if (my $rel_collision_map = $self->rel_collision_map) {
1245 if (my $reftype = ref $rel_collision_map) {
1246 if ($reftype ne 'HASH') {
1247 croak "Invalid type $reftype for option 'rel_collision_map'";
1251 $self->rel_collision_map({ '(.*)' => $rel_collision_map });
1255 if (defined(my $rel_name_map = $self->rel_name_map)) {
1256 my $reftype = ref $rel_name_map;
1257 if ($reftype ne 'HASH' && $reftype ne 'CODE') {
1258 croak "Invalid type $reftype for option 'rel_name_map', must be HASH or CODE";
1262 if (defined(my $filter = $self->filter_generated_code)) {
1263 my $reftype = ref $filter;
1264 if ($reftype && $reftype ne 'CODE') {
1265 croak "Invalid type $reftype for option 'filter_generated_code, must be a scalar or a CODE reference";
1269 if (defined $self->db_schema) {
1270 if (ref $self->db_schema eq 'ARRAY') {
1271 if (@{ $self->db_schema } > 1 && not defined $self->{qualify_objects}) {
1272 $self->{qualify_objects} = 1;
1274 elsif (@{ $self->db_schema } == 0) {
1275 $self->{db_schema} = undef;
1278 elsif (not ref $self->db_schema) {
1279 if ($self->db_schema eq '%' && not defined $self->{qualify_objects}) {
1280 $self->{qualify_objects} = 1;
1283 $self->{db_schema} = [ $self->db_schema ];
1287 if (not $self->moniker_parts) {
1288 $self->moniker_parts(['name']);
1291 if (not ref $self->moniker_parts) {
1292 $self->moniker_parts([ $self->moniker_parts ]);
1294 if (ref $self->moniker_parts ne 'ARRAY') {
1295 croak 'moniker_parts must be an arrayref';
1297 if (none { $_ eq 'name' } @{ $self->moniker_parts }) {
1298 croak "moniker_parts option *must* contain 'name'";
1302 if (not defined $self->moniker_part_separator) {
1303 $self->moniker_part_separator('');
1305 if (not defined $self->moniker_part_map) {
1306 $self->moniker_part_map({}),
1312 sub _check_back_compat {
1315 # dynamic schemas will always be in 0.04006 mode, unless overridden
1316 if ($self->dynamic) {
1317 # just in case, though no one is likely to dump a dynamic schema
1318 $self->schema_version_to_dump('0.04006');
1320 if (not $self->naming_set) {
1321 warn <<EOF unless $ENV{SCHEMA_LOADER_BACKCOMPAT};
1323 Dynamic schema detected, will run in 0.04006 mode.
1325 Set the 'naming' attribute or the SCHEMA_LOADER_BACKCOMPAT environment variable
1326 to disable this warning.
1328 See perldoc DBIx::Class::Schema::Loader::Manual::UpgradingFromV4 for more
1333 $self->_upgrading_from('v4');
1336 if ((not defined $self->use_namespaces) && ($self->naming_set)) {
1337 $self->use_namespaces(1);
1340 $self->naming->{relationships} ||= 'v4';
1341 $self->naming->{monikers} ||= 'v4';
1343 if ($self->use_namespaces) {
1344 $self->_upgrading_from_load_classes(1);
1347 $self->use_namespaces(0);
1353 # otherwise check if we need backcompat mode for a static schema
1354 my $filename = $self->get_dump_filename($self->schema_class);
1355 return unless -e $filename;
1357 my ($old_gen, $old_md5, $old_ver, $old_ts, $old_custom) =
1358 $self->_parse_generated_file($filename);
1360 return unless $old_ver;
1362 # determine if the existing schema was dumped with use_moose => 1
1363 if (! defined $self->use_moose) {
1364 $self->{use_moose} = 1 if $old_gen =~ /^ (?!\s*\#) use \s+ Moose/xm;
1367 my $load_classes = ($old_gen =~ /^__PACKAGE__->load_classes;/m) ? 1 : 0;
1369 my $result_namespace = do { ($old_gen =~ /result_namespace => (.+)/) ? $1 : '' };
1370 my $ds = eval $result_namespace;
1372 Could not eval expression '$result_namespace' for result_namespace from
1375 $result_namespace = $ds || '';
1377 if ($load_classes && (not defined $self->use_namespaces)) {
1378 warn <<"EOF" unless $ENV{SCHEMA_LOADER_BACKCOMPAT};
1380 'load_classes;' static schema detected, turning off 'use_namespaces'.
1382 Set the 'use_namespaces' attribute or the SCHEMA_LOADER_BACKCOMPAT environment
1383 variable to disable this warning.
1385 See perldoc DBIx::Class::Schema::Loader::Manual::UpgradingFromV4 for more
1388 $self->use_namespaces(0);
1390 elsif ($load_classes && $self->use_namespaces) {
1391 $self->_upgrading_from_load_classes(1);
1393 elsif ((not $load_classes) && defined $self->use_namespaces && ! $self->use_namespaces) {
1394 $self->_downgrading_to_load_classes(
1395 $result_namespace || 'Result'
1398 elsif ((not defined $self->use_namespaces) || $self->use_namespaces) {
1399 if (not $self->result_namespace) {
1400 $self->result_namespace($result_namespace || 'Result');
1402 elsif ($result_namespace ne $self->result_namespace) {
1403 $self->_rewriting_result_namespace(
1404 $result_namespace || 'Result'
1409 # XXX when we go past .0 this will need fixing
1410 my ($v) = $old_ver =~ /([1-9])/;
1413 return if ($v eq $CURRENT_V || $old_ver =~ /^0\.\d\d999/);
1415 if (not %{ $self->naming }) {
1416 warn <<"EOF" unless $ENV{SCHEMA_LOADER_BACKCOMPAT};
1418 Version $old_ver static schema detected, turning on backcompat mode.
1420 Set the 'naming' attribute or the SCHEMA_LOADER_BACKCOMPAT environment variable
1421 to disable this warning.
1423 See: 'naming' in perldoc DBIx::Class::Schema::Loader::Base .
1425 See perldoc DBIx::Class::Schema::Loader::Manual::UpgradingFromV4 if upgrading
1426 from version 0.04006.
1429 $self->naming->{relationships} ||= $v;
1430 $self->naming->{monikers} ||= $v;
1431 $self->naming->{column_accessors} ||= $v;
1433 $self->schema_version_to_dump($old_ver);
1436 $self->_upgrading_from($v);
1440 sub _validate_class_args {
1443 foreach my $k (@CLASS_ARGS) {
1444 next unless $self->$k;
1446 my @classes = ref $self->$k eq 'ARRAY' ? @{ $self->$k } : $self->$k;
1447 $self->_validate_classes($k, \@classes);
1451 sub _validate_result_components_map {
1454 foreach my $classes (values %{ $self->result_components_map }) {
1455 $self->_validate_classes('result_components_map', $classes);
1459 sub _validate_result_roles_map {
1462 foreach my $classes (values %{ $self->result_roles_map }) {
1463 $self->_validate_classes('result_roles_map', $classes);
1467 sub _validate_classes {
1470 my $classes = shift;
1472 # make a copy to not destroy original
1473 my @classes = @$classes;
1475 foreach my $c (@classes) {
1476 # components default to being under the DBIx::Class namespace unless they
1477 # are preceded with a '+'
1478 if ( $key =~ m/component/ && $c !~ s/^\+// ) {
1479 $c = 'DBIx::Class::' . $c;
1482 # 1 == installed, 0 == not installed, undef == invalid classname
1483 my $installed = Class::Inspector->installed($c);
1484 if ( defined($installed) ) {
1485 if ( $installed == 0 ) {
1486 croak qq/$c, as specified in the loader option "$key", is not installed/;
1489 croak qq/$c, as specified in the loader option "$key", is an invalid class name/;
1495 sub _find_file_in_inc {
1496 my ($self, $file) = @_;
1498 foreach my $prefix (@INC) {
1499 my $fullpath = File::Spec->catfile($prefix, $file);
1500 # abs_path pure-perl fallback warns for non-existent files
1501 local $SIG{__WARN__} = sigwarn_silencer(qr/^stat\(.*\Q$file\E\)/);
1502 return $fullpath if -f $fullpath
1503 # abs_path throws on Windows for nonexistent files
1504 and (try { Cwd::abs_path($fullpath) }) ne
1505 ((try { Cwd::abs_path(File::Spec->catfile($self->dump_directory, $file)) }) || '');
1511 sub _find_class_in_inc {
1512 my ($self, $class) = @_;
1514 return $self->_find_file_in_inc(class_path($class));
1520 return $self->_upgrading_from
1521 || $self->_upgrading_from_load_classes
1522 || $self->_downgrading_to_load_classes
1523 || $self->_rewriting_result_namespace
1527 sub _rewrite_old_classnames {
1528 my ($self, $code) = @_;
1530 return $code unless $self->_rewriting;
1532 my %old_classes = reverse %{ $self->_upgrading_classes };
1534 my $re = join '|', keys %old_classes;
1535 $re = qr/\b($re)\b/;
1537 $code =~ s/$re/$old_classes{$1} || $1/eg;
1542 sub _load_external {
1543 my ($self, $class) = @_;
1545 return if $self->{skip_load_external};
1547 # so that we don't load our own classes, under any circumstances
1548 local *INC = [ grep $_ ne $self->dump_directory, @INC ];
1550 my $real_inc_path = $self->_find_class_in_inc($class);
1552 my $old_class = $self->_upgrading_classes->{$class}
1553 if $self->_rewriting;
1555 my $old_real_inc_path = $self->_find_class_in_inc($old_class)
1556 if $old_class && $old_class ne $class;
1558 return unless $real_inc_path || $old_real_inc_path;
1560 if ($real_inc_path) {
1561 # If we make it to here, we loaded an external definition
1562 warn qq/# Loaded external class definition for '$class'\n/
1565 my $code = $self->_rewrite_old_classnames(slurp_file $real_inc_path);
1567 if (my ($gen, $real_md5, $ver, $ts, $custom) = try {
1568 local $self->{overwrite_modifications} = 0;
1569 $self->_parse_generated_code($real_inc_path, $code);
1571 # Ignore unmodified generated code.
1572 $code = $custom eq $self->_default_custom_content ? '' : $custom;
1576 if ($self->dynamic) { # load the class too
1577 eval_package_without_redefine_warnings($class, $code);
1580 $self->_ext_stmt($class,
1581 qq|# These lines were loaded from '$real_inc_path' found in \@INC.\n|
1582 .qq|# They are now part of the custom portion of this file\n|
1583 .qq|# for you to hand-edit. If you do not either delete\n|
1584 .qq|# this section or remove that file from \@INC, this section\n|
1585 .qq|# will be repeated redundantly when you re-create this\n|
1586 .qq|# file again via Loader! See skip_load_external to disable\n|
1587 .qq|# this feature.\n|
1590 $self->_ext_stmt($class, $code);
1591 $self->_ext_stmt($class,
1592 qq|# End of lines loaded from '$real_inc_path'|
1597 if ($old_real_inc_path) {
1598 my $code = slurp_file $old_real_inc_path;
1600 $self->_ext_stmt($class, <<"EOF");
1602 # These lines were loaded from '$old_real_inc_path',
1603 # based on the Result class name that would have been created by an older
1604 # version of the Loader. For a static schema, this happens only once during
1605 # upgrade. See skip_load_external to disable this feature.
1608 $code = $self->_rewrite_old_classnames($code);
1610 if ($self->dynamic) {
1613 Detected external content in '$old_real_inc_path', a class name that would have
1614 been used by an older version of the Loader.
1616 * PLEASE RENAME THIS CLASS: from '$old_class' to '$class', as that is the
1617 new name of the Result.
1619 eval_package_without_redefine_warnings($class, $code);
1623 $self->_ext_stmt($class, $code);
1624 $self->_ext_stmt($class,
1625 qq|# End of lines loaded from '$old_real_inc_path'|
1632 Does the actual schema-construction work.
1639 $self->_load_tables($self->_tables_list);
1646 Rescan the database for changes. Returns a list of the newly added table
1649 The schema argument should be the schema class or object to be affected. It
1650 should probably be derived from the original schema_class used during L</load>.
1655 my ($self, $schema) = @_;
1657 $self->{schema} = $schema;
1658 $self->_relbuilder->{schema} = $schema;
1661 my @current = $self->_tables_list;
1663 foreach my $table (@current) {
1664 if(!exists $self->_tables->{$table->sql_name}) {
1665 push(@created, $table);
1670 @current{map $_->sql_name, @current} = ();
1671 foreach my $table (values %{ $self->_tables }) {
1672 if (not exists $current{$table->sql_name}) {
1673 $self->_remove_table($table);
1677 delete @$self{qw/_dump_storage _relations_started _uniqs_started/};
1679 my $loaded = $self->_load_tables(@current);
1681 foreach my $table (@created) {
1682 $self->monikers->{$table->sql_name} = $self->_table2moniker($table);
1685 return map { $self->monikers->{$_->sql_name} } @created;
1691 return if $self->{skip_relationships};
1693 return $self->{relbuilder} ||= do {
1694 my $relbuilder_suff =
1701 ->{$self->naming->{relationships}||$CURRENT_V} || '';
1703 my $relbuilder_class = 'DBIx::Class::Schema::Loader::RelBuilder'.$relbuilder_suff;
1704 $self->ensure_class_loaded($relbuilder_class);
1705 $relbuilder_class->new($self);
1710 my ($self, @tables) = @_;
1712 # Save the new tables to the tables list and compute monikers
1714 $self->_tables->{$_->sql_name} = $_;
1715 $self->monikers->{$_->sql_name} = $self->_table2moniker($_);
1718 # check for moniker clashes
1719 my $inverse_moniker_idx;
1720 foreach my $imtable (values %{ $self->_tables }) {
1721 push @{ $inverse_moniker_idx->{$self->monikers->{$imtable->sql_name}} }, $imtable;
1725 foreach my $moniker (keys %$inverse_moniker_idx) {
1726 my $imtables = $inverse_moniker_idx->{$moniker};
1727 if (@$imtables > 1) {
1728 my $different_databases =
1729 $imtables->[0]->can('database') && (uniq map $_->database||'', @$imtables) > 1;
1731 my $different_schemas =
1732 (uniq map $_->schema||'', @$imtables) > 1;
1734 if ($different_databases || $different_schemas) {
1735 my ($use_schema, $use_database) = (1, 0);
1737 if ($different_databases) {
1740 # If any monikers are in the same database, we have to distinguish by
1741 # both schema and database.
1743 $db_counts{$_}++ for map $_->database, @$imtables;
1744 $use_schema = any { $_ > 1 } values %db_counts;
1747 foreach my $tbl (@$imtables) { delete $self->monikers->{$tbl->sql_name}; }
1749 my $moniker_parts = [ @{ $self->moniker_parts } ];
1751 my $have_schema = any { $_ eq 'schema' } @{ $self->moniker_parts };
1752 my $have_database = any { $_ eq 'database' } @{ $self->moniker_parts };
1754 unshift @$moniker_parts, 'schema' if $use_schema && !$have_schema;
1755 unshift @$moniker_parts, 'database' if $use_database && !$have_database;
1757 local $self->{moniker_parts} = $moniker_parts;
1761 foreach my $tbl (@$imtables) { $new_monikers{$tbl->sql_name} = $self->_table2moniker($tbl); }
1762 foreach my $name (map $_->sql_name, @$imtables) { $self->monikers->{$name} = $new_monikers{$name}; }
1764 # check if there are still clashes
1767 while (my ($t, $m) = each %new_monikers) {
1768 push @{ $by_moniker{$m} }, $t;
1771 foreach my $m (grep @{ $by_moniker{$_} } > 1, keys %by_moniker) {
1772 push @clashes, sprintf ("tried disambiguating by moniker_parts, but tables %s still reduced to the same source moniker '%s'",
1773 join (', ', @{ $by_moniker{$m} }),
1779 push @clashes, sprintf ("tables %s reduced to the same source moniker '%s'",
1780 join (', ', map $_->sql_name, @$imtables),
1788 die 'Unable to load schema - chosen moniker/class naming style results in moniker clashes. '
1789 . 'Change the naming style, or supply an explicit moniker_map: '
1790 . join ('; ', @clashes)
1795 foreach my $tbl (@tables) { $self->_make_src_class($tbl); }
1796 foreach my $tbl (@tables) { $self->_setup_src_meta($tbl); }
1798 if(!$self->skip_relationships) {
1799 # The relationship loader needs a working schema
1800 local $self->{quiet} = 1;
1801 local $self->{dump_directory} = $self->{temp_directory};
1802 local $self->{generated_classes} = [];
1803 local $self->{dry_run} = 0;
1804 $self->_reload_classes(\@tables);
1805 $self->_load_relationships(\@tables);
1807 # Remove that temp dir from INC so it doesn't get reloaded
1808 @INC = grep $_ ne $self->dump_directory, @INC;
1811 foreach my $tbl (@tables) { $self->_load_roles($tbl); }
1812 foreach my $tbl (map { $self->classes->{$_->sql_name} } @tables) { $self->_load_external($tbl); }
1814 # Reload without unloading first to preserve any symbols from external
1816 $self->_reload_classes(\@tables, { unload => 0 });
1818 # Drop temporary cache
1819 delete $self->{_cache};
1824 sub _reload_classes {
1825 my ($self, $tables, $opts) = @_;
1827 my @tables = @$tables;
1829 my $unload = $opts->{unload};
1830 $unload = 1 unless defined $unload;
1832 # so that we don't repeat custom sections
1833 @INC = grep $_ ne $self->dump_directory, @INC;
1835 $self->_dump_to_dir(map { $self->classes->{$_->sql_name} } @tables);
1837 unshift @INC, $self->dump_directory;
1839 return if $self->dry_run;
1842 my %have_source = map { $_ => $self->schema->source($_) }
1843 $self->schema->sources;
1845 for my $table (@tables) {
1846 my $moniker = $self->monikers->{$table->sql_name};
1847 my $class = $self->classes->{$table->sql_name};
1850 no warnings 'redefine';
1851 local *Class::C3::reinitialize = sub {}; # to speed things up, reinitialized below
1854 if (my $mc = $self->_moose_metaclass($class)) {
1857 Class::Unload->unload($class) if $unload;
1858 my ($source, $resultset_class);
1860 ($source = $have_source{$moniker})
1861 && ($resultset_class = $source->resultset_class)
1862 && ($resultset_class ne 'DBIx::Class::ResultSet')
1864 my $has_file = Class::Inspector->loaded_filename($resultset_class);
1865 if (my $mc = $self->_moose_metaclass($resultset_class)) {
1868 Class::Unload->unload($resultset_class) if $unload;
1869 $self->_reload_class($resultset_class) if $has_file;
1871 $self->_reload_class($class);
1873 push @to_register, [$moniker, $class];
1876 Class::C3->reinitialize;
1877 for (@to_register) {
1878 $self->schema->register_class(@$_);
1882 sub _moose_metaclass {
1883 return undef unless $INC{'Class/MOP.pm'}; # if CMOP is not loaded the class could not have loaded in the 1st place
1887 my $mc = try { Class::MOP::class_of($class) }
1890 return $mc->isa('Moose::Meta::Class') ? $mc : undef;
1893 # We use this instead of ensure_class_loaded when there are package symbols we
1896 my ($self, $class) = @_;
1898 delete $INC{ +class_path($class) };
1901 eval_package_without_redefine_warnings ($class, "require $class");
1904 my $source = slurp_file $self->_get_dump_filename($class);
1905 die "Failed to reload class $class: $_.\n\nCLASS SOURCE:\n\n$source";
1909 sub _get_dump_filename {
1910 my ($self, $class) = (@_);
1912 $class =~ s{::}{/}g;
1913 return $self->dump_directory . q{/} . $class . q{.pm};
1916 =head2 get_dump_filename
1920 Returns the full path to the file for a class that the class has been or will
1921 be dumped to. This is a file in a temp dir for a dynamic schema.
1925 sub get_dump_filename {
1926 my ($self, $class) = (@_);
1928 local $self->{dump_directory} = $self->real_dump_directory;
1930 return $self->_get_dump_filename($class);
1933 sub _ensure_dump_subdirs {
1934 my ($self, $class) = (@_);
1936 return if $self->dry_run;
1938 my @name_parts = split(/::/, $class);
1939 pop @name_parts; # we don't care about the very last element,
1940 # which is a filename
1942 my $dir = $self->dump_directory;
1945 mkdir($dir) or croak "mkdir('$dir') failed: $!";
1947 last if !@name_parts;
1948 $dir = File::Spec->catdir($dir, shift @name_parts);
1953 my ($self, @classes) = @_;
1955 my $schema_class = $self->schema_class;
1956 my $schema_base_class = $self->schema_base_class || 'DBIx::Class::Schema';
1958 my $target_dir = $self->dump_directory;
1959 warn "Dumping manual schema for $schema_class to directory $target_dir ...\n"
1960 unless $self->dynamic or $self->quiet;
1964 . qq|package $schema_class;\n\n|
1965 . qq|# Created by DBIx::Class::Schema::Loader\n|
1966 . qq|# DO NOT MODIFY THE FIRST PART OF THIS FILE\n\n|;
1969 = $self->only_autoclean
1970 ? 'namespace::autoclean'
1971 : 'MooseX::MarkAsMethods autoclean => 1'
1974 if ($self->use_moose) {
1976 $schema_text.= qq|use Moose;\nuse $autoclean;\nextends '$schema_base_class';\n\n|;
1979 $schema_text .= qq|use strict;\nuse warnings;\n\nuse base '$schema_base_class';\n\n|;
1982 my @schema_components = @{ $self->schema_components || [] };
1984 if (@schema_components) {
1985 my $schema_components = dump @schema_components;
1986 $schema_components = "($schema_components)" if @schema_components == 1;
1988 $schema_text .= "__PACKAGE__->load_components${schema_components};\n\n";
1991 if ($self->use_namespaces) {
1992 $schema_text .= qq|__PACKAGE__->load_namespaces|;
1993 my $namespace_options;
1995 my @attr = qw/resultset_namespace default_resultset_class/;
1997 unshift @attr, 'result_namespace' unless (not $self->result_namespace) || $self->result_namespace eq 'Result';
1999 for my $attr (@attr) {
2001 my $code = dumper_squashed $self->$attr;
2002 $namespace_options .= qq| $attr => $code,\n|
2005 $schema_text .= qq|(\n$namespace_options)| if $namespace_options;
2006 $schema_text .= qq|;\n|;
2009 $schema_text .= qq|__PACKAGE__->load_classes;\n|;
2013 local $self->{version_to_dump} = $self->schema_version_to_dump;
2014 $self->_write_classfile($schema_class, $schema_text, 1);
2017 my $result_base_class = $self->result_base_class || 'DBIx::Class::Core';
2019 foreach my $src_class (@classes) {
2022 . qq|package $src_class;\n\n|
2023 . qq|# Created by DBIx::Class::Schema::Loader\n|
2024 . qq|# DO NOT MODIFY THE FIRST PART OF THIS FILE\n\n|;
2026 $src_text .= $self->_make_pod_heading($src_class);
2028 $src_text .= qq|use strict;\nuse warnings;\n\n|;
2030 $src_text .= $self->_base_class_pod($result_base_class)
2031 unless $result_base_class eq 'DBIx::Class::Core';
2033 if ($self->use_moose) {
2034 $src_text.= qq|use Moose;\nuse MooseX::NonMoose;\nuse $autoclean;|;
2036 # these options 'use base' which is compile time
2037 if (@{ $self->left_base_classes } || @{ $self->additional_base_classes }) {
2038 $src_text .= qq|\nBEGIN { extends '$result_base_class' }\n|;
2041 $src_text .= qq|\nextends '$result_base_class';\n|;
2045 $src_text .= qq|use base '$result_base_class';\n|;
2048 $self->_write_classfile($src_class, $src_text);
2051 # remove Result dir if downgrading from use_namespaces, and there are no
2053 if (my $result_ns = $self->_downgrading_to_load_classes
2054 || $self->_rewriting_result_namespace) {
2055 my $result_namespace = $self->_result_namespace(
2060 (my $result_dir = $result_namespace) =~ s{::}{/}g;
2061 $result_dir = $self->dump_directory . '/' . $result_dir;
2063 unless (my @files = glob "$result_dir/*") {
2068 warn "Schema dump completed.\n" unless $self->dynamic or $self->quiet;
2072 my ($self, $version, $ts) = @_;
2073 return qq|\n\n# Created by DBIx::Class::Schema::Loader|
2074 . (defined($version) ? q| v| . $version : '')
2075 . (defined($ts) ? q| @ | . $ts : '')
2076 . qq|\n# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:|;
2079 sub _write_classfile {
2080 my ($self, $class, $text, $is_schema) = @_;
2082 my $filename = $self->_get_dump_filename($class);
2083 $self->_ensure_dump_subdirs($class);
2085 if (-f $filename && $self->really_erase_my_files && !$self->dry_run) {
2086 warn "Deleting existing file '$filename' due to "
2087 . "'really_erase_my_files' setting\n" unless $self->quiet;
2091 my ($old_gen, $old_md5, $old_ver, $old_ts, $old_custom)
2092 = $self->_parse_generated_file($filename);
2094 if (! $old_gen && -f $filename) {
2095 croak "Cannot overwrite '$filename' without 'really_erase_my_files',"
2096 . " it does not appear to have been generated by Loader"
2099 my $custom_content = $old_custom || '';
2101 # Use custom content from a renamed class, the class names in it are
2103 if (my $renamed_class = $self->_upgrading_classes->{$class}) {
2104 my $old_filename = $self->_get_dump_filename($renamed_class);
2106 if (-f $old_filename) {
2107 $custom_content = ($self->_parse_generated_file ($old_filename))[4];
2109 unlink $old_filename unless $self->dry_run;
2113 $custom_content ||= $self->_default_custom_content($is_schema);
2115 # If upgrading to use_moose=1 replace default custom content with default Moose custom content.
2116 # If there is already custom content, which does not have the Moose content, add it.
2117 if ($self->use_moose) {
2119 my $non_moose_custom_content = do {
2120 local $self->{use_moose} = 0;
2121 $self->_default_custom_content;
2124 if ($custom_content eq $non_moose_custom_content) {
2125 $custom_content = $self->_default_custom_content($is_schema);
2127 elsif ($custom_content !~ /\Q@{[$self->_default_moose_custom_content($is_schema)]}\E/) {
2128 $custom_content .= $self->_default_custom_content($is_schema);
2131 elsif (defined $self->use_moose && $old_gen) {
2132 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'
2133 if $old_gen =~ /use \s+ MooseX?\b/x;
2136 $custom_content = $self->_rewrite_old_classnames($custom_content);
2139 for @{$self->{_dump_storage}->{$class} || []};
2141 if ($self->filter_generated_code) {
2142 my $filter = $self->filter_generated_code;
2144 if (ref $filter eq 'CODE') {
2146 ($is_schema ? 'schema' : 'result'),
2152 my ($fh, $temp_file) = tempfile();
2154 binmode $fh, ':encoding(UTF-8)';
2158 open my $out, qq{$filter < "$temp_file"|}
2159 or croak "Could not open pipe to $filter: $!";
2161 $text = decode('UTF-8', do { local $/; <$out> });
2163 $text =~ s/$CR?$LF/\n/g;
2167 my $exit_code = $? >> 8;
2170 or croak "Could not remove temporary file '$temp_file': $!";
2172 if ($exit_code != 0) {
2173 croak "filter '$filter' exited non-zero: $exit_code";
2176 if (not $text or not $text =~ /\bpackage\b/) {
2177 warn("$class skipped due to filter") if $self->debug;
2182 # Check and see if the dump is in fact different
2186 $compare_to = $text . $self->_sig_comment($old_ver, $old_ts);
2187 if (Digest::MD5::md5_base64(encode 'UTF-8', $compare_to) eq $old_md5) {
2188 return unless $self->_upgrading_from && $is_schema;
2192 push @{$self->generated_classes}, $class;
2194 return if $self->dry_run;
2196 $text .= $self->_sig_comment(
2197 $self->omit_version ? undef : $self->version_to_dump,
2198 $self->omit_timestamp ? undef : POSIX::strftime('%Y-%m-%d %H:%M:%S', localtime)
2201 open(my $fh, '>:raw:encoding(UTF-8)', $filename)
2202 or croak "Cannot open '$filename' for writing: $!";
2204 # Write the top half and its MD5 sum
2205 print $fh $text . Digest::MD5::md5_base64(encode 'UTF-8', $text) . "\n";
2207 # Write out anything loaded via external partial class file in @INC
2209 for @{$self->{_ext_storage}->{$class} || []};
2211 # Write out any custom content the user has added
2212 print $fh $custom_content;
2215 or croak "Error closing '$filename': $!";
2218 sub _default_moose_custom_content {
2219 my ($self, $is_schema) = @_;
2221 if (not $is_schema) {
2222 return qq|\n__PACKAGE__->meta->make_immutable;|;
2225 return qq|\n__PACKAGE__->meta->make_immutable(inline_constructor => 0);|;
2228 sub _default_custom_content {
2229 my ($self, $is_schema) = @_;
2230 my $default = qq|\n\n# You can replace this text with custom|
2231 . qq| code or comments, and it will be preserved on regeneration|;
2232 if ($self->use_moose) {
2233 $default .= $self->_default_moose_custom_content($is_schema);
2235 $default .= qq|\n1;\n|;
2239 sub _parse_generated_file {
2240 my ($self, $fn) = @_;
2242 return unless -f $fn;
2244 return $self->_parse_generated_code($fn, slurp_file $fn);
2247 sub _parse_generated_code {
2248 my ($self, $fn, $code) = @_;
2250 my ($gen, $ver, $ts, $mark_md5, $custom) = (
2255 ^\# \Q Created by DBIx::Class::Schema::Loader\E
2256 (\ v [\d.]+ )? (\ @\ [\d-]+\ [\d:]+)?\r?\n # verison/time stamp
2257 ^\# \Q DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:\E
2259 ([A-Za-z0-9/+]{22})\r?\n # checksum
2265 $ver =~ s/^ v// if $ver;
2266 $ts =~ s/^ @ // if $ts;
2268 my $real_md5 = Digest::MD5::md5_base64(encode 'UTF-8', $gen);
2269 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"
2270 if !$self->overwrite_modifications && $real_md5 ne $mark_md5;
2272 return ($gen, $real_md5, $ver, $ts, $custom);
2280 warn "$target: use $_;" if $self->debug;
2281 $self->_raw_stmt($target, "use $_;");
2289 my $blist = join(q{ }, @_);
2291 return unless $blist;
2293 warn "$target: use base qw/$blist/;" if $self->debug;
2294 $self->_raw_stmt($target, "use base qw/$blist/;");
2301 my $rlist = join(q{, }, map { qq{'$_'} } @_);
2303 return unless $rlist;
2305 warn "$target: with $rlist;" if $self->debug;
2306 $self->_raw_stmt($target, "\nwith $rlist;");
2309 sub _result_namespace {
2310 my ($self, $schema_class, $ns) = @_;
2311 my @result_namespace;
2313 $ns = $ns->[0] if ref $ns;
2315 if ($ns =~ /^\+(.*)/) {
2316 # Fully qualified namespace
2317 @result_namespace = ($1)
2320 # Relative namespace
2321 @result_namespace = ($schema_class, $ns);
2324 return wantarray ? @result_namespace : join '::', @result_namespace;
2327 # Create class with applicable bases, setup monikers, etc
2328 sub _make_src_class {
2329 my ($self, $table) = @_;
2331 my $schema = $self->schema;
2332 my $schema_class = $self->schema_class;
2334 my $table_moniker = $self->monikers->{$table->sql_name};
2335 my @result_namespace = ($schema_class);
2336 if ($self->use_namespaces) {
2337 my $result_namespace = $self->result_namespace || 'Result';
2338 @result_namespace = $self->_result_namespace(
2343 my $table_class = join(q{::}, @result_namespace, $table_moniker);
2345 if ((my $upgrading_v = $self->_upgrading_from)
2346 || $self->_rewriting) {
2347 local $self->naming->{monikers} = $upgrading_v
2350 my @result_namespace = @result_namespace;
2351 if ($self->_upgrading_from_load_classes) {
2352 @result_namespace = ($schema_class);
2354 elsif (my $ns = $self->_downgrading_to_load_classes) {
2355 @result_namespace = $self->_result_namespace(
2360 elsif ($ns = $self->_rewriting_result_namespace) {
2361 @result_namespace = $self->_result_namespace(
2367 my $old_table_moniker = do {
2368 local $self->naming->{monikers} = $upgrading_v;
2369 $self->_table2moniker($table);
2372 my $old_class = join(q{::}, @result_namespace, $old_table_moniker);
2374 $self->_upgrading_classes->{$table_class} = $old_class
2375 unless $table_class eq $old_class;
2378 $self->classes->{$table->sql_name} = $table_class;
2379 $self->moniker_to_table->{$table_moniker} = $table;
2380 $self->class_to_table->{$table_class} = $table;
2382 $self->_pod_class_list($table_class, 'ADDITIONAL CLASSES USED', @{$self->additional_classes});
2384 $self->_use ($table_class, @{$self->additional_classes});
2386 $self->_pod_class_list($table_class, 'LEFT BASE CLASSES', @{$self->left_base_classes});
2388 $self->_inject($table_class, @{$self->left_base_classes});
2390 my @components = @{ $self->components || [] };
2392 push @components, @{ $self->result_components_map->{$table_moniker} }
2393 if exists $self->result_components_map->{$table_moniker};
2395 my @fq_components = @components;
2396 foreach my $component (@fq_components) {
2397 if ($component !~ s/^\+//) {
2398 $component = "DBIx::Class::$component";
2402 $self->_pod_class_list($table_class, 'COMPONENTS LOADED', @fq_components);
2404 $self->_dbic_stmt($table_class, 'load_components', @components) if @components;
2406 $self->_pod_class_list($table_class, 'ADDITIONAL BASE CLASSES', @{$self->additional_base_classes});
2408 $self->_inject($table_class, @{$self->additional_base_classes});
2411 sub _is_result_class_method {
2412 my ($self, $name, $table) = @_;
2414 my $table_moniker = $table ? $self->monikers->{$table->sql_name} : '';
2416 $self->_result_class_methods({})
2417 if not defined $self->_result_class_methods;
2419 if (not exists $self->_result_class_methods->{$table_moniker}) {
2420 my (@methods, %methods);
2421 my $base = $self->result_base_class || 'DBIx::Class::Core';
2423 my @components = @{ $self->components || [] };
2425 push @components, @{ $self->result_components_map->{$table_moniker} }
2426 if exists $self->result_components_map->{$table_moniker};
2428 for my $c (@components) {
2429 $c = $c =~ /^\+/ ? substr($c,1) : "DBIx::Class::$c";
2432 my @roles = @{ $self->result_roles || [] };
2434 push @roles, @{ $self->result_roles_map->{$table_moniker} }
2435 if exists $self->result_roles_map->{$table_moniker};
2438 $base, @components, @roles,
2439 ($self->use_moose ? 'Moose::Object' : ()),
2441 $self->ensure_class_loaded($class);
2443 push @methods, @{ Class::Inspector->methods($class) || [] };
2446 push @methods, @{ Class::Inspector->methods('UNIVERSAL') };
2448 @methods{@methods} = ();
2450 $self->_result_class_methods->{$table_moniker} = \%methods;
2452 my $result_methods = $self->_result_class_methods->{$table_moniker};
2454 return exists $result_methods->{$name};
2457 sub _resolve_col_accessor_collisions {
2458 my ($self, $table, $col_info) = @_;
2460 while (my ($col, $info) = each %$col_info) {
2461 my $accessor = $info->{accessor} || $col;
2463 next if $accessor eq 'id'; # special case (very common column)
2465 if ($self->_is_result_class_method($accessor, $table)) {
2468 if (my $map = $self->col_collision_map) {
2469 for my $re (keys %$map) {
2470 if (my @matches = $col =~ /$re/) {
2471 $info->{accessor} = sprintf $map->{$re}, @matches;
2479 Column '$col' in table '$table' collides with an inherited method.
2480 See "COLUMN ACCESSOR COLLISIONS" in perldoc DBIx::Class::Schema::Loader::Base .
2482 $info->{accessor} = undef;
2488 # use the same logic to run moniker_map, col_accessor_map
2490 my ( $self, $map, $default_code, $ident, @extra ) = @_;
2492 my $default_ident = $default_code->( $ident, @extra );
2494 if( $map && ref $map eq 'HASH' ) {
2495 if (my @parts = try{ @{ $ident } }) {
2496 my $part_map = $map;
2498 my $part = shift @parts;
2499 last unless exists $part_map->{ $part };
2500 if ( !ref $part_map->{ $part } && !@parts ) {
2501 $new_ident = $part_map->{ $part };
2504 elsif ( ref $part_map->{ $part } eq 'HASH' ) {
2505 $part_map = $part_map->{ $part };
2509 if( !$new_ident && !ref $map->{ $ident } ) {
2510 $new_ident = $map->{ $ident };
2513 elsif( $map && ref $map eq 'CODE' ) {
2516 croak "reentered map must be a hashref"
2517 unless 'HASH' eq ref($cb_map);
2518 return $self->_run_user_map($cb_map, $default_code, $ident, @extra);
2520 $new_ident = $map->( $ident, $default_ident, @extra, $cb );
2523 $new_ident ||= $default_ident;
2528 sub _default_column_accessor_name {
2529 my ( $self, $column_name ) = @_;
2531 my $preserve = ($self->naming->{column_accessors}||'') eq 'preserve';
2533 my $v = $self->_get_naming_v('column_accessors');
2535 my $accessor_name = $preserve ?
2536 $self->_to_identifier('column_accessors', $column_name) # assume CamelCase
2538 $self->_to_identifier('column_accessors', $column_name, '_');
2540 $accessor_name =~ s/\W+/_/g; # only if naming < v8, otherwise to_identifier
2544 return $accessor_name;
2546 elsif ($v < 7 || (not $self->preserve_case)) {
2547 # older naming just lc'd the col accessor and that's all.
2548 return lc $accessor_name;
2551 return join '_', map lc, split_name $column_name, $v;
2554 sub _make_column_accessor_name {
2555 my ($self, $column_name, $column_context_info ) = @_;
2557 my $accessor = $self->_run_user_map(
2558 $self->col_accessor_map,
2559 sub { $self->_default_column_accessor_name( shift ) },
2561 $column_context_info,
2567 sub _table_is_view {
2568 #my ($self, $table) = @_;
2572 # Set up metadata (cols, pks, etc)
2573 sub _setup_src_meta {
2574 my ($self, $table) = @_;
2576 my $schema = $self->schema;
2577 my $schema_class = $self->schema_class;
2579 my $table_class = $self->classes->{$table->sql_name};
2580 my $table_moniker = $self->monikers->{$table->sql_name};
2582 $self->_dbic_stmt($table_class, 'table_class', 'DBIx::Class::ResultSource::View')
2583 if $self->_table_is_view($table);
2585 $self->_dbic_stmt($table_class, 'table', $table->dbic_name);
2587 my $cols = $self->_table_columns($table);
2588 my $col_info = $self->__columns_info_for($table);
2590 ### generate all the column accessor names
2591 while (my ($col, $info) = each %$col_info) {
2592 # hashref of other info that could be used by
2593 # user-defined accessor map functions
2595 table_class => $table_class,
2596 table_moniker => $table_moniker,
2597 table_name => $table, # bugwards compatibility, RT#84050
2599 full_table_name => $table->dbic_name,
2600 schema_class => $schema_class,
2601 column_info => $info,
2604 $info->{accessor} = $self->_make_column_accessor_name( $col, $context );
2607 $self->_resolve_col_accessor_collisions($table, $col_info);
2609 # prune any redundant accessor names
2610 while (my ($col, $info) = each %$col_info) {
2611 no warnings 'uninitialized';
2612 delete $info->{accessor} if $info->{accessor} eq $col;
2615 my $fks = $self->_table_fk_info($table);
2617 foreach my $fkdef (@$fks) {
2618 for my $col (@{ $fkdef->{local_columns} }) {
2619 $col_info->{$col}{is_foreign_key} = 1;
2623 my $pks = $self->_table_pk_info($table) || [];
2625 my %uniq_tag; # used to eliminate duplicate uniqs
2627 $uniq_tag{ join("\0", @$pks) }++ if @$pks; # pk is a uniq
2629 my $uniqs = $self->_table_uniq_info($table) || [];
2632 foreach my $uniq (@$uniqs) {
2633 my ($name, $cols) = @$uniq;
2634 next if $uniq_tag{ join("\0", @$cols) }++; # skip duplicates
2635 push @uniqs, [$name, $cols];
2638 my @non_nullable_uniqs = grep {
2639 all { $col_info->{$_}{is_nullable} == 0 } @{ $_->[1] }
2642 if ($self->uniq_to_primary && (not @$pks) && @non_nullable_uniqs) {
2643 my @by_colnum = sort { $b->[0] <=> $a->[0] }
2644 map [ scalar @{ $_->[1] }, $_ ], @non_nullable_uniqs;
2646 if (not (@by_colnum > 1 && $by_colnum[0][0] == $by_colnum[1][0])) {
2647 my @keys = map $_->[1], @by_colnum;
2651 # remove the uniq from list
2652 @uniqs = grep { $_->[0] ne $pk->[0] } @uniqs;
2658 foreach my $pkcol (@$pks) {
2659 $col_info->{$pkcol}{is_nullable} = 0;
2665 map { $_, ($col_info->{$_}||{}) } @$cols
2668 $self->_dbic_stmt($table_class, 'set_primary_key', @$pks)
2671 # Sort unique constraints by constraint name for repeatable results (rels
2672 # are sorted as well elsewhere.)
2673 @uniqs = sort { $a->[0] cmp $b->[0] } @uniqs;
2675 foreach my $uniq (@uniqs) {
2676 my ($name, $cols) = @$uniq;
2677 $self->_dbic_stmt($table_class,'add_unique_constraint', $name, $cols);
2681 sub __columns_info_for {
2682 my ($self, $table) = @_;
2684 my $result = $self->_columns_info_for($table);
2686 while (my ($col, $info) = each %$result) {
2687 $info = { %$info, %{ $self->_custom_column_info ($table, $col, $info) } };
2688 $info = { %$info, %{ $self->_datetime_column_info($table, $col, $info) } };
2690 $result->{$col} = $info;
2698 Returns a sorted list of loaded tables, using the original database table
2706 return values %{$self->_tables};
2710 my ($self, $naming_key) = @_;
2714 if (($self->naming->{$naming_key}||'') =~ /^v(\d+)\z/) {
2718 ($v) = $CURRENT_V =~ /^v(\d+)\z/;
2724 sub _to_identifier {
2725 my ($self, $naming_key, $name, $sep_char, $force) = @_;
2727 my $v = $self->_get_naming_v($naming_key);
2729 my $to_identifier = $self->naming->{force_ascii} ?
2730 \&String::ToIdentifier::EN::to_identifier
2731 : \&String::ToIdentifier::EN::Unicode::to_identifier;
2733 return $v >= 8 || $force ? $to_identifier->($name, $sep_char) : $name;
2736 # Make a moniker from a table
2737 sub _default_table2moniker {
2738 my ($self, $table) = @_;
2740 my $v = $self->_get_naming_v('monikers');
2742 my @moniker_parts = @{ $self->moniker_parts };
2743 my @name_parts = map $table->$_, @moniker_parts;
2745 my $name_idx = firstidx { $_ eq 'name' } @{ $self->moniker_parts };
2749 foreach my $i (0 .. $#name_parts) {
2750 my $part = $name_parts[$i];
2752 my $moniker_part = $self->_run_user_map(
2753 $self->moniker_part_map->{$moniker_parts[$i]},
2755 $part, $moniker_parts[$i],
2757 if (length $moniker_part) {
2758 push @all_parts, $moniker_part;
2762 if ($i != $name_idx || $v >= 8) {
2763 $part = $self->_to_identifier('monikers', $part, '_', 1);
2766 if ($i == $name_idx && $v == 5) {
2767 $part = Lingua::EN::Inflect::Number::to_S($part);
2770 my @part_parts = map lc, $v > 6 ?
2771 # use v8 semantics for all moniker parts except name
2772 ($i == $name_idx ? split_name $part, $v : split_name $part)
2773 : split /[\W_]+/, $part;
2775 if ($i == $name_idx && $v >= 6) {
2776 my $as_phrase = join ' ', @part_parts;
2778 my $inflected = ($self->naming->{monikers}||'') eq 'plural' ?
2779 Lingua::EN::Inflect::Phrase::to_PL($as_phrase)
2781 ($self->naming->{monikers}||'') eq 'preserve' ?
2784 Lingua::EN::Inflect::Phrase::to_S($as_phrase);
2786 @part_parts = split /\s+/, $inflected;
2789 push @all_parts, join '', map ucfirst, @part_parts;
2792 return join $self->moniker_part_separator, @all_parts;
2795 sub _table2moniker {
2796 my ( $self, $table ) = @_;
2798 $self->_run_user_map(
2800 sub { $self->_default_table2moniker( shift ) },
2805 sub _load_relationships {
2806 my ($self, $tables) = @_;
2810 foreach my $table (@$tables) {
2811 my $local_moniker = $self->monikers->{$table->sql_name};
2813 my $tbl_fk_info = $self->_table_fk_info($table);
2815 foreach my $fkdef (@$tbl_fk_info) {
2816 $fkdef->{local_table} = $table;
2817 $fkdef->{local_moniker} = $local_moniker;
2818 $fkdef->{remote_source} =
2819 $self->monikers->{$fkdef->{remote_table}->sql_name};
2821 my $tbl_uniq_info = $self->_table_uniq_info($table);
2823 push @tables, [ $local_moniker, $tbl_fk_info, $tbl_uniq_info ];
2826 my $rel_stmts = $self->_relbuilder->generate_code(\@tables);
2828 foreach my $src_class (sort keys %$rel_stmts) {
2830 my @src_stmts = map $_->[2],
2836 ($_->{method} eq 'many_to_many' ? 1 : 0),
2839 ], @{ $rel_stmts->{$src_class} };
2841 foreach my $stmt (@src_stmts) {
2842 $self->_dbic_stmt($src_class,$stmt->{method}, @{$stmt->{args}});
2848 my ($self, $table) = @_;
2850 my $table_moniker = $self->monikers->{$table->sql_name};
2851 my $table_class = $self->classes->{$table->sql_name};
2853 my @roles = @{ $self->result_roles || [] };
2854 push @roles, @{ $self->result_roles_map->{$table_moniker} }
2855 if exists $self->result_roles_map->{$table_moniker};
2858 $self->_pod_class_list($table_class, 'L<Moose> ROLES APPLIED', @roles);
2860 $self->_with($table_class, @roles);
2864 # Overload these in driver class:
2866 # Returns an arrayref of column names
2867 sub _table_columns { croak "ABSTRACT METHOD" }
2869 # Returns arrayref of pk col names
2870 sub _table_pk_info { croak "ABSTRACT METHOD" }
2872 # Returns an arrayref of uniqs [ [ foo => [ col1, col2 ] ], [ bar => [ ... ] ] ]
2873 sub _table_uniq_info { croak "ABSTRACT METHOD" }
2875 # Returns an arrayref of foreign key constraints, each
2876 # being a hashref with 3 keys:
2877 # local_columns (arrayref), remote_columns (arrayref), remote_table
2878 sub _table_fk_info { croak "ABSTRACT METHOD" }
2880 # Returns an array of lower case table names
2881 sub _tables_list { croak "ABSTRACT METHOD" }
2883 # Execute a constructive DBIC class method, with debug/dump_to_dir hooks.
2889 # generate the pod for this statement, storing it with $self->_pod
2890 $self->_make_pod( $class, $method, @_ ) if $self->generate_pod;
2892 my $args = dump(@_);
2893 $args = '(' . $args . ')' if @_ < 2;
2894 my $stmt = $method . $args . q{;};
2896 warn qq|$class\->$stmt\n| if $self->debug;
2897 $self->_raw_stmt($class, '__PACKAGE__->' . $stmt);
2901 sub _make_pod_heading {
2902 my ($self, $class) = @_;
2904 return '' if not $self->generate_pod;
2906 my $table = $self->class_to_table->{$class};
2909 my $pcm = $self->pod_comment_mode;
2910 my ($comment, $comment_overflows, $comment_in_name, $comment_in_desc);
2911 $comment = $self->__table_comment($table);
2912 $comment_overflows = ($comment and length $comment > $self->pod_comment_spillover_length);
2913 $comment_in_name = ($pcm eq 'name' or ($pcm eq 'auto' and !$comment_overflows));
2914 $comment_in_desc = ($pcm eq 'description' or ($pcm eq 'auto' and $comment_overflows));
2916 $pod .= "=head1 NAME\n\n";
2918 my $table_descr = $class;
2919 $table_descr .= " - " . $comment if $comment and $comment_in_name;
2921 $pod .= "$table_descr\n\n";
2923 if ($comment and $comment_in_desc) {
2924 $pod .= "=head1 DESCRIPTION\n\n${comment}\n\n";
2931 # generates the accompanying pod for a DBIC class method statement,
2932 # storing it with $self->_pod
2938 if ($method eq 'table') {
2940 $table = $$table if ref $table eq 'SCALAR';
2941 $self->_pod($class, "=head1 TABLE: C<$table>");
2942 $self->_pod_cut($class);
2944 elsif ( $method eq 'add_columns' ) {
2945 $self->_pod( $class, "=head1 ACCESSORS" );
2946 my $col_counter = 0;
2948 while( my ($name,$attrs) = splice @cols,0,2 ) {
2950 $self->_pod( $class, '=head2 ' . $name );
2951 $self->_pod( $class,
2953 my $s = $attrs->{$_};
2954 $s = !defined $s ? 'undef' :
2955 length($s) == 0 ? '(empty string)' :
2956 ref($s) eq 'SCALAR' ? $$s :
2957 ref($s) ? dumper_squashed $s :
2958 looks_like_number($s) ? $s : qq{'$s'};
2961 } sort keys %$attrs,
2963 if (my $comment = $self->__column_comment($self->class_to_table->{$class}, $col_counter, $name)) {
2964 $self->_pod( $class, $comment );
2967 $self->_pod_cut( $class );
2968 } elsif ( $method =~ /^(?:belongs_to|has_many|might_have)\z/ ) {
2969 $self->_pod( $class, "=head1 RELATIONS" ) unless $self->{_relations_started} { $class } ;
2970 my ( $accessor, $rel_class ) = @_;
2971 $self->_pod( $class, "=head2 $accessor" );
2972 $self->_pod( $class, 'Type: ' . $method );
2973 $self->_pod( $class, "Related object: L<$rel_class>" );
2974 $self->_pod_cut( $class );
2975 $self->{_relations_started} { $class } = 1;
2976 } elsif ( $method eq 'many_to_many' ) {
2977 $self->_pod( $class, "=head1 RELATIONS" ) unless $self->{_relations_started} { $class } ;
2978 my ( $accessor, $rel1, $rel2 ) = @_;
2979 $self->_pod( $class, "=head2 $accessor" );
2980 $self->_pod( $class, 'Type: many_to_many' );
2981 $self->_pod( $class, "Composing rels: L</$rel1> -> $rel2" );
2982 $self->_pod_cut( $class );
2983 $self->{_relations_started} { $class } = 1;
2985 elsif ($method eq 'add_unique_constraint') {
2986 $self->_pod($class, '=head1 UNIQUE CONSTRAINTS')
2987 unless $self->{_uniqs_started}{$class};
2989 my ($name, $cols) = @_;
2991 $self->_pod($class, "=head2 C<$name>");
2992 $self->_pod($class, '=over 4');
2994 foreach my $col (@$cols) {
2995 $self->_pod($class, "=item \* L</$col>");
2998 $self->_pod($class, '=back');
2999 $self->_pod_cut($class);
3001 $self->{_uniqs_started}{$class} = 1;
3003 elsif ($method eq 'set_primary_key') {
3004 $self->_pod($class, "=head1 PRIMARY KEY");
3005 $self->_pod($class, '=over 4');
3007 foreach my $col (@_) {
3008 $self->_pod($class, "=item \* L</$col>");
3011 $self->_pod($class, '=back');
3012 $self->_pod_cut($class);
3016 sub _pod_class_list {
3017 my ($self, $class, $title, @classes) = @_;
3019 return unless @classes && $self->generate_pod;
3021 $self->_pod($class, "=head1 $title");
3022 $self->_pod($class, '=over 4');
3024 foreach my $link (@classes) {
3025 $self->_pod($class, "=item * L<$link>");
3028 $self->_pod($class, '=back');
3029 $self->_pod_cut($class);
3032 sub _base_class_pod {
3033 my ($self, $base_class) = @_;
3035 return '' unless $self->generate_pod;
3037 return "\n=head1 BASE CLASS: L<$base_class>\n\n=cut\n\n";
3040 sub _filter_comment {
3041 my ($self, $txt) = @_;
3043 $txt = '' if not defined $txt;
3045 $txt =~ s/(?:\015?\012|\015\012?)/\n/g;
3050 sub __table_comment {
3053 if (my $code = $self->can('_table_comment')) {
3054 return $self->_filter_comment($self->$code(@_));
3060 sub __column_comment {
3063 if (my $code = $self->can('_column_comment')) {
3064 return $self->_filter_comment($self->$code(@_));
3070 # Stores a POD documentation
3072 my ($self, $class, $stmt) = @_;
3073 $self->_raw_stmt( $class, "\n" . $stmt );
3077 my ($self, $class ) = @_;
3078 $self->_raw_stmt( $class, "\n=cut\n" );
3081 # Store a raw source line for a class (for dumping purposes)
3083 my ($self, $class, $stmt) = @_;
3084 push(@{$self->{_dump_storage}->{$class}}, $stmt);
3087 # Like above, but separately for the externally loaded stuff
3089 my ($self, $class, $stmt) = @_;
3090 push(@{$self->{_ext_storage}->{$class}}, $stmt);
3093 sub _custom_column_info {
3094 my ( $self, $table_name, $column_name, $column_info ) = @_;
3096 if (my $code = $self->custom_column_info) {
3097 return $code->($table_name, $column_name, $column_info) || {};
3102 sub _datetime_column_info {
3103 my ( $self, $table_name, $column_name, $column_info ) = @_;
3105 my $type = $column_info->{data_type} || '';
3106 if ((grep $_, @{ $column_info }{map "inflate_$_", qw/date datetime timestamp/})
3107 or ($type =~ /date|timestamp/i)) {
3108 $result->{timezone} = $self->datetime_timezone if $self->datetime_timezone;
3109 $result->{locale} = $self->datetime_locale if $self->datetime_locale;
3115 my ($self, $name) = @_;
3117 return $self->preserve_case ? $name : lc($name);
3121 my ($self, $name) = @_;
3123 return $self->preserve_case ? $name : uc($name);
3127 my ($self, $table) = @_;
3130 my $schema = $self->schema;
3131 # in older DBIC it's a private method
3132 my $unregister = $schema->can('unregister_source') || $schema->can('_unregister_source');
3133 $schema->$unregister(delete $self->monikers->{$table->sql_name});
3134 delete $self->_upgrading_classes->{delete $self->classes->{$table->sql_name}};
3135 delete $self->_tables->{$table->sql_name};
3139 # remove the dump dir from @INC on destruction
3143 @INC = grep $_ ne $self->dump_directory, @INC;
3148 Returns a hashref of loaded table to moniker mappings. There will
3149 be two entries for each table, the original name and the "normalized"
3150 name, in the case that the two are different (such as databases
3151 that like uppercase table names, or preserve your original mixed-case
3152 definitions, or what-have-you).
3156 Returns a hashref of table to class mappings. In some cases it will
3157 contain multiple entries per table for the original and normalized table
3158 names, as above in L</monikers>.
3160 =head2 generated_classes
3162 Returns an arrayref of classes that were actually generated (i.e. not
3163 skipped because there were no changes).
3165 =head1 NON-ENGLISH DATABASES
3167 If you use the loader on a database with table and column names in a language
3168 other than English, you will want to turn off the English language specific
3171 To do so, use something like this in your loader options:
3173 naming => { monikers => 'v4' },
3174 inflect_singular => sub { "$_[0]_rel" },
3175 inflect_plural => sub { "$_[0]_rel" },
3177 =head1 COLUMN ACCESSOR COLLISIONS
3179 Occasionally you may have a column name that collides with a perl method, such
3180 as C<can>. In such cases, the default action is to set the C<accessor> of the
3181 column spec to C<undef>.
3183 You can then name the accessor yourself by placing code such as the following
3186 __PACKAGE__->add_column('+can' => { accessor => 'my_can' });
3188 Another option is to use the L</col_collision_map> option.
3190 =head1 RELATIONSHIP NAME COLLISIONS
3192 In very rare cases, you may get a collision between a generated relationship
3193 name and a method in your Result class, for example if you have a foreign key
3194 called C<belongs_to>.
3196 This is a problem because relationship names are also relationship accessor
3197 methods in L<DBIx::Class>.
3199 The default behavior is to append C<_rel> to the relationship name and print
3200 out a warning that refers to this text.
3202 You can also control the renaming with the L</rel_collision_map> option.
3206 L<DBIx::Class::Schema::Loader>, L<dbicdump>
3210 See L<DBIx::Class::Schema::Loader/AUTHORS>.
3214 This library is free software; you can redistribute it and/or modify it under
3215 the same terms as Perl itself.
3220 # vim:et sts=4 sw=4 tw=0: