1 package DBIx::Class::Schema::Loader::Base;
5 use base qw/Class::Accessor::Grouped Class::C3::Componentised/;
7 use Carp::Clan qw/^DBIx::Class/;
8 use DBIx::Class::Schema::Loader::RelBuilder ();
14 use Lingua::EN::Inflect::Number ();
15 use Lingua::EN::Inflect::Phrase ();
16 use String::ToIdentifier::EN ();
17 use String::ToIdentifier::EN::Unicode ();
20 use Class::Inspector ();
21 use Scalar::Util 'looks_like_number';
22 use DBIx::Class::Schema::Loader::Utils qw/split_name dumper_squashed eval_package_without_redefine_warnings class_path slurp_file/;
23 use DBIx::Class::Schema::Loader::Optional::Dependencies ();
26 use Encode qw/encode decode/;
27 use List::MoreUtils qw/all firstidx/;
28 use File::Temp 'tempfile';
31 our $VERSION = '0.07011';
33 __PACKAGE__->mk_group_ro_accessors('simple', qw/
40 additional_base_classes
56 default_resultset_class
62 overwrite_modifications
85 __PACKAGE__->mk_group_accessors('simple', qw/
87 schema_version_to_dump
89 _upgrading_from_load_classes
90 _downgrading_to_load_classes
91 _rewriting_result_namespace
96 pod_comment_spillover_length
102 result_components_map
104 datetime_undef_if_invalid
105 _result_class_methods
107 filter_generated_code
113 my $CURRENT_V = 'v7';
116 schema_components schema_base_class result_base_class
117 additional_base_classes left_base_classes additional_classes components
123 my $CRLF = "\x0d\x0a";
127 DBIx::Class::Schema::Loader::Base - Base DBIx::Class::Schema::Loader Implementation.
131 See L<DBIx::Class::Schema::Loader>.
135 This is the base class for the storage-specific C<DBIx::Class::Schema::*>
136 classes, and implements the common functionality between them.
138 =head1 CONSTRUCTOR OPTIONS
140 These constructor options are the base options for
141 L<DBIx::Class::Schema::Loader/loader_options>. Available constructor options are:
143 =head2 skip_relationships
145 Skip setting up relationships. The default is to attempt the loading
148 =head2 skip_load_external
150 Skip loading of other classes in @INC. The default is to merge all other classes
151 with the same name found in @INC into the schema file we are creating.
155 Static schemas (ones dumped to disk) will, by default, use the new-style
156 relationship names and singularized Results, unless you're overwriting an
157 existing dump made by an older version of L<DBIx::Class::Schema::Loader>, in
158 which case the backward compatible RelBuilder will be activated, and the
159 appropriate monikerization used.
165 will disable the backward-compatible RelBuilder and use
166 the new-style relationship names along with singularized Results, even when
167 overwriting a dump made with an earlier version.
169 The option also takes a hashref:
172 relationships => 'v8',
174 column_accessors => 'v8',
180 naming => { ALL => 'v8', force_ascii => 1 }
188 Set L</relationships>, L</monikers> and L</column_accessors> to the specified
193 How to name relationship accessors.
197 How to name Result classes.
199 =item column_accessors
201 How to name column accessors in Result classes.
205 For L</v8> mode and later, uses L<String::ToIdentifier::EN> instead of
206 L<String::ToIdentifier::EM::Unicode> to force monikers and other identifiers to
217 Latest style, whatever that happens to be.
221 Unsingularlized monikers, C<has_many> only relationships with no _id stripping.
225 Monikers singularized as whole words, C<might_have> relationships for FKs on
226 C<UNIQUE> constraints, C<_id> stripping for belongs_to relationships.
228 Some of the C<_id> stripping edge cases in C<0.05003> have been reverted for
233 All monikers and relationships are inflected using
234 L<Lingua::EN::Inflect::Phrase>, and there is more aggressive C<_id> stripping
235 from relationship names.
237 In general, there is very little difference between v5 and v6 schemas.
241 This mode is identical to C<v6> mode, except that monikerization of CamelCase
242 table names is also done correctly.
244 CamelCase column names in case-preserving mode will also be handled correctly
245 for relationship name inflection. See L</preserve_case>.
247 In this mode, CamelCase L</column_accessors> are normalized based on case
248 transition instead of just being lowercased, so C<FooId> becomes C<foo_id>.
250 If you don't have any CamelCase table or column names, you can upgrade without
251 breaking any of your code.
257 The default mode is L</v7>, to get L</v8> mode, you have to specify it in
258 L</naming> explictly 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
386 by type. Also supports relationship type 'all', containing options to
387 pass to all generated relationships. Attributes set for more specific
388 relationship types override those set in 'all'.
392 relationship_attrs => {
393 belongs_to => { is_deferrable => 0 },
396 use this to turn off DEFERRABLE on your foreign key constraints.
400 If set to true, each constructive L<DBIx::Class> statement the loader
401 decides to execute will be C<warn>-ed before execution.
405 Set the name of the schema to load (schema in the sense that your database
408 Can be set to an arrayref of schema names for multiple schemas, or the special
409 value C<%> for all schemas.
411 For MSSQL, Sybase ASE, and Informix can be set to a hashref of databases as
412 keys and arrays of owners as values, set to the value:
416 for all owners in all databases.
418 You may need to control naming of monikers with L</moniker_parts> if you have
419 name clashes for tables in different schemas/databases.
423 The database table names are represented by the
424 L<DBIx::Class::Schema::Loader::Table> class in the loader, the
425 L<DBIx::Class::Schema::Loader::Table::Sybase> class for Sybase ASE and
426 L<DBIx::Class::Schema::Loader::Table::Informix> for Informix.
428 Monikers are created normally based on just the
429 L<name|DBIx::Class::Schema::Loader::DBObject/name> property, corresponding to
430 the table name, but can consist of other parts of the fully qualified name of
433 The L</moniker_parts> option is an arrayref of methods on the table class
434 corresponding to parts of the fully qualified table name, defaulting to
435 C<['name']>, in the order those parts are used to create the moniker name.
437 The C<'name'> entry B<must> be present.
439 Below is a table of supported databases and possible L</moniker_parts>.
443 =item * DB2, Firebird, mysql, Oracle, Pg, SQLAnywhere, SQLite, MS Access
447 =item * Informix, MSSQL, Sybase ASE
449 C<database>, C<schema>, C<name>
455 Only load tables matching regex. Best specified as a qr// regex.
459 Exclude tables matching regex. Best specified as a qr// regex.
463 Overrides the default table name to moniker translation. Can be either
464 a hashref of table keys and moniker values, or a coderef for a translator
465 function taking a single scalar table name argument and returning
466 a scalar moniker. If the hash entry does not exist, or the function
467 returns a false value, the code falls back to default behavior
470 The default behavior is to split on case transition and non-alphanumeric
471 boundaries, singularize the resulting phrase, then join the titlecased words
474 Table Name | Moniker Name
475 ---------------------------------
477 luser_group | LuserGroup
478 luser-opts | LuserOpt
479 stations_visited | StationVisited
480 routeChange | RouteChange
482 =head2 col_accessor_map
484 Same as moniker_map, but for column accessor names. If a coderef is
485 passed, the code is called with arguments of
487 the name of the column in the underlying database,
488 default accessor name that DBICSL would ordinarily give this column,
490 table_class => name of the DBIC class we are building,
491 table_moniker => calculated moniker for this table (after moniker_map if present),
492 table_name => name of the database table,
493 full_table_name => schema-qualified name of the database table (RDBMS specific),
494 schema_class => name of the schema class we are building,
495 column_info => hashref of column info (data_type, is_nullable, etc),
500 Similar in idea to moniker_map, but different in the details. It can be
501 a hashref or a code ref.
503 If it is a hashref, keys can be either the default relationship name, or the
504 moniker. The keys that are the default relationship name should map to the
505 name you want to change the relationship to. Keys that are monikers should map
506 to hashes mapping relationship names to their translation. You can do both at
507 once, and the more specific moniker version will be picked up first. So, for
508 instance, you could have
517 and relationships that would have been named C<bar> will now be named C<baz>
518 except that in the table whose moniker is C<Foo> it will be named C<blat>.
520 If it is a coderef, the argument passed will be a hashref of this form:
523 name => default relationship name,
524 type => the relationship type eg: C<has_many>,
525 local_class => name of the DBIC class we are building,
526 local_moniker => moniker of the DBIC class we are building,
527 local_columns => columns in this table in the relationship,
528 remote_class => name of the DBIC class we are related to,
529 remote_moniker => moniker of the DBIC class we are related to,
530 remote_columns => columns in the other table in the relationship,
533 DBICSL will try to use the value returned as the relationship name.
535 =head2 inflect_plural
537 Just like L</moniker_map> above (can be hash/code-ref, falls back to default
538 if hash key does not exist or coderef returns false), but acts as a map
539 for pluralizing relationship names. The default behavior is to utilize
540 L<Lingua::EN::Inflect::Phrase/to_PL>.
542 =head2 inflect_singular
544 As L</inflect_plural> above, but for singularizing relationship names.
545 Default behavior is to utilize L<Lingua::EN::Inflect::Phrase/to_S>.
547 =head2 schema_base_class
549 Base class for your schema classes. Defaults to 'DBIx::Class::Schema'.
551 =head2 schema_components
553 List of components to load into the Schema class.
555 =head2 result_base_class
557 Base class for your table classes (aka result classes). Defaults to
560 =head2 additional_base_classes
562 List of additional base classes all of your table classes will use.
564 =head2 left_base_classes
566 List of additional base classes all of your table classes will use
567 that need to be leftmost.
569 =head2 additional_classes
571 List of additional classes which all of your table classes will use.
575 List of additional components to be loaded into all of your Result
576 classes. A good example would be
577 L<InflateColumn::DateTime|DBIx::Class::InflateColumn::DateTime>
579 =head2 result_components_map
581 A hashref of moniker keys and component values. Unlike L</components>, which
582 loads the given components into every Result class, this option allows you to
583 load certain components for specified Result classes. For example:
585 result_components_map => {
586 StationVisited => '+YourApp::Schema::Component::StationVisited',
588 '+YourApp::Schema::Component::RouteChange',
589 'InflateColumn::DateTime',
593 You may use this in conjunction with L</components>.
597 List of L<Moose> roles to be applied to all of your Result classes.
599 =head2 result_roles_map
601 A hashref of moniker keys and role values. Unlike L</result_roles>, which
602 applies the given roles to every Result class, this option allows you to apply
603 certain roles for specified Result classes. For example:
605 result_roles_map => {
607 'YourApp::Role::Building',
608 'YourApp::Role::Destination',
610 RouteChange => 'YourApp::Role::TripEvent',
613 You may use this in conjunction with L</result_roles>.
615 =head2 use_namespaces
617 This is now the default, to go back to L<DBIx::Class::Schema/load_classes> pass
620 Generate result class names suitable for
621 L<DBIx::Class::Schema/load_namespaces> and call that instead of
622 L<DBIx::Class::Schema/load_classes>. When using this option you can also
623 specify any of the options for C<load_namespaces> (i.e. C<result_namespace>,
624 C<resultset_namespace>, C<default_resultset_class>), and they will be added
625 to the call (and the generated result class names adjusted appropriately).
627 =head2 dump_directory
629 The value of this option is a perl libdir pathname. Within
630 that directory this module will create a baseline manual
631 L<DBIx::Class::Schema> module set, based on what it creates at runtime.
633 The created schema class will have the same classname as the one on
634 which you are setting this option (and the ResultSource classes will be
635 based on this name as well).
637 Normally you wouldn't hard-code this setting in your schema class, as it
638 is meant for one-time manual usage.
640 See L<DBIx::Class::Schema::Loader/dump_to_dir> for examples of the
641 recommended way to access this functionality.
643 =head2 dump_overwrite
645 Deprecated. See L</really_erase_my_files> below, which does *not* mean
646 the same thing as the old C<dump_overwrite> setting from previous releases.
648 =head2 really_erase_my_files
650 Default false. If true, Loader will unconditionally delete any existing
651 files before creating the new ones from scratch when dumping a schema to disk.
653 The default behavior is instead to only replace the top portion of the
654 file, up to and including the final stanza which contains
655 C<# DO NOT MODIFY THE FIRST PART OF THIS FILE>
656 leaving any customizations you placed after that as they were.
658 When C<really_erase_my_files> is not set, if the output file already exists,
659 but the aforementioned final stanza is not found, or the checksum
660 contained there does not match the generated contents, Loader will
661 croak and not touch the file.
663 You should really be using version control on your schema classes (and all
664 of the rest of your code for that matter). Don't blame me if a bug in this
665 code wipes something out when it shouldn't have, you've been warned.
667 =head2 overwrite_modifications
669 Default false. If false, when updating existing files, Loader will
670 refuse to modify any Loader-generated code that has been modified
671 since its last run (as determined by the checksum Loader put in its
674 If true, Loader will discard any manual modifications that have been
675 made to Loader-generated code.
677 Again, you should be using version control on your schema classes. Be
678 careful with this option.
680 =head2 custom_column_info
682 Hook for adding extra attributes to the
683 L<column_info|DBIx::Class::ResultSource/column_info> for a column.
685 Must be a coderef that returns a hashref with the extra attributes.
687 Receives the table name, column name and column_info.
691 custom_column_info => sub {
692 my ($table_name, $column_name, $column_info) = @_;
694 if ($column_name eq 'dog' && $column_info->{default_value} eq 'snoopy') {
695 return { is_snoopy => 1 };
699 This attribute can also be used to set C<inflate_datetime> on a non-datetime
700 column so it also receives the L</datetime_timezone> and/or L</datetime_locale>.
702 =head2 datetime_timezone
704 Sets the timezone attribute for L<DBIx::Class::InflateColumn::DateTime> for all
705 columns with the DATE/DATETIME/TIMESTAMP data_types.
707 =head2 datetime_locale
709 Sets the locale attribute for L<DBIx::Class::InflateColumn::DateTime> for all
710 columns with the DATE/DATETIME/TIMESTAMP data_types.
712 =head2 datetime_undef_if_invalid
714 Pass a C<0> for this option when using MySQL if you B<DON'T> want C<<
715 datetime_undef_if_invalid => 1 >> in your column info for DATE, DATETIME and
718 The default is recommended to deal with data such as C<00/00/00> which
719 sometimes ends up in such columns in MySQL.
723 File in Perl format, which should return a HASH reference, from which to read
728 Normally database names are lowercased and split by underscore, use this option
729 if you have CamelCase database names.
731 Drivers for case sensitive databases like Sybase ASE or MSSQL with a
732 case-sensitive collation will turn this option on unconditionally.
734 B<NOTE:> L</naming> = C<v8> is highly recommended with this option as the
735 semantics of this mode are much improved for CamelCase database names.
737 L</naming> = C<v7> or greater is required with this option.
739 =head2 qualify_objects
741 Set to true to prepend the L</db_schema> to table names for C<<
742 __PACKAGE__->table >> calls, and to some other things like Oracle sequences.
746 Creates Schema and Result classes that use L<Moose>, L<MooseX::NonMoose> and
747 L<MooseX::MarkAsMethods> (or L<namespace::autoclean>, see below). The default
748 content after the md5 sum also makes the classes immutable.
750 It is safe to upgrade your existing Schema to this option.
752 =head2 only_autoclean
754 By default, we use L<MooseX::MarkAsMethods> to remove imported functions from
755 your generated classes. It uses L<namespace::autoclean> to do this, after
756 telling your object's metaclass that any operator L<overload>s in your class
757 are methods, which will cause namespace::autoclean to spare them from removal.
759 This prevents the "Hey, where'd my overloads go?!" effect.
761 If you don't care about operator overloads, enabling this option falls back to
762 just using L<namespace::autoclean> itself.
764 If none of the above made any sense, or you don't have some pressing need to
765 only use L<namespace::autoclean>, leaving this set to the default is
768 =head2 col_collision_map
770 This option controls how accessors for column names which collide with perl
771 methods are named. See L</COLUMN ACCESSOR COLLISIONS> for more information.
773 This option takes either a single L<sprintf|perlfunc/sprintf> format or a hashref of
774 strings which are compiled to regular expressions that map to
775 L<sprintf|perlfunc/sprintf> formats.
779 col_collision_map => 'column_%s'
781 col_collision_map => { '(.*)' => 'column_%s' }
783 col_collision_map => { '(foo).*(bar)' => 'column_%s_%s' }
785 =head2 rel_collision_map
787 Works just like L</col_collision_map>, but for relationship names/accessors
788 rather than column names/accessors.
790 The default is to just append C<_rel> to the relationship name, see
791 L</RELATIONSHIP NAME COLLISIONS>.
793 =head2 uniq_to_primary
795 Automatically promotes the largest unique constraints with non-nullable columns
796 on tables to primary keys, assuming there is only one largest unique
799 =head2 filter_generated_code
801 An optional hook that lets you filter the generated text for various classes
802 through a function that change it in any way that you want. The function will
803 receive the type of file, C<schema> or C<result>, class and code; and returns
804 the new code to use instead. For instance you could add custom comments, or do
805 anything else that you want.
807 The option can also be set to a string, which is then used as a filter program,
810 If this exists but fails to return text matching C</\bpackage\b/>, no file will
813 filter_generated_code => sub {
814 my ($type, $class, $text) = @_;
821 None of these methods are intended for direct invocation by regular
822 users of L<DBIx::Class::Schema::Loader>. Some are proxied via
823 L<DBIx::Class::Schema::Loader>.
827 # ensure that a peice of object data is a valid arrayref, creating
828 # an empty one or encapsulating whatever's there.
829 sub _ensure_arrayref {
834 $self->{$_} = [ $self->{$_} ]
835 unless ref $self->{$_} eq 'ARRAY';
841 Constructor for L<DBIx::Class::Schema::Loader::Base>, used internally
842 by L<DBIx::Class::Schema::Loader>.
847 my ( $class, %args ) = @_;
849 if (exists $args{column_accessor_map}) {
850 $args{col_accessor_map} = delete $args{column_accessor_map};
853 my $self = { %args };
855 # don't lose undef options
856 for (values %$self) {
857 $_ = 0 unless defined $_;
860 bless $self => $class;
862 if (my $config_file = $self->config_file) {
863 my $config_opts = do $config_file;
865 croak "Error reading config from $config_file: $@" if $@;
867 croak "Config file $config_file must be a hashref" unless ref($config_opts) eq 'HASH';
869 while (my ($k, $v) = each %$config_opts) {
870 $self->{$k} = $v unless exists $self->{$k};
874 if (defined $self->{result_component_map}) {
875 if (defined $self->result_components_map) {
876 croak "Specify only one of result_components_map or result_component_map";
878 $self->result_components_map($self->{result_component_map})
881 if (defined $self->{result_role_map}) {
882 if (defined $self->result_roles_map) {
883 croak "Specify only one of result_roles_map or result_role_map";
885 $self->result_roles_map($self->{result_role_map})
888 croak "the result_roles and result_roles_map options may only be used in conjunction with use_moose=1"
889 if ((not defined $self->use_moose) || (not $self->use_moose))
890 && ((defined $self->result_roles) || (defined $self->result_roles_map));
892 $self->_ensure_arrayref(qw/schema_components
894 additional_base_classes
900 $self->_validate_class_args;
902 croak "result_components_map must be a hash"
903 if defined $self->result_components_map
904 && ref $self->result_components_map ne 'HASH';
906 if ($self->result_components_map) {
907 my %rc_map = %{ $self->result_components_map };
908 foreach my $moniker (keys %rc_map) {
909 $rc_map{$moniker} = [ $rc_map{$moniker} ] unless ref $rc_map{$moniker};
911 $self->result_components_map(\%rc_map);
914 $self->result_components_map({});
916 $self->_validate_result_components_map;
918 croak "result_roles_map must be a hash"
919 if defined $self->result_roles_map
920 && ref $self->result_roles_map ne 'HASH';
922 if ($self->result_roles_map) {
923 my %rr_map = %{ $self->result_roles_map };
924 foreach my $moniker (keys %rr_map) {
925 $rr_map{$moniker} = [ $rr_map{$moniker} ] unless ref $rr_map{$moniker};
927 $self->result_roles_map(\%rr_map);
929 $self->result_roles_map({});
931 $self->_validate_result_roles_map;
933 if ($self->use_moose) {
934 if (not DBIx::Class::Schema::Loader::Optional::Dependencies->req_ok_for('use_moose')) {
935 die sprintf "You must install the following CPAN modules to enable the use_moose option: %s.\n",
936 DBIx::Class::Schema::Loader::Optional::Dependencies->req_missing_for('use_moose');
940 $self->{_tables} = {};
941 $self->{monikers} = {};
942 $self->{moniker_to_table} = {};
943 $self->{class_to_table} = {};
944 $self->{classes} = {};
945 $self->{_upgrading_classes} = {};
947 $self->{schema_class} ||= ( ref $self->{schema} || $self->{schema} );
948 $self->{schema} ||= $self->{schema_class};
949 $self->{table_comments_table} ||= 'table_comments';
950 $self->{column_comments_table} ||= 'column_comments';
952 croak "dump_overwrite is deprecated. Please read the"
953 . " DBIx::Class::Schema::Loader::Base documentation"
954 if $self->{dump_overwrite};
956 $self->{dynamic} = ! $self->{dump_directory};
957 $self->{temp_directory} ||= File::Temp::tempdir( 'dbicXXXX',
962 $self->{dump_directory} ||= $self->{temp_directory};
964 $self->real_dump_directory($self->{dump_directory});
966 $self->version_to_dump($DBIx::Class::Schema::Loader::VERSION);
967 $self->schema_version_to_dump($DBIx::Class::Schema::Loader::VERSION);
969 if (not defined $self->naming) {
970 $self->naming_set(0);
973 $self->naming_set(1);
976 if ((not ref $self->naming) && defined $self->naming) {
977 my $naming_ver = $self->naming;
979 relationships => $naming_ver,
980 monikers => $naming_ver,
981 column_accessors => $naming_ver,
984 elsif (ref $self->naming eq 'HASH' && exists $self->naming->{ALL}) {
985 my $val = delete $self->naming->{ALL};
987 $self->naming->{$_} = $val
988 foreach qw/relationships monikers column_accessors/;
992 foreach my $key (qw/relationships monikers column_accessors/) {
993 $self->naming->{$key} = $CURRENT_V if ($self->naming->{$key}||'') eq 'current';
996 $self->{naming} ||= {};
998 if ($self->custom_column_info && ref $self->custom_column_info ne 'CODE') {
999 croak 'custom_column_info must be a CODE ref';
1002 $self->_check_back_compat;
1004 $self->use_namespaces(1) unless defined $self->use_namespaces;
1005 $self->generate_pod(1) unless defined $self->generate_pod;
1006 $self->pod_comment_mode('auto') unless defined $self->pod_comment_mode;
1007 $self->pod_comment_spillover_length(60) unless defined $self->pod_comment_spillover_length;
1009 if (my $col_collision_map = $self->col_collision_map) {
1010 if (my $reftype = ref $col_collision_map) {
1011 if ($reftype ne 'HASH') {
1012 croak "Invalid type $reftype for option 'col_collision_map'";
1016 $self->col_collision_map({ '(.*)' => $col_collision_map });
1020 if (my $rel_collision_map = $self->rel_collision_map) {
1021 if (my $reftype = ref $rel_collision_map) {
1022 if ($reftype ne 'HASH') {
1023 croak "Invalid type $reftype for option 'rel_collision_map'";
1027 $self->rel_collision_map({ '(.*)' => $rel_collision_map });
1031 if (defined(my $rel_name_map = $self->rel_name_map)) {
1032 my $reftype = ref $rel_name_map;
1033 if ($reftype ne 'HASH' && $reftype ne 'CODE') {
1034 croak "Invalid type $reftype for option 'rel_name_map', must be HASH or CODE";
1038 if (defined(my $filter = $self->filter_generated_code)) {
1039 my $reftype = ref $filter;
1040 if ($reftype && $reftype ne 'CODE') {
1041 croak "Invalid type $reftype for option 'filter_generated_code, must be a scalar or a CODE reference";
1045 if (defined $self->db_schema) {
1046 if (ref $self->db_schema eq 'ARRAY') {
1047 if (@{ $self->db_schema } > 1) {
1048 $self->{qualify_objects} = 1;
1050 elsif (@{ $self->db_schema } == 0) {
1051 $self->{db_schema} = undef;
1054 elsif (not ref $self->db_schema) {
1055 if ($self->db_schema eq '%') {
1056 $self->{qualify_objects} = 1;
1059 $self->{db_schema} = [ $self->db_schema ];
1063 if (not $self->moniker_parts) {
1064 $self->moniker_parts(['name']);
1067 if (not ref $self->moniker_parts) {
1068 $self->moniker_parts([ $self->moniker_parts ]);
1070 if (ref $self->moniker_parts ne 'ARRAY') {
1071 croak 'moniker_parts must be an arrayref';
1073 if ((firstidx { $_ eq 'name' } @{ $self->moniker_parts }) == -1) {
1074 croak "moniker_parts option *must* contain 'name'";
1081 sub _check_back_compat {
1084 # dynamic schemas will always be in 0.04006 mode, unless overridden
1085 if ($self->dynamic) {
1086 # just in case, though no one is likely to dump a dynamic schema
1087 $self->schema_version_to_dump('0.04006');
1089 if (not $self->naming_set) {
1090 warn <<EOF unless $ENV{SCHEMA_LOADER_BACKCOMPAT};
1092 Dynamic schema detected, will run in 0.04006 mode.
1094 Set the 'naming' attribute or the SCHEMA_LOADER_BACKCOMPAT environment variable
1095 to disable this warning.
1097 See perldoc DBIx::Class::Schema::Loader::Manual::UpgradingFromV4 for more
1102 $self->_upgrading_from('v4');
1105 if ((not defined $self->use_namespaces) && ($self->naming_set)) {
1106 $self->use_namespaces(1);
1109 $self->naming->{relationships} ||= 'v4';
1110 $self->naming->{monikers} ||= 'v4';
1112 if ($self->use_namespaces) {
1113 $self->_upgrading_from_load_classes(1);
1116 $self->use_namespaces(0);
1122 # otherwise check if we need backcompat mode for a static schema
1123 my $filename = $self->get_dump_filename($self->schema_class);
1124 return unless -e $filename;
1126 my ($old_gen, $old_md5, $old_ver, $old_ts, $old_custom) =
1127 $self->_parse_generated_file($filename);
1129 return unless $old_ver;
1131 # determine if the existing schema was dumped with use_moose => 1
1132 if (! defined $self->use_moose) {
1133 $self->{use_moose} = 1 if $old_gen =~ /^ (?!\s*\#) use \s+ Moose/xm;
1136 my $load_classes = ($old_gen =~ /^__PACKAGE__->load_classes;/m) ? 1 : 0;
1138 my $result_namespace = do { ($old_gen =~ /result_namespace => (.+)/) ? $1 : '' };
1139 my $ds = eval $result_namespace;
1141 Could not eval expression '$result_namespace' for result_namespace from
1144 $result_namespace = $ds || '';
1146 if ($load_classes && (not defined $self->use_namespaces)) {
1147 warn <<"EOF" unless $ENV{SCHEMA_LOADER_BACKCOMPAT};
1149 'load_classes;' static schema detected, turning off 'use_namespaces'.
1151 Set the 'use_namespaces' attribute or the SCHEMA_LOADER_BACKCOMPAT environment
1152 variable to disable this warning.
1154 See perldoc DBIx::Class::Schema::Loader::Manual::UpgradingFromV4 for more
1157 $self->use_namespaces(0);
1159 elsif ($load_classes && $self->use_namespaces) {
1160 $self->_upgrading_from_load_classes(1);
1162 elsif ((not $load_classes) && defined $self->use_namespaces && ! $self->use_namespaces) {
1163 $self->_downgrading_to_load_classes(
1164 $result_namespace || 'Result'
1167 elsif ((not defined $self->use_namespaces) || $self->use_namespaces) {
1168 if (not $self->result_namespace) {
1169 $self->result_namespace($result_namespace || 'Result');
1171 elsif ($result_namespace ne $self->result_namespace) {
1172 $self->_rewriting_result_namespace(
1173 $result_namespace || 'Result'
1178 # XXX when we go past .0 this will need fixing
1179 my ($v) = $old_ver =~ /([1-9])/;
1182 return if ($v eq $CURRENT_V || $old_ver =~ /^0\.\d\d999/);
1184 if (not %{ $self->naming }) {
1185 warn <<"EOF" unless $ENV{SCHEMA_LOADER_BACKCOMPAT};
1187 Version $old_ver static schema detected, turning on backcompat mode.
1189 Set the 'naming' attribute or the SCHEMA_LOADER_BACKCOMPAT environment variable
1190 to disable this warning.
1192 See: 'naming' in perldoc DBIx::Class::Schema::Loader::Base .
1194 See perldoc DBIx::Class::Schema::Loader::Manual::UpgradingFromV4 if upgrading
1195 from version 0.04006.
1198 $self->naming->{relationships} ||= $v;
1199 $self->naming->{monikers} ||= $v;
1200 $self->naming->{column_accessors} ||= $v;
1202 $self->schema_version_to_dump($old_ver);
1205 $self->_upgrading_from($v);
1209 sub _validate_class_args {
1212 foreach my $k (@CLASS_ARGS) {
1213 next unless $self->$k;
1215 my @classes = ref $self->$k eq 'ARRAY' ? @{ $self->$k } : $self->$k;
1216 $self->_validate_classes($k, \@classes);
1220 sub _validate_result_components_map {
1223 foreach my $classes (values %{ $self->result_components_map }) {
1224 $self->_validate_classes('result_components_map', $classes);
1228 sub _validate_result_roles_map {
1231 foreach my $classes (values %{ $self->result_roles_map }) {
1232 $self->_validate_classes('result_roles_map', $classes);
1236 sub _validate_classes {
1239 my $classes = shift;
1241 # make a copy to not destroy original
1242 my @classes = @$classes;
1244 foreach my $c (@classes) {
1245 # components default to being under the DBIx::Class namespace unless they
1246 # are preceeded with a '+'
1247 if ( $key =~ m/component/ && $c !~ s/^\+// ) {
1248 $c = 'DBIx::Class::' . $c;
1251 # 1 == installed, 0 == not installed, undef == invalid classname
1252 my $installed = Class::Inspector->installed($c);
1253 if ( defined($installed) ) {
1254 if ( $installed == 0 ) {
1255 croak qq/$c, as specified in the loader option "$key", is not installed/;
1258 croak qq/$c, as specified in the loader option "$key", is an invalid class name/;
1264 sub _find_file_in_inc {
1265 my ($self, $file) = @_;
1267 foreach my $prefix (@INC) {
1268 my $fullpath = File::Spec->catfile($prefix, $file);
1269 return $fullpath if -f $fullpath
1270 # abs_path throws on Windows for nonexistant files
1271 and (try { Cwd::abs_path($fullpath) }) ne
1272 ((try { Cwd::abs_path(File::Spec->catfile($self->dump_directory, $file)) }) || '');
1278 sub _find_class_in_inc {
1279 my ($self, $class) = @_;
1281 return $self->_find_file_in_inc(class_path($class));
1287 return $self->_upgrading_from
1288 || $self->_upgrading_from_load_classes
1289 || $self->_downgrading_to_load_classes
1290 || $self->_rewriting_result_namespace
1294 sub _rewrite_old_classnames {
1295 my ($self, $code) = @_;
1297 return $code unless $self->_rewriting;
1299 my %old_classes = reverse %{ $self->_upgrading_classes };
1301 my $re = join '|', keys %old_classes;
1302 $re = qr/\b($re)\b/;
1304 $code =~ s/$re/$old_classes{$1} || $1/eg;
1309 sub _load_external {
1310 my ($self, $class) = @_;
1312 return if $self->{skip_load_external};
1314 # so that we don't load our own classes, under any circumstances
1315 local *INC = [ grep $_ ne $self->dump_directory, @INC ];
1317 my $real_inc_path = $self->_find_class_in_inc($class);
1319 my $old_class = $self->_upgrading_classes->{$class}
1320 if $self->_rewriting;
1322 my $old_real_inc_path = $self->_find_class_in_inc($old_class)
1323 if $old_class && $old_class ne $class;
1325 return unless $real_inc_path || $old_real_inc_path;
1327 if ($real_inc_path) {
1328 # If we make it to here, we loaded an external definition
1329 warn qq/# Loaded external class definition for '$class'\n/
1332 my $code = $self->_rewrite_old_classnames(slurp_file $real_inc_path);
1334 if ($self->dynamic) { # load the class too
1335 eval_package_without_redefine_warnings($class, $code);
1338 $self->_ext_stmt($class,
1339 qq|# These lines were loaded from '$real_inc_path' found in \@INC.\n|
1340 .qq|# They are now part of the custom portion of this file\n|
1341 .qq|# for you to hand-edit. If you do not either delete\n|
1342 .qq|# this section or remove that file from \@INC, this section\n|
1343 .qq|# will be repeated redundantly when you re-create this\n|
1344 .qq|# file again via Loader! See skip_load_external to disable\n|
1345 .qq|# this feature.\n|
1348 $self->_ext_stmt($class, $code);
1349 $self->_ext_stmt($class,
1350 qq|# End of lines loaded from '$real_inc_path' |
1354 if ($old_real_inc_path) {
1355 my $code = slurp_file $old_real_inc_path;
1357 $self->_ext_stmt($class, <<"EOF");
1359 # These lines were loaded from '$old_real_inc_path',
1360 # based on the Result class name that would have been created by an older
1361 # version of the Loader. For a static schema, this happens only once during
1362 # upgrade. See skip_load_external to disable this feature.
1365 $code = $self->_rewrite_old_classnames($code);
1367 if ($self->dynamic) {
1370 Detected external content in '$old_real_inc_path', a class name that would have
1371 been used by an older version of the Loader.
1373 * PLEASE RENAME THIS CLASS: from '$old_class' to '$class', as that is the
1374 new name of the Result.
1376 eval_package_without_redefine_warnings($class, $code);
1380 $self->_ext_stmt($class, $code);
1381 $self->_ext_stmt($class,
1382 qq|# End of lines loaded from '$old_real_inc_path' |
1389 Does the actual schema-construction work.
1396 $self->_load_tables(
1397 $self->_tables_list({ constraint => $self->constraint, exclude => $self->exclude })
1405 Rescan the database for changes. Returns a list of the newly added table
1408 The schema argument should be the schema class or object to be affected. It
1409 should probably be derived from the original schema_class used during L</load>.
1414 my ($self, $schema) = @_;
1416 $self->{schema} = $schema;
1417 $self->_relbuilder->{schema} = $schema;
1420 my @current = $self->_tables_list({ constraint => $self->constraint, exclude => $self->exclude });
1422 foreach my $table (@current) {
1423 if(!exists $self->_tables->{$table->sql_name}) {
1424 push(@created, $table);
1429 @current{map $_->sql_name, @current} = ();
1430 foreach my $table (values %{ $self->_tables }) {
1431 if (not exists $current{$table->sql_name}) {
1432 $self->_remove_table($table);
1436 delete @$self{qw/_dump_storage _relations_started _uniqs_started/};
1438 my $loaded = $self->_load_tables(@current);
1440 foreach my $table (@created) {
1441 $self->monikers->{$table->sql_name} = $self->_table2moniker($table);
1444 return map { $self->monikers->{$_->sql_name} } @created;
1450 return if $self->{skip_relationships};
1452 return $self->{relbuilder} ||= do {
1453 my $relbuilder_suff =
1460 ->{$self->naming->{relationships}||$CURRENT_V} || '';
1462 my $relbuilder_class = 'DBIx::Class::Schema::Loader::RelBuilder'.$relbuilder_suff;
1463 $self->ensure_class_loaded($relbuilder_class);
1464 $relbuilder_class->new($self);
1469 my ($self, @tables) = @_;
1471 # Save the new tables to the tables list
1473 $self->_tables->{$_->sql_name} = $_;
1476 $self->_make_src_class($_) for @tables;
1478 # sanity-check for moniker clashes
1479 my $inverse_moniker_idx;
1480 foreach my $table (values %{ $self->_tables }) {
1481 push @{ $inverse_moniker_idx->{$self->monikers->{$table->sql_name}} }, $table;
1485 foreach my $moniker (keys %$inverse_moniker_idx) {
1486 my $tables = $inverse_moniker_idx->{$moniker};
1488 push @clashes, sprintf ("tables %s reduced to the same source moniker '%s'",
1489 join (', ', map $_->sql_name, @$tables),
1496 die 'Unable to load schema - chosen moniker/class naming style results in moniker clashes. '
1497 . 'In multi db_schema configurations you may need to set moniker_parts, '
1498 . 'otherwise change the naming style, or supply an explicit moniker_map: '
1499 . join ('; ', @clashes)
1504 $self->_setup_src_meta($_) for @tables;
1506 if(!$self->skip_relationships) {
1507 # The relationship loader needs a working schema
1508 local $self->{quiet} = 1;
1509 local $self->{dump_directory} = $self->{temp_directory};
1510 $self->_reload_classes(\@tables);
1511 $self->_load_relationships(\@tables);
1513 # Remove that temp dir from INC so it doesn't get reloaded
1514 @INC = grep $_ ne $self->dump_directory, @INC;
1517 $self->_load_roles($_) for @tables;
1519 $self->_load_external($_)
1520 for map { $self->classes->{$_->sql_name} } @tables;
1522 # Reload without unloading first to preserve any symbols from external
1524 $self->_reload_classes(\@tables, { unload => 0 });
1526 # Drop temporary cache
1527 delete $self->{_cache};
1532 sub _reload_classes {
1533 my ($self, $tables, $opts) = @_;
1535 my @tables = @$tables;
1537 my $unload = $opts->{unload};
1538 $unload = 1 unless defined $unload;
1540 # so that we don't repeat custom sections
1541 @INC = grep $_ ne $self->dump_directory, @INC;
1543 $self->_dump_to_dir(map { $self->classes->{$_->sql_name} } @tables);
1545 unshift @INC, $self->dump_directory;
1548 my %have_source = map { $_ => $self->schema->source($_) }
1549 $self->schema->sources;
1551 for my $table (@tables) {
1552 my $moniker = $self->monikers->{$table->sql_name};
1553 my $class = $self->classes->{$table->sql_name};
1556 no warnings 'redefine';
1557 local *Class::C3::reinitialize = sub {}; # to speed things up, reinitialized below
1560 if (my $mc = $self->_moose_metaclass($class)) {
1563 Class::Unload->unload($class) if $unload;
1564 my ($source, $resultset_class);
1566 ($source = $have_source{$moniker})
1567 && ($resultset_class = $source->resultset_class)
1568 && ($resultset_class ne 'DBIx::Class::ResultSet')
1570 my $has_file = Class::Inspector->loaded_filename($resultset_class);
1571 if (my $mc = $self->_moose_metaclass($resultset_class)) {
1574 Class::Unload->unload($resultset_class) if $unload;
1575 $self->_reload_class($resultset_class) if $has_file;
1577 $self->_reload_class($class);
1579 push @to_register, [$moniker, $class];
1582 Class::C3->reinitialize;
1583 for (@to_register) {
1584 $self->schema->register_class(@$_);
1588 sub _moose_metaclass {
1589 return undef unless $INC{'Class/MOP.pm'}; # if CMOP is not loaded the class could not have loaded in the 1st place
1593 my $mc = try { Class::MOP::class_of($class) }
1596 return $mc->isa('Moose::Meta::Class') ? $mc : undef;
1599 # We use this instead of ensure_class_loaded when there are package symbols we
1602 my ($self, $class) = @_;
1604 delete $INC{ +class_path($class) };
1607 eval_package_without_redefine_warnings ($class, "require $class");
1610 my $source = slurp_file $self->_get_dump_filename($class);
1611 die "Failed to reload class $class: $_.\n\nCLASS SOURCE:\n\n$source";
1615 sub _get_dump_filename {
1616 my ($self, $class) = (@_);
1618 $class =~ s{::}{/}g;
1619 return $self->dump_directory . q{/} . $class . q{.pm};
1622 =head2 get_dump_filename
1626 Returns the full path to the file for a class that the class has been or will
1627 be dumped to. This is a file in a temp dir for a dynamic schema.
1631 sub get_dump_filename {
1632 my ($self, $class) = (@_);
1634 local $self->{dump_directory} = $self->real_dump_directory;
1636 return $self->_get_dump_filename($class);
1639 sub _ensure_dump_subdirs {
1640 my ($self, $class) = (@_);
1642 my @name_parts = split(/::/, $class);
1643 pop @name_parts; # we don't care about the very last element,
1644 # which is a filename
1646 my $dir = $self->dump_directory;
1649 mkdir($dir) or croak "mkdir('$dir') failed: $!";
1651 last if !@name_parts;
1652 $dir = File::Spec->catdir($dir, shift @name_parts);
1657 my ($self, @classes) = @_;
1659 my $schema_class = $self->schema_class;
1660 my $schema_base_class = $self->schema_base_class || 'DBIx::Class::Schema';
1662 my $target_dir = $self->dump_directory;
1663 warn "Dumping manual schema for $schema_class to directory $target_dir ...\n"
1664 unless $self->dynamic or $self->quiet;
1668 . qq|package $schema_class;\n\n|
1669 . qq|# Created by DBIx::Class::Schema::Loader\n|
1670 . qq|# DO NOT MODIFY THE FIRST PART OF THIS FILE\n\n|;
1673 = $self->only_autoclean
1674 ? 'namespace::autoclean'
1675 : 'MooseX::MarkAsMethods autoclean => 1'
1678 if ($self->use_moose) {
1680 $schema_text.= qq|use Moose;\nuse $autoclean;\nextends '$schema_base_class';\n\n|;
1683 $schema_text .= qq|use strict;\nuse warnings;\n\nuse base '$schema_base_class';\n\n|;
1686 my @schema_components = @{ $self->schema_components || [] };
1688 if (@schema_components) {
1689 my $schema_components = dump @schema_components;
1690 $schema_components = "($schema_components)" if @schema_components == 1;
1692 $schema_text .= "__PACKAGE__->load_components${schema_components};\n\n";
1695 if ($self->use_namespaces) {
1696 $schema_text .= qq|__PACKAGE__->load_namespaces|;
1697 my $namespace_options;
1699 my @attr = qw/resultset_namespace default_resultset_class/;
1701 unshift @attr, 'result_namespace' unless (not $self->result_namespace) || $self->result_namespace eq 'Result';
1703 for my $attr (@attr) {
1705 my $code = dumper_squashed $self->$attr;
1706 $namespace_options .= qq| $attr => $code,\n|
1709 $schema_text .= qq|(\n$namespace_options)| if $namespace_options;
1710 $schema_text .= qq|;\n|;
1713 $schema_text .= qq|__PACKAGE__->load_classes;\n|;
1717 local $self->{version_to_dump} = $self->schema_version_to_dump;
1718 $self->_write_classfile($schema_class, $schema_text, 1);
1721 my $result_base_class = $self->result_base_class || 'DBIx::Class::Core';
1723 foreach my $src_class (@classes) {
1726 . qq|package $src_class;\n\n|
1727 . qq|# Created by DBIx::Class::Schema::Loader\n|
1728 . qq|# DO NOT MODIFY THE FIRST PART OF THIS FILE\n\n|;
1730 $src_text .= $self->_make_pod_heading($src_class);
1732 $src_text .= qq|use strict;\nuse warnings;\n\n|;
1734 $src_text .= $self->_base_class_pod($result_base_class)
1735 unless $result_base_class eq 'DBIx::Class::Core';
1737 if ($self->use_moose) {
1738 $src_text.= qq|use Moose;\nuse MooseX::NonMoose;\nuse $autoclean;|;
1740 # these options 'use base' which is compile time
1741 if (@{ $self->left_base_classes } || @{ $self->additional_base_classes }) {
1742 $src_text .= qq|\nBEGIN { extends '$result_base_class' }\n|;
1745 $src_text .= qq|\nextends '$result_base_class';\n|;
1749 $src_text .= qq|use base '$result_base_class';\n|;
1752 $self->_write_classfile($src_class, $src_text);
1755 # remove Result dir if downgrading from use_namespaces, and there are no
1757 if (my $result_ns = $self->_downgrading_to_load_classes
1758 || $self->_rewriting_result_namespace) {
1759 my $result_namespace = $self->_result_namespace(
1764 (my $result_dir = $result_namespace) =~ s{::}{/}g;
1765 $result_dir = $self->dump_directory . '/' . $result_dir;
1767 unless (my @files = glob "$result_dir/*") {
1772 warn "Schema dump completed.\n" unless $self->dynamic or $self->quiet;
1776 my ($self, $version, $ts) = @_;
1777 return qq|\n\n# Created by DBIx::Class::Schema::Loader|
1780 . qq|\n# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:|;
1783 sub _write_classfile {
1784 my ($self, $class, $text, $is_schema) = @_;
1786 my $filename = $self->_get_dump_filename($class);
1787 $self->_ensure_dump_subdirs($class);
1789 if (-f $filename && $self->really_erase_my_files) {
1790 warn "Deleting existing file '$filename' due to "
1791 . "'really_erase_my_files' setting\n" unless $self->quiet;
1795 my ($old_gen, $old_md5, $old_ver, $old_ts, $old_custom)
1796 = $self->_parse_generated_file($filename);
1798 if (! $old_gen && -f $filename) {
1799 croak "Cannot overwrite '$filename' without 'really_erase_my_files',"
1800 . " it does not appear to have been generated by Loader"
1803 my $custom_content = $old_custom || '';
1805 # Use custom content from a renamed class, the class names in it are
1807 if (my $renamed_class = $self->_upgrading_classes->{$class}) {
1808 my $old_filename = $self->_get_dump_filename($renamed_class);
1810 if (-f $old_filename) {
1811 $custom_content = ($self->_parse_generated_file ($old_filename))[4];
1813 unlink $old_filename;
1817 $custom_content ||= $self->_default_custom_content($is_schema);
1819 # If upgrading to use_moose=1 replace default custom content with default Moose custom content.
1820 # If there is already custom content, which does not have the Moose content, add it.
1821 if ($self->use_moose) {
1823 my $non_moose_custom_content = do {
1824 local $self->{use_moose} = 0;
1825 $self->_default_custom_content;
1828 if ($custom_content eq $non_moose_custom_content) {
1829 $custom_content = $self->_default_custom_content($is_schema);
1831 elsif ($custom_content !~ /\Q@{[$self->_default_moose_custom_content($is_schema)]}\E/) {
1832 $custom_content .= $self->_default_custom_content($is_schema);
1835 elsif (defined $self->use_moose && $old_gen) {
1836 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'
1837 if $old_gen =~ /use \s+ MooseX?\b/x;
1840 $custom_content = $self->_rewrite_old_classnames($custom_content);
1843 for @{$self->{_dump_storage}->{$class} || []};
1845 if ($self->filter_generated_code) {
1846 my $filter = $self->filter_generated_code;
1848 if (ref $filter eq 'CODE') {
1850 ($is_schema ? 'schema' : 'result'),
1856 my ($fh, $temp_file) = tempfile();
1858 binmode $fh, ':encoding(UTF-8)';
1862 open my $out, qq{$filter < "$temp_file"|}
1863 or croak "Could not open pipe to $filter: $!";
1865 $text = decode('UTF-8', do { local $/; <$out> });
1867 $text =~ s/$CR?$LF/\n/g;
1871 my $exit_code = $? >> 8;
1874 or croak "Could not remove temporary file '$temp_file': $!";
1876 if ($exit_code != 0) {
1877 croak "filter '$filter' exited non-zero: $exit_code";
1880 if (not $text or not $text =~ /\bpackage\b/) {
1881 warn("$class skipped due to filter") if $self->debug;
1886 # Check and see if the dump is in fact different
1890 $compare_to = $text . $self->_sig_comment($old_ver, $old_ts);
1891 if (Digest::MD5::md5_base64(encode 'UTF-8', $compare_to) eq $old_md5) {
1892 return unless $self->_upgrading_from && $is_schema;
1896 $text .= $self->_sig_comment(
1897 $self->version_to_dump,
1898 POSIX::strftime('%Y-%m-%d %H:%M:%S', localtime)
1901 open(my $fh, '>:encoding(UTF-8)', $filename)
1902 or croak "Cannot open '$filename' for writing: $!";
1904 # Write the top half and its MD5 sum
1905 print $fh $text . Digest::MD5::md5_base64(encode 'UTF-8', $text) . "\n";
1907 # Write out anything loaded via external partial class file in @INC
1909 for @{$self->{_ext_storage}->{$class} || []};
1911 # Write out any custom content the user has added
1912 print $fh $custom_content;
1915 or croak "Error closing '$filename': $!";
1918 sub _default_moose_custom_content {
1919 my ($self, $is_schema) = @_;
1921 if (not $is_schema) {
1922 return qq|\n__PACKAGE__->meta->make_immutable;|;
1925 return qq|\n__PACKAGE__->meta->make_immutable(inline_constructor => 0);|;
1928 sub _default_custom_content {
1929 my ($self, $is_schema) = @_;
1930 my $default = qq|\n\n# You can replace this text with custom|
1931 . qq| code or comments, and it will be preserved on regeneration|;
1932 if ($self->use_moose) {
1933 $default .= $self->_default_moose_custom_content($is_schema);
1935 $default .= qq|\n1;\n|;
1939 sub _parse_generated_file {
1940 my ($self, $fn) = @_;
1942 return unless -f $fn;
1944 open(my $fh, '<:encoding(UTF-8)', $fn)
1945 or croak "Cannot open '$fn' for reading: $!";
1948 qr{^(# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:)([A-Za-z0-9/+]{22})\r?\n};
1950 my ($md5, $ts, $ver, $gen);
1956 # Pull out the version and timestamp from the line above
1957 ($ver, $ts) = $gen =~ m/^# Created by DBIx::Class::Schema::Loader v(.*?) @ (.*?)\r?\Z/m;
1960 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"
1961 if !$self->overwrite_modifications && Digest::MD5::md5_base64(encode 'UTF-8', $gen) ne $md5;
1970 my $custom = do { local $/; <$fh> }
1974 $custom =~ s/$CRLF|$LF/\n/g;
1978 return ($gen, $md5, $ver, $ts, $custom);
1986 warn "$target: use $_;" if $self->debug;
1987 $self->_raw_stmt($target, "use $_;");
1995 my $blist = join(q{ }, @_);
1997 return unless $blist;
1999 warn "$target: use base qw/$blist/;" if $self->debug;
2000 $self->_raw_stmt($target, "use base qw/$blist/;");
2007 my $rlist = join(q{, }, map { qq{'$_'} } @_);
2009 return unless $rlist;
2011 warn "$target: with $rlist;" if $self->debug;
2012 $self->_raw_stmt($target, "\nwith $rlist;");
2015 sub _result_namespace {
2016 my ($self, $schema_class, $ns) = @_;
2017 my @result_namespace;
2019 $ns = $ns->[0] if ref $ns;
2021 if ($ns =~ /^\+(.*)/) {
2022 # Fully qualified namespace
2023 @result_namespace = ($1)
2026 # Relative namespace
2027 @result_namespace = ($schema_class, $ns);
2030 return wantarray ? @result_namespace : join '::', @result_namespace;
2033 # Create class with applicable bases, setup monikers, etc
2034 sub _make_src_class {
2035 my ($self, $table) = @_;
2037 my $schema = $self->schema;
2038 my $schema_class = $self->schema_class;
2040 my $table_moniker = $self->_table2moniker($table);
2041 my @result_namespace = ($schema_class);
2042 if ($self->use_namespaces) {
2043 my $result_namespace = $self->result_namespace || 'Result';
2044 @result_namespace = $self->_result_namespace(
2049 my $table_class = join(q{::}, @result_namespace, $table_moniker);
2051 if ((my $upgrading_v = $self->_upgrading_from)
2052 || $self->_rewriting) {
2053 local $self->naming->{monikers} = $upgrading_v
2056 my @result_namespace = @result_namespace;
2057 if ($self->_upgrading_from_load_classes) {
2058 @result_namespace = ($schema_class);
2060 elsif (my $ns = $self->_downgrading_to_load_classes) {
2061 @result_namespace = $self->_result_namespace(
2066 elsif ($ns = $self->_rewriting_result_namespace) {
2067 @result_namespace = $self->_result_namespace(
2073 my $old_table_moniker = do {
2074 local $self->naming->{monikers} = $upgrading_v;
2075 $self->_table2moniker($table);
2078 my $old_class = join(q{::}, @result_namespace, $old_table_moniker);
2080 $self->_upgrading_classes->{$table_class} = $old_class
2081 unless $table_class eq $old_class;
2084 $self->classes->{$table->sql_name} = $table_class;
2085 $self->monikers->{$table->sql_name} = $table_moniker;
2086 $self->moniker_to_table->{$table_moniker} = $table;
2087 $self->class_to_table->{$table_class} = $table;
2089 $self->_pod_class_list($table_class, 'ADDITIONAL CLASSES USED', @{$self->additional_classes});
2091 $self->_use ($table_class, @{$self->additional_classes});
2093 $self->_pod_class_list($table_class, 'LEFT BASE CLASSES', @{$self->left_base_classes});
2095 $self->_inject($table_class, @{$self->left_base_classes});
2097 my @components = @{ $self->components || [] };
2099 push @components, @{ $self->result_components_map->{$table_moniker} }
2100 if exists $self->result_components_map->{$table_moniker};
2102 my @fq_components = @components;
2103 foreach my $component (@fq_components) {
2104 if ($component !~ s/^\+//) {
2105 $component = "DBIx::Class::$component";
2109 $self->_pod_class_list($table_class, 'COMPONENTS LOADED', @fq_components);
2111 $self->_dbic_stmt($table_class, 'load_components', @components) if @components;
2113 $self->_pod_class_list($table_class, 'ADDITIONAL BASE CLASSES', @{$self->additional_base_classes});
2115 $self->_inject($table_class, @{$self->additional_base_classes});
2118 sub _is_result_class_method {
2119 my ($self, $name, $table) = @_;
2121 my $table_moniker = $table ? $self->monikers->{$table->sql_name} : '';
2123 $self->_result_class_methods({})
2124 if not defined $self->_result_class_methods;
2126 if (not exists $self->_result_class_methods->{$table_moniker}) {
2127 my (@methods, %methods);
2128 my $base = $self->result_base_class || 'DBIx::Class::Core';
2130 my @components = @{ $self->components || [] };
2132 push @components, @{ $self->result_components_map->{$table_moniker} }
2133 if exists $self->result_components_map->{$table_moniker};
2135 for my $c (@components) {
2136 $c = $c =~ /^\+/ ? substr($c,1) : "DBIx::Class::$c";
2139 my @roles = @{ $self->result_roles || [] };
2141 push @roles, @{ $self->result_roles_map->{$table_moniker} }
2142 if exists $self->result_roles_map->{$table_moniker};
2144 for my $class ($base, @components,
2145 ($self->use_moose ? 'Moose::Object' : ()), @roles) {
2146 $self->ensure_class_loaded($class);
2148 push @methods, @{ Class::Inspector->methods($class) || [] };
2151 push @methods, @{ Class::Inspector->methods('UNIVERSAL') };
2153 @methods{@methods} = ();
2155 $self->_result_class_methods->{$table_moniker} = \%methods;
2157 my $result_methods = $self->_result_class_methods->{$table_moniker};
2159 return exists $result_methods->{$name};
2162 sub _resolve_col_accessor_collisions {
2163 my ($self, $table, $col_info) = @_;
2165 while (my ($col, $info) = each %$col_info) {
2166 my $accessor = $info->{accessor} || $col;
2168 next if $accessor eq 'id'; # special case (very common column)
2170 if ($self->_is_result_class_method($accessor, $table)) {
2173 if (my $map = $self->col_collision_map) {
2174 for my $re (keys %$map) {
2175 if (my @matches = $col =~ /$re/) {
2176 $info->{accessor} = sprintf $map->{$re}, @matches;
2184 Column '$col' in table '$table' collides with an inherited method.
2185 See "COLUMN ACCESSOR COLLISIONS" in perldoc DBIx::Class::Schema::Loader::Base .
2187 $info->{accessor} = undef;
2193 # use the same logic to run moniker_map, col_accessor_map
2195 my ( $self, $map, $default_code, $ident, @extra ) = @_;
2197 my $default_ident = $default_code->( $ident, @extra );
2199 if( $map && ref $map eq 'HASH' ) {
2200 $new_ident = $map->{ $ident };
2202 elsif( $map && ref $map eq 'CODE' ) {
2203 $new_ident = $map->( $ident, $default_ident, @extra );
2206 $new_ident ||= $default_ident;
2211 sub _default_column_accessor_name {
2212 my ( $self, $column_name ) = @_;
2214 my $preserve = ($self->naming->{column_accessors}||'') eq 'preserve';
2216 my $v = $self->_get_naming_v('column_accessors');
2218 my $accessor_name = $preserve ?
2219 $self->_to_identifier('column_accessors', $column_name) # assume CamelCase
2221 $self->_to_identifier('column_accessors', $column_name, '_');
2223 $accessor_name =~ s/\W+/_/g; # only if naming < v8, otherwise to_identifier
2227 return $accessor_name;
2229 elsif ($v < 7 || (not $self->preserve_case)) {
2230 # older naming just lc'd the col accessor and that's all.
2231 return lc $accessor_name;
2234 return join '_', map lc, split_name $column_name, $v;
2237 sub _make_column_accessor_name {
2238 my ($self, $column_name, $column_context_info ) = @_;
2240 my $accessor = $self->_run_user_map(
2241 $self->col_accessor_map,
2242 sub { $self->_default_column_accessor_name( shift ) },
2244 $column_context_info,
2250 # Set up metadata (cols, pks, etc)
2251 sub _setup_src_meta {
2252 my ($self, $table) = @_;
2254 my $schema = $self->schema;
2255 my $schema_class = $self->schema_class;
2257 my $table_class = $self->classes->{$table->sql_name};
2258 my $table_moniker = $self->monikers->{$table->sql_name};
2260 $self->_dbic_stmt($table_class, 'table', $table->dbic_name);
2262 my $cols = $self->_table_columns($table);
2263 my $col_info = $self->__columns_info_for($table);
2265 ### generate all the column accessor names
2266 while (my ($col, $info) = each %$col_info) {
2267 # hashref of other info that could be used by
2268 # user-defined accessor map functions
2270 table_class => $table_class,
2271 table_moniker => $table_moniker,
2272 table_name => $table,
2273 full_table_name => $table->dbic_name,
2274 schema_class => $schema_class,
2275 column_info => $info,
2278 $info->{accessor} = $self->_make_column_accessor_name( $col, $context );
2281 $self->_resolve_col_accessor_collisions($table, $col_info);
2283 # prune any redundant accessor names
2284 while (my ($col, $info) = each %$col_info) {
2285 no warnings 'uninitialized';
2286 delete $info->{accessor} if $info->{accessor} eq $col;
2289 my $fks = $self->_table_fk_info($table);
2291 foreach my $fkdef (@$fks) {
2292 for my $col (@{ $fkdef->{local_columns} }) {
2293 $col_info->{$col}{is_foreign_key} = 1;
2297 my $pks = $self->_table_pk_info($table) || [];
2299 my %uniq_tag; # used to eliminate duplicate uniqs
2301 $uniq_tag{ join("\0", @$pks) }++ if @$pks; # pk is a uniq
2303 my $uniqs = $self->_table_uniq_info($table) || [];
2306 foreach my $uniq (@$uniqs) {
2307 my ($name, $cols) = @$uniq;
2308 next if $uniq_tag{ join("\0", @$cols) }++; # skip duplicates
2309 push @uniqs, [$name, $cols];
2312 my @non_nullable_uniqs = grep {
2313 all { $col_info->{$_}{is_nullable} == 0 } @{ $_->[1] }
2316 if ($self->uniq_to_primary && (not @$pks) && @non_nullable_uniqs) {
2317 my @by_colnum = sort { $b->[0] <=> $a->[0] }
2318 map [ scalar @{ $_->[1] }, $_ ], @non_nullable_uniqs;
2320 if (not (@by_colnum > 1 && $by_colnum[0][0] == $by_colnum[1][0])) {
2321 my @keys = map $_->[1], @by_colnum;
2325 # remove the uniq from list
2326 @uniqs = grep { $_->[0] ne $pk->[0] } @uniqs;
2332 foreach my $pkcol (@$pks) {
2333 $col_info->{$pkcol}{is_nullable} = 0;
2339 map { $_, ($col_info->{$_}||{}) } @$cols
2342 $self->_dbic_stmt($table_class, 'set_primary_key', @$pks)
2345 # Sort unique constraints by constraint name for repeatable results (rels
2346 # are sorted as well elsewhere.)
2347 @uniqs = sort { $a->[0] cmp $b->[0] } @uniqs;
2349 foreach my $uniq (@uniqs) {
2350 my ($name, $cols) = @$uniq;
2351 $self->_dbic_stmt($table_class,'add_unique_constraint', $name, $cols);
2355 sub __columns_info_for {
2356 my ($self, $table) = @_;
2358 my $result = $self->_columns_info_for($table);
2360 while (my ($col, $info) = each %$result) {
2361 $info = { %$info, %{ $self->_custom_column_info ($table, $col, $info) } };
2362 $info = { %$info, %{ $self->_datetime_column_info($table, $col, $info) } };
2364 $result->{$col} = $info;
2372 Returns a sorted list of loaded tables, using the original database table
2380 return values %{$self->_tables};
2384 my ($self, $naming_key) = @_;
2388 if (($self->naming->{$naming_key}||'') =~ /^v(\d+)\z/) {
2392 ($v) = $CURRENT_V =~ /^v(\d+)\z/;
2398 sub _to_identifier {
2399 my ($self, $naming_key, $name, $sep_char, $force) = @_;
2401 my $v = $self->_get_naming_v($naming_key);
2403 my $to_identifier = $self->naming->{force_ascii} ?
2404 \&String::ToIdentifier::EN::to_identifier
2405 : \&String::ToIdentifier::EN::Unicode::to_identifier;
2407 return $v >= 8 || $force ? $to_identifier->($name, $sep_char) : $name;
2410 # Make a moniker from a table
2411 sub _default_table2moniker {
2412 my ($self, $table) = @_;
2414 my $v = $self->_get_naming_v('monikers');
2416 my @name_parts = map $table->$_, @{ $self->moniker_parts };
2418 my $name_idx = firstidx { $_ eq 'name' } @{ $self->moniker_parts };
2422 foreach my $i (0 .. $#name_parts) {
2423 my $part = $name_parts[$i];
2425 if ($i != $name_idx || $v >= 8) {
2426 $part = $self->_to_identifier('monikers', $part, '_', 1);
2429 if ($i == $name_idx && $v == 5) {
2430 $part = Lingua::EN::Inflect::Number::to_S($part);
2433 my @part_parts = map lc, $v > 6 ?
2434 # use v8 semantics for all moniker parts except name
2435 ($i == $name_idx ? split_name $part, $v : split_name $part)
2436 : split /[\W_]+/, $part;
2438 if ($i == $name_idx && $v >= 6) {
2439 my $as_phrase = join ' ', @part_parts;
2441 my $inflected = ($self->naming->{monikers}||'') eq 'plural' ?
2442 Lingua::EN::Inflect::Phrase::to_PL($as_phrase)
2444 ($self->naming->{monikers}||'') eq 'preserve' ?
2447 Lingua::EN::Inflect::Phrase::to_S($as_phrase);
2449 @part_parts = split /\s+/, $inflected;
2452 push @all_parts, map ucfirst, @part_parts;
2455 return join '', @all_parts;
2458 sub _table2moniker {
2459 my ( $self, $table ) = @_;
2461 $self->_run_user_map(
2463 sub { $self->_default_table2moniker( shift ) },
2468 sub _load_relationships {
2469 my ($self, $tables) = @_;
2473 foreach my $table (@$tables) {
2474 my $local_moniker = $self->monikers->{$table->sql_name};
2476 my $tbl_fk_info = $self->_table_fk_info($table);
2478 foreach my $fkdef (@$tbl_fk_info) {
2479 $fkdef->{local_table} = $table;
2480 $fkdef->{local_moniker} = $local_moniker;
2481 $fkdef->{remote_source} =
2482 $self->monikers->{$fkdef->{remote_table}->sql_name};
2484 my $tbl_uniq_info = $self->_table_uniq_info($table);
2486 push @tables, [ $local_moniker, $tbl_fk_info, $tbl_uniq_info ];
2489 my $rel_stmts = $self->_relbuilder->generate_code(\@tables);
2491 foreach my $src_class (sort keys %$rel_stmts) {
2493 my @src_stmts = map $_->[1],
2494 sort { $a->[0] cmp $b->[0] }
2495 map [ $_->{args}[0], $_ ], @{ $rel_stmts->{$src_class} };
2497 foreach my $stmt (@src_stmts) {
2498 $self->_dbic_stmt($src_class,$stmt->{method}, @{$stmt->{args}});
2504 my ($self, $table) = @_;
2506 my $table_moniker = $self->monikers->{$table->sql_name};
2507 my $table_class = $self->classes->{$table->sql_name};
2509 my @roles = @{ $self->result_roles || [] };
2510 push @roles, @{ $self->result_roles_map->{$table_moniker} }
2511 if exists $self->result_roles_map->{$table_moniker};
2514 $self->_pod_class_list($table_class, 'L<Moose> ROLES APPLIED', @roles);
2516 $self->_with($table_class, @roles);
2520 # Overload these in driver class:
2522 # Returns an arrayref of column names
2523 sub _table_columns { croak "ABSTRACT METHOD" }
2525 # Returns arrayref of pk col names
2526 sub _table_pk_info { croak "ABSTRACT METHOD" }
2528 # Returns an arrayref of uniqs [ [ foo => [ col1, col2 ] ], [ bar => [ ... ] ] ]
2529 sub _table_uniq_info { croak "ABSTRACT METHOD" }
2531 # Returns an arrayref of foreign key constraints, each
2532 # being a hashref with 3 keys:
2533 # local_columns (arrayref), remote_columns (arrayref), remote_table
2534 sub _table_fk_info { croak "ABSTRACT METHOD" }
2536 # Returns an array of lower case table names
2537 sub _tables_list { croak "ABSTRACT METHOD" }
2539 # Execute a constructive DBIC class method, with debug/dump_to_dir hooks.
2545 # generate the pod for this statement, storing it with $self->_pod
2546 $self->_make_pod( $class, $method, @_ ) if $self->generate_pod;
2548 my $args = dump(@_);
2549 $args = '(' . $args . ')' if @_ < 2;
2550 my $stmt = $method . $args . q{;};
2552 warn qq|$class\->$stmt\n| if $self->debug;
2553 $self->_raw_stmt($class, '__PACKAGE__->' . $stmt);
2557 sub _make_pod_heading {
2558 my ($self, $class) = @_;
2560 return '' if not $self->generate_pod;
2562 my $table = $self->class_to_table->{$class};
2565 my $pcm = $self->pod_comment_mode;
2566 my ($comment, $comment_overflows, $comment_in_name, $comment_in_desc);
2567 $comment = $self->__table_comment($table);
2568 $comment_overflows = ($comment and length $comment > $self->pod_comment_spillover_length);
2569 $comment_in_name = ($pcm eq 'name' or ($pcm eq 'auto' and !$comment_overflows));
2570 $comment_in_desc = ($pcm eq 'description' or ($pcm eq 'auto' and $comment_overflows));
2572 $pod .= "=head1 NAME\n\n";
2574 my $table_descr = $class;
2575 $table_descr .= " - " . $comment if $comment and $comment_in_name;
2577 $pod .= "$table_descr\n\n";
2579 if ($comment and $comment_in_desc) {
2580 $pod .= "=head1 DESCRIPTION\n\n${comment}\n\n";
2587 # generates the accompanying pod for a DBIC class method statement,
2588 # storing it with $self->_pod
2594 if ($method eq 'table') {
2596 $table = $$table if ref $table eq 'SCALAR';
2597 $self->_pod($class, "=head1 TABLE: C<$table>");
2598 $self->_pod_cut($class);
2600 elsif ( $method eq 'add_columns' ) {
2601 $self->_pod( $class, "=head1 ACCESSORS" );
2602 my $col_counter = 0;
2604 while( my ($name,$attrs) = splice @cols,0,2 ) {
2606 $self->_pod( $class, '=head2 ' . $name );
2607 $self->_pod( $class,
2609 my $s = $attrs->{$_};
2610 $s = !defined $s ? 'undef' :
2611 length($s) == 0 ? '(empty string)' :
2612 ref($s) eq 'SCALAR' ? $$s :
2613 ref($s) ? dumper_squashed $s :
2614 looks_like_number($s) ? $s : qq{'$s'};
2617 } sort keys %$attrs,
2619 if (my $comment = $self->__column_comment($self->class_to_table->{$class}, $col_counter, $name)) {
2620 $self->_pod( $class, $comment );
2623 $self->_pod_cut( $class );
2624 } elsif ( $method =~ /^(belongs_to|has_many|might_have)$/ ) {
2625 $self->_pod( $class, "=head1 RELATIONS" ) unless $self->{_relations_started} { $class } ;
2626 my ( $accessor, $rel_class ) = @_;
2627 $self->_pod( $class, "=head2 $accessor" );
2628 $self->_pod( $class, 'Type: ' . $method );
2629 $self->_pod( $class, "Related object: L<$rel_class>" );
2630 $self->_pod_cut( $class );
2631 $self->{_relations_started} { $class } = 1;
2633 elsif ($method eq 'add_unique_constraint') {
2634 $self->_pod($class, '=head1 UNIQUE CONSTRAINTS')
2635 unless $self->{_uniqs_started}{$class};
2637 my ($name, $cols) = @_;
2639 $self->_pod($class, "=head2 C<$name>");
2640 $self->_pod($class, '=over 4');
2642 foreach my $col (@$cols) {
2643 $self->_pod($class, "=item \* L</$col>");
2646 $self->_pod($class, '=back');
2647 $self->_pod_cut($class);
2649 $self->{_uniqs_started}{$class} = 1;
2651 elsif ($method eq 'set_primary_key') {
2652 $self->_pod($class, "=head1 PRIMARY KEY");
2653 $self->_pod($class, '=over 4');
2655 foreach my $col (@_) {
2656 $self->_pod($class, "=item \* L</$col>");
2659 $self->_pod($class, '=back');
2660 $self->_pod_cut($class);
2664 sub _pod_class_list {
2665 my ($self, $class, $title, @classes) = @_;
2667 return unless @classes && $self->generate_pod;
2669 $self->_pod($class, "=head1 $title");
2670 $self->_pod($class, '=over 4');
2672 foreach my $link (@classes) {
2673 $self->_pod($class, "=item * L<$link>");
2676 $self->_pod($class, '=back');
2677 $self->_pod_cut($class);
2680 sub _base_class_pod {
2681 my ($self, $base_class) = @_;
2683 return '' unless $self->generate_pod;
2686 =head1 BASE CLASS: L<$base_class>
2693 sub _filter_comment {
2694 my ($self, $txt) = @_;
2696 $txt = '' if not defined $txt;
2698 $txt =~ s/(?:\015?\012|\015\012?)/\n/g;
2703 sub __table_comment {
2706 if (my $code = $self->can('_table_comment')) {
2707 return $self->_filter_comment($self->$code(@_));
2713 sub __column_comment {
2716 if (my $code = $self->can('_column_comment')) {
2717 return $self->_filter_comment($self->$code(@_));
2723 # Stores a POD documentation
2725 my ($self, $class, $stmt) = @_;
2726 $self->_raw_stmt( $class, "\n" . $stmt );
2730 my ($self, $class ) = @_;
2731 $self->_raw_stmt( $class, "\n=cut\n" );
2734 # Store a raw source line for a class (for dumping purposes)
2736 my ($self, $class, $stmt) = @_;
2737 push(@{$self->{_dump_storage}->{$class}}, $stmt);
2740 # Like above, but separately for the externally loaded stuff
2742 my ($self, $class, $stmt) = @_;
2743 push(@{$self->{_ext_storage}->{$class}}, $stmt);
2746 sub _custom_column_info {
2747 my ( $self, $table_name, $column_name, $column_info ) = @_;
2749 if (my $code = $self->custom_column_info) {
2750 return $code->($table_name, $column_name, $column_info) || {};
2755 sub _datetime_column_info {
2756 my ( $self, $table_name, $column_name, $column_info ) = @_;
2758 my $type = $column_info->{data_type} || '';
2759 if ((grep $_, @{ $column_info }{map "inflate_$_", qw/date datetime timestamp/})
2760 or ($type =~ /date|timestamp/i)) {
2761 $result->{timezone} = $self->datetime_timezone if $self->datetime_timezone;
2762 $result->{locale} = $self->datetime_locale if $self->datetime_locale;
2768 my ($self, $name) = @_;
2770 return $self->preserve_case ? $name : lc($name);
2774 my ($self, $name) = @_;
2776 return $self->preserve_case ? $name : uc($name);
2780 my ($self, $table) = @_;
2783 my $schema = $self->schema;
2784 # in older DBIC it's a private method
2785 my $unregister = $schema->can('unregister_source') || $schema->can('_unregister_source');
2786 $schema->$unregister(delete $self->monikers->{$table->sql_name});
2787 delete $self->_upgrading_classes->{delete $self->classes->{$table->sql_name}};
2788 delete $self->_tables->{$table->sql_name};
2792 # remove the dump dir from @INC on destruction
2796 @INC = grep $_ ne $self->dump_directory, @INC;
2801 Returns a hashref of loaded table to moniker mappings. There will
2802 be two entries for each table, the original name and the "normalized"
2803 name, in the case that the two are different (such as databases
2804 that like uppercase table names, or preserve your original mixed-case
2805 definitions, or what-have-you).
2809 Returns a hashref of table to class mappings. In some cases it will
2810 contain multiple entries per table for the original and normalized table
2811 names, as above in L</monikers>.
2813 =head1 NON-ENGLISH DATABASES
2815 If you use the loader on a database with table and column names in a language
2816 other than English, you will want to turn off the English language specific
2819 To do so, use something like this in your laoder options:
2821 naming => { monikers => 'v4' },
2822 inflect_singular => sub { "$_[0]_rel" },
2823 inflect_plural => sub { "$_[0]_rel" },
2825 =head1 COLUMN ACCESSOR COLLISIONS
2827 Occasionally you may have a column name that collides with a perl method, such
2828 as C<can>. In such cases, the default action is to set the C<accessor> of the
2829 column spec to C<undef>.
2831 You can then name the accessor yourself by placing code such as the following
2834 __PACKAGE__->add_column('+can' => { accessor => 'my_can' });
2836 Another option is to use the L</col_collision_map> option.
2838 =head1 RELATIONSHIP NAME COLLISIONS
2840 In very rare cases, you may get a collision between a generated relationship
2841 name and a method in your Result class, for example if you have a foreign key
2842 called C<belongs_to>.
2844 This is a problem because relationship names are also relationship accessor
2845 methods in L<DBIx::Class>.
2847 The default behavior is to append C<_rel> to the relationship name and print
2848 out a warning that refers to this text.
2850 You can also control the renaming with the L</rel_collision_map> option.
2854 L<DBIx::Class::Schema::Loader>
2858 See L<DBIx::Class::Schema::Loader/AUTHOR> and L<DBIx::Class::Schema::Loader/CONTRIBUTORS>.
2862 This library is free software; you can redistribute it and/or modify it under
2863 the same terms as Perl itself.
2868 # vim:et sts=4 sw=4 tw=0: