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/;
24 use DBIx::Class::Schema::Loader::Optional::Dependencies ();
27 use Encode qw/encode decode/;
28 use List::MoreUtils qw/all any firstidx uniq/;
29 use File::Temp 'tempfile';
32 our $VERSION = '0.07037';
34 __PACKAGE__->mk_group_ro_accessors('simple', qw/
41 additional_base_classes
57 default_resultset_class
63 overwrite_modifications
86 __PACKAGE__->mk_group_accessors('simple', qw/
88 schema_version_to_dump
90 _upgrading_from_load_classes
91 _downgrading_to_load_classes
92 _rewriting_result_namespace
97 pod_comment_spillover_length
103 result_components_map
105 datetime_undef_if_invalid
106 _result_class_methods
108 filter_generated_code
112 moniker_part_separator
116 my $CURRENT_V = 'v7';
119 schema_components schema_base_class result_base_class
120 additional_base_classes left_base_classes additional_classes components
126 my $CRLF = "\x0d\x0a";
130 DBIx::Class::Schema::Loader::Base - Base DBIx::Class::Schema::Loader Implementation.
134 See L<DBIx::Class::Schema::Loader>.
138 This is the base class for the storage-specific C<DBIx::Class::Schema::*>
139 classes, and implements the common functionality between them.
141 =head1 CONSTRUCTOR OPTIONS
143 These constructor options are the base options for
144 L<DBIx::Class::Schema::Loader/loader_options>. Available constructor options are:
146 =head2 skip_relationships
148 Skip setting up relationships. The default is to attempt the loading
151 =head2 skip_load_external
153 Skip loading of other classes in @INC. The default is to merge all other classes
154 with the same name found in @INC into the schema file we are creating.
158 Static schemas (ones dumped to disk) will, by default, use the new-style
159 relationship names and singularized Results, unless you're overwriting an
160 existing dump made by an older version of L<DBIx::Class::Schema::Loader>, in
161 which case the backward compatible RelBuilder will be activated, and the
162 appropriate monikerization used.
168 will disable the backward-compatible RelBuilder and use
169 the new-style relationship names along with singularized Results, even when
170 overwriting a dump made with an earlier version.
172 The option also takes a hashref:
175 relationships => 'v8',
177 column_accessors => 'v8',
183 naming => { ALL => 'v8', force_ascii => 1 }
191 Set L</relationships>, L</monikers> and L</column_accessors> to the specified
196 How to name relationship accessors.
200 How to name Result classes.
202 =item column_accessors
204 How to name column accessors in Result classes.
208 For L</v8> mode and later, uses L<String::ToIdentifier::EN> instead of
209 L<String::ToIdentifier::EM::Unicode> to force monikers and other identifiers to
220 Latest style, whatever that happens to be.
224 Unsingularlized monikers, C<has_many> only relationships with no _id stripping.
228 Monikers singularized as whole words, C<might_have> relationships for FKs on
229 C<UNIQUE> constraints, C<_id> stripping for belongs_to relationships.
231 Some of the C<_id> stripping edge cases in C<0.05003> have been reverted for
236 All monikers and relationships are inflected using
237 L<Lingua::EN::Inflect::Phrase>, and there is more aggressive C<_id> stripping
238 from relationship names.
240 In general, there is very little difference between v5 and v6 schemas.
244 This mode is identical to C<v6> mode, except that monikerization of CamelCase
245 table names is also done better (but best in v8.)
247 CamelCase column names in case-preserving mode will also be handled better
248 for relationship name inflection (but best in v8.) See L</preserve_case>.
250 In this mode, CamelCase L</column_accessors> are normalized based on case
251 transition instead of just being lowercased, so C<FooId> becomes C<foo_id>.
257 The default mode is L</v7>, to get L</v8> mode, you have to specify it in
258 L</naming> explicitly until C<0.08> comes out.
260 L</monikers> and L</column_accessors> are created using
261 L<String::ToIdentifier::EN::Unicode> or L<String::ToIdentifier::EN> if
262 L</force_ascii> is set; this is only significant for names with non-C<\w>
263 characters such as C<.>.
265 CamelCase identifiers with words in all caps, e.g. C<VLANValidID> are supported
266 correctly in this mode.
268 For relationships, belongs_to accessors are made from column names by stripping
269 postfixes other than C<_id> as well, for example just C<Id>, C<_?ref>, C<_?cd>,
270 C<_?code> and C<_?num>, case insensitively.
274 For L</monikers>, this option does not inflect the table names but makes
275 monikers based on the actual name. For L</column_accessors> this option does
276 not normalize CamelCase column names to lowercase column accessors, but makes
277 accessors that are the same names as the columns (with any non-\w chars
278 replaced with underscores.)
282 For L</monikers>, singularizes the names using the most current inflector. This
283 is the same as setting the option to L</current>.
287 For L</monikers>, pluralizes the names, using the most current inflector.
291 Dynamic schemas will always default to the 0.04XXX relationship names and won't
292 singularize Results for backward compatibility, to activate the new RelBuilder
293 and singularization put this in your C<Schema.pm> file:
295 __PACKAGE__->naming('current');
297 Or if you prefer to use 0.07XXX features but insure that nothing breaks in the
298 next major version upgrade:
300 __PACKAGE__->naming('v7');
304 If true, will not print the usual C<Dumping manual schema ... Schema dump
305 completed.> messages. Does not affect warnings (except for warnings related to
306 L</really_erase_my_files>.)
310 By default POD will be generated for columns and relationships, using database
311 metadata for the text if available and supported.
313 Comment metadata can be stored in two ways.
315 The first is that you can create two tables named C<table_comments> and
316 C<column_comments> respectively. These tables must exist in the same database
317 and schema as the tables they describe. They both need to have columns named
318 C<table_name> and C<comment_text>. The second one needs to have a column named
319 C<column_name>. Then data stored in these tables will be used as a source of
320 metadata about tables and comments.
322 (If you wish you can change the name of these tables with the parameters
323 L</table_comments_table> and L</column_comments_table>.)
325 As a fallback you can use built-in commenting mechanisms. Currently this is
326 only supported for PostgreSQL, Oracle and MySQL. To create comments in
327 PostgreSQL you add statements of the form C<COMMENT ON TABLE some_table IS
328 '...'>, the same syntax is used in Oracle. To create comments in MySQL you add
329 C<COMMENT '...'> to the end of the column or table definition. Note that MySQL
330 restricts the length of comments, and also does not handle complex Unicode
333 Set this to C<0> to turn off all POD generation.
335 =head2 pod_comment_mode
337 Controls where table comments appear in the generated POD. Smaller table
338 comments are appended to the C<NAME> section of the documentation, and larger
339 ones are inserted into C<DESCRIPTION> instead. You can force a C<DESCRIPTION>
340 section to be generated with the comment always, only use C<NAME>, or choose
341 the length threshold at which the comment is forced into the description.
347 Use C<NAME> section only.
351 Force C<DESCRIPTION> always.
355 Use C<DESCRIPTION> if length > L</pod_comment_spillover_length>, this is the
360 =head2 pod_comment_spillover_length
362 When pod_comment_mode is set to C<auto>, this is the length of the comment at
363 which it will be forced into a separate description section.
367 =head2 table_comments_table
369 The table to look for comments about tables in. By default C<table_comments>.
370 See L</generate_pod> for details.
372 This must not be a fully qualified name, the table will be looked for in the
373 same database and schema as the table whose comment is being retrieved.
375 =head2 column_comments_table
377 The table to look for comments about columns in. By default C<column_comments>.
378 See L</generate_pod> for details.
380 This must not be a fully qualified name, the table will be looked for in the
381 same database and schema as the table/column whose comment is being retrieved.
383 =head2 relationship_attrs
385 Hashref of attributes to pass to each generated relationship, listed by type.
386 Also supports relationship type 'all', containing options to pass to all
387 generated relationships. Attributes set for more specific relationship types
388 override those set in 'all', and any attributes specified by this option
389 override the introspected attributes of the foreign key if any.
393 relationship_attrs => {
394 has_many => { cascade_delete => 1, cascade_copy => 1 },
395 might_have => { cascade_delete => 1, cascade_copy => 1 },
398 use this to turn L<DBIx::Class> cascades to on on your
399 L<has_many|DBIx::Class::Relationship/has_many> and
400 L<might_have|DBIx::Class::Relationship/might_have> relationships, they default
403 Can also be a coderef, for more precise control, in which case the coderef gets
404 this hash of parameters (as a list:)
406 rel_name # the name of the relationship
407 rel_type # the type of the relationship: 'belongs_to', 'has_many' or 'might_have'
408 local_source # the DBIx::Class::ResultSource object for the source the rel is *from*
409 remote_source # the DBIx::Class::ResultSource object for the source the rel is *to*
410 local_table # a DBIx::Class::Schema::Loader::Table object for the table of the source the rel is from
411 local_cols # an arrayref of column names of columns used in the rel in the source it is from
412 remote_table # a DBIx::Class::Schema::Loader::Table object for the table of the source the rel is to
413 remote_cols # an arrayref of column names of columns used in the rel in the source it is to
414 attrs # the attributes that would be set
416 it should return the new hashref of attributes, or nothing for no changes.
420 relationship_attrs => sub {
423 say "the relationship name is: $p{rel_name}";
424 say "the relationship is a: $p{rel_type}";
425 say "the local class is: ", $p{local_source}->result_class;
426 say "the remote class is: ", $p{remote_source}->result_class;
427 say "the local table is: ", $p{local_table}->sql_name;
428 say "the rel columns in the local table are: ", (join ", ", @{$p{local_cols}});
429 say "the remote table is: ", $p{remote_table}->sql_name;
430 say "the rel columns in the remote table are: ", (join ", ", @{$p{remote_cols}});
432 if ($p{local_table} eq 'dogs' && @{$p{local_cols}} == 1 && $p{local_cols}[0] eq 'name') {
433 $p{attrs}{could_be_snoopy} = 1;
439 These are the default attributes:
450 on_delete => 'CASCADE',
451 on_update => 'CASCADE',
455 For L<belongs_to|DBIx::Class::Relationship/belongs_to> relationships, these
456 defaults are overridden by the attributes introspected from the foreign key in
457 the database, if this information is available (and the driver is capable of
460 This information overrides the defaults mentioned above, and is then itself
461 overridden by the user's L</relationship_attrs> for C<belongs_to> if any are
464 In general, for most databases, for a plain foreign key with no rules, the
465 values for a L<belongs_to|DBIx::Class::Relationship/belongs_to> relationship
468 on_delete => 'NO ACTION',
469 on_update => 'NO ACTION',
472 In the cases where an attribute is not supported by the DB, a value matching
473 the actual behavior is used, for example Oracle does not support C<ON UPDATE>
474 rules, so C<on_update> is set to C<NO ACTION>. This is done so that the
475 behavior of the schema is preserved when cross deploying to a different RDBMS
476 such as SQLite for testing.
478 In the cases where the DB does not support C<DEFERRABLE> foreign keys, the
479 value is set to C<1> if L<DBIx::Class> has a working C<<
480 $storage->with_deferred_fk_checks >>. This is done so that the same
481 L<DBIx::Class> code can be used, and cross deployed from and to such databases.
485 If set to true, each constructive L<DBIx::Class> statement the loader
486 decides to execute will be C<warn>-ed before execution.
490 Set the name of the schema to load (schema in the sense that your database
493 Can be set to an arrayref of schema names for multiple schemas, or the special
494 value C<%> for all schemas.
496 For MSSQL, Sybase ASE, and Informix can be set to a hashref of databases as
497 keys and arrays of owners as values, set to the value:
501 for all owners in all databases.
503 Name clashes resulting from the same table name in different databases/schemas
504 will be resolved automatically by prefixing the moniker with the database
507 To prefix/suffix all monikers with the database and/or schema, see
512 The database table names are represented by the
513 L<DBIx::Class::Schema::Loader::Table> class in the loader, the
514 L<DBIx::Class::Schema::Loader::Table::Sybase> class for Sybase ASE and
515 L<DBIx::Class::Schema::Loader::Table::Informix> for Informix.
517 Monikers are created normally based on just the
518 L<name|DBIx::Class::Schema::Loader::DBObject/name> property, corresponding to
519 the table name, but can consist of other parts of the fully qualified name of
522 The L</moniker_parts> option is an arrayref of methods on the table class
523 corresponding to parts of the fully qualified table name, defaulting to
524 C<['name']>, in the order those parts are used to create the moniker name.
525 The parts are joined together using L</moniker_part_separator>.
527 The C<'name'> entry B<must> be present.
529 Below is a table of supported databases and possible L</moniker_parts>.
533 =item * DB2, Firebird, mysql, Oracle, Pg, SQLAnywhere, SQLite, MS Access
537 =item * Informix, MSSQL, Sybase ASE
539 C<database>, C<schema>, C<name>
543 =head2 moniker_part_separator
545 String used to join L</moniker_parts> when creating the moniker.
546 Defaults to the empty string. Use C<::> to get a separate namespace per
547 database and/or schema.
551 Only load matching tables.
555 Exclude matching tables.
557 These can be specified either as a regex (preferrably on the C<qr//>
558 form), or as an arrayref of arrayrefs. Regexes are matched against
559 the (unqualified) table name, while arrayrefs are matched according to
564 db_schema => [qw(some_schema other_schema)],
565 moniker_parts => [qw(schema name)],
567 [ qr/\Asome_schema\z/ => qr/\A(?:foo|bar)\z/ ],
568 [ qr/\Aother_schema\z/ => qr/\Abaz\z/ ],
571 In this case only the tables C<foo> and C<bar> in C<some_schema> and
572 C<baz> in C<other_schema> will be dumped.
576 Overrides the default table name to moniker translation. Either
582 a nested hashref, which will be traversed according to L</moniker_parts>
586 moniker_parts => [qw(schema name)],
593 In which case the table C<bar> in the C<foo> schema would get the moniker
598 a hashref of unqualified table name keys and moniker values
602 a coderef for a translator function taking a L<table
603 object|DBIx::Class::Schema::Loader::Table> argument (which stringifies to the
604 unqualified table name) and returning a scalar moniker
608 If the hash entry does not exist, or the function returns a false
609 value, the code falls back to default behavior for that table name.
611 The default behavior is to split on case transition and non-alphanumeric
612 boundaries, singularize the resulting phrase, then join the titlecased words
615 Table Name | Moniker Name
616 ---------------------------------
618 luser_group | LuserGroup
619 luser-opts | LuserOpt
620 stations_visited | StationVisited
621 routeChange | RouteChange
623 =head2 moniker_part_map
625 Map for overriding the monikerization of individual L</moniker_parts>.
626 The keys are the moniker part to override, the value is either a
627 hashref of coderef for mapping the corresponding part of the
628 moniker. If a coderef is used, it gets called with the moniker part
629 and the hash key the code ref was found under.
633 moniker_part_map => {
634 schema => sub { ... },
637 Given the table C<foo.bar>, the code ref would be called with the
638 arguments C<foo> and C<schema>.
640 L</moniker_map> takes precedence over this.
642 =head2 col_accessor_map
644 Same as moniker_map, but for column accessor names. If a coderef is
645 passed, the code is called with arguments of
647 the name of the column in the underlying database,
648 default accessor name that DBICSL would ordinarily give this column,
650 table_class => name of the DBIC class we are building,
651 table_moniker => calculated moniker for this table (after moniker_map if present),
652 table => table object of interface DBIx::Class::Schema::Loader::Table,
653 full_table_name => schema-qualified name of the database table (RDBMS specific),
654 schema_class => name of the schema class we are building,
655 column_info => hashref of column info (data_type, is_nullable, etc),
658 the L<table object|DBIx::Class::Schema::Loader::Table> stringifies to the
659 unqualified table name.
663 Similar in idea to moniker_map, but different in the details. It can be
664 a hashref or a code ref.
666 If it is a hashref, keys can be either the default relationship name, or the
667 moniker. The keys that are the default relationship name should map to the
668 name you want to change the relationship to. Keys that are monikers should map
669 to hashes mapping relationship names to their translation. You can do both at
670 once, and the more specific moniker version will be picked up first. So, for
671 instance, you could have
680 and relationships that would have been named C<bar> will now be named C<baz>
681 except that in the table whose moniker is C<Foo> it will be named C<blat>.
683 If it is a coderef, the argument passed will be a hashref of this form:
686 name => default relationship name,
687 type => the relationship type eg: C<has_many>,
688 local_class => name of the DBIC class we are building,
689 local_moniker => moniker of the DBIC class we are building,
690 local_columns => columns in this table in the relationship,
691 remote_class => name of the DBIC class we are related to,
692 remote_moniker => moniker of the DBIC class we are related to,
693 remote_columns => columns in the other table in the relationship,
694 # for type => "many_to_many" only:
695 link_class => name of the DBIC class for the link table
696 link_moniker => moniker of the DBIC class for the link table
697 link_rel_name => name of the relationship to the link table
700 DBICSL will try to use the value returned as the relationship name.
702 =head2 inflect_plural
704 Just like L</moniker_map> above (can be hash/code-ref, falls back to default
705 if hash key does not exist or coderef returns false), but acts as a map
706 for pluralizing relationship names. The default behavior is to utilize
707 L<Lingua::EN::Inflect::Phrase/to_PL>.
709 =head2 inflect_singular
711 As L</inflect_plural> above, but for singularizing relationship names.
712 Default behavior is to utilize L<Lingua::EN::Inflect::Phrase/to_S>.
714 =head2 schema_base_class
716 Base class for your schema classes. Defaults to 'DBIx::Class::Schema'.
718 =head2 schema_components
720 List of components to load into the Schema class.
722 =head2 result_base_class
724 Base class for your table classes (aka result classes). Defaults to
727 =head2 additional_base_classes
729 List of additional base classes all of your table classes will use.
731 =head2 left_base_classes
733 List of additional base classes all of your table classes will use
734 that need to be leftmost.
736 =head2 additional_classes
738 List of additional classes which all of your table classes will use.
742 List of additional components to be loaded into all of your Result
743 classes. A good example would be
744 L<InflateColumn::DateTime|DBIx::Class::InflateColumn::DateTime>
746 =head2 result_components_map
748 A hashref of moniker keys and component values. Unlike L</components>, which
749 loads the given components into every Result class, this option allows you to
750 load certain components for specified Result classes. For example:
752 result_components_map => {
753 StationVisited => '+YourApp::Schema::Component::StationVisited',
755 '+YourApp::Schema::Component::RouteChange',
756 'InflateColumn::DateTime',
760 You may use this in conjunction with L</components>.
764 List of L<Moose> roles to be applied to all of your Result classes.
766 =head2 result_roles_map
768 A hashref of moniker keys and role values. Unlike L</result_roles>, which
769 applies the given roles to every Result class, this option allows you to apply
770 certain roles for specified Result classes. For example:
772 result_roles_map => {
774 'YourApp::Role::Building',
775 'YourApp::Role::Destination',
777 RouteChange => 'YourApp::Role::TripEvent',
780 You may use this in conjunction with L</result_roles>.
782 =head2 use_namespaces
784 This is now the default, to go back to L<DBIx::Class::Schema/load_classes> pass
787 Generate result class names suitable for
788 L<DBIx::Class::Schema/load_namespaces> and call that instead of
789 L<DBIx::Class::Schema/load_classes>. When using this option you can also
790 specify any of the options for C<load_namespaces> (i.e. C<result_namespace>,
791 C<resultset_namespace>, C<default_resultset_class>), and they will be added
792 to the call (and the generated result class names adjusted appropriately).
794 =head2 dump_directory
796 The value of this option is a perl libdir pathname. Within
797 that directory this module will create a baseline manual
798 L<DBIx::Class::Schema> module set, based on what it creates at runtime.
800 The created schema class will have the same classname as the one on
801 which you are setting this option (and the ResultSource classes will be
802 based on this name as well).
804 Normally you wouldn't hard-code this setting in your schema class, as it
805 is meant for one-time manual usage.
807 See L<DBIx::Class::Schema::Loader/dump_to_dir> for examples of the
808 recommended way to access this functionality.
810 =head2 dump_overwrite
812 Deprecated. See L</really_erase_my_files> below, which does *not* mean
813 the same thing as the old C<dump_overwrite> setting from previous releases.
815 =head2 really_erase_my_files
817 Default false. If true, Loader will unconditionally delete any existing
818 files before creating the new ones from scratch when dumping a schema to disk.
820 The default behavior is instead to only replace the top portion of the
821 file, up to and including the final stanza which contains
822 C<# DO NOT MODIFY THE FIRST PART OF THIS FILE>
823 leaving any customizations you placed after that as they were.
825 When C<really_erase_my_files> is not set, if the output file already exists,
826 but the aforementioned final stanza is not found, or the checksum
827 contained there does not match the generated contents, Loader will
828 croak and not touch the file.
830 You should really be using version control on your schema classes (and all
831 of the rest of your code for that matter). Don't blame me if a bug in this
832 code wipes something out when it shouldn't have, you've been warned.
834 =head2 overwrite_modifications
836 Default false. If false, when updating existing files, Loader will
837 refuse to modify any Loader-generated code that has been modified
838 since its last run (as determined by the checksum Loader put in its
841 If true, Loader will discard any manual modifications that have been
842 made to Loader-generated code.
844 Again, you should be using version control on your schema classes. Be
845 careful with this option.
847 =head2 custom_column_info
849 Hook for adding extra attributes to the
850 L<column_info|DBIx::Class::ResultSource/column_info> for a column.
852 Must be a coderef that returns a hashref with the extra attributes.
854 Receives the L<table object|DBIx::Class::Schema::Loader::Table> (which
855 stringifies to the unqualified table name), column name and column_info.
859 custom_column_info => sub {
860 my ($table, $column_name, $column_info) = @_;
862 if ($column_name eq 'dog' && $column_info->{default_value} eq 'snoopy') {
863 return { is_snoopy => 1 };
867 This attribute can also be used to set C<inflate_datetime> on a non-datetime
868 column so it also receives the L</datetime_timezone> and/or L</datetime_locale>.
870 =head2 datetime_timezone
872 Sets the timezone attribute for L<DBIx::Class::InflateColumn::DateTime> for all
873 columns with the DATE/DATETIME/TIMESTAMP data_types.
875 =head2 datetime_locale
877 Sets the locale attribute for L<DBIx::Class::InflateColumn::DateTime> for all
878 columns with the DATE/DATETIME/TIMESTAMP data_types.
880 =head2 datetime_undef_if_invalid
882 Pass a C<0> for this option when using MySQL if you B<DON'T> want C<<
883 datetime_undef_if_invalid => 1 >> in your column info for DATE, DATETIME and
886 The default is recommended to deal with data such as C<00/00/00> which
887 sometimes ends up in such columns in MySQL.
891 File in Perl format, which should return a HASH reference, from which to read
896 Normally database names are lowercased and split by underscore, use this option
897 if you have CamelCase database names.
899 Drivers for case sensitive databases like Sybase ASE or MSSQL with a
900 case-sensitive collation will turn this option on unconditionally.
902 B<NOTE:> L</naming> = C<v8> is highly recommended with this option as the
903 semantics of this mode are much improved for CamelCase database names.
905 L</naming> = C<v7> or greater is required with this option.
907 =head2 qualify_objects
909 Set to true to prepend the L</db_schema> to table names for C<<
910 __PACKAGE__->table >> calls, and to some other things like Oracle sequences.
912 This attribute is automatically set to true for multi db_schema configurations,
913 unless explicitly set to false by the user.
917 Creates Schema and Result classes that use L<Moose>, L<MooseX::NonMoose> and
918 L<MooseX::MarkAsMethods> (or L<namespace::autoclean>, see below). The default
919 content after the md5 sum also makes the classes immutable.
921 It is safe to upgrade your existing Schema to this option.
923 =head2 only_autoclean
925 By default, we use L<MooseX::MarkAsMethods> to remove imported functions from
926 your generated classes. It uses L<namespace::autoclean> to do this, after
927 telling your object's metaclass that any operator L<overload>s in your class
928 are methods, which will cause namespace::autoclean to spare them from removal.
930 This prevents the "Hey, where'd my overloads go?!" effect.
932 If you don't care about operator overloads, enabling this option falls back to
933 just using L<namespace::autoclean> itself.
935 If none of the above made any sense, or you don't have some pressing need to
936 only use L<namespace::autoclean>, leaving this set to the default is
939 =head2 col_collision_map
941 This option controls how accessors for column names which collide with perl
942 methods are named. See L</COLUMN ACCESSOR COLLISIONS> for more information.
944 This option takes either a single L<sprintf|perlfunc/sprintf> format or a hashref of
945 strings which are compiled to regular expressions that map to
946 L<sprintf|perlfunc/sprintf> formats.
950 col_collision_map => 'column_%s'
952 col_collision_map => { '(.*)' => 'column_%s' }
954 col_collision_map => { '(foo).*(bar)' => 'column_%s_%s' }
956 =head2 rel_collision_map
958 Works just like L</col_collision_map>, but for relationship names/accessors
959 rather than column names/accessors.
961 The default is to just append C<_rel> to the relationship name, see
962 L</RELATIONSHIP NAME COLLISIONS>.
964 =head2 uniq_to_primary
966 Automatically promotes the largest unique constraints with non-nullable columns
967 on tables to primary keys, assuming there is only one largest unique
970 =head2 filter_generated_code
972 An optional hook that lets you filter the generated text for various classes
973 through a function that change it in any way that you want. The function will
974 receive the type of file, C<schema> or C<result>, class and code; and returns
975 the new code to use instead. For instance you could add custom comments, or do
976 anything else that you want.
978 The option can also be set to a string, which is then used as a filter program,
981 If this exists but fails to return text matching C</\bpackage\b/>, no file will
984 filter_generated_code => sub {
985 my ($type, $class, $text) = @_;
992 None of these methods are intended for direct invocation by regular
993 users of L<DBIx::Class::Schema::Loader>. Some are proxied via
994 L<DBIx::Class::Schema::Loader>.
998 # ensure that a piece of object data is a valid arrayref, creating
999 # an empty one or encapsulating whatever's there.
1000 sub _ensure_arrayref {
1005 $self->{$_} = [ $self->{$_} ]
1006 unless ref $self->{$_} eq 'ARRAY';
1012 Constructor for L<DBIx::Class::Schema::Loader::Base>, used internally
1013 by L<DBIx::Class::Schema::Loader>.
1018 my ( $class, %args ) = @_;
1020 if (exists $args{column_accessor_map}) {
1021 $args{col_accessor_map} = delete $args{column_accessor_map};
1024 my $self = { %args };
1026 # don't lose undef options
1027 for (values %$self) {
1028 $_ = 0 unless defined $_;
1031 bless $self => $class;
1033 if (my $config_file = $self->config_file) {
1034 my $config_opts = do $config_file;
1036 croak "Error reading config from $config_file: $@" if $@;
1038 croak "Config file $config_file must be a hashref" unless ref($config_opts) eq 'HASH';
1040 while (my ($k, $v) = each %$config_opts) {
1041 $self->{$k} = $v unless exists $self->{$k};
1045 if (defined $self->{result_component_map}) {
1046 if (defined $self->result_components_map) {
1047 croak "Specify only one of result_components_map or result_component_map";
1049 $self->result_components_map($self->{result_component_map})
1052 if (defined $self->{result_role_map}) {
1053 if (defined $self->result_roles_map) {
1054 croak "Specify only one of result_roles_map or result_role_map";
1056 $self->result_roles_map($self->{result_role_map})
1059 croak "the result_roles and result_roles_map options may only be used in conjunction with use_moose=1"
1060 if ((not defined $self->use_moose) || (not $self->use_moose))
1061 && ((defined $self->result_roles) || (defined $self->result_roles_map));
1063 $self->_ensure_arrayref(qw/schema_components
1065 additional_base_classes
1071 $self->_validate_class_args;
1073 croak "result_components_map must be a hash"
1074 if defined $self->result_components_map
1075 && ref $self->result_components_map ne 'HASH';
1077 if ($self->result_components_map) {
1078 my %rc_map = %{ $self->result_components_map };
1079 foreach my $moniker (keys %rc_map) {
1080 $rc_map{$moniker} = [ $rc_map{$moniker} ] unless ref $rc_map{$moniker};
1082 $self->result_components_map(\%rc_map);
1085 $self->result_components_map({});
1087 $self->_validate_result_components_map;
1089 croak "result_roles_map must be a hash"
1090 if defined $self->result_roles_map
1091 && ref $self->result_roles_map ne 'HASH';
1093 if ($self->result_roles_map) {
1094 my %rr_map = %{ $self->result_roles_map };
1095 foreach my $moniker (keys %rr_map) {
1096 $rr_map{$moniker} = [ $rr_map{$moniker} ] unless ref $rr_map{$moniker};
1098 $self->result_roles_map(\%rr_map);
1100 $self->result_roles_map({});
1102 $self->_validate_result_roles_map;
1104 if ($self->use_moose) {
1105 if (not DBIx::Class::Schema::Loader::Optional::Dependencies->req_ok_for('use_moose')) {
1106 die sprintf "You must install the following CPAN modules to enable the use_moose option: %s.\n",
1107 DBIx::Class::Schema::Loader::Optional::Dependencies->req_missing_for('use_moose');
1111 $self->{_tables} = {};
1112 $self->{monikers} = {};
1113 $self->{moniker_to_table} = {};
1114 $self->{class_to_table} = {};
1115 $self->{classes} = {};
1116 $self->{_upgrading_classes} = {};
1118 $self->{schema_class} ||= ( ref $self->{schema} || $self->{schema} );
1119 $self->{schema} ||= $self->{schema_class};
1120 $self->{table_comments_table} ||= 'table_comments';
1121 $self->{column_comments_table} ||= 'column_comments';
1123 croak "dump_overwrite is deprecated. Please read the"
1124 . " DBIx::Class::Schema::Loader::Base documentation"
1125 if $self->{dump_overwrite};
1127 $self->{dynamic} = ! $self->{dump_directory};
1128 $self->{temp_directory} ||= File::Temp::tempdir( 'dbicXXXX',
1133 $self->{dump_directory} ||= $self->{temp_directory};
1135 $self->real_dump_directory($self->{dump_directory});
1137 $self->version_to_dump($DBIx::Class::Schema::Loader::VERSION);
1138 $self->schema_version_to_dump($DBIx::Class::Schema::Loader::VERSION);
1140 if (not defined $self->naming) {
1141 $self->naming_set(0);
1144 $self->naming_set(1);
1147 if ((not ref $self->naming) && defined $self->naming) {
1148 my $naming_ver = $self->naming;
1150 relationships => $naming_ver,
1151 monikers => $naming_ver,
1152 column_accessors => $naming_ver,
1155 elsif (ref $self->naming eq 'HASH' && exists $self->naming->{ALL}) {
1156 my $val = delete $self->naming->{ALL};
1158 $self->naming->{$_} = $val
1159 foreach qw/relationships monikers column_accessors/;
1162 if ($self->naming) {
1163 foreach my $key (qw/relationships monikers column_accessors/) {
1164 $self->naming->{$key} = $CURRENT_V if ($self->naming->{$key}||'') eq 'current';
1167 $self->{naming} ||= {};
1169 if ($self->custom_column_info && ref $self->custom_column_info ne 'CODE') {
1170 croak 'custom_column_info must be a CODE ref';
1173 $self->_check_back_compat;
1175 $self->use_namespaces(1) unless defined $self->use_namespaces;
1176 $self->generate_pod(1) unless defined $self->generate_pod;
1177 $self->pod_comment_mode('auto') unless defined $self->pod_comment_mode;
1178 $self->pod_comment_spillover_length(60) unless defined $self->pod_comment_spillover_length;
1180 if (my $col_collision_map = $self->col_collision_map) {
1181 if (my $reftype = ref $col_collision_map) {
1182 if ($reftype ne 'HASH') {
1183 croak "Invalid type $reftype for option 'col_collision_map'";
1187 $self->col_collision_map({ '(.*)' => $col_collision_map });
1191 if (my $rel_collision_map = $self->rel_collision_map) {
1192 if (my $reftype = ref $rel_collision_map) {
1193 if ($reftype ne 'HASH') {
1194 croak "Invalid type $reftype for option 'rel_collision_map'";
1198 $self->rel_collision_map({ '(.*)' => $rel_collision_map });
1202 if (defined(my $rel_name_map = $self->rel_name_map)) {
1203 my $reftype = ref $rel_name_map;
1204 if ($reftype ne 'HASH' && $reftype ne 'CODE') {
1205 croak "Invalid type $reftype for option 'rel_name_map', must be HASH or CODE";
1209 if (defined(my $filter = $self->filter_generated_code)) {
1210 my $reftype = ref $filter;
1211 if ($reftype && $reftype ne 'CODE') {
1212 croak "Invalid type $reftype for option 'filter_generated_code, must be a scalar or a CODE reference";
1216 if (defined $self->db_schema) {
1217 if (ref $self->db_schema eq 'ARRAY') {
1218 if (@{ $self->db_schema } > 1 && not defined $self->{qualify_objects}) {
1219 $self->{qualify_objects} = 1;
1221 elsif (@{ $self->db_schema } == 0) {
1222 $self->{db_schema} = undef;
1225 elsif (not ref $self->db_schema) {
1226 if ($self->db_schema eq '%' && not defined $self->{qualify_objects}) {
1227 $self->{qualify_objects} = 1;
1230 $self->{db_schema} = [ $self->db_schema ];
1234 if (not $self->moniker_parts) {
1235 $self->moniker_parts(['name']);
1238 if (not ref $self->moniker_parts) {
1239 $self->moniker_parts([ $self->moniker_parts ]);
1241 if (ref $self->moniker_parts ne 'ARRAY') {
1242 croak 'moniker_parts must be an arrayref';
1244 if ((firstidx { $_ eq 'name' } @{ $self->moniker_parts }) == -1) {
1245 croak "moniker_parts option *must* contain 'name'";
1249 if (not defined $self->moniker_part_separator) {
1250 $self->moniker_part_separator('');
1252 if (not defined $self->moniker_part_map) {
1253 $self->moniker_part_map({}),
1259 sub _check_back_compat {
1262 # dynamic schemas will always be in 0.04006 mode, unless overridden
1263 if ($self->dynamic) {
1264 # just in case, though no one is likely to dump a dynamic schema
1265 $self->schema_version_to_dump('0.04006');
1267 if (not $self->naming_set) {
1268 warn <<EOF unless $ENV{SCHEMA_LOADER_BACKCOMPAT};
1270 Dynamic schema detected, will run in 0.04006 mode.
1272 Set the 'naming' attribute or the SCHEMA_LOADER_BACKCOMPAT environment variable
1273 to disable this warning.
1275 See perldoc DBIx::Class::Schema::Loader::Manual::UpgradingFromV4 for more
1280 $self->_upgrading_from('v4');
1283 if ((not defined $self->use_namespaces) && ($self->naming_set)) {
1284 $self->use_namespaces(1);
1287 $self->naming->{relationships} ||= 'v4';
1288 $self->naming->{monikers} ||= 'v4';
1290 if ($self->use_namespaces) {
1291 $self->_upgrading_from_load_classes(1);
1294 $self->use_namespaces(0);
1300 # otherwise check if we need backcompat mode for a static schema
1301 my $filename = $self->get_dump_filename($self->schema_class);
1302 return unless -e $filename;
1304 my ($old_gen, $old_md5, $old_ver, $old_ts, $old_custom) =
1305 $self->_parse_generated_file($filename);
1307 return unless $old_ver;
1309 # determine if the existing schema was dumped with use_moose => 1
1310 if (! defined $self->use_moose) {
1311 $self->{use_moose} = 1 if $old_gen =~ /^ (?!\s*\#) use \s+ Moose/xm;
1314 my $load_classes = ($old_gen =~ /^__PACKAGE__->load_classes;/m) ? 1 : 0;
1316 my $result_namespace = do { ($old_gen =~ /result_namespace => (.+)/) ? $1 : '' };
1317 my $ds = eval $result_namespace;
1319 Could not eval expression '$result_namespace' for result_namespace from
1322 $result_namespace = $ds || '';
1324 if ($load_classes && (not defined $self->use_namespaces)) {
1325 warn <<"EOF" unless $ENV{SCHEMA_LOADER_BACKCOMPAT};
1327 'load_classes;' static schema detected, turning off 'use_namespaces'.
1329 Set the 'use_namespaces' attribute or the SCHEMA_LOADER_BACKCOMPAT environment
1330 variable to disable this warning.
1332 See perldoc DBIx::Class::Schema::Loader::Manual::UpgradingFromV4 for more
1335 $self->use_namespaces(0);
1337 elsif ($load_classes && $self->use_namespaces) {
1338 $self->_upgrading_from_load_classes(1);
1340 elsif ((not $load_classes) && defined $self->use_namespaces && ! $self->use_namespaces) {
1341 $self->_downgrading_to_load_classes(
1342 $result_namespace || 'Result'
1345 elsif ((not defined $self->use_namespaces) || $self->use_namespaces) {
1346 if (not $self->result_namespace) {
1347 $self->result_namespace($result_namespace || 'Result');
1349 elsif ($result_namespace ne $self->result_namespace) {
1350 $self->_rewriting_result_namespace(
1351 $result_namespace || 'Result'
1356 # XXX when we go past .0 this will need fixing
1357 my ($v) = $old_ver =~ /([1-9])/;
1360 return if ($v eq $CURRENT_V || $old_ver =~ /^0\.\d\d999/);
1362 if (not %{ $self->naming }) {
1363 warn <<"EOF" unless $ENV{SCHEMA_LOADER_BACKCOMPAT};
1365 Version $old_ver static schema detected, turning on backcompat mode.
1367 Set the 'naming' attribute or the SCHEMA_LOADER_BACKCOMPAT environment variable
1368 to disable this warning.
1370 See: 'naming' in perldoc DBIx::Class::Schema::Loader::Base .
1372 See perldoc DBIx::Class::Schema::Loader::Manual::UpgradingFromV4 if upgrading
1373 from version 0.04006.
1376 $self->naming->{relationships} ||= $v;
1377 $self->naming->{monikers} ||= $v;
1378 $self->naming->{column_accessors} ||= $v;
1380 $self->schema_version_to_dump($old_ver);
1383 $self->_upgrading_from($v);
1387 sub _validate_class_args {
1390 foreach my $k (@CLASS_ARGS) {
1391 next unless $self->$k;
1393 my @classes = ref $self->$k eq 'ARRAY' ? @{ $self->$k } : $self->$k;
1394 $self->_validate_classes($k, \@classes);
1398 sub _validate_result_components_map {
1401 foreach my $classes (values %{ $self->result_components_map }) {
1402 $self->_validate_classes('result_components_map', $classes);
1406 sub _validate_result_roles_map {
1409 foreach my $classes (values %{ $self->result_roles_map }) {
1410 $self->_validate_classes('result_roles_map', $classes);
1414 sub _validate_classes {
1417 my $classes = shift;
1419 # make a copy to not destroy original
1420 my @classes = @$classes;
1422 foreach my $c (@classes) {
1423 # components default to being under the DBIx::Class namespace unless they
1424 # are preceded with a '+'
1425 if ( $key =~ m/component/ && $c !~ s/^\+// ) {
1426 $c = 'DBIx::Class::' . $c;
1429 # 1 == installed, 0 == not installed, undef == invalid classname
1430 my $installed = Class::Inspector->installed($c);
1431 if ( defined($installed) ) {
1432 if ( $installed == 0 ) {
1433 croak qq/$c, as specified in the loader option "$key", is not installed/;
1436 croak qq/$c, as specified in the loader option "$key", is an invalid class name/;
1442 sub _find_file_in_inc {
1443 my ($self, $file) = @_;
1445 foreach my $prefix (@INC) {
1446 my $fullpath = File::Spec->catfile($prefix, $file);
1447 # abs_path pure-perl fallback warns for non-existent files
1448 local $SIG{__WARN__} = sigwarn_silencer(qr/^stat\(.*\Q$file\E\)/);
1449 return $fullpath if -f $fullpath
1450 # abs_path throws on Windows for nonexistent files
1451 and (try { Cwd::abs_path($fullpath) }) ne
1452 ((try { Cwd::abs_path(File::Spec->catfile($self->dump_directory, $file)) }) || '');
1458 sub _find_class_in_inc {
1459 my ($self, $class) = @_;
1461 return $self->_find_file_in_inc(class_path($class));
1467 return $self->_upgrading_from
1468 || $self->_upgrading_from_load_classes
1469 || $self->_downgrading_to_load_classes
1470 || $self->_rewriting_result_namespace
1474 sub _rewrite_old_classnames {
1475 my ($self, $code) = @_;
1477 return $code unless $self->_rewriting;
1479 my %old_classes = reverse %{ $self->_upgrading_classes };
1481 my $re = join '|', keys %old_classes;
1482 $re = qr/\b($re)\b/;
1484 $code =~ s/$re/$old_classes{$1} || $1/eg;
1489 sub _load_external {
1490 my ($self, $class) = @_;
1492 return if $self->{skip_load_external};
1494 # so that we don't load our own classes, under any circumstances
1495 local *INC = [ grep $_ ne $self->dump_directory, @INC ];
1497 my $real_inc_path = $self->_find_class_in_inc($class);
1499 my $old_class = $self->_upgrading_classes->{$class}
1500 if $self->_rewriting;
1502 my $old_real_inc_path = $self->_find_class_in_inc($old_class)
1503 if $old_class && $old_class ne $class;
1505 return unless $real_inc_path || $old_real_inc_path;
1507 if ($real_inc_path) {
1508 # If we make it to here, we loaded an external definition
1509 warn qq/# Loaded external class definition for '$class'\n/
1512 my $code = $self->_rewrite_old_classnames(slurp_file $real_inc_path);
1514 if ($self->dynamic) { # load the class too
1515 eval_package_without_redefine_warnings($class, $code);
1518 $self->_ext_stmt($class,
1519 qq|# These lines were loaded from '$real_inc_path' found in \@INC.\n|
1520 .qq|# They are now part of the custom portion of this file\n|
1521 .qq|# for you to hand-edit. If you do not either delete\n|
1522 .qq|# this section or remove that file from \@INC, this section\n|
1523 .qq|# will be repeated redundantly when you re-create this\n|
1524 .qq|# file again via Loader! See skip_load_external to disable\n|
1525 .qq|# this feature.\n|
1528 $self->_ext_stmt($class, $code);
1529 $self->_ext_stmt($class,
1530 qq|# End of lines loaded from '$real_inc_path' |
1534 if ($old_real_inc_path) {
1535 my $code = slurp_file $old_real_inc_path;
1537 $self->_ext_stmt($class, <<"EOF");
1539 # These lines were loaded from '$old_real_inc_path',
1540 # based on the Result class name that would have been created by an older
1541 # version of the Loader. For a static schema, this happens only once during
1542 # upgrade. See skip_load_external to disable this feature.
1545 $code = $self->_rewrite_old_classnames($code);
1547 if ($self->dynamic) {
1550 Detected external content in '$old_real_inc_path', a class name that would have
1551 been used by an older version of the Loader.
1553 * PLEASE RENAME THIS CLASS: from '$old_class' to '$class', as that is the
1554 new name of the Result.
1556 eval_package_without_redefine_warnings($class, $code);
1560 $self->_ext_stmt($class, $code);
1561 $self->_ext_stmt($class,
1562 qq|# End of lines loaded from '$old_real_inc_path' |
1569 Does the actual schema-construction work.
1576 $self->_load_tables(
1577 $self->_tables_list({ constraint => $self->constraint, exclude => $self->exclude })
1585 Rescan the database for changes. Returns a list of the newly added table
1588 The schema argument should be the schema class or object to be affected. It
1589 should probably be derived from the original schema_class used during L</load>.
1594 my ($self, $schema) = @_;
1596 $self->{schema} = $schema;
1597 $self->_relbuilder->{schema} = $schema;
1600 my @current = $self->_tables_list({ constraint => $self->constraint, exclude => $self->exclude });
1602 foreach my $table (@current) {
1603 if(!exists $self->_tables->{$table->sql_name}) {
1604 push(@created, $table);
1609 @current{map $_->sql_name, @current} = ();
1610 foreach my $table (values %{ $self->_tables }) {
1611 if (not exists $current{$table->sql_name}) {
1612 $self->_remove_table($table);
1616 delete @$self{qw/_dump_storage _relations_started _uniqs_started/};
1618 my $loaded = $self->_load_tables(@current);
1620 foreach my $table (@created) {
1621 $self->monikers->{$table->sql_name} = $self->_table2moniker($table);
1624 return map { $self->monikers->{$_->sql_name} } @created;
1630 return if $self->{skip_relationships};
1632 return $self->{relbuilder} ||= do {
1633 my $relbuilder_suff =
1640 ->{$self->naming->{relationships}||$CURRENT_V} || '';
1642 my $relbuilder_class = 'DBIx::Class::Schema::Loader::RelBuilder'.$relbuilder_suff;
1643 $self->ensure_class_loaded($relbuilder_class);
1644 $relbuilder_class->new($self);
1649 my ($self, @tables) = @_;
1651 # Save the new tables to the tables list and compute monikers
1653 $self->_tables->{$_->sql_name} = $_;
1654 $self->monikers->{$_->sql_name} = $self->_table2moniker($_);
1657 # check for moniker clashes
1658 my $inverse_moniker_idx;
1659 foreach my $imtable (values %{ $self->_tables }) {
1660 push @{ $inverse_moniker_idx->{$self->monikers->{$imtable->sql_name}} }, $imtable;
1664 foreach my $moniker (keys %$inverse_moniker_idx) {
1665 my $imtables = $inverse_moniker_idx->{$moniker};
1666 if (@$imtables > 1) {
1667 my $different_databases =
1668 $imtables->[0]->can('database') && (uniq map $_->database||'', @$imtables) > 1;
1670 my $different_schemas =
1671 (uniq map $_->schema||'', @$imtables) > 1;
1673 if ($different_databases || $different_schemas) {
1674 my ($use_schema, $use_database) = (1, 0);
1676 if ($different_databases) {
1679 # If any monikers are in the same database, we have to distinguish by
1680 # both schema and database.
1682 $db_counts{$_}++ for map $_->database, @$imtables;
1683 $use_schema = any { $_ > 1 } values %db_counts;
1686 foreach my $tbl (@$imtables) { delete $self->monikers->{$tbl->sql_name}; }
1688 my $moniker_parts = [ @{ $self->moniker_parts } ];
1690 my $have_schema = any { $_ eq 'schema' } @{ $self->moniker_parts };
1691 my $have_database = any { $_ eq 'database' } @{ $self->moniker_parts };
1693 unshift @$moniker_parts, 'schema' if $use_schema && !$have_schema;
1694 unshift @$moniker_parts, 'database' if $use_database && !$have_database;
1696 local $self->{moniker_parts} = $moniker_parts;
1700 foreach my $tbl (@$imtables) { $new_monikers{$tbl->sql_name} = $self->_table2moniker($tbl); }
1701 foreach my $name (map $_->sql_name, @$imtables) { $self->monikers->{$name} = $new_monikers{$name}; }
1703 # check if there are still clashes
1706 while (my ($t, $m) = each %new_monikers) {
1707 push @{ $by_moniker{$m} }, $t;
1710 foreach my $m (grep @{ $by_moniker{$_} } > 1, keys %by_moniker) {
1711 push @clashes, sprintf ("tried disambiguating by moniker_parts, but tables %s still reduced to the same source moniker '%s'",
1712 join (', ', @{ $by_moniker{$m} }),
1718 push @clashes, sprintf ("tables %s reduced to the same source moniker '%s'",
1719 join (', ', map $_->sql_name, @$imtables),
1727 die 'Unable to load schema - chosen moniker/class naming style results in moniker clashes. '
1728 . 'Change the naming style, or supply an explicit moniker_map: '
1729 . join ('; ', @clashes)
1734 foreach my $tbl (@tables) { $self->_make_src_class($tbl); }
1735 foreach my $tbl (@tables) { $self->_setup_src_meta($tbl); }
1737 if(!$self->skip_relationships) {
1738 # The relationship loader needs a working schema
1739 local $self->{quiet} = 1;
1740 local $self->{dump_directory} = $self->{temp_directory};
1741 $self->_reload_classes(\@tables);
1742 $self->_load_relationships(\@tables);
1744 # Remove that temp dir from INC so it doesn't get reloaded
1745 @INC = grep $_ ne $self->dump_directory, @INC;
1748 foreach my $tbl (@tables) { $self->_load_roles($tbl); }
1749 foreach my $tbl (map { $self->classes->{$_->sql_name} } @tables) { $self->_load_external($tbl); }
1751 # Reload without unloading first to preserve any symbols from external
1753 $self->_reload_classes(\@tables, { unload => 0 });
1755 # Drop temporary cache
1756 delete $self->{_cache};
1761 sub _reload_classes {
1762 my ($self, $tables, $opts) = @_;
1764 my @tables = @$tables;
1766 my $unload = $opts->{unload};
1767 $unload = 1 unless defined $unload;
1769 # so that we don't repeat custom sections
1770 @INC = grep $_ ne $self->dump_directory, @INC;
1772 $self->_dump_to_dir(map { $self->classes->{$_->sql_name} } @tables);
1774 unshift @INC, $self->dump_directory;
1777 my %have_source = map { $_ => $self->schema->source($_) }
1778 $self->schema->sources;
1780 for my $table (@tables) {
1781 my $moniker = $self->monikers->{$table->sql_name};
1782 my $class = $self->classes->{$table->sql_name};
1785 no warnings 'redefine';
1786 local *Class::C3::reinitialize = sub {}; # to speed things up, reinitialized below
1789 if (my $mc = $self->_moose_metaclass($class)) {
1792 Class::Unload->unload($class) if $unload;
1793 my ($source, $resultset_class);
1795 ($source = $have_source{$moniker})
1796 && ($resultset_class = $source->resultset_class)
1797 && ($resultset_class ne 'DBIx::Class::ResultSet')
1799 my $has_file = Class::Inspector->loaded_filename($resultset_class);
1800 if (my $mc = $self->_moose_metaclass($resultset_class)) {
1803 Class::Unload->unload($resultset_class) if $unload;
1804 $self->_reload_class($resultset_class) if $has_file;
1806 $self->_reload_class($class);
1808 push @to_register, [$moniker, $class];
1811 Class::C3->reinitialize;
1812 for (@to_register) {
1813 $self->schema->register_class(@$_);
1817 sub _moose_metaclass {
1818 return undef unless $INC{'Class/MOP.pm'}; # if CMOP is not loaded the class could not have loaded in the 1st place
1822 my $mc = try { Class::MOP::class_of($class) }
1825 return $mc->isa('Moose::Meta::Class') ? $mc : undef;
1828 # We use this instead of ensure_class_loaded when there are package symbols we
1831 my ($self, $class) = @_;
1833 delete $INC{ +class_path($class) };
1836 eval_package_without_redefine_warnings ($class, "require $class");
1839 my $source = slurp_file $self->_get_dump_filename($class);
1840 die "Failed to reload class $class: $_.\n\nCLASS SOURCE:\n\n$source";
1844 sub _get_dump_filename {
1845 my ($self, $class) = (@_);
1847 $class =~ s{::}{/}g;
1848 return $self->dump_directory . q{/} . $class . q{.pm};
1851 =head2 get_dump_filename
1855 Returns the full path to the file for a class that the class has been or will
1856 be dumped to. This is a file in a temp dir for a dynamic schema.
1860 sub get_dump_filename {
1861 my ($self, $class) = (@_);
1863 local $self->{dump_directory} = $self->real_dump_directory;
1865 return $self->_get_dump_filename($class);
1868 sub _ensure_dump_subdirs {
1869 my ($self, $class) = (@_);
1871 my @name_parts = split(/::/, $class);
1872 pop @name_parts; # we don't care about the very last element,
1873 # which is a filename
1875 my $dir = $self->dump_directory;
1878 mkdir($dir) or croak "mkdir('$dir') failed: $!";
1880 last if !@name_parts;
1881 $dir = File::Spec->catdir($dir, shift @name_parts);
1886 my ($self, @classes) = @_;
1888 my $schema_class = $self->schema_class;
1889 my $schema_base_class = $self->schema_base_class || 'DBIx::Class::Schema';
1891 my $target_dir = $self->dump_directory;
1892 warn "Dumping manual schema for $schema_class to directory $target_dir ...\n"
1893 unless $self->dynamic or $self->quiet;
1897 . qq|package $schema_class;\n\n|
1898 . qq|# Created by DBIx::Class::Schema::Loader\n|
1899 . qq|# DO NOT MODIFY THE FIRST PART OF THIS FILE\n\n|;
1902 = $self->only_autoclean
1903 ? 'namespace::autoclean'
1904 : 'MooseX::MarkAsMethods autoclean => 1'
1907 if ($self->use_moose) {
1909 $schema_text.= qq|use Moose;\nuse $autoclean;\nextends '$schema_base_class';\n\n|;
1912 $schema_text .= qq|use strict;\nuse warnings;\n\nuse base '$schema_base_class';\n\n|;
1915 my @schema_components = @{ $self->schema_components || [] };
1917 if (@schema_components) {
1918 my $schema_components = dump @schema_components;
1919 $schema_components = "($schema_components)" if @schema_components == 1;
1921 $schema_text .= "__PACKAGE__->load_components${schema_components};\n\n";
1924 if ($self->use_namespaces) {
1925 $schema_text .= qq|__PACKAGE__->load_namespaces|;
1926 my $namespace_options;
1928 my @attr = qw/resultset_namespace default_resultset_class/;
1930 unshift @attr, 'result_namespace' unless (not $self->result_namespace) || $self->result_namespace eq 'Result';
1932 for my $attr (@attr) {
1934 my $code = dumper_squashed $self->$attr;
1935 $namespace_options .= qq| $attr => $code,\n|
1938 $schema_text .= qq|(\n$namespace_options)| if $namespace_options;
1939 $schema_text .= qq|;\n|;
1942 $schema_text .= qq|__PACKAGE__->load_classes;\n|;
1946 local $self->{version_to_dump} = $self->schema_version_to_dump;
1947 $self->_write_classfile($schema_class, $schema_text, 1);
1950 my $result_base_class = $self->result_base_class || 'DBIx::Class::Core';
1952 foreach my $src_class (@classes) {
1955 . qq|package $src_class;\n\n|
1956 . qq|# Created by DBIx::Class::Schema::Loader\n|
1957 . qq|# DO NOT MODIFY THE FIRST PART OF THIS FILE\n\n|;
1959 $src_text .= $self->_make_pod_heading($src_class);
1961 $src_text .= qq|use strict;\nuse warnings;\n\n|;
1963 $src_text .= $self->_base_class_pod($result_base_class)
1964 unless $result_base_class eq 'DBIx::Class::Core';
1966 if ($self->use_moose) {
1967 $src_text.= qq|use Moose;\nuse MooseX::NonMoose;\nuse $autoclean;|;
1969 # these options 'use base' which is compile time
1970 if (@{ $self->left_base_classes } || @{ $self->additional_base_classes }) {
1971 $src_text .= qq|\nBEGIN { extends '$result_base_class' }\n|;
1974 $src_text .= qq|\nextends '$result_base_class';\n|;
1978 $src_text .= qq|use base '$result_base_class';\n|;
1981 $self->_write_classfile($src_class, $src_text);
1984 # remove Result dir if downgrading from use_namespaces, and there are no
1986 if (my $result_ns = $self->_downgrading_to_load_classes
1987 || $self->_rewriting_result_namespace) {
1988 my $result_namespace = $self->_result_namespace(
1993 (my $result_dir = $result_namespace) =~ s{::}{/}g;
1994 $result_dir = $self->dump_directory . '/' . $result_dir;
1996 unless (my @files = glob "$result_dir/*") {
2001 warn "Schema dump completed.\n" unless $self->dynamic or $self->quiet;
2005 my ($self, $version, $ts) = @_;
2006 return qq|\n\n# Created by DBIx::Class::Schema::Loader|
2009 . qq|\n# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:|;
2012 sub _write_classfile {
2013 my ($self, $class, $text, $is_schema) = @_;
2015 my $filename = $self->_get_dump_filename($class);
2016 $self->_ensure_dump_subdirs($class);
2018 if (-f $filename && $self->really_erase_my_files) {
2019 warn "Deleting existing file '$filename' due to "
2020 . "'really_erase_my_files' setting\n" unless $self->quiet;
2024 my ($old_gen, $old_md5, $old_ver, $old_ts, $old_custom)
2025 = $self->_parse_generated_file($filename);
2027 if (! $old_gen && -f $filename) {
2028 croak "Cannot overwrite '$filename' without 'really_erase_my_files',"
2029 . " it does not appear to have been generated by Loader"
2032 my $custom_content = $old_custom || '';
2034 # Use custom content from a renamed class, the class names in it are
2036 if (my $renamed_class = $self->_upgrading_classes->{$class}) {
2037 my $old_filename = $self->_get_dump_filename($renamed_class);
2039 if (-f $old_filename) {
2040 $custom_content = ($self->_parse_generated_file ($old_filename))[4];
2042 unlink $old_filename;
2046 $custom_content ||= $self->_default_custom_content($is_schema);
2048 # If upgrading to use_moose=1 replace default custom content with default Moose custom content.
2049 # If there is already custom content, which does not have the Moose content, add it.
2050 if ($self->use_moose) {
2052 my $non_moose_custom_content = do {
2053 local $self->{use_moose} = 0;
2054 $self->_default_custom_content;
2057 if ($custom_content eq $non_moose_custom_content) {
2058 $custom_content = $self->_default_custom_content($is_schema);
2060 elsif ($custom_content !~ /\Q@{[$self->_default_moose_custom_content($is_schema)]}\E/) {
2061 $custom_content .= $self->_default_custom_content($is_schema);
2064 elsif (defined $self->use_moose && $old_gen) {
2065 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'
2066 if $old_gen =~ /use \s+ MooseX?\b/x;
2069 $custom_content = $self->_rewrite_old_classnames($custom_content);
2072 for @{$self->{_dump_storage}->{$class} || []};
2074 if ($self->filter_generated_code) {
2075 my $filter = $self->filter_generated_code;
2077 if (ref $filter eq 'CODE') {
2079 ($is_schema ? 'schema' : 'result'),
2085 my ($fh, $temp_file) = tempfile();
2087 binmode $fh, ':encoding(UTF-8)';
2091 open my $out, qq{$filter < "$temp_file"|}
2092 or croak "Could not open pipe to $filter: $!";
2094 $text = decode('UTF-8', do { local $/; <$out> });
2096 $text =~ s/$CR?$LF/\n/g;
2100 my $exit_code = $? >> 8;
2103 or croak "Could not remove temporary file '$temp_file': $!";
2105 if ($exit_code != 0) {
2106 croak "filter '$filter' exited non-zero: $exit_code";
2109 if (not $text or not $text =~ /\bpackage\b/) {
2110 warn("$class skipped due to filter") if $self->debug;
2115 # Check and see if the dump is in fact different
2119 $compare_to = $text . $self->_sig_comment($old_ver, $old_ts);
2120 if (Digest::MD5::md5_base64(encode 'UTF-8', $compare_to) eq $old_md5) {
2121 return unless $self->_upgrading_from && $is_schema;
2125 $text .= $self->_sig_comment(
2126 $self->version_to_dump,
2127 POSIX::strftime('%Y-%m-%d %H:%M:%S', localtime)
2130 open(my $fh, '>:encoding(UTF-8)', $filename)
2131 or croak "Cannot open '$filename' for writing: $!";
2133 # Write the top half and its MD5 sum
2134 print $fh $text . Digest::MD5::md5_base64(encode 'UTF-8', $text) . "\n";
2136 # Write out anything loaded via external partial class file in @INC
2138 for @{$self->{_ext_storage}->{$class} || []};
2140 # Write out any custom content the user has added
2141 print $fh $custom_content;
2144 or croak "Error closing '$filename': $!";
2147 sub _default_moose_custom_content {
2148 my ($self, $is_schema) = @_;
2150 if (not $is_schema) {
2151 return qq|\n__PACKAGE__->meta->make_immutable;|;
2154 return qq|\n__PACKAGE__->meta->make_immutable(inline_constructor => 0);|;
2157 sub _default_custom_content {
2158 my ($self, $is_schema) = @_;
2159 my $default = qq|\n\n# You can replace this text with custom|
2160 . qq| code or comments, and it will be preserved on regeneration|;
2161 if ($self->use_moose) {
2162 $default .= $self->_default_moose_custom_content($is_schema);
2164 $default .= qq|\n1;\n|;
2168 sub _parse_generated_file {
2169 my ($self, $fn) = @_;
2171 return unless -f $fn;
2173 open(my $fh, '<:encoding(UTF-8)', $fn)
2174 or croak "Cannot open '$fn' for reading: $!";
2177 qr{^(# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:)([A-Za-z0-9/+]{22})\r?\n};
2179 my ($md5, $ts, $ver, $gen);
2185 # Pull out the version and timestamp from the line above
2186 ($ver, $ts) = $gen =~ m/^# Created by DBIx::Class::Schema::Loader v(.*?) @ (.*?)\r?\Z/m;
2189 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"
2190 if !$self->overwrite_modifications && Digest::MD5::md5_base64(encode 'UTF-8', $gen) ne $md5;
2199 my $custom = do { local $/; <$fh> }
2203 $custom =~ s/$CRLF|$LF/\n/g;
2207 return ($gen, $md5, $ver, $ts, $custom);
2215 warn "$target: use $_;" if $self->debug;
2216 $self->_raw_stmt($target, "use $_;");
2224 my $blist = join(q{ }, @_);
2226 return unless $blist;
2228 warn "$target: use base qw/$blist/;" if $self->debug;
2229 $self->_raw_stmt($target, "use base qw/$blist/;");
2236 my $rlist = join(q{, }, map { qq{'$_'} } @_);
2238 return unless $rlist;
2240 warn "$target: with $rlist;" if $self->debug;
2241 $self->_raw_stmt($target, "\nwith $rlist;");
2244 sub _result_namespace {
2245 my ($self, $schema_class, $ns) = @_;
2246 my @result_namespace;
2248 $ns = $ns->[0] if ref $ns;
2250 if ($ns =~ /^\+(.*)/) {
2251 # Fully qualified namespace
2252 @result_namespace = ($1)
2255 # Relative namespace
2256 @result_namespace = ($schema_class, $ns);
2259 return wantarray ? @result_namespace : join '::', @result_namespace;
2262 # Create class with applicable bases, setup monikers, etc
2263 sub _make_src_class {
2264 my ($self, $table) = @_;
2266 my $schema = $self->schema;
2267 my $schema_class = $self->schema_class;
2269 my $table_moniker = $self->monikers->{$table->sql_name};
2270 my @result_namespace = ($schema_class);
2271 if ($self->use_namespaces) {
2272 my $result_namespace = $self->result_namespace || 'Result';
2273 @result_namespace = $self->_result_namespace(
2278 my $table_class = join(q{::}, @result_namespace, $table_moniker);
2280 if ((my $upgrading_v = $self->_upgrading_from)
2281 || $self->_rewriting) {
2282 local $self->naming->{monikers} = $upgrading_v
2285 my @result_namespace = @result_namespace;
2286 if ($self->_upgrading_from_load_classes) {
2287 @result_namespace = ($schema_class);
2289 elsif (my $ns = $self->_downgrading_to_load_classes) {
2290 @result_namespace = $self->_result_namespace(
2295 elsif ($ns = $self->_rewriting_result_namespace) {
2296 @result_namespace = $self->_result_namespace(
2302 my $old_table_moniker = do {
2303 local $self->naming->{monikers} = $upgrading_v;
2304 $self->_table2moniker($table);
2307 my $old_class = join(q{::}, @result_namespace, $old_table_moniker);
2309 $self->_upgrading_classes->{$table_class} = $old_class
2310 unless $table_class eq $old_class;
2313 $self->classes->{$table->sql_name} = $table_class;
2314 $self->moniker_to_table->{$table_moniker} = $table;
2315 $self->class_to_table->{$table_class} = $table;
2317 $self->_pod_class_list($table_class, 'ADDITIONAL CLASSES USED', @{$self->additional_classes});
2319 $self->_use ($table_class, @{$self->additional_classes});
2321 $self->_pod_class_list($table_class, 'LEFT BASE CLASSES', @{$self->left_base_classes});
2323 $self->_inject($table_class, @{$self->left_base_classes});
2325 my @components = @{ $self->components || [] };
2327 push @components, @{ $self->result_components_map->{$table_moniker} }
2328 if exists $self->result_components_map->{$table_moniker};
2330 my @fq_components = @components;
2331 foreach my $component (@fq_components) {
2332 if ($component !~ s/^\+//) {
2333 $component = "DBIx::Class::$component";
2337 $self->_pod_class_list($table_class, 'COMPONENTS LOADED', @fq_components);
2339 $self->_dbic_stmt($table_class, 'load_components', @components) if @components;
2341 $self->_pod_class_list($table_class, 'ADDITIONAL BASE CLASSES', @{$self->additional_base_classes});
2343 $self->_inject($table_class, @{$self->additional_base_classes});
2346 sub _is_result_class_method {
2347 my ($self, $name, $table) = @_;
2349 my $table_moniker = $table ? $self->monikers->{$table->sql_name} : '';
2351 $self->_result_class_methods({})
2352 if not defined $self->_result_class_methods;
2354 if (not exists $self->_result_class_methods->{$table_moniker}) {
2355 my (@methods, %methods);
2356 my $base = $self->result_base_class || 'DBIx::Class::Core';
2358 my @components = @{ $self->components || [] };
2360 push @components, @{ $self->result_components_map->{$table_moniker} }
2361 if exists $self->result_components_map->{$table_moniker};
2363 for my $c (@components) {
2364 $c = $c =~ /^\+/ ? substr($c,1) : "DBIx::Class::$c";
2367 my @roles = @{ $self->result_roles || [] };
2369 push @roles, @{ $self->result_roles_map->{$table_moniker} }
2370 if exists $self->result_roles_map->{$table_moniker};
2372 for my $class ($base, @components,
2373 ($self->use_moose ? 'Moose::Object' : ()), @roles) {
2374 $self->ensure_class_loaded($class);
2376 push @methods, @{ Class::Inspector->methods($class) || [] };
2379 push @methods, @{ Class::Inspector->methods('UNIVERSAL') };
2381 @methods{@methods} = ();
2383 $self->_result_class_methods->{$table_moniker} = \%methods;
2385 my $result_methods = $self->_result_class_methods->{$table_moniker};
2387 return exists $result_methods->{$name};
2390 sub _resolve_col_accessor_collisions {
2391 my ($self, $table, $col_info) = @_;
2393 while (my ($col, $info) = each %$col_info) {
2394 my $accessor = $info->{accessor} || $col;
2396 next if $accessor eq 'id'; # special case (very common column)
2398 if ($self->_is_result_class_method($accessor, $table)) {
2401 if (my $map = $self->col_collision_map) {
2402 for my $re (keys %$map) {
2403 if (my @matches = $col =~ /$re/) {
2404 $info->{accessor} = sprintf $map->{$re}, @matches;
2412 Column '$col' in table '$table' collides with an inherited method.
2413 See "COLUMN ACCESSOR COLLISIONS" in perldoc DBIx::Class::Schema::Loader::Base .
2415 $info->{accessor} = undef;
2421 # use the same logic to run moniker_map, col_accessor_map
2423 my ( $self, $map, $default_code, $ident, @extra ) = @_;
2425 my $default_ident = $default_code->( $ident, @extra );
2427 if( $map && ref $map eq 'HASH' ) {
2428 if (my @parts = try{ @{ $ident } }) {
2429 my $part_map = $map;
2431 my $part = shift @parts;
2432 last unless exists $part_map->{ $part };
2433 if ( !ref $part_map->{ $part } && !@parts ) {
2434 $new_ident = $part_map->{ $part };
2437 elsif ( ref $part_map->{ $part } eq 'HASH' ) {
2438 $part_map = $part_map->{ $part };
2442 if( !$new_ident && !ref $map->{ $ident } ) {
2443 $new_ident = $map->{ $ident };
2446 elsif( $map && ref $map eq 'CODE' ) {
2447 $new_ident = $map->( $ident, $default_ident, @extra );
2450 $new_ident ||= $default_ident;
2455 sub _default_column_accessor_name {
2456 my ( $self, $column_name ) = @_;
2458 my $preserve = ($self->naming->{column_accessors}||'') eq 'preserve';
2460 my $v = $self->_get_naming_v('column_accessors');
2462 my $accessor_name = $preserve ?
2463 $self->_to_identifier('column_accessors', $column_name) # assume CamelCase
2465 $self->_to_identifier('column_accessors', $column_name, '_');
2467 $accessor_name =~ s/\W+/_/g; # only if naming < v8, otherwise to_identifier
2471 return $accessor_name;
2473 elsif ($v < 7 || (not $self->preserve_case)) {
2474 # older naming just lc'd the col accessor and that's all.
2475 return lc $accessor_name;
2478 return join '_', map lc, split_name $column_name, $v;
2481 sub _make_column_accessor_name {
2482 my ($self, $column_name, $column_context_info ) = @_;
2484 my $accessor = $self->_run_user_map(
2485 $self->col_accessor_map,
2486 sub { $self->_default_column_accessor_name( shift ) },
2488 $column_context_info,
2494 sub _table_is_view {
2495 #my ($self, $table) = @_;
2499 # Set up metadata (cols, pks, etc)
2500 sub _setup_src_meta {
2501 my ($self, $table) = @_;
2503 my $schema = $self->schema;
2504 my $schema_class = $self->schema_class;
2506 my $table_class = $self->classes->{$table->sql_name};
2507 my $table_moniker = $self->monikers->{$table->sql_name};
2509 $self->_dbic_stmt($table_class, 'table_class', 'DBIx::Class::ResultSource::View')
2510 if $self->_table_is_view($table);
2512 $self->_dbic_stmt($table_class, 'table', $table->dbic_name);
2514 my $cols = $self->_table_columns($table);
2515 my $col_info = $self->__columns_info_for($table);
2517 ### generate all the column accessor names
2518 while (my ($col, $info) = each %$col_info) {
2519 # hashref of other info that could be used by
2520 # user-defined accessor map functions
2522 table_class => $table_class,
2523 table_moniker => $table_moniker,
2524 table_name => $table, # bugwards compatibility, RT#84050
2526 full_table_name => $table->dbic_name,
2527 schema_class => $schema_class,
2528 column_info => $info,
2531 $info->{accessor} = $self->_make_column_accessor_name( $col, $context );
2534 $self->_resolve_col_accessor_collisions($table, $col_info);
2536 # prune any redundant accessor names
2537 while (my ($col, $info) = each %$col_info) {
2538 no warnings 'uninitialized';
2539 delete $info->{accessor} if $info->{accessor} eq $col;
2542 my $fks = $self->_table_fk_info($table);
2544 foreach my $fkdef (@$fks) {
2545 for my $col (@{ $fkdef->{local_columns} }) {
2546 $col_info->{$col}{is_foreign_key} = 1;
2550 my $pks = $self->_table_pk_info($table) || [];
2552 my %uniq_tag; # used to eliminate duplicate uniqs
2554 $uniq_tag{ join("\0", @$pks) }++ if @$pks; # pk is a uniq
2556 my $uniqs = $self->_table_uniq_info($table) || [];
2559 foreach my $uniq (@$uniqs) {
2560 my ($name, $cols) = @$uniq;
2561 next if $uniq_tag{ join("\0", @$cols) }++; # skip duplicates
2562 push @uniqs, [$name, $cols];
2565 my @non_nullable_uniqs = grep {
2566 all { $col_info->{$_}{is_nullable} == 0 } @{ $_->[1] }
2569 if ($self->uniq_to_primary && (not @$pks) && @non_nullable_uniqs) {
2570 my @by_colnum = sort { $b->[0] <=> $a->[0] }
2571 map [ scalar @{ $_->[1] }, $_ ], @non_nullable_uniqs;
2573 if (not (@by_colnum > 1 && $by_colnum[0][0] == $by_colnum[1][0])) {
2574 my @keys = map $_->[1], @by_colnum;
2578 # remove the uniq from list
2579 @uniqs = grep { $_->[0] ne $pk->[0] } @uniqs;
2585 foreach my $pkcol (@$pks) {
2586 $col_info->{$pkcol}{is_nullable} = 0;
2592 map { $_, ($col_info->{$_}||{}) } @$cols
2595 $self->_dbic_stmt($table_class, 'set_primary_key', @$pks)
2598 # Sort unique constraints by constraint name for repeatable results (rels
2599 # are sorted as well elsewhere.)
2600 @uniqs = sort { $a->[0] cmp $b->[0] } @uniqs;
2602 foreach my $uniq (@uniqs) {
2603 my ($name, $cols) = @$uniq;
2604 $self->_dbic_stmt($table_class,'add_unique_constraint', $name, $cols);
2608 sub __columns_info_for {
2609 my ($self, $table) = @_;
2611 my $result = $self->_columns_info_for($table);
2613 while (my ($col, $info) = each %$result) {
2614 $info = { %$info, %{ $self->_custom_column_info ($table, $col, $info) } };
2615 $info = { %$info, %{ $self->_datetime_column_info($table, $col, $info) } };
2617 $result->{$col} = $info;
2625 Returns a sorted list of loaded tables, using the original database table
2633 return values %{$self->_tables};
2637 my ($self, $naming_key) = @_;
2641 if (($self->naming->{$naming_key}||'') =~ /^v(\d+)\z/) {
2645 ($v) = $CURRENT_V =~ /^v(\d+)\z/;
2651 sub _to_identifier {
2652 my ($self, $naming_key, $name, $sep_char, $force) = @_;
2654 my $v = $self->_get_naming_v($naming_key);
2656 my $to_identifier = $self->naming->{force_ascii} ?
2657 \&String::ToIdentifier::EN::to_identifier
2658 : \&String::ToIdentifier::EN::Unicode::to_identifier;
2660 return $v >= 8 || $force ? $to_identifier->($name, $sep_char) : $name;
2663 # Make a moniker from a table
2664 sub _default_table2moniker {
2665 my ($self, $table) = @_;
2667 my $v = $self->_get_naming_v('monikers');
2669 my @moniker_parts = @{ $self->moniker_parts };
2670 my @name_parts = map $table->$_, @moniker_parts;
2672 my $name_idx = firstidx { $_ eq 'name' } @{ $self->moniker_parts };
2676 foreach my $i (0 .. $#name_parts) {
2677 my $part = $name_parts[$i];
2679 my $moniker_part = $self->_run_user_map(
2680 $self->moniker_part_map->{$moniker_parts[$i]},
2682 $part, $moniker_parts[$i],
2684 if (length $moniker_part) {
2685 push @all_parts, $moniker_part;
2689 if ($i != $name_idx || $v >= 8) {
2690 $part = $self->_to_identifier('monikers', $part, '_', 1);
2693 if ($i == $name_idx && $v == 5) {
2694 $part = Lingua::EN::Inflect::Number::to_S($part);
2697 my @part_parts = map lc, $v > 6 ?
2698 # use v8 semantics for all moniker parts except name
2699 ($i == $name_idx ? split_name $part, $v : split_name $part)
2700 : split /[\W_]+/, $part;
2702 if ($i == $name_idx && $v >= 6) {
2703 my $as_phrase = join ' ', @part_parts;
2705 my $inflected = ($self->naming->{monikers}||'') eq 'plural' ?
2706 Lingua::EN::Inflect::Phrase::to_PL($as_phrase)
2708 ($self->naming->{monikers}||'') eq 'preserve' ?
2711 Lingua::EN::Inflect::Phrase::to_S($as_phrase);
2713 @part_parts = split /\s+/, $inflected;
2716 push @all_parts, join '', map ucfirst, @part_parts;
2719 return join $self->moniker_part_separator, @all_parts;
2722 sub _table2moniker {
2723 my ( $self, $table ) = @_;
2725 $self->_run_user_map(
2727 sub { $self->_default_table2moniker( shift ) },
2732 sub _load_relationships {
2733 my ($self, $tables) = @_;
2737 foreach my $table (@$tables) {
2738 my $local_moniker = $self->monikers->{$table->sql_name};
2740 my $tbl_fk_info = $self->_table_fk_info($table);
2742 foreach my $fkdef (@$tbl_fk_info) {
2743 $fkdef->{local_table} = $table;
2744 $fkdef->{local_moniker} = $local_moniker;
2745 $fkdef->{remote_source} =
2746 $self->monikers->{$fkdef->{remote_table}->sql_name};
2748 my $tbl_uniq_info = $self->_table_uniq_info($table);
2750 push @tables, [ $local_moniker, $tbl_fk_info, $tbl_uniq_info ];
2753 my $rel_stmts = $self->_relbuilder->generate_code(\@tables);
2755 foreach my $src_class (sort keys %$rel_stmts) {
2757 my @src_stmts = map $_->[2],
2763 ($_->{method} eq 'many_to_many' ? 1 : 0),
2766 ], @{ $rel_stmts->{$src_class} };
2768 foreach my $stmt (@src_stmts) {
2769 $self->_dbic_stmt($src_class,$stmt->{method}, @{$stmt->{args}});
2775 my ($self, $table) = @_;
2777 my $table_moniker = $self->monikers->{$table->sql_name};
2778 my $table_class = $self->classes->{$table->sql_name};
2780 my @roles = @{ $self->result_roles || [] };
2781 push @roles, @{ $self->result_roles_map->{$table_moniker} }
2782 if exists $self->result_roles_map->{$table_moniker};
2785 $self->_pod_class_list($table_class, 'L<Moose> ROLES APPLIED', @roles);
2787 $self->_with($table_class, @roles);
2791 # Overload these in driver class:
2793 # Returns an arrayref of column names
2794 sub _table_columns { croak "ABSTRACT METHOD" }
2796 # Returns arrayref of pk col names
2797 sub _table_pk_info { croak "ABSTRACT METHOD" }
2799 # Returns an arrayref of uniqs [ [ foo => [ col1, col2 ] ], [ bar => [ ... ] ] ]
2800 sub _table_uniq_info { croak "ABSTRACT METHOD" }
2802 # Returns an arrayref of foreign key constraints, each
2803 # being a hashref with 3 keys:
2804 # local_columns (arrayref), remote_columns (arrayref), remote_table
2805 sub _table_fk_info { croak "ABSTRACT METHOD" }
2807 # Returns an array of lower case table names
2808 sub _tables_list { croak "ABSTRACT METHOD" }
2810 # Execute a constructive DBIC class method, with debug/dump_to_dir hooks.
2816 # generate the pod for this statement, storing it with $self->_pod
2817 $self->_make_pod( $class, $method, @_ ) if $self->generate_pod;
2819 my $args = dump(@_);
2820 $args = '(' . $args . ')' if @_ < 2;
2821 my $stmt = $method . $args . q{;};
2823 warn qq|$class\->$stmt\n| if $self->debug;
2824 $self->_raw_stmt($class, '__PACKAGE__->' . $stmt);
2828 sub _make_pod_heading {
2829 my ($self, $class) = @_;
2831 return '' if not $self->generate_pod;
2833 my $table = $self->class_to_table->{$class};
2836 my $pcm = $self->pod_comment_mode;
2837 my ($comment, $comment_overflows, $comment_in_name, $comment_in_desc);
2838 $comment = $self->__table_comment($table);
2839 $comment_overflows = ($comment and length $comment > $self->pod_comment_spillover_length);
2840 $comment_in_name = ($pcm eq 'name' or ($pcm eq 'auto' and !$comment_overflows));
2841 $comment_in_desc = ($pcm eq 'description' or ($pcm eq 'auto' and $comment_overflows));
2843 $pod .= "=head1 NAME\n\n";
2845 my $table_descr = $class;
2846 $table_descr .= " - " . $comment if $comment and $comment_in_name;
2848 $pod .= "$table_descr\n\n";
2850 if ($comment and $comment_in_desc) {
2851 $pod .= "=head1 DESCRIPTION\n\n${comment}\n\n";
2858 # generates the accompanying pod for a DBIC class method statement,
2859 # storing it with $self->_pod
2865 if ($method eq 'table') {
2867 $table = $$table if ref $table eq 'SCALAR';
2868 $self->_pod($class, "=head1 TABLE: C<$table>");
2869 $self->_pod_cut($class);
2871 elsif ( $method eq 'add_columns' ) {
2872 $self->_pod( $class, "=head1 ACCESSORS" );
2873 my $col_counter = 0;
2875 while( my ($name,$attrs) = splice @cols,0,2 ) {
2877 $self->_pod( $class, '=head2 ' . $name );
2878 $self->_pod( $class,
2880 my $s = $attrs->{$_};
2881 $s = !defined $s ? 'undef' :
2882 length($s) == 0 ? '(empty string)' :
2883 ref($s) eq 'SCALAR' ? $$s :
2884 ref($s) ? dumper_squashed $s :
2885 looks_like_number($s) ? $s : qq{'$s'};
2888 } sort keys %$attrs,
2890 if (my $comment = $self->__column_comment($self->class_to_table->{$class}, $col_counter, $name)) {
2891 $self->_pod( $class, $comment );
2894 $self->_pod_cut( $class );
2895 } elsif ( $method =~ /^(?:belongs_to|has_many|might_have)\z/ ) {
2896 $self->_pod( $class, "=head1 RELATIONS" ) unless $self->{_relations_started} { $class } ;
2897 my ( $accessor, $rel_class ) = @_;
2898 $self->_pod( $class, "=head2 $accessor" );
2899 $self->_pod( $class, 'Type: ' . $method );
2900 $self->_pod( $class, "Related object: L<$rel_class>" );
2901 $self->_pod_cut( $class );
2902 $self->{_relations_started} { $class } = 1;
2903 } elsif ( $method eq 'many_to_many' ) {
2904 $self->_pod( $class, "=head1 RELATIONS" ) unless $self->{_relations_started} { $class } ;
2905 my ( $accessor, $rel1, $rel2 ) = @_;
2906 $self->_pod( $class, "=head2 $accessor" );
2907 $self->_pod( $class, 'Type: many_to_many' );
2908 $self->_pod( $class, "Composing rels: L</$rel1> -> $rel2" );
2909 $self->_pod_cut( $class );
2910 $self->{_relations_started} { $class } = 1;
2912 elsif ($method eq 'add_unique_constraint') {
2913 $self->_pod($class, '=head1 UNIQUE CONSTRAINTS')
2914 unless $self->{_uniqs_started}{$class};
2916 my ($name, $cols) = @_;
2918 $self->_pod($class, "=head2 C<$name>");
2919 $self->_pod($class, '=over 4');
2921 foreach my $col (@$cols) {
2922 $self->_pod($class, "=item \* L</$col>");
2925 $self->_pod($class, '=back');
2926 $self->_pod_cut($class);
2928 $self->{_uniqs_started}{$class} = 1;
2930 elsif ($method eq 'set_primary_key') {
2931 $self->_pod($class, "=head1 PRIMARY KEY");
2932 $self->_pod($class, '=over 4');
2934 foreach my $col (@_) {
2935 $self->_pod($class, "=item \* L</$col>");
2938 $self->_pod($class, '=back');
2939 $self->_pod_cut($class);
2943 sub _pod_class_list {
2944 my ($self, $class, $title, @classes) = @_;
2946 return unless @classes && $self->generate_pod;
2948 $self->_pod($class, "=head1 $title");
2949 $self->_pod($class, '=over 4');
2951 foreach my $link (@classes) {
2952 $self->_pod($class, "=item * L<$link>");
2955 $self->_pod($class, '=back');
2956 $self->_pod_cut($class);
2959 sub _base_class_pod {
2960 my ($self, $base_class) = @_;
2962 return '' unless $self->generate_pod;
2965 =head1 BASE CLASS: L<$base_class>
2972 sub _filter_comment {
2973 my ($self, $txt) = @_;
2975 $txt = '' if not defined $txt;
2977 $txt =~ s/(?:\015?\012|\015\012?)/\n/g;
2982 sub __table_comment {
2985 if (my $code = $self->can('_table_comment')) {
2986 return $self->_filter_comment($self->$code(@_));
2992 sub __column_comment {
2995 if (my $code = $self->can('_column_comment')) {
2996 return $self->_filter_comment($self->$code(@_));
3002 # Stores a POD documentation
3004 my ($self, $class, $stmt) = @_;
3005 $self->_raw_stmt( $class, "\n" . $stmt );
3009 my ($self, $class ) = @_;
3010 $self->_raw_stmt( $class, "\n=cut\n" );
3013 # Store a raw source line for a class (for dumping purposes)
3015 my ($self, $class, $stmt) = @_;
3016 push(@{$self->{_dump_storage}->{$class}}, $stmt);
3019 # Like above, but separately for the externally loaded stuff
3021 my ($self, $class, $stmt) = @_;
3022 push(@{$self->{_ext_storage}->{$class}}, $stmt);
3025 sub _custom_column_info {
3026 my ( $self, $table_name, $column_name, $column_info ) = @_;
3028 if (my $code = $self->custom_column_info) {
3029 return $code->($table_name, $column_name, $column_info) || {};
3034 sub _datetime_column_info {
3035 my ( $self, $table_name, $column_name, $column_info ) = @_;
3037 my $type = $column_info->{data_type} || '';
3038 if ((grep $_, @{ $column_info }{map "inflate_$_", qw/date datetime timestamp/})
3039 or ($type =~ /date|timestamp/i)) {
3040 $result->{timezone} = $self->datetime_timezone if $self->datetime_timezone;
3041 $result->{locale} = $self->datetime_locale if $self->datetime_locale;
3047 my ($self, $name) = @_;
3049 return $self->preserve_case ? $name : lc($name);
3053 my ($self, $name) = @_;
3055 return $self->preserve_case ? $name : uc($name);
3059 my ($self, $table) = @_;
3062 my $schema = $self->schema;
3063 # in older DBIC it's a private method
3064 my $unregister = $schema->can('unregister_source') || $schema->can('_unregister_source');
3065 $schema->$unregister(delete $self->monikers->{$table->sql_name});
3066 delete $self->_upgrading_classes->{delete $self->classes->{$table->sql_name}};
3067 delete $self->_tables->{$table->sql_name};
3071 # remove the dump dir from @INC on destruction
3075 @INC = grep $_ ne $self->dump_directory, @INC;
3080 Returns a hashref of loaded table to moniker mappings. There will
3081 be two entries for each table, the original name and the "normalized"
3082 name, in the case that the two are different (such as databases
3083 that like uppercase table names, or preserve your original mixed-case
3084 definitions, or what-have-you).
3088 Returns a hashref of table to class mappings. In some cases it will
3089 contain multiple entries per table for the original and normalized table
3090 names, as above in L</monikers>.
3092 =head1 NON-ENGLISH DATABASES
3094 If you use the loader on a database with table and column names in a language
3095 other than English, you will want to turn off the English language specific
3098 To do so, use something like this in your loader options:
3100 naming => { monikers => 'v4' },
3101 inflect_singular => sub { "$_[0]_rel" },
3102 inflect_plural => sub { "$_[0]_rel" },
3104 =head1 COLUMN ACCESSOR COLLISIONS
3106 Occasionally you may have a column name that collides with a perl method, such
3107 as C<can>. In such cases, the default action is to set the C<accessor> of the
3108 column spec to C<undef>.
3110 You can then name the accessor yourself by placing code such as the following
3113 __PACKAGE__->add_column('+can' => { accessor => 'my_can' });
3115 Another option is to use the L</col_collision_map> option.
3117 =head1 RELATIONSHIP NAME COLLISIONS
3119 In very rare cases, you may get a collision between a generated relationship
3120 name and a method in your Result class, for example if you have a foreign key
3121 called C<belongs_to>.
3123 This is a problem because relationship names are also relationship accessor
3124 methods in L<DBIx::Class>.
3126 The default behavior is to append C<_rel> to the relationship name and print
3127 out a warning that refers to this text.
3129 You can also control the renaming with the L</rel_collision_map> option.
3133 L<DBIx::Class::Schema::Loader>, L<dbicdump>
3137 See L<DBIx::Class::Schema::Loader/AUTHOR> and L<DBIx::Class::Schema::Loader/CONTRIBUTORS>.
3141 This library is free software; you can redistribute it and/or modify it under
3142 the same terms as Perl itself.
3147 # vim:et sts=4 sw=4 tw=0: