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.07038';
34 __PACKAGE__->mk_group_ro_accessors('simple', qw/
41 additional_base_classes
57 default_resultset_class
63 overwrite_modifications
87 __PACKAGE__->mk_group_accessors('simple', qw/
89 schema_version_to_dump
91 _upgrading_from_load_classes
92 _downgrading_to_load_classes
93 _rewriting_result_namespace
98 pod_comment_spillover_length
104 result_components_map
106 datetime_undef_if_invalid
107 _result_class_methods
109 filter_generated_code
113 moniker_part_separator
117 my $CURRENT_V = 'v7';
120 schema_components schema_base_class result_base_class
121 additional_base_classes left_base_classes additional_classes components
127 my $CRLF = "\x0d\x0a";
131 DBIx::Class::Schema::Loader::Base - Base DBIx::Class::Schema::Loader Implementation.
135 See L<DBIx::Class::Schema::Loader>.
139 This is the base class for the storage-specific C<DBIx::Class::Schema::*>
140 classes, and implements the common functionality between them.
142 =head1 CONSTRUCTOR OPTIONS
144 These constructor options are the base options for
145 L<DBIx::Class::Schema::Loader/loader_options>. Available constructor options are:
147 =head2 skip_relationships
149 Skip setting up relationships. The default is to attempt the loading
152 =head2 skip_load_external
154 Skip loading of other classes in @INC. The default is to merge all other classes
155 with the same name found in @INC into the schema file we are creating.
159 Static schemas (ones dumped to disk) will, by default, use the new-style
160 relationship names and singularized Results, unless you're overwriting an
161 existing dump made by an older version of L<DBIx::Class::Schema::Loader>, in
162 which case the backward compatible RelBuilder will be activated, and the
163 appropriate monikerization used.
169 will disable the backward-compatible RelBuilder and use
170 the new-style relationship names along with singularized Results, even when
171 overwriting a dump made with an earlier version.
173 The option also takes a hashref:
176 relationships => 'v8',
178 column_accessors => 'v8',
184 naming => { ALL => 'v8', force_ascii => 1 }
192 Set L</relationships>, L</monikers> and L</column_accessors> to the specified
197 How to name relationship accessors.
201 How to name Result classes.
203 =item column_accessors
205 How to name column accessors in Result classes.
209 For L</v8> mode and later, uses L<String::ToIdentifier::EN> instead of
210 L<String::ToIdentifier::EM::Unicode> to force monikers and other identifiers to
221 Latest style, whatever that happens to be.
225 Unsingularlized monikers, C<has_many> only relationships with no _id stripping.
229 Monikers singularized as whole words, C<might_have> relationships for FKs on
230 C<UNIQUE> constraints, C<_id> stripping for belongs_to relationships.
232 Some of the C<_id> stripping edge cases in C<0.05003> have been reverted for
237 All monikers and relationships are inflected using
238 L<Lingua::EN::Inflect::Phrase>, and there is more aggressive C<_id> stripping
239 from relationship names.
241 In general, there is very little difference between v5 and v6 schemas.
245 This mode is identical to C<v6> mode, except that monikerization of CamelCase
246 table names is also done better (but best in v8.)
248 CamelCase column names in case-preserving mode will also be handled better
249 for relationship name inflection (but best in v8.) See L</preserve_case>.
251 In this mode, CamelCase L</column_accessors> are normalized based on case
252 transition instead of just being lowercased, so C<FooId> becomes C<foo_id>.
258 The default mode is L</v7>, to get L</v8> mode, you have to specify it in
259 L</naming> explicitly until C<0.08> comes out.
261 L</monikers> and L</column_accessors> are created using
262 L<String::ToIdentifier::EN::Unicode> or L<String::ToIdentifier::EN> if
263 L</force_ascii> is set; this is only significant for names with non-C<\w>
264 characters such as C<.>.
266 CamelCase identifiers with words in all caps, e.g. C<VLANValidID> are supported
267 correctly in this mode.
269 For relationships, belongs_to accessors are made from column names by stripping
270 postfixes other than C<_id> as well, for example just C<Id>, C<_?ref>, C<_?cd>,
271 C<_?code> and C<_?num>, case insensitively.
275 For L</monikers>, this option does not inflect the table names but makes
276 monikers based on the actual name. For L</column_accessors> this option does
277 not normalize CamelCase column names to lowercase column accessors, but makes
278 accessors that are the same names as the columns (with any non-\w chars
279 replaced with underscores.)
283 For L</monikers>, singularizes the names using the most current inflector. This
284 is the same as setting the option to L</current>.
288 For L</monikers>, pluralizes the names, using the most current inflector.
292 Dynamic schemas will always default to the 0.04XXX relationship names and won't
293 singularize Results for backward compatibility, to activate the new RelBuilder
294 and singularization put this in your C<Schema.pm> file:
296 __PACKAGE__->naming('current');
298 Or if you prefer to use 0.07XXX features but insure that nothing breaks in the
299 next major version upgrade:
301 __PACKAGE__->naming('v7');
305 If true, will not print the usual C<Dumping manual schema ... Schema dump
306 completed.> messages. Does not affect warnings (except for warnings related to
307 L</really_erase_my_files>.)
311 By default POD will be generated for columns and relationships, using database
312 metadata for the text if available and supported.
314 Comment metadata can be stored in two ways.
316 The first is that you can create two tables named C<table_comments> and
317 C<column_comments> respectively. These tables must exist in the same database
318 and schema as the tables they describe. They both need to have columns named
319 C<table_name> and C<comment_text>. The second one needs to have a column named
320 C<column_name>. Then data stored in these tables will be used as a source of
321 metadata about tables and comments.
323 (If you wish you can change the name of these tables with the parameters
324 L</table_comments_table> and L</column_comments_table>.)
326 As a fallback you can use built-in commenting mechanisms. Currently this is
327 only supported for PostgreSQL, Oracle and MySQL. To create comments in
328 PostgreSQL you add statements of the form C<COMMENT ON TABLE some_table IS
329 '...'>, the same syntax is used in Oracle. To create comments in MySQL you add
330 C<COMMENT '...'> to the end of the column or table definition. Note that MySQL
331 restricts the length of comments, and also does not handle complex Unicode
334 Set this to C<0> to turn off all POD generation.
336 =head2 pod_comment_mode
338 Controls where table comments appear in the generated POD. Smaller table
339 comments are appended to the C<NAME> section of the documentation, and larger
340 ones are inserted into C<DESCRIPTION> instead. You can force a C<DESCRIPTION>
341 section to be generated with the comment always, only use C<NAME>, or choose
342 the length threshold at which the comment is forced into the description.
348 Use C<NAME> section only.
352 Force C<DESCRIPTION> always.
356 Use C<DESCRIPTION> if length > L</pod_comment_spillover_length>, this is the
361 =head2 pod_comment_spillover_length
363 When pod_comment_mode is set to C<auto>, this is the length of the comment at
364 which it will be forced into a separate description section.
368 =head2 table_comments_table
370 The table to look for comments about tables in. By default C<table_comments>.
371 See L</generate_pod> for details.
373 This must not be a fully qualified name, the table will be looked for in the
374 same database and schema as the table whose comment is being retrieved.
376 =head2 column_comments_table
378 The table to look for comments about columns in. By default C<column_comments>.
379 See L</generate_pod> for details.
381 This must not be a fully qualified name, the table will be looked for in the
382 same database and schema as the table/column whose comment is being retrieved.
384 =head2 relationship_attrs
386 Hashref of attributes to pass to each generated relationship, listed by type.
387 Also supports relationship type 'all', containing options to pass to all
388 generated relationships. Attributes set for more specific relationship types
389 override those set in 'all', and any attributes specified by this option
390 override the introspected attributes of the foreign key if any.
394 relationship_attrs => {
395 has_many => { cascade_delete => 1, cascade_copy => 1 },
396 might_have => { cascade_delete => 1, cascade_copy => 1 },
399 use this to turn L<DBIx::Class> cascades to on on your
400 L<has_many|DBIx::Class::Relationship/has_many> and
401 L<might_have|DBIx::Class::Relationship/might_have> relationships, they default
404 Can also be a coderef, for more precise control, in which case the coderef gets
405 this hash of parameters (as a list:)
407 rel_name # the name of the relationship
408 rel_type # the type of the relationship: 'belongs_to', 'has_many' or 'might_have'
409 local_source # the DBIx::Class::ResultSource object for the source the rel is *from*
410 remote_source # the DBIx::Class::ResultSource object for the source the rel is *to*
411 local_table # a DBIx::Class::Schema::Loader::Table object for the table of the source the rel is from
412 local_cols # an arrayref of column names of columns used in the rel in the source it is from
413 remote_table # a DBIx::Class::Schema::Loader::Table object for the table of the source the rel is to
414 remote_cols # an arrayref of column names of columns used in the rel in the source it is to
415 attrs # the attributes that would be set
417 it should return the new hashref of attributes, or nothing for no changes.
421 relationship_attrs => sub {
424 say "the relationship name is: $p{rel_name}";
425 say "the relationship is a: $p{rel_type}";
426 say "the local class is: ", $p{local_source}->result_class;
427 say "the remote class is: ", $p{remote_source}->result_class;
428 say "the local table is: ", $p{local_table}->sql_name;
429 say "the rel columns in the local table are: ", (join ", ", @{$p{local_cols}});
430 say "the remote table is: ", $p{remote_table}->sql_name;
431 say "the rel columns in the remote table are: ", (join ", ", @{$p{remote_cols}});
433 if ($p{local_table} eq 'dogs' && @{$p{local_cols}} == 1 && $p{local_cols}[0] eq 'name') {
434 $p{attrs}{could_be_snoopy} = 1;
440 These are the default attributes:
451 on_delete => 'CASCADE',
452 on_update => 'CASCADE',
456 For L<belongs_to|DBIx::Class::Relationship/belongs_to> relationships, these
457 defaults are overridden by the attributes introspected from the foreign key in
458 the database, if this information is available (and the driver is capable of
461 This information overrides the defaults mentioned above, and is then itself
462 overridden by the user's L</relationship_attrs> for C<belongs_to> if any are
465 In general, for most databases, for a plain foreign key with no rules, the
466 values for a L<belongs_to|DBIx::Class::Relationship/belongs_to> relationship
469 on_delete => 'NO ACTION',
470 on_update => 'NO ACTION',
473 In the cases where an attribute is not supported by the DB, a value matching
474 the actual behavior is used, for example Oracle does not support C<ON UPDATE>
475 rules, so C<on_update> is set to C<NO ACTION>. This is done so that the
476 behavior of the schema is preserved when cross deploying to a different RDBMS
477 such as SQLite for testing.
479 In the cases where the DB does not support C<DEFERRABLE> foreign keys, the
480 value is set to C<1> if L<DBIx::Class> has a working C<<
481 $storage->with_deferred_fk_checks >>. This is done so that the same
482 L<DBIx::Class> code can be used, and cross deployed from and to such databases.
486 If set to true, each constructive L<DBIx::Class> statement the loader
487 decides to execute will be C<warn>-ed before execution.
491 Set the name of the schema to load (schema in the sense that your database
494 Can be set to an arrayref of schema names for multiple schemas, or the special
495 value C<%> for all schemas.
497 For MSSQL, Sybase ASE, and Informix can be set to a hashref of databases as
498 keys and arrays of owners as values, set to the value:
502 for all owners in all databases.
504 Name clashes resulting from the same table name in different databases/schemas
505 will be resolved automatically by prefixing the moniker with the database
508 To prefix/suffix all monikers with the database and/or schema, see
513 The database table names are represented by the
514 L<DBIx::Class::Schema::Loader::Table> class in the loader, the
515 L<DBIx::Class::Schema::Loader::Table::Sybase> class for Sybase ASE and
516 L<DBIx::Class::Schema::Loader::Table::Informix> for Informix.
518 Monikers are created normally based on just the
519 L<name|DBIx::Class::Schema::Loader::DBObject/name> property, corresponding to
520 the table name, but can consist of other parts of the fully qualified name of
523 The L</moniker_parts> option is an arrayref of methods on the table class
524 corresponding to parts of the fully qualified table name, defaulting to
525 C<['name']>, in the order those parts are used to create the moniker name.
526 The parts are joined together using L</moniker_part_separator>.
528 The C<'name'> entry B<must> be present.
530 Below is a table of supported databases and possible L</moniker_parts>.
534 =item * DB2, Firebird, mysql, Oracle, Pg, SQLAnywhere, SQLite, MS Access
538 =item * Informix, MSSQL, Sybase ASE
540 C<database>, C<schema>, C<name>
544 =head2 moniker_part_separator
546 String used to join L</moniker_parts> when creating the moniker.
547 Defaults to the empty string. Use C<::> to get a separate namespace per
548 database and/or schema.
552 Only load matching tables.
556 Exclude matching tables.
558 These can be specified either as a regex (preferrably on the C<qr//>
559 form), or as an arrayref of arrayrefs. Regexes are matched against
560 the (unqualified) table name, while arrayrefs are matched according to
565 db_schema => [qw(some_schema other_schema)],
566 moniker_parts => [qw(schema name)],
568 [ qr/\Asome_schema\z/ => qr/\A(?:foo|bar)\z/ ],
569 [ qr/\Aother_schema\z/ => qr/\Abaz\z/ ],
572 In this case only the tables C<foo> and C<bar> in C<some_schema> and
573 C<baz> in C<other_schema> will be dumped.
577 Overrides the default table name to moniker translation. Either
583 a nested hashref, which will be traversed according to L</moniker_parts>
587 moniker_parts => [qw(schema name)],
594 In which case the table C<bar> in the C<foo> schema would get the moniker
599 a hashref of unqualified table name keys and moniker values
603 a coderef for a translator function taking a L<table
604 object|DBIx::Class::Schema::Loader::Table> argument (which stringifies to the
605 unqualified table name) and returning a scalar moniker
607 The function is also passed a coderef that can be called with either
608 of the hashref forms to get the moniker mapped accordingly. This is
609 useful if you need to handle some monikers specially, but want to use
610 the hashref form for the rest.
614 If the hash entry does not exist, or the function returns a false
615 value, the code falls back to default behavior for that table name.
617 The default behavior is to split on case transition and non-alphanumeric
618 boundaries, singularize the resulting phrase, then join the titlecased words
621 Table Name | Moniker Name
622 ---------------------------------
624 luser_group | LuserGroup
625 luser-opts | LuserOpt
626 stations_visited | StationVisited
627 routeChange | RouteChange
629 =head2 moniker_part_map
631 Map for overriding the monikerization of individual L</moniker_parts>.
632 The keys are the moniker part to override, the value is either a
633 hashref of coderef for mapping the corresponding part of the
634 moniker. If a coderef is used, it gets called with the moniker part
635 and the hash key the code ref was found under.
639 moniker_part_map => {
640 schema => sub { ... },
643 Given the table C<foo.bar>, the code ref would be called with the
644 arguments C<foo> and C<schema>, plus a coderef similar to the one
645 described in L</moniker_map>.
647 L</moniker_map> takes precedence over this.
649 =head2 col_accessor_map
651 Same as moniker_map, but for column accessor names. If a coderef is
652 passed, the code is called with arguments of
654 the name of the column in the underlying database,
655 default accessor name that DBICSL would ordinarily give this column,
657 table_class => name of the DBIC class we are building,
658 table_moniker => calculated moniker for this table (after moniker_map if present),
659 table => table object of interface DBIx::Class::Schema::Loader::Table,
660 full_table_name => schema-qualified name of the database table (RDBMS specific),
661 schema_class => name of the schema class we are building,
662 column_info => hashref of column info (data_type, is_nullable, etc),
664 coderef ref that can be called with a hashref map
666 the L<table object|DBIx::Class::Schema::Loader::Table> stringifies to the
667 unqualified table name.
671 Similar in idea to moniker_map, but different in the details. It can be
672 a hashref or a code ref.
674 If it is a hashref, keys can be either the default relationship name, or the
675 moniker. The keys that are the default relationship name should map to the
676 name you want to change the relationship to. Keys that are monikers should map
677 to hashes mapping relationship names to their translation. You can do both at
678 once, and the more specific moniker version will be picked up first. So, for
679 instance, you could have
688 and relationships that would have been named C<bar> will now be named C<baz>
689 except that in the table whose moniker is C<Foo> it will be named C<blat>.
691 If it is a coderef, it will be passed a hashref of this form:
694 name => default relationship name,
695 type => the relationship type eg: C<has_many>,
696 local_class => name of the DBIC class we are building,
697 local_moniker => moniker of the DBIC class we are building,
698 local_columns => columns in this table in the relationship,
699 remote_class => name of the DBIC class we are related to,
700 remote_moniker => moniker of the DBIC class we are related to,
701 remote_columns => columns in the other table in the relationship,
702 # for type => "many_to_many" only:
703 link_class => name of the DBIC class for the link table
704 link_moniker => moniker of the DBIC class for the link table
705 link_rel_name => name of the relationship to the link table
708 In addition it is passed a coderef that can be called with a hashref map.
710 DBICSL will try to use the value returned as the relationship name.
712 =head2 inflect_plural
714 Just like L</moniker_map> above (can be hash/code-ref, falls back to default
715 if hash key does not exist or coderef returns false), but acts as a map
716 for pluralizing relationship names. The default behavior is to utilize
717 L<Lingua::EN::Inflect::Phrase/to_PL>.
719 =head2 inflect_singular
721 As L</inflect_plural> above, but for singularizing relationship names.
722 Default behavior is to utilize L<Lingua::EN::Inflect::Phrase/to_S>.
724 =head2 schema_base_class
726 Base class for your schema classes. Defaults to 'DBIx::Class::Schema'.
728 =head2 schema_components
730 List of components to load into the Schema class.
732 =head2 result_base_class
734 Base class for your table classes (aka result classes). Defaults to
737 =head2 additional_base_classes
739 List of additional base classes all of your table classes will use.
741 =head2 left_base_classes
743 List of additional base classes all of your table classes will use
744 that need to be leftmost.
746 =head2 additional_classes
748 List of additional classes which all of your table classes will use.
752 List of additional components to be loaded into all of your Result
753 classes. A good example would be
754 L<InflateColumn::DateTime|DBIx::Class::InflateColumn::DateTime>
756 =head2 result_components_map
758 A hashref of moniker keys and component values. Unlike L</components>, which
759 loads the given components into every Result class, this option allows you to
760 load certain components for specified Result classes. For example:
762 result_components_map => {
763 StationVisited => '+YourApp::Schema::Component::StationVisited',
765 '+YourApp::Schema::Component::RouteChange',
766 'InflateColumn::DateTime',
770 You may use this in conjunction with L</components>.
774 List of L<Moose> roles to be applied to all of your Result classes.
776 =head2 result_roles_map
778 A hashref of moniker keys and role values. Unlike L</result_roles>, which
779 applies the given roles to every Result class, this option allows you to apply
780 certain roles for specified Result classes. For example:
782 result_roles_map => {
784 'YourApp::Role::Building',
785 'YourApp::Role::Destination',
787 RouteChange => 'YourApp::Role::TripEvent',
790 You may use this in conjunction with L</result_roles>.
792 =head2 use_namespaces
794 This is now the default, to go back to L<DBIx::Class::Schema/load_classes> pass
797 Generate result class names suitable for
798 L<DBIx::Class::Schema/load_namespaces> and call that instead of
799 L<DBIx::Class::Schema/load_classes>. When using this option you can also
800 specify any of the options for C<load_namespaces> (i.e. C<result_namespace>,
801 C<resultset_namespace>, C<default_resultset_class>), and they will be added
802 to the call (and the generated result class names adjusted appropriately).
804 =head2 dump_directory
806 The value of this option is a perl libdir pathname. Within
807 that directory this module will create a baseline manual
808 L<DBIx::Class::Schema> module set, based on what it creates at runtime.
810 The created schema class will have the same classname as the one on
811 which you are setting this option (and the ResultSource classes will be
812 based on this name as well).
814 Normally you wouldn't hard-code this setting in your schema class, as it
815 is meant for one-time manual usage.
817 See L<DBIx::Class::Schema::Loader/dump_to_dir> for examples of the
818 recommended way to access this functionality.
820 =head2 dump_overwrite
822 Deprecated. See L</really_erase_my_files> below, which does *not* mean
823 the same thing as the old C<dump_overwrite> setting from previous releases.
825 =head2 really_erase_my_files
827 Default false. If true, Loader will unconditionally delete any existing
828 files before creating the new ones from scratch when dumping a schema to disk.
830 The default behavior is instead to only replace the top portion of the
831 file, up to and including the final stanza which contains
832 C<# DO NOT MODIFY THE FIRST PART OF THIS FILE>
833 leaving any customizations you placed after that as they were.
835 When C<really_erase_my_files> is not set, if the output file already exists,
836 but the aforementioned final stanza is not found, or the checksum
837 contained there does not match the generated contents, Loader will
838 croak and not touch the file.
840 You should really be using version control on your schema classes (and all
841 of the rest of your code for that matter). Don't blame me if a bug in this
842 code wipes something out when it shouldn't have, you've been warned.
844 =head2 overwrite_modifications
846 Default false. If false, when updating existing files, Loader will
847 refuse to modify any Loader-generated code that has been modified
848 since its last run (as determined by the checksum Loader put in its
851 If true, Loader will discard any manual modifications that have been
852 made to Loader-generated code.
854 Again, you should be using version control on your schema classes. Be
855 careful with this option.
857 =head2 custom_column_info
859 Hook for adding extra attributes to the
860 L<column_info|DBIx::Class::ResultSource/column_info> for a column.
862 Must be a coderef that returns a hashref with the extra attributes.
864 Receives the L<table object|DBIx::Class::Schema::Loader::Table> (which
865 stringifies to the unqualified table name), column name and column_info.
869 custom_column_info => sub {
870 my ($table, $column_name, $column_info) = @_;
872 if ($column_name eq 'dog' && $column_info->{default_value} eq 'snoopy') {
873 return { is_snoopy => 1 };
877 This attribute can also be used to set C<inflate_datetime> on a non-datetime
878 column so it also receives the L</datetime_timezone> and/or L</datetime_locale>.
880 =head2 datetime_timezone
882 Sets the timezone attribute for L<DBIx::Class::InflateColumn::DateTime> for all
883 columns with the DATE/DATETIME/TIMESTAMP data_types.
885 =head2 datetime_locale
887 Sets the locale attribute for L<DBIx::Class::InflateColumn::DateTime> for all
888 columns with the DATE/DATETIME/TIMESTAMP data_types.
890 =head2 datetime_undef_if_invalid
892 Pass a C<0> for this option when using MySQL if you B<DON'T> want C<<
893 datetime_undef_if_invalid => 1 >> in your column info for DATE, DATETIME and
896 The default is recommended to deal with data such as C<00/00/00> which
897 sometimes ends up in such columns in MySQL.
901 File in Perl format, which should return a HASH reference, from which to read
906 Normally database names are lowercased and split by underscore, use this option
907 if you have CamelCase database names.
909 Drivers for case sensitive databases like Sybase ASE or MSSQL with a
910 case-sensitive collation will turn this option on unconditionally.
912 B<NOTE:> L</naming> = C<v8> is highly recommended with this option as the
913 semantics of this mode are much improved for CamelCase database names.
915 L</naming> = C<v7> or greater is required with this option.
917 =head2 qualify_objects
919 Set to true to prepend the L</db_schema> to table names for C<<
920 __PACKAGE__->table >> calls, and to some other things like Oracle sequences.
922 This attribute is automatically set to true for multi db_schema configurations,
923 unless explicitly set to false by the user.
927 Creates Schema and Result classes that use L<Moose>, L<MooseX::NonMoose> and
928 L<MooseX::MarkAsMethods> (or L<namespace::autoclean>, see below). The default
929 content after the md5 sum also makes the classes immutable.
931 It is safe to upgrade your existing Schema to this option.
933 =head2 only_autoclean
935 By default, we use L<MooseX::MarkAsMethods> to remove imported functions from
936 your generated classes. It uses L<namespace::autoclean> to do this, after
937 telling your object's metaclass that any operator L<overload>s in your class
938 are methods, which will cause namespace::autoclean to spare them from removal.
940 This prevents the "Hey, where'd my overloads go?!" effect.
942 If you don't care about operator overloads, enabling this option falls back to
943 just using L<namespace::autoclean> itself.
945 If none of the above made any sense, or you don't have some pressing need to
946 only use L<namespace::autoclean>, leaving this set to the default is
949 =head2 col_collision_map
951 This option controls how accessors for column names which collide with perl
952 methods are named. See L</COLUMN ACCESSOR COLLISIONS> for more information.
954 This option takes either a single L<sprintf|perlfunc/sprintf> format or a hashref of
955 strings which are compiled to regular expressions that map to
956 L<sprintf|perlfunc/sprintf> formats.
960 col_collision_map => 'column_%s'
962 col_collision_map => { '(.*)' => 'column_%s' }
964 col_collision_map => { '(foo).*(bar)' => 'column_%s_%s' }
966 =head2 rel_collision_map
968 Works just like L</col_collision_map>, but for relationship names/accessors
969 rather than column names/accessors.
971 The default is to just append C<_rel> to the relationship name, see
972 L</RELATIONSHIP NAME COLLISIONS>.
974 =head2 uniq_to_primary
976 Automatically promotes the largest unique constraints with non-nullable columns
977 on tables to primary keys, assuming there is only one largest unique
980 =head2 filter_generated_code
982 An optional hook that lets you filter the generated text for various classes
983 through a function that change it in any way that you want. The function will
984 receive the type of file, C<schema> or C<result>, class and code; and returns
985 the new code to use instead. For instance you could add custom comments, or do
986 anything else that you want.
988 The option can also be set to a string, which is then used as a filter program,
991 If this exists but fails to return text matching C</\bpackage\b/>, no file will
994 filter_generated_code => sub {
995 my ($type, $class, $text) = @_;
1002 None of these methods are intended for direct invocation by regular
1003 users of L<DBIx::Class::Schema::Loader>. Some are proxied via
1004 L<DBIx::Class::Schema::Loader>.
1008 # ensure that a piece of object data is a valid arrayref, creating
1009 # an empty one or encapsulating whatever's there.
1010 sub _ensure_arrayref {
1015 $self->{$_} = [ $self->{$_} ]
1016 unless ref $self->{$_} eq 'ARRAY';
1022 Constructor for L<DBIx::Class::Schema::Loader::Base>, used internally
1023 by L<DBIx::Class::Schema::Loader>.
1028 my ( $class, %args ) = @_;
1030 if (exists $args{column_accessor_map}) {
1031 $args{col_accessor_map} = delete $args{column_accessor_map};
1034 my $self = { %args };
1036 # don't lose undef options
1037 for (values %$self) {
1038 $_ = 0 unless defined $_;
1041 bless $self => $class;
1043 if (my $config_file = $self->config_file) {
1044 my $config_opts = do $config_file;
1046 croak "Error reading config from $config_file: $@" if $@;
1048 croak "Config file $config_file must be a hashref" unless ref($config_opts) eq 'HASH';
1050 while (my ($k, $v) = each %$config_opts) {
1051 $self->{$k} = $v unless exists $self->{$k};
1055 if (defined $self->{result_component_map}) {
1056 if (defined $self->result_components_map) {
1057 croak "Specify only one of result_components_map or result_component_map";
1059 $self->result_components_map($self->{result_component_map})
1062 if (defined $self->{result_role_map}) {
1063 if (defined $self->result_roles_map) {
1064 croak "Specify only one of result_roles_map or result_role_map";
1066 $self->result_roles_map($self->{result_role_map})
1069 croak "the result_roles and result_roles_map options may only be used in conjunction with use_moose=1"
1070 if ((not defined $self->use_moose) || (not $self->use_moose))
1071 && ((defined $self->result_roles) || (defined $self->result_roles_map));
1073 $self->_ensure_arrayref(qw/schema_components
1075 additional_base_classes
1081 $self->_validate_class_args;
1083 croak "result_components_map must be a hash"
1084 if defined $self->result_components_map
1085 && ref $self->result_components_map ne 'HASH';
1087 if ($self->result_components_map) {
1088 my %rc_map = %{ $self->result_components_map };
1089 foreach my $moniker (keys %rc_map) {
1090 $rc_map{$moniker} = [ $rc_map{$moniker} ] unless ref $rc_map{$moniker};
1092 $self->result_components_map(\%rc_map);
1095 $self->result_components_map({});
1097 $self->_validate_result_components_map;
1099 croak "result_roles_map must be a hash"
1100 if defined $self->result_roles_map
1101 && ref $self->result_roles_map ne 'HASH';
1103 if ($self->result_roles_map) {
1104 my %rr_map = %{ $self->result_roles_map };
1105 foreach my $moniker (keys %rr_map) {
1106 $rr_map{$moniker} = [ $rr_map{$moniker} ] unless ref $rr_map{$moniker};
1108 $self->result_roles_map(\%rr_map);
1110 $self->result_roles_map({});
1112 $self->_validate_result_roles_map;
1114 if ($self->use_moose) {
1115 if (not DBIx::Class::Schema::Loader::Optional::Dependencies->req_ok_for('use_moose')) {
1116 die sprintf "You must install the following CPAN modules to enable the use_moose option: %s.\n",
1117 DBIx::Class::Schema::Loader::Optional::Dependencies->req_missing_for('use_moose');
1121 $self->{_tables} = {};
1122 $self->{monikers} = {};
1123 $self->{moniker_to_table} = {};
1124 $self->{class_to_table} = {};
1125 $self->{classes} = {};
1126 $self->{_upgrading_classes} = {};
1127 $self->{generated_classes} = [];
1129 $self->{schema_class} ||= ( ref $self->{schema} || $self->{schema} );
1130 $self->{schema} ||= $self->{schema_class};
1131 $self->{table_comments_table} ||= 'table_comments';
1132 $self->{column_comments_table} ||= 'column_comments';
1134 croak "dump_overwrite is deprecated. Please read the"
1135 . " DBIx::Class::Schema::Loader::Base documentation"
1136 if $self->{dump_overwrite};
1138 $self->{dynamic} = ! $self->{dump_directory};
1139 $self->{temp_directory} ||= File::Temp::tempdir( 'dbicXXXX',
1144 $self->{dump_directory} ||= $self->{temp_directory};
1146 $self->real_dump_directory($self->{dump_directory});
1148 $self->version_to_dump($DBIx::Class::Schema::Loader::VERSION);
1149 $self->schema_version_to_dump($DBIx::Class::Schema::Loader::VERSION);
1151 if (not defined $self->naming) {
1152 $self->naming_set(0);
1155 $self->naming_set(1);
1158 if ((not ref $self->naming) && defined $self->naming) {
1159 my $naming_ver = $self->naming;
1161 relationships => $naming_ver,
1162 monikers => $naming_ver,
1163 column_accessors => $naming_ver,
1166 elsif (ref $self->naming eq 'HASH' && exists $self->naming->{ALL}) {
1167 my $val = delete $self->naming->{ALL};
1169 $self->naming->{$_} = $val
1170 foreach qw/relationships monikers column_accessors/;
1173 if ($self->naming) {
1174 foreach my $key (qw/relationships monikers column_accessors/) {
1175 $self->naming->{$key} = $CURRENT_V if ($self->naming->{$key}||'') eq 'current';
1178 $self->{naming} ||= {};
1180 if ($self->custom_column_info && ref $self->custom_column_info ne 'CODE') {
1181 croak 'custom_column_info must be a CODE ref';
1184 $self->_check_back_compat;
1186 $self->use_namespaces(1) unless defined $self->use_namespaces;
1187 $self->generate_pod(1) unless defined $self->generate_pod;
1188 $self->pod_comment_mode('auto') unless defined $self->pod_comment_mode;
1189 $self->pod_comment_spillover_length(60) unless defined $self->pod_comment_spillover_length;
1191 if (my $col_collision_map = $self->col_collision_map) {
1192 if (my $reftype = ref $col_collision_map) {
1193 if ($reftype ne 'HASH') {
1194 croak "Invalid type $reftype for option 'col_collision_map'";
1198 $self->col_collision_map({ '(.*)' => $col_collision_map });
1202 if (my $rel_collision_map = $self->rel_collision_map) {
1203 if (my $reftype = ref $rel_collision_map) {
1204 if ($reftype ne 'HASH') {
1205 croak "Invalid type $reftype for option 'rel_collision_map'";
1209 $self->rel_collision_map({ '(.*)' => $rel_collision_map });
1213 if (defined(my $rel_name_map = $self->rel_name_map)) {
1214 my $reftype = ref $rel_name_map;
1215 if ($reftype ne 'HASH' && $reftype ne 'CODE') {
1216 croak "Invalid type $reftype for option 'rel_name_map', must be HASH or CODE";
1220 if (defined(my $filter = $self->filter_generated_code)) {
1221 my $reftype = ref $filter;
1222 if ($reftype && $reftype ne 'CODE') {
1223 croak "Invalid type $reftype for option 'filter_generated_code, must be a scalar or a CODE reference";
1227 if (defined $self->db_schema) {
1228 if (ref $self->db_schema eq 'ARRAY') {
1229 if (@{ $self->db_schema } > 1 && not defined $self->{qualify_objects}) {
1230 $self->{qualify_objects} = 1;
1232 elsif (@{ $self->db_schema } == 0) {
1233 $self->{db_schema} = undef;
1236 elsif (not ref $self->db_schema) {
1237 if ($self->db_schema eq '%' && not defined $self->{qualify_objects}) {
1238 $self->{qualify_objects} = 1;
1241 $self->{db_schema} = [ $self->db_schema ];
1245 if (not $self->moniker_parts) {
1246 $self->moniker_parts(['name']);
1249 if (not ref $self->moniker_parts) {
1250 $self->moniker_parts([ $self->moniker_parts ]);
1252 if (ref $self->moniker_parts ne 'ARRAY') {
1253 croak 'moniker_parts must be an arrayref';
1255 if ((firstidx { $_ eq 'name' } @{ $self->moniker_parts }) == -1) {
1256 croak "moniker_parts option *must* contain 'name'";
1260 if (not defined $self->moniker_part_separator) {
1261 $self->moniker_part_separator('');
1263 if (not defined $self->moniker_part_map) {
1264 $self->moniker_part_map({}),
1270 sub _check_back_compat {
1273 # dynamic schemas will always be in 0.04006 mode, unless overridden
1274 if ($self->dynamic) {
1275 # just in case, though no one is likely to dump a dynamic schema
1276 $self->schema_version_to_dump('0.04006');
1278 if (not $self->naming_set) {
1279 warn <<EOF unless $ENV{SCHEMA_LOADER_BACKCOMPAT};
1281 Dynamic schema detected, will run in 0.04006 mode.
1283 Set the 'naming' attribute or the SCHEMA_LOADER_BACKCOMPAT environment variable
1284 to disable this warning.
1286 See perldoc DBIx::Class::Schema::Loader::Manual::UpgradingFromV4 for more
1291 $self->_upgrading_from('v4');
1294 if ((not defined $self->use_namespaces) && ($self->naming_set)) {
1295 $self->use_namespaces(1);
1298 $self->naming->{relationships} ||= 'v4';
1299 $self->naming->{monikers} ||= 'v4';
1301 if ($self->use_namespaces) {
1302 $self->_upgrading_from_load_classes(1);
1305 $self->use_namespaces(0);
1311 # otherwise check if we need backcompat mode for a static schema
1312 my $filename = $self->get_dump_filename($self->schema_class);
1313 return unless -e $filename;
1315 my ($old_gen, $old_md5, $old_ver, $old_ts, $old_custom) =
1316 $self->_parse_generated_file($filename);
1318 return unless $old_ver;
1320 # determine if the existing schema was dumped with use_moose => 1
1321 if (! defined $self->use_moose) {
1322 $self->{use_moose} = 1 if $old_gen =~ /^ (?!\s*\#) use \s+ Moose/xm;
1325 my $load_classes = ($old_gen =~ /^__PACKAGE__->load_classes;/m) ? 1 : 0;
1327 my $result_namespace = do { ($old_gen =~ /result_namespace => (.+)/) ? $1 : '' };
1328 my $ds = eval $result_namespace;
1330 Could not eval expression '$result_namespace' for result_namespace from
1333 $result_namespace = $ds || '';
1335 if ($load_classes && (not defined $self->use_namespaces)) {
1336 warn <<"EOF" unless $ENV{SCHEMA_LOADER_BACKCOMPAT};
1338 'load_classes;' static schema detected, turning off 'use_namespaces'.
1340 Set the 'use_namespaces' attribute or the SCHEMA_LOADER_BACKCOMPAT environment
1341 variable to disable this warning.
1343 See perldoc DBIx::Class::Schema::Loader::Manual::UpgradingFromV4 for more
1346 $self->use_namespaces(0);
1348 elsif ($load_classes && $self->use_namespaces) {
1349 $self->_upgrading_from_load_classes(1);
1351 elsif ((not $load_classes) && defined $self->use_namespaces && ! $self->use_namespaces) {
1352 $self->_downgrading_to_load_classes(
1353 $result_namespace || 'Result'
1356 elsif ((not defined $self->use_namespaces) || $self->use_namespaces) {
1357 if (not $self->result_namespace) {
1358 $self->result_namespace($result_namespace || 'Result');
1360 elsif ($result_namespace ne $self->result_namespace) {
1361 $self->_rewriting_result_namespace(
1362 $result_namespace || 'Result'
1367 # XXX when we go past .0 this will need fixing
1368 my ($v) = $old_ver =~ /([1-9])/;
1371 return if ($v eq $CURRENT_V || $old_ver =~ /^0\.\d\d999/);
1373 if (not %{ $self->naming }) {
1374 warn <<"EOF" unless $ENV{SCHEMA_LOADER_BACKCOMPAT};
1376 Version $old_ver static schema detected, turning on backcompat mode.
1378 Set the 'naming' attribute or the SCHEMA_LOADER_BACKCOMPAT environment variable
1379 to disable this warning.
1381 See: 'naming' in perldoc DBIx::Class::Schema::Loader::Base .
1383 See perldoc DBIx::Class::Schema::Loader::Manual::UpgradingFromV4 if upgrading
1384 from version 0.04006.
1387 $self->naming->{relationships} ||= $v;
1388 $self->naming->{monikers} ||= $v;
1389 $self->naming->{column_accessors} ||= $v;
1391 $self->schema_version_to_dump($old_ver);
1394 $self->_upgrading_from($v);
1398 sub _validate_class_args {
1401 foreach my $k (@CLASS_ARGS) {
1402 next unless $self->$k;
1404 my @classes = ref $self->$k eq 'ARRAY' ? @{ $self->$k } : $self->$k;
1405 $self->_validate_classes($k, \@classes);
1409 sub _validate_result_components_map {
1412 foreach my $classes (values %{ $self->result_components_map }) {
1413 $self->_validate_classes('result_components_map', $classes);
1417 sub _validate_result_roles_map {
1420 foreach my $classes (values %{ $self->result_roles_map }) {
1421 $self->_validate_classes('result_roles_map', $classes);
1425 sub _validate_classes {
1428 my $classes = shift;
1430 # make a copy to not destroy original
1431 my @classes = @$classes;
1433 foreach my $c (@classes) {
1434 # components default to being under the DBIx::Class namespace unless they
1435 # are preceded with a '+'
1436 if ( $key =~ m/component/ && $c !~ s/^\+// ) {
1437 $c = 'DBIx::Class::' . $c;
1440 # 1 == installed, 0 == not installed, undef == invalid classname
1441 my $installed = Class::Inspector->installed($c);
1442 if ( defined($installed) ) {
1443 if ( $installed == 0 ) {
1444 croak qq/$c, as specified in the loader option "$key", is not installed/;
1447 croak qq/$c, as specified in the loader option "$key", is an invalid class name/;
1453 sub _find_file_in_inc {
1454 my ($self, $file) = @_;
1456 foreach my $prefix (@INC) {
1457 my $fullpath = File::Spec->catfile($prefix, $file);
1458 # abs_path pure-perl fallback warns for non-existent files
1459 local $SIG{__WARN__} = sigwarn_silencer(qr/^stat\(.*\Q$file\E\)/);
1460 return $fullpath if -f $fullpath
1461 # abs_path throws on Windows for nonexistent files
1462 and (try { Cwd::abs_path($fullpath) }) ne
1463 ((try { Cwd::abs_path(File::Spec->catfile($self->dump_directory, $file)) }) || '');
1469 sub _find_class_in_inc {
1470 my ($self, $class) = @_;
1472 return $self->_find_file_in_inc(class_path($class));
1478 return $self->_upgrading_from
1479 || $self->_upgrading_from_load_classes
1480 || $self->_downgrading_to_load_classes
1481 || $self->_rewriting_result_namespace
1485 sub _rewrite_old_classnames {
1486 my ($self, $code) = @_;
1488 return $code unless $self->_rewriting;
1490 my %old_classes = reverse %{ $self->_upgrading_classes };
1492 my $re = join '|', keys %old_classes;
1493 $re = qr/\b($re)\b/;
1495 $code =~ s/$re/$old_classes{$1} || $1/eg;
1500 sub _load_external {
1501 my ($self, $class) = @_;
1503 return if $self->{skip_load_external};
1505 # so that we don't load our own classes, under any circumstances
1506 local *INC = [ grep $_ ne $self->dump_directory, @INC ];
1508 my $real_inc_path = $self->_find_class_in_inc($class);
1510 my $old_class = $self->_upgrading_classes->{$class}
1511 if $self->_rewriting;
1513 my $old_real_inc_path = $self->_find_class_in_inc($old_class)
1514 if $old_class && $old_class ne $class;
1516 return unless $real_inc_path || $old_real_inc_path;
1518 if ($real_inc_path) {
1519 # If we make it to here, we loaded an external definition
1520 warn qq/# Loaded external class definition for '$class'\n/
1523 my $code = $self->_rewrite_old_classnames(slurp_file $real_inc_path);
1525 if ($self->dynamic) { # load the class too
1526 eval_package_without_redefine_warnings($class, $code);
1529 $self->_ext_stmt($class,
1530 qq|# These lines were loaded from '$real_inc_path' found in \@INC.\n|
1531 .qq|# They are now part of the custom portion of this file\n|
1532 .qq|# for you to hand-edit. If you do not either delete\n|
1533 .qq|# this section or remove that file from \@INC, this section\n|
1534 .qq|# will be repeated redundantly when you re-create this\n|
1535 .qq|# file again via Loader! See skip_load_external to disable\n|
1536 .qq|# this feature.\n|
1539 $self->_ext_stmt($class, $code);
1540 $self->_ext_stmt($class,
1541 qq|# End of lines loaded from '$real_inc_path' |
1545 if ($old_real_inc_path) {
1546 my $code = slurp_file $old_real_inc_path;
1548 $self->_ext_stmt($class, <<"EOF");
1550 # These lines were loaded from '$old_real_inc_path',
1551 # based on the Result class name that would have been created by an older
1552 # version of the Loader. For a static schema, this happens only once during
1553 # upgrade. See skip_load_external to disable this feature.
1556 $code = $self->_rewrite_old_classnames($code);
1558 if ($self->dynamic) {
1561 Detected external content in '$old_real_inc_path', a class name that would have
1562 been used by an older version of the Loader.
1564 * PLEASE RENAME THIS CLASS: from '$old_class' to '$class', as that is the
1565 new name of the Result.
1567 eval_package_without_redefine_warnings($class, $code);
1571 $self->_ext_stmt($class, $code);
1572 $self->_ext_stmt($class,
1573 qq|# End of lines loaded from '$old_real_inc_path' |
1580 Does the actual schema-construction work.
1587 $self->_load_tables(
1588 $self->_tables_list({ constraint => $self->constraint, exclude => $self->exclude })
1596 Rescan the database for changes. Returns a list of the newly added table
1599 The schema argument should be the schema class or object to be affected. It
1600 should probably be derived from the original schema_class used during L</load>.
1605 my ($self, $schema) = @_;
1607 $self->{schema} = $schema;
1608 $self->_relbuilder->{schema} = $schema;
1611 my @current = $self->_tables_list({ constraint => $self->constraint, exclude => $self->exclude });
1613 foreach my $table (@current) {
1614 if(!exists $self->_tables->{$table->sql_name}) {
1615 push(@created, $table);
1620 @current{map $_->sql_name, @current} = ();
1621 foreach my $table (values %{ $self->_tables }) {
1622 if (not exists $current{$table->sql_name}) {
1623 $self->_remove_table($table);
1627 delete @$self{qw/_dump_storage _relations_started _uniqs_started/};
1629 my $loaded = $self->_load_tables(@current);
1631 foreach my $table (@created) {
1632 $self->monikers->{$table->sql_name} = $self->_table2moniker($table);
1635 return map { $self->monikers->{$_->sql_name} } @created;
1641 return if $self->{skip_relationships};
1643 return $self->{relbuilder} ||= do {
1644 my $relbuilder_suff =
1651 ->{$self->naming->{relationships}||$CURRENT_V} || '';
1653 my $relbuilder_class = 'DBIx::Class::Schema::Loader::RelBuilder'.$relbuilder_suff;
1654 $self->ensure_class_loaded($relbuilder_class);
1655 $relbuilder_class->new($self);
1660 my ($self, @tables) = @_;
1662 # Save the new tables to the tables list and compute monikers
1664 $self->_tables->{$_->sql_name} = $_;
1665 $self->monikers->{$_->sql_name} = $self->_table2moniker($_);
1668 # check for moniker clashes
1669 my $inverse_moniker_idx;
1670 foreach my $imtable (values %{ $self->_tables }) {
1671 push @{ $inverse_moniker_idx->{$self->monikers->{$imtable->sql_name}} }, $imtable;
1675 foreach my $moniker (keys %$inverse_moniker_idx) {
1676 my $imtables = $inverse_moniker_idx->{$moniker};
1677 if (@$imtables > 1) {
1678 my $different_databases =
1679 $imtables->[0]->can('database') && (uniq map $_->database||'', @$imtables) > 1;
1681 my $different_schemas =
1682 (uniq map $_->schema||'', @$imtables) > 1;
1684 if ($different_databases || $different_schemas) {
1685 my ($use_schema, $use_database) = (1, 0);
1687 if ($different_databases) {
1690 # If any monikers are in the same database, we have to distinguish by
1691 # both schema and database.
1693 $db_counts{$_}++ for map $_->database, @$imtables;
1694 $use_schema = any { $_ > 1 } values %db_counts;
1697 foreach my $tbl (@$imtables) { delete $self->monikers->{$tbl->sql_name}; }
1699 my $moniker_parts = [ @{ $self->moniker_parts } ];
1701 my $have_schema = any { $_ eq 'schema' } @{ $self->moniker_parts };
1702 my $have_database = any { $_ eq 'database' } @{ $self->moniker_parts };
1704 unshift @$moniker_parts, 'schema' if $use_schema && !$have_schema;
1705 unshift @$moniker_parts, 'database' if $use_database && !$have_database;
1707 local $self->{moniker_parts} = $moniker_parts;
1711 foreach my $tbl (@$imtables) { $new_monikers{$tbl->sql_name} = $self->_table2moniker($tbl); }
1712 foreach my $name (map $_->sql_name, @$imtables) { $self->monikers->{$name} = $new_monikers{$name}; }
1714 # check if there are still clashes
1717 while (my ($t, $m) = each %new_monikers) {
1718 push @{ $by_moniker{$m} }, $t;
1721 foreach my $m (grep @{ $by_moniker{$_} } > 1, keys %by_moniker) {
1722 push @clashes, sprintf ("tried disambiguating by moniker_parts, but tables %s still reduced to the same source moniker '%s'",
1723 join (', ', @{ $by_moniker{$m} }),
1729 push @clashes, sprintf ("tables %s reduced to the same source moniker '%s'",
1730 join (', ', map $_->sql_name, @$imtables),
1738 die 'Unable to load schema - chosen moniker/class naming style results in moniker clashes. '
1739 . 'Change the naming style, or supply an explicit moniker_map: '
1740 . join ('; ', @clashes)
1745 foreach my $tbl (@tables) { $self->_make_src_class($tbl); }
1746 foreach my $tbl (@tables) { $self->_setup_src_meta($tbl); }
1748 if(!$self->skip_relationships) {
1749 # The relationship loader needs a working schema
1750 local $self->{quiet} = 1;
1751 local $self->{dump_directory} = $self->{temp_directory};
1752 local $self->{generated_classes} = [];
1753 $self->_reload_classes(\@tables);
1754 $self->_load_relationships(\@tables);
1756 # Remove that temp dir from INC so it doesn't get reloaded
1757 @INC = grep $_ ne $self->dump_directory, @INC;
1760 foreach my $tbl (@tables) { $self->_load_roles($tbl); }
1761 foreach my $tbl (map { $self->classes->{$_->sql_name} } @tables) { $self->_load_external($tbl); }
1763 # Reload without unloading first to preserve any symbols from external
1765 $self->_reload_classes(\@tables, { unload => 0 });
1767 # Drop temporary cache
1768 delete $self->{_cache};
1773 sub _reload_classes {
1774 my ($self, $tables, $opts) = @_;
1776 my @tables = @$tables;
1778 my $unload = $opts->{unload};
1779 $unload = 1 unless defined $unload;
1781 # so that we don't repeat custom sections
1782 @INC = grep $_ ne $self->dump_directory, @INC;
1784 $self->_dump_to_dir(map { $self->classes->{$_->sql_name} } @tables);
1786 unshift @INC, $self->dump_directory;
1789 my %have_source = map { $_ => $self->schema->source($_) }
1790 $self->schema->sources;
1792 for my $table (@tables) {
1793 my $moniker = $self->monikers->{$table->sql_name};
1794 my $class = $self->classes->{$table->sql_name};
1797 no warnings 'redefine';
1798 local *Class::C3::reinitialize = sub {}; # to speed things up, reinitialized below
1801 if (my $mc = $self->_moose_metaclass($class)) {
1804 Class::Unload->unload($class) if $unload;
1805 my ($source, $resultset_class);
1807 ($source = $have_source{$moniker})
1808 && ($resultset_class = $source->resultset_class)
1809 && ($resultset_class ne 'DBIx::Class::ResultSet')
1811 my $has_file = Class::Inspector->loaded_filename($resultset_class);
1812 if (my $mc = $self->_moose_metaclass($resultset_class)) {
1815 Class::Unload->unload($resultset_class) if $unload;
1816 $self->_reload_class($resultset_class) if $has_file;
1818 $self->_reload_class($class);
1820 push @to_register, [$moniker, $class];
1823 Class::C3->reinitialize;
1824 for (@to_register) {
1825 $self->schema->register_class(@$_);
1829 sub _moose_metaclass {
1830 return undef unless $INC{'Class/MOP.pm'}; # if CMOP is not loaded the class could not have loaded in the 1st place
1834 my $mc = try { Class::MOP::class_of($class) }
1837 return $mc->isa('Moose::Meta::Class') ? $mc : undef;
1840 # We use this instead of ensure_class_loaded when there are package symbols we
1843 my ($self, $class) = @_;
1845 delete $INC{ +class_path($class) };
1848 eval_package_without_redefine_warnings ($class, "require $class");
1851 my $source = slurp_file $self->_get_dump_filename($class);
1852 die "Failed to reload class $class: $_.\n\nCLASS SOURCE:\n\n$source";
1856 sub _get_dump_filename {
1857 my ($self, $class) = (@_);
1859 $class =~ s{::}{/}g;
1860 return $self->dump_directory . q{/} . $class . q{.pm};
1863 =head2 get_dump_filename
1867 Returns the full path to the file for a class that the class has been or will
1868 be dumped to. This is a file in a temp dir for a dynamic schema.
1872 sub get_dump_filename {
1873 my ($self, $class) = (@_);
1875 local $self->{dump_directory} = $self->real_dump_directory;
1877 return $self->_get_dump_filename($class);
1880 sub _ensure_dump_subdirs {
1881 my ($self, $class) = (@_);
1883 my @name_parts = split(/::/, $class);
1884 pop @name_parts; # we don't care about the very last element,
1885 # which is a filename
1887 my $dir = $self->dump_directory;
1890 mkdir($dir) or croak "mkdir('$dir') failed: $!";
1892 last if !@name_parts;
1893 $dir = File::Spec->catdir($dir, shift @name_parts);
1898 my ($self, @classes) = @_;
1900 my $schema_class = $self->schema_class;
1901 my $schema_base_class = $self->schema_base_class || 'DBIx::Class::Schema';
1903 my $target_dir = $self->dump_directory;
1904 warn "Dumping manual schema for $schema_class to directory $target_dir ...\n"
1905 unless $self->dynamic or $self->quiet;
1909 . qq|package $schema_class;\n\n|
1910 . qq|# Created by DBIx::Class::Schema::Loader\n|
1911 . qq|# DO NOT MODIFY THE FIRST PART OF THIS FILE\n\n|;
1914 = $self->only_autoclean
1915 ? 'namespace::autoclean'
1916 : 'MooseX::MarkAsMethods autoclean => 1'
1919 if ($self->use_moose) {
1921 $schema_text.= qq|use Moose;\nuse $autoclean;\nextends '$schema_base_class';\n\n|;
1924 $schema_text .= qq|use strict;\nuse warnings;\n\nuse base '$schema_base_class';\n\n|;
1927 my @schema_components = @{ $self->schema_components || [] };
1929 if (@schema_components) {
1930 my $schema_components = dump @schema_components;
1931 $schema_components = "($schema_components)" if @schema_components == 1;
1933 $schema_text .= "__PACKAGE__->load_components${schema_components};\n\n";
1936 if ($self->use_namespaces) {
1937 $schema_text .= qq|__PACKAGE__->load_namespaces|;
1938 my $namespace_options;
1940 my @attr = qw/resultset_namespace default_resultset_class/;
1942 unshift @attr, 'result_namespace' unless (not $self->result_namespace) || $self->result_namespace eq 'Result';
1944 for my $attr (@attr) {
1946 my $code = dumper_squashed $self->$attr;
1947 $namespace_options .= qq| $attr => $code,\n|
1950 $schema_text .= qq|(\n$namespace_options)| if $namespace_options;
1951 $schema_text .= qq|;\n|;
1954 $schema_text .= qq|__PACKAGE__->load_classes;\n|;
1958 local $self->{version_to_dump} = $self->schema_version_to_dump;
1959 $self->_write_classfile($schema_class, $schema_text, 1);
1962 my $result_base_class = $self->result_base_class || 'DBIx::Class::Core';
1964 foreach my $src_class (@classes) {
1967 . qq|package $src_class;\n\n|
1968 . qq|# Created by DBIx::Class::Schema::Loader\n|
1969 . qq|# DO NOT MODIFY THE FIRST PART OF THIS FILE\n\n|;
1971 $src_text .= $self->_make_pod_heading($src_class);
1973 $src_text .= qq|use strict;\nuse warnings;\n\n|;
1975 $src_text .= $self->_base_class_pod($result_base_class)
1976 unless $result_base_class eq 'DBIx::Class::Core';
1978 if ($self->use_moose) {
1979 $src_text.= qq|use Moose;\nuse MooseX::NonMoose;\nuse $autoclean;|;
1981 # these options 'use base' which is compile time
1982 if (@{ $self->left_base_classes } || @{ $self->additional_base_classes }) {
1983 $src_text .= qq|\nBEGIN { extends '$result_base_class' }\n|;
1986 $src_text .= qq|\nextends '$result_base_class';\n|;
1990 $src_text .= qq|use base '$result_base_class';\n|;
1993 $self->_write_classfile($src_class, $src_text);
1996 # remove Result dir if downgrading from use_namespaces, and there are no
1998 if (my $result_ns = $self->_downgrading_to_load_classes
1999 || $self->_rewriting_result_namespace) {
2000 my $result_namespace = $self->_result_namespace(
2005 (my $result_dir = $result_namespace) =~ s{::}{/}g;
2006 $result_dir = $self->dump_directory . '/' . $result_dir;
2008 unless (my @files = glob "$result_dir/*") {
2013 warn "Schema dump completed.\n" unless $self->dynamic or $self->quiet;
2017 my ($self, $version, $ts) = @_;
2018 return qq|\n\n# Created by DBIx::Class::Schema::Loader|
2021 . qq|\n# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:|;
2024 sub _write_classfile {
2025 my ($self, $class, $text, $is_schema) = @_;
2027 my $filename = $self->_get_dump_filename($class);
2028 $self->_ensure_dump_subdirs($class);
2030 if (-f $filename && $self->really_erase_my_files) {
2031 warn "Deleting existing file '$filename' due to "
2032 . "'really_erase_my_files' setting\n" unless $self->quiet;
2036 my ($old_gen, $old_md5, $old_ver, $old_ts, $old_custom)
2037 = $self->_parse_generated_file($filename);
2039 if (! $old_gen && -f $filename) {
2040 croak "Cannot overwrite '$filename' without 'really_erase_my_files',"
2041 . " it does not appear to have been generated by Loader"
2044 my $custom_content = $old_custom || '';
2046 # Use custom content from a renamed class, the class names in it are
2048 if (my $renamed_class = $self->_upgrading_classes->{$class}) {
2049 my $old_filename = $self->_get_dump_filename($renamed_class);
2051 if (-f $old_filename) {
2052 $custom_content = ($self->_parse_generated_file ($old_filename))[4];
2054 unlink $old_filename;
2058 $custom_content ||= $self->_default_custom_content($is_schema);
2060 # If upgrading to use_moose=1 replace default custom content with default Moose custom content.
2061 # If there is already custom content, which does not have the Moose content, add it.
2062 if ($self->use_moose) {
2064 my $non_moose_custom_content = do {
2065 local $self->{use_moose} = 0;
2066 $self->_default_custom_content;
2069 if ($custom_content eq $non_moose_custom_content) {
2070 $custom_content = $self->_default_custom_content($is_schema);
2072 elsif ($custom_content !~ /\Q@{[$self->_default_moose_custom_content($is_schema)]}\E/) {
2073 $custom_content .= $self->_default_custom_content($is_schema);
2076 elsif (defined $self->use_moose && $old_gen) {
2077 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'
2078 if $old_gen =~ /use \s+ MooseX?\b/x;
2081 $custom_content = $self->_rewrite_old_classnames($custom_content);
2084 for @{$self->{_dump_storage}->{$class} || []};
2086 if ($self->filter_generated_code) {
2087 my $filter = $self->filter_generated_code;
2089 if (ref $filter eq 'CODE') {
2091 ($is_schema ? 'schema' : 'result'),
2097 my ($fh, $temp_file) = tempfile();
2099 binmode $fh, ':encoding(UTF-8)';
2103 open my $out, qq{$filter < "$temp_file"|}
2104 or croak "Could not open pipe to $filter: $!";
2106 $text = decode('UTF-8', do { local $/; <$out> });
2108 $text =~ s/$CR?$LF/\n/g;
2112 my $exit_code = $? >> 8;
2115 or croak "Could not remove temporary file '$temp_file': $!";
2117 if ($exit_code != 0) {
2118 croak "filter '$filter' exited non-zero: $exit_code";
2121 if (not $text or not $text =~ /\bpackage\b/) {
2122 warn("$class skipped due to filter") if $self->debug;
2127 # Check and see if the dump is in fact different
2131 $compare_to = $text . $self->_sig_comment($old_ver, $old_ts);
2132 if (Digest::MD5::md5_base64(encode 'UTF-8', $compare_to) eq $old_md5) {
2133 return unless $self->_upgrading_from && $is_schema;
2137 push @{$self->generated_classes}, $class;
2139 $text .= $self->_sig_comment(
2140 $self->version_to_dump,
2141 POSIX::strftime('%Y-%m-%d %H:%M:%S', localtime)
2144 open(my $fh, '>:encoding(UTF-8)', $filename)
2145 or croak "Cannot open '$filename' for writing: $!";
2147 # Write the top half and its MD5 sum
2148 print $fh $text . Digest::MD5::md5_base64(encode 'UTF-8', $text) . "\n";
2150 # Write out anything loaded via external partial class file in @INC
2152 for @{$self->{_ext_storage}->{$class} || []};
2154 # Write out any custom content the user has added
2155 print $fh $custom_content;
2158 or croak "Error closing '$filename': $!";
2161 sub _default_moose_custom_content {
2162 my ($self, $is_schema) = @_;
2164 if (not $is_schema) {
2165 return qq|\n__PACKAGE__->meta->make_immutable;|;
2168 return qq|\n__PACKAGE__->meta->make_immutable(inline_constructor => 0);|;
2171 sub _default_custom_content {
2172 my ($self, $is_schema) = @_;
2173 my $default = qq|\n\n# You can replace this text with custom|
2174 . qq| code or comments, and it will be preserved on regeneration|;
2175 if ($self->use_moose) {
2176 $default .= $self->_default_moose_custom_content($is_schema);
2178 $default .= qq|\n1;\n|;
2182 sub _parse_generated_file {
2183 my ($self, $fn) = @_;
2185 return unless -f $fn;
2187 open(my $fh, '<:encoding(UTF-8)', $fn)
2188 or croak "Cannot open '$fn' for reading: $!";
2191 qr{^(# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:)([A-Za-z0-9/+]{22})\r?\n};
2193 my ($md5, $ts, $ver, $gen);
2199 # Pull out the version and timestamp from the line above
2200 ($ver, $ts) = $gen =~ m/^# Created by DBIx::Class::Schema::Loader v(.*?) @ (.*?)\r?\Z/m;
2203 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"
2204 if !$self->overwrite_modifications && Digest::MD5::md5_base64(encode 'UTF-8', $gen) ne $md5;
2213 my $custom = do { local $/; <$fh> }
2217 $custom =~ s/$CRLF|$LF/\n/g;
2221 return ($gen, $md5, $ver, $ts, $custom);
2229 warn "$target: use $_;" if $self->debug;
2230 $self->_raw_stmt($target, "use $_;");
2238 my $blist = join(q{ }, @_);
2240 return unless $blist;
2242 warn "$target: use base qw/$blist/;" if $self->debug;
2243 $self->_raw_stmt($target, "use base qw/$blist/;");
2250 my $rlist = join(q{, }, map { qq{'$_'} } @_);
2252 return unless $rlist;
2254 warn "$target: with $rlist;" if $self->debug;
2255 $self->_raw_stmt($target, "\nwith $rlist;");
2258 sub _result_namespace {
2259 my ($self, $schema_class, $ns) = @_;
2260 my @result_namespace;
2262 $ns = $ns->[0] if ref $ns;
2264 if ($ns =~ /^\+(.*)/) {
2265 # Fully qualified namespace
2266 @result_namespace = ($1)
2269 # Relative namespace
2270 @result_namespace = ($schema_class, $ns);
2273 return wantarray ? @result_namespace : join '::', @result_namespace;
2276 # Create class with applicable bases, setup monikers, etc
2277 sub _make_src_class {
2278 my ($self, $table) = @_;
2280 my $schema = $self->schema;
2281 my $schema_class = $self->schema_class;
2283 my $table_moniker = $self->monikers->{$table->sql_name};
2284 my @result_namespace = ($schema_class);
2285 if ($self->use_namespaces) {
2286 my $result_namespace = $self->result_namespace || 'Result';
2287 @result_namespace = $self->_result_namespace(
2292 my $table_class = join(q{::}, @result_namespace, $table_moniker);
2294 if ((my $upgrading_v = $self->_upgrading_from)
2295 || $self->_rewriting) {
2296 local $self->naming->{monikers} = $upgrading_v
2299 my @result_namespace = @result_namespace;
2300 if ($self->_upgrading_from_load_classes) {
2301 @result_namespace = ($schema_class);
2303 elsif (my $ns = $self->_downgrading_to_load_classes) {
2304 @result_namespace = $self->_result_namespace(
2309 elsif ($ns = $self->_rewriting_result_namespace) {
2310 @result_namespace = $self->_result_namespace(
2316 my $old_table_moniker = do {
2317 local $self->naming->{monikers} = $upgrading_v;
2318 $self->_table2moniker($table);
2321 my $old_class = join(q{::}, @result_namespace, $old_table_moniker);
2323 $self->_upgrading_classes->{$table_class} = $old_class
2324 unless $table_class eq $old_class;
2327 $self->classes->{$table->sql_name} = $table_class;
2328 $self->moniker_to_table->{$table_moniker} = $table;
2329 $self->class_to_table->{$table_class} = $table;
2331 $self->_pod_class_list($table_class, 'ADDITIONAL CLASSES USED', @{$self->additional_classes});
2333 $self->_use ($table_class, @{$self->additional_classes});
2335 $self->_pod_class_list($table_class, 'LEFT BASE CLASSES', @{$self->left_base_classes});
2337 $self->_inject($table_class, @{$self->left_base_classes});
2339 my @components = @{ $self->components || [] };
2341 push @components, @{ $self->result_components_map->{$table_moniker} }
2342 if exists $self->result_components_map->{$table_moniker};
2344 my @fq_components = @components;
2345 foreach my $component (@fq_components) {
2346 if ($component !~ s/^\+//) {
2347 $component = "DBIx::Class::$component";
2351 $self->_pod_class_list($table_class, 'COMPONENTS LOADED', @fq_components);
2353 $self->_dbic_stmt($table_class, 'load_components', @components) if @components;
2355 $self->_pod_class_list($table_class, 'ADDITIONAL BASE CLASSES', @{$self->additional_base_classes});
2357 $self->_inject($table_class, @{$self->additional_base_classes});
2360 sub _is_result_class_method {
2361 my ($self, $name, $table) = @_;
2363 my $table_moniker = $table ? $self->monikers->{$table->sql_name} : '';
2365 $self->_result_class_methods({})
2366 if not defined $self->_result_class_methods;
2368 if (not exists $self->_result_class_methods->{$table_moniker}) {
2369 my (@methods, %methods);
2370 my $base = $self->result_base_class || 'DBIx::Class::Core';
2372 my @components = @{ $self->components || [] };
2374 push @components, @{ $self->result_components_map->{$table_moniker} }
2375 if exists $self->result_components_map->{$table_moniker};
2377 for my $c (@components) {
2378 $c = $c =~ /^\+/ ? substr($c,1) : "DBIx::Class::$c";
2381 my @roles = @{ $self->result_roles || [] };
2383 push @roles, @{ $self->result_roles_map->{$table_moniker} }
2384 if exists $self->result_roles_map->{$table_moniker};
2386 for my $class ($base, @components,
2387 ($self->use_moose ? 'Moose::Object' : ()), @roles) {
2388 $self->ensure_class_loaded($class);
2390 push @methods, @{ Class::Inspector->methods($class) || [] };
2393 push @methods, @{ Class::Inspector->methods('UNIVERSAL') };
2395 @methods{@methods} = ();
2397 $self->_result_class_methods->{$table_moniker} = \%methods;
2399 my $result_methods = $self->_result_class_methods->{$table_moniker};
2401 return exists $result_methods->{$name};
2404 sub _resolve_col_accessor_collisions {
2405 my ($self, $table, $col_info) = @_;
2407 while (my ($col, $info) = each %$col_info) {
2408 my $accessor = $info->{accessor} || $col;
2410 next if $accessor eq 'id'; # special case (very common column)
2412 if ($self->_is_result_class_method($accessor, $table)) {
2415 if (my $map = $self->col_collision_map) {
2416 for my $re (keys %$map) {
2417 if (my @matches = $col =~ /$re/) {
2418 $info->{accessor} = sprintf $map->{$re}, @matches;
2426 Column '$col' in table '$table' collides with an inherited method.
2427 See "COLUMN ACCESSOR COLLISIONS" in perldoc DBIx::Class::Schema::Loader::Base .
2429 $info->{accessor} = undef;
2435 # use the same logic to run moniker_map, col_accessor_map
2437 my ( $self, $map, $default_code, $ident, @extra ) = @_;
2439 my $default_ident = $default_code->( $ident, @extra );
2441 if( $map && ref $map eq 'HASH' ) {
2442 if (my @parts = try{ @{ $ident } }) {
2443 my $part_map = $map;
2445 my $part = shift @parts;
2446 last unless exists $part_map->{ $part };
2447 if ( !ref $part_map->{ $part } && !@parts ) {
2448 $new_ident = $part_map->{ $part };
2451 elsif ( ref $part_map->{ $part } eq 'HASH' ) {
2452 $part_map = $part_map->{ $part };
2456 if( !$new_ident && !ref $map->{ $ident } ) {
2457 $new_ident = $map->{ $ident };
2460 elsif( $map && ref $map eq 'CODE' ) {
2463 croak "reentered map must be a hashref"
2464 unless 'HASH' eq ref($cb_map);
2465 return $self->_run_user_map($cb_map, $default_code, $ident, @extra);
2467 $new_ident = $map->( $ident, $default_ident, @extra, $cb );
2470 $new_ident ||= $default_ident;
2475 sub _default_column_accessor_name {
2476 my ( $self, $column_name ) = @_;
2478 my $preserve = ($self->naming->{column_accessors}||'') eq 'preserve';
2480 my $v = $self->_get_naming_v('column_accessors');
2482 my $accessor_name = $preserve ?
2483 $self->_to_identifier('column_accessors', $column_name) # assume CamelCase
2485 $self->_to_identifier('column_accessors', $column_name, '_');
2487 $accessor_name =~ s/\W+/_/g; # only if naming < v8, otherwise to_identifier
2491 return $accessor_name;
2493 elsif ($v < 7 || (not $self->preserve_case)) {
2494 # older naming just lc'd the col accessor and that's all.
2495 return lc $accessor_name;
2498 return join '_', map lc, split_name $column_name, $v;
2501 sub _make_column_accessor_name {
2502 my ($self, $column_name, $column_context_info ) = @_;
2504 my $accessor = $self->_run_user_map(
2505 $self->col_accessor_map,
2506 sub { $self->_default_column_accessor_name( shift ) },
2508 $column_context_info,
2514 sub _table_is_view {
2515 #my ($self, $table) = @_;
2519 # Set up metadata (cols, pks, etc)
2520 sub _setup_src_meta {
2521 my ($self, $table) = @_;
2523 my $schema = $self->schema;
2524 my $schema_class = $self->schema_class;
2526 my $table_class = $self->classes->{$table->sql_name};
2527 my $table_moniker = $self->monikers->{$table->sql_name};
2529 $self->_dbic_stmt($table_class, 'table_class', 'DBIx::Class::ResultSource::View')
2530 if $self->_table_is_view($table);
2532 $self->_dbic_stmt($table_class, 'table', $table->dbic_name);
2534 my $cols = $self->_table_columns($table);
2535 my $col_info = $self->__columns_info_for($table);
2537 ### generate all the column accessor names
2538 while (my ($col, $info) = each %$col_info) {
2539 # hashref of other info that could be used by
2540 # user-defined accessor map functions
2542 table_class => $table_class,
2543 table_moniker => $table_moniker,
2544 table_name => $table, # bugwards compatibility, RT#84050
2546 full_table_name => $table->dbic_name,
2547 schema_class => $schema_class,
2548 column_info => $info,
2551 $info->{accessor} = $self->_make_column_accessor_name( $col, $context );
2554 $self->_resolve_col_accessor_collisions($table, $col_info);
2556 # prune any redundant accessor names
2557 while (my ($col, $info) = each %$col_info) {
2558 no warnings 'uninitialized';
2559 delete $info->{accessor} if $info->{accessor} eq $col;
2562 my $fks = $self->_table_fk_info($table);
2564 foreach my $fkdef (@$fks) {
2565 for my $col (@{ $fkdef->{local_columns} }) {
2566 $col_info->{$col}{is_foreign_key} = 1;
2570 my $pks = $self->_table_pk_info($table) || [];
2572 my %uniq_tag; # used to eliminate duplicate uniqs
2574 $uniq_tag{ join("\0", @$pks) }++ if @$pks; # pk is a uniq
2576 my $uniqs = $self->_table_uniq_info($table) || [];
2579 foreach my $uniq (@$uniqs) {
2580 my ($name, $cols) = @$uniq;
2581 next if $uniq_tag{ join("\0", @$cols) }++; # skip duplicates
2582 push @uniqs, [$name, $cols];
2585 my @non_nullable_uniqs = grep {
2586 all { $col_info->{$_}{is_nullable} == 0 } @{ $_->[1] }
2589 if ($self->uniq_to_primary && (not @$pks) && @non_nullable_uniqs) {
2590 my @by_colnum = sort { $b->[0] <=> $a->[0] }
2591 map [ scalar @{ $_->[1] }, $_ ], @non_nullable_uniqs;
2593 if (not (@by_colnum > 1 && $by_colnum[0][0] == $by_colnum[1][0])) {
2594 my @keys = map $_->[1], @by_colnum;
2598 # remove the uniq from list
2599 @uniqs = grep { $_->[0] ne $pk->[0] } @uniqs;
2605 foreach my $pkcol (@$pks) {
2606 $col_info->{$pkcol}{is_nullable} = 0;
2612 map { $_, ($col_info->{$_}||{}) } @$cols
2615 $self->_dbic_stmt($table_class, 'set_primary_key', @$pks)
2618 # Sort unique constraints by constraint name for repeatable results (rels
2619 # are sorted as well elsewhere.)
2620 @uniqs = sort { $a->[0] cmp $b->[0] } @uniqs;
2622 foreach my $uniq (@uniqs) {
2623 my ($name, $cols) = @$uniq;
2624 $self->_dbic_stmt($table_class,'add_unique_constraint', $name, $cols);
2628 sub __columns_info_for {
2629 my ($self, $table) = @_;
2631 my $result = $self->_columns_info_for($table);
2633 while (my ($col, $info) = each %$result) {
2634 $info = { %$info, %{ $self->_custom_column_info ($table, $col, $info) } };
2635 $info = { %$info, %{ $self->_datetime_column_info($table, $col, $info) } };
2637 $result->{$col} = $info;
2645 Returns a sorted list of loaded tables, using the original database table
2653 return values %{$self->_tables};
2657 my ($self, $naming_key) = @_;
2661 if (($self->naming->{$naming_key}||'') =~ /^v(\d+)\z/) {
2665 ($v) = $CURRENT_V =~ /^v(\d+)\z/;
2671 sub _to_identifier {
2672 my ($self, $naming_key, $name, $sep_char, $force) = @_;
2674 my $v = $self->_get_naming_v($naming_key);
2676 my $to_identifier = $self->naming->{force_ascii} ?
2677 \&String::ToIdentifier::EN::to_identifier
2678 : \&String::ToIdentifier::EN::Unicode::to_identifier;
2680 return $v >= 8 || $force ? $to_identifier->($name, $sep_char) : $name;
2683 # Make a moniker from a table
2684 sub _default_table2moniker {
2685 my ($self, $table) = @_;
2687 my $v = $self->_get_naming_v('monikers');
2689 my @moniker_parts = @{ $self->moniker_parts };
2690 my @name_parts = map $table->$_, @moniker_parts;
2692 my $name_idx = firstidx { $_ eq 'name' } @{ $self->moniker_parts };
2696 foreach my $i (0 .. $#name_parts) {
2697 my $part = $name_parts[$i];
2699 my $moniker_part = $self->_run_user_map(
2700 $self->moniker_part_map->{$moniker_parts[$i]},
2702 $part, $moniker_parts[$i],
2704 if (length $moniker_part) {
2705 push @all_parts, $moniker_part;
2709 if ($i != $name_idx || $v >= 8) {
2710 $part = $self->_to_identifier('monikers', $part, '_', 1);
2713 if ($i == $name_idx && $v == 5) {
2714 $part = Lingua::EN::Inflect::Number::to_S($part);
2717 my @part_parts = map lc, $v > 6 ?
2718 # use v8 semantics for all moniker parts except name
2719 ($i == $name_idx ? split_name $part, $v : split_name $part)
2720 : split /[\W_]+/, $part;
2722 if ($i == $name_idx && $v >= 6) {
2723 my $as_phrase = join ' ', @part_parts;
2725 my $inflected = ($self->naming->{monikers}||'') eq 'plural' ?
2726 Lingua::EN::Inflect::Phrase::to_PL($as_phrase)
2728 ($self->naming->{monikers}||'') eq 'preserve' ?
2731 Lingua::EN::Inflect::Phrase::to_S($as_phrase);
2733 @part_parts = split /\s+/, $inflected;
2736 push @all_parts, join '', map ucfirst, @part_parts;
2739 return join $self->moniker_part_separator, @all_parts;
2742 sub _table2moniker {
2743 my ( $self, $table ) = @_;
2745 $self->_run_user_map(
2747 sub { $self->_default_table2moniker( shift ) },
2752 sub _load_relationships {
2753 my ($self, $tables) = @_;
2757 foreach my $table (@$tables) {
2758 my $local_moniker = $self->monikers->{$table->sql_name};
2760 my $tbl_fk_info = $self->_table_fk_info($table);
2762 foreach my $fkdef (@$tbl_fk_info) {
2763 $fkdef->{local_table} = $table;
2764 $fkdef->{local_moniker} = $local_moniker;
2765 $fkdef->{remote_source} =
2766 $self->monikers->{$fkdef->{remote_table}->sql_name};
2768 my $tbl_uniq_info = $self->_table_uniq_info($table);
2770 push @tables, [ $local_moniker, $tbl_fk_info, $tbl_uniq_info ];
2773 my $rel_stmts = $self->_relbuilder->generate_code(\@tables);
2775 foreach my $src_class (sort keys %$rel_stmts) {
2777 my @src_stmts = map $_->[2],
2783 ($_->{method} eq 'many_to_many' ? 1 : 0),
2786 ], @{ $rel_stmts->{$src_class} };
2788 foreach my $stmt (@src_stmts) {
2789 $self->_dbic_stmt($src_class,$stmt->{method}, @{$stmt->{args}});
2795 my ($self, $table) = @_;
2797 my $table_moniker = $self->monikers->{$table->sql_name};
2798 my $table_class = $self->classes->{$table->sql_name};
2800 my @roles = @{ $self->result_roles || [] };
2801 push @roles, @{ $self->result_roles_map->{$table_moniker} }
2802 if exists $self->result_roles_map->{$table_moniker};
2805 $self->_pod_class_list($table_class, 'L<Moose> ROLES APPLIED', @roles);
2807 $self->_with($table_class, @roles);
2811 # Overload these in driver class:
2813 # Returns an arrayref of column names
2814 sub _table_columns { croak "ABSTRACT METHOD" }
2816 # Returns arrayref of pk col names
2817 sub _table_pk_info { croak "ABSTRACT METHOD" }
2819 # Returns an arrayref of uniqs [ [ foo => [ col1, col2 ] ], [ bar => [ ... ] ] ]
2820 sub _table_uniq_info { croak "ABSTRACT METHOD" }
2822 # Returns an arrayref of foreign key constraints, each
2823 # being a hashref with 3 keys:
2824 # local_columns (arrayref), remote_columns (arrayref), remote_table
2825 sub _table_fk_info { croak "ABSTRACT METHOD" }
2827 # Returns an array of lower case table names
2828 sub _tables_list { croak "ABSTRACT METHOD" }
2830 # Execute a constructive DBIC class method, with debug/dump_to_dir hooks.
2836 # generate the pod for this statement, storing it with $self->_pod
2837 $self->_make_pod( $class, $method, @_ ) if $self->generate_pod;
2839 my $args = dump(@_);
2840 $args = '(' . $args . ')' if @_ < 2;
2841 my $stmt = $method . $args . q{;};
2843 warn qq|$class\->$stmt\n| if $self->debug;
2844 $self->_raw_stmt($class, '__PACKAGE__->' . $stmt);
2848 sub _make_pod_heading {
2849 my ($self, $class) = @_;
2851 return '' if not $self->generate_pod;
2853 my $table = $self->class_to_table->{$class};
2856 my $pcm = $self->pod_comment_mode;
2857 my ($comment, $comment_overflows, $comment_in_name, $comment_in_desc);
2858 $comment = $self->__table_comment($table);
2859 $comment_overflows = ($comment and length $comment > $self->pod_comment_spillover_length);
2860 $comment_in_name = ($pcm eq 'name' or ($pcm eq 'auto' and !$comment_overflows));
2861 $comment_in_desc = ($pcm eq 'description' or ($pcm eq 'auto' and $comment_overflows));
2863 $pod .= "=head1 NAME\n\n";
2865 my $table_descr = $class;
2866 $table_descr .= " - " . $comment if $comment and $comment_in_name;
2868 $pod .= "$table_descr\n\n";
2870 if ($comment and $comment_in_desc) {
2871 $pod .= "=head1 DESCRIPTION\n\n${comment}\n\n";
2878 # generates the accompanying pod for a DBIC class method statement,
2879 # storing it with $self->_pod
2885 if ($method eq 'table') {
2887 $table = $$table if ref $table eq 'SCALAR';
2888 $self->_pod($class, "=head1 TABLE: C<$table>");
2889 $self->_pod_cut($class);
2891 elsif ( $method eq 'add_columns' ) {
2892 $self->_pod( $class, "=head1 ACCESSORS" );
2893 my $col_counter = 0;
2895 while( my ($name,$attrs) = splice @cols,0,2 ) {
2897 $self->_pod( $class, '=head2 ' . $name );
2898 $self->_pod( $class,
2900 my $s = $attrs->{$_};
2901 $s = !defined $s ? 'undef' :
2902 length($s) == 0 ? '(empty string)' :
2903 ref($s) eq 'SCALAR' ? $$s :
2904 ref($s) ? dumper_squashed $s :
2905 looks_like_number($s) ? $s : qq{'$s'};
2908 } sort keys %$attrs,
2910 if (my $comment = $self->__column_comment($self->class_to_table->{$class}, $col_counter, $name)) {
2911 $self->_pod( $class, $comment );
2914 $self->_pod_cut( $class );
2915 } elsif ( $method =~ /^(?:belongs_to|has_many|might_have)\z/ ) {
2916 $self->_pod( $class, "=head1 RELATIONS" ) unless $self->{_relations_started} { $class } ;
2917 my ( $accessor, $rel_class ) = @_;
2918 $self->_pod( $class, "=head2 $accessor" );
2919 $self->_pod( $class, 'Type: ' . $method );
2920 $self->_pod( $class, "Related object: L<$rel_class>" );
2921 $self->_pod_cut( $class );
2922 $self->{_relations_started} { $class } = 1;
2923 } elsif ( $method eq 'many_to_many' ) {
2924 $self->_pod( $class, "=head1 RELATIONS" ) unless $self->{_relations_started} { $class } ;
2925 my ( $accessor, $rel1, $rel2 ) = @_;
2926 $self->_pod( $class, "=head2 $accessor" );
2927 $self->_pod( $class, 'Type: many_to_many' );
2928 $self->_pod( $class, "Composing rels: L</$rel1> -> $rel2" );
2929 $self->_pod_cut( $class );
2930 $self->{_relations_started} { $class } = 1;
2932 elsif ($method eq 'add_unique_constraint') {
2933 $self->_pod($class, '=head1 UNIQUE CONSTRAINTS')
2934 unless $self->{_uniqs_started}{$class};
2936 my ($name, $cols) = @_;
2938 $self->_pod($class, "=head2 C<$name>");
2939 $self->_pod($class, '=over 4');
2941 foreach my $col (@$cols) {
2942 $self->_pod($class, "=item \* L</$col>");
2945 $self->_pod($class, '=back');
2946 $self->_pod_cut($class);
2948 $self->{_uniqs_started}{$class} = 1;
2950 elsif ($method eq 'set_primary_key') {
2951 $self->_pod($class, "=head1 PRIMARY KEY");
2952 $self->_pod($class, '=over 4');
2954 foreach my $col (@_) {
2955 $self->_pod($class, "=item \* L</$col>");
2958 $self->_pod($class, '=back');
2959 $self->_pod_cut($class);
2963 sub _pod_class_list {
2964 my ($self, $class, $title, @classes) = @_;
2966 return unless @classes && $self->generate_pod;
2968 $self->_pod($class, "=head1 $title");
2969 $self->_pod($class, '=over 4');
2971 foreach my $link (@classes) {
2972 $self->_pod($class, "=item * L<$link>");
2975 $self->_pod($class, '=back');
2976 $self->_pod_cut($class);
2979 sub _base_class_pod {
2980 my ($self, $base_class) = @_;
2982 return '' unless $self->generate_pod;
2985 =head1 BASE CLASS: L<$base_class>
2992 sub _filter_comment {
2993 my ($self, $txt) = @_;
2995 $txt = '' if not defined $txt;
2997 $txt =~ s/(?:\015?\012|\015\012?)/\n/g;
3002 sub __table_comment {
3005 if (my $code = $self->can('_table_comment')) {
3006 return $self->_filter_comment($self->$code(@_));
3012 sub __column_comment {
3015 if (my $code = $self->can('_column_comment')) {
3016 return $self->_filter_comment($self->$code(@_));
3022 # Stores a POD documentation
3024 my ($self, $class, $stmt) = @_;
3025 $self->_raw_stmt( $class, "\n" . $stmt );
3029 my ($self, $class ) = @_;
3030 $self->_raw_stmt( $class, "\n=cut\n" );
3033 # Store a raw source line for a class (for dumping purposes)
3035 my ($self, $class, $stmt) = @_;
3036 push(@{$self->{_dump_storage}->{$class}}, $stmt);
3039 # Like above, but separately for the externally loaded stuff
3041 my ($self, $class, $stmt) = @_;
3042 push(@{$self->{_ext_storage}->{$class}}, $stmt);
3045 sub _custom_column_info {
3046 my ( $self, $table_name, $column_name, $column_info ) = @_;
3048 if (my $code = $self->custom_column_info) {
3049 return $code->($table_name, $column_name, $column_info) || {};
3054 sub _datetime_column_info {
3055 my ( $self, $table_name, $column_name, $column_info ) = @_;
3057 my $type = $column_info->{data_type} || '';
3058 if ((grep $_, @{ $column_info }{map "inflate_$_", qw/date datetime timestamp/})
3059 or ($type =~ /date|timestamp/i)) {
3060 $result->{timezone} = $self->datetime_timezone if $self->datetime_timezone;
3061 $result->{locale} = $self->datetime_locale if $self->datetime_locale;
3067 my ($self, $name) = @_;
3069 return $self->preserve_case ? $name : lc($name);
3073 my ($self, $name) = @_;
3075 return $self->preserve_case ? $name : uc($name);
3079 my ($self, $table) = @_;
3082 my $schema = $self->schema;
3083 # in older DBIC it's a private method
3084 my $unregister = $schema->can('unregister_source') || $schema->can('_unregister_source');
3085 $schema->$unregister(delete $self->monikers->{$table->sql_name});
3086 delete $self->_upgrading_classes->{delete $self->classes->{$table->sql_name}};
3087 delete $self->_tables->{$table->sql_name};
3091 # remove the dump dir from @INC on destruction
3095 @INC = grep $_ ne $self->dump_directory, @INC;
3100 Returns a hashref of loaded table to moniker mappings. There will
3101 be two entries for each table, the original name and the "normalized"
3102 name, in the case that the two are different (such as databases
3103 that like uppercase table names, or preserve your original mixed-case
3104 definitions, or what-have-you).
3108 Returns a hashref of table to class mappings. In some cases it will
3109 contain multiple entries per table for the original and normalized table
3110 names, as above in L</monikers>.
3112 =head2 generated_classes
3114 Returns an arrayref of classes that were actually generated (i.e. not
3115 skipped because there were no changes).
3117 =head1 NON-ENGLISH DATABASES
3119 If you use the loader on a database with table and column names in a language
3120 other than English, you will want to turn off the English language specific
3123 To do so, use something like this in your loader options:
3125 naming => { monikers => 'v4' },
3126 inflect_singular => sub { "$_[0]_rel" },
3127 inflect_plural => sub { "$_[0]_rel" },
3129 =head1 COLUMN ACCESSOR COLLISIONS
3131 Occasionally you may have a column name that collides with a perl method, such
3132 as C<can>. In such cases, the default action is to set the C<accessor> of the
3133 column spec to C<undef>.
3135 You can then name the accessor yourself by placing code such as the following
3138 __PACKAGE__->add_column('+can' => { accessor => 'my_can' });
3140 Another option is to use the L</col_collision_map> option.
3142 =head1 RELATIONSHIP NAME COLLISIONS
3144 In very rare cases, you may get a collision between a generated relationship
3145 name and a method in your Result class, for example if you have a foreign key
3146 called C<belongs_to>.
3148 This is a problem because relationship names are also relationship accessor
3149 methods in L<DBIx::Class>.
3151 The default behavior is to append C<_rel> to the relationship name and print
3152 out a warning that refers to this text.
3154 You can also control the renaming with the L</rel_collision_map> option.
3158 L<DBIx::Class::Schema::Loader>, L<dbicdump>
3162 See L<DBIx::Class::Schema::Loader/AUTHOR> and L<DBIx::Class::Schema::Loader/CONTRIBUTORS>.
3166 This library is free software; you can redistribute it and/or modify it under
3167 the same terms as Perl itself.
3172 # vim:et sts=4 sw=4 tw=0: