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.07012';
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 a
464 hashref of table keys and moniker values, or a coderef for a translator
465 function taking a L<table object|DBIx::Class::Schema::Loader::Table> argument
466 and returning a scalar moniker. If the hash entry does not exist, or the
467 function returns a false value, the code falls back to default behavior for
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 => table object of interface DBIx::Class::Schema::Loader::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 L<table object|DBIx::Class::Schema::Loader::Table>, column name
692 custom_column_info => sub {
693 my ($table, $column_name, $column_info) = @_;
695 if ($column_name eq 'dog' && $column_info->{default_value} eq 'snoopy') {
696 return { is_snoopy => 1 };
700 This attribute can also be used to set C<inflate_datetime> on a non-datetime
701 column so it also receives the L</datetime_timezone> and/or L</datetime_locale>.
703 =head2 datetime_timezone
705 Sets the timezone attribute for L<DBIx::Class::InflateColumn::DateTime> for all
706 columns with the DATE/DATETIME/TIMESTAMP data_types.
708 =head2 datetime_locale
710 Sets the locale attribute for L<DBIx::Class::InflateColumn::DateTime> for all
711 columns with the DATE/DATETIME/TIMESTAMP data_types.
713 =head2 datetime_undef_if_invalid
715 Pass a C<0> for this option when using MySQL if you B<DON'T> want C<<
716 datetime_undef_if_invalid => 1 >> in your column info for DATE, DATETIME and
719 The default is recommended to deal with data such as C<00/00/00> which
720 sometimes ends up in such columns in MySQL.
724 File in Perl format, which should return a HASH reference, from which to read
729 Normally database names are lowercased and split by underscore, use this option
730 if you have CamelCase database names.
732 Drivers for case sensitive databases like Sybase ASE or MSSQL with a
733 case-sensitive collation will turn this option on unconditionally.
735 B<NOTE:> L</naming> = C<v8> is highly recommended with this option as the
736 semantics of this mode are much improved for CamelCase database names.
738 L</naming> = C<v7> or greater is required with this option.
740 =head2 qualify_objects
742 Set to true to prepend the L</db_schema> to table names for C<<
743 __PACKAGE__->table >> calls, and to some other things like Oracle sequences.
745 This attribute is automatically set to true for multi db_schema configurations.
749 Creates Schema and Result classes that use L<Moose>, L<MooseX::NonMoose> and
750 L<MooseX::MarkAsMethods> (or L<namespace::autoclean>, see below). The default
751 content after the md5 sum also makes the classes immutable.
753 It is safe to upgrade your existing Schema to this option.
755 =head2 only_autoclean
757 By default, we use L<MooseX::MarkAsMethods> to remove imported functions from
758 your generated classes. It uses L<namespace::autoclean> to do this, after
759 telling your object's metaclass that any operator L<overload>s in your class
760 are methods, which will cause namespace::autoclean to spare them from removal.
762 This prevents the "Hey, where'd my overloads go?!" effect.
764 If you don't care about operator overloads, enabling this option falls back to
765 just using L<namespace::autoclean> itself.
767 If none of the above made any sense, or you don't have some pressing need to
768 only use L<namespace::autoclean>, leaving this set to the default is
771 =head2 col_collision_map
773 This option controls how accessors for column names which collide with perl
774 methods are named. See L</COLUMN ACCESSOR COLLISIONS> for more information.
776 This option takes either a single L<sprintf|perlfunc/sprintf> format or a hashref of
777 strings which are compiled to regular expressions that map to
778 L<sprintf|perlfunc/sprintf> formats.
782 col_collision_map => 'column_%s'
784 col_collision_map => { '(.*)' => 'column_%s' }
786 col_collision_map => { '(foo).*(bar)' => 'column_%s_%s' }
788 =head2 rel_collision_map
790 Works just like L</col_collision_map>, but for relationship names/accessors
791 rather than column names/accessors.
793 The default is to just append C<_rel> to the relationship name, see
794 L</RELATIONSHIP NAME COLLISIONS>.
796 =head2 uniq_to_primary
798 Automatically promotes the largest unique constraints with non-nullable columns
799 on tables to primary keys, assuming there is only one largest unique
802 =head2 filter_generated_code
804 An optional hook that lets you filter the generated text for various classes
805 through a function that change it in any way that you want. The function will
806 receive the type of file, C<schema> or C<result>, class and code; and returns
807 the new code to use instead. For instance you could add custom comments, or do
808 anything else that you want.
810 The option can also be set to a string, which is then used as a filter program,
813 If this exists but fails to return text matching C</\bpackage\b/>, no file will
816 filter_generated_code => sub {
817 my ($type, $class, $text) = @_;
824 None of these methods are intended for direct invocation by regular
825 users of L<DBIx::Class::Schema::Loader>. Some are proxied via
826 L<DBIx::Class::Schema::Loader>.
830 # ensure that a peice of object data is a valid arrayref, creating
831 # an empty one or encapsulating whatever's there.
832 sub _ensure_arrayref {
837 $self->{$_} = [ $self->{$_} ]
838 unless ref $self->{$_} eq 'ARRAY';
844 Constructor for L<DBIx::Class::Schema::Loader::Base>, used internally
845 by L<DBIx::Class::Schema::Loader>.
850 my ( $class, %args ) = @_;
852 if (exists $args{column_accessor_map}) {
853 $args{col_accessor_map} = delete $args{column_accessor_map};
856 my $self = { %args };
858 # don't lose undef options
859 for (values %$self) {
860 $_ = 0 unless defined $_;
863 bless $self => $class;
865 if (my $config_file = $self->config_file) {
866 my $config_opts = do $config_file;
868 croak "Error reading config from $config_file: $@" if $@;
870 croak "Config file $config_file must be a hashref" unless ref($config_opts) eq 'HASH';
872 while (my ($k, $v) = each %$config_opts) {
873 $self->{$k} = $v unless exists $self->{$k};
877 if (defined $self->{result_component_map}) {
878 if (defined $self->result_components_map) {
879 croak "Specify only one of result_components_map or result_component_map";
881 $self->result_components_map($self->{result_component_map})
884 if (defined $self->{result_role_map}) {
885 if (defined $self->result_roles_map) {
886 croak "Specify only one of result_roles_map or result_role_map";
888 $self->result_roles_map($self->{result_role_map})
891 croak "the result_roles and result_roles_map options may only be used in conjunction with use_moose=1"
892 if ((not defined $self->use_moose) || (not $self->use_moose))
893 && ((defined $self->result_roles) || (defined $self->result_roles_map));
895 $self->_ensure_arrayref(qw/schema_components
897 additional_base_classes
903 $self->_validate_class_args;
905 croak "result_components_map must be a hash"
906 if defined $self->result_components_map
907 && ref $self->result_components_map ne 'HASH';
909 if ($self->result_components_map) {
910 my %rc_map = %{ $self->result_components_map };
911 foreach my $moniker (keys %rc_map) {
912 $rc_map{$moniker} = [ $rc_map{$moniker} ] unless ref $rc_map{$moniker};
914 $self->result_components_map(\%rc_map);
917 $self->result_components_map({});
919 $self->_validate_result_components_map;
921 croak "result_roles_map must be a hash"
922 if defined $self->result_roles_map
923 && ref $self->result_roles_map ne 'HASH';
925 if ($self->result_roles_map) {
926 my %rr_map = %{ $self->result_roles_map };
927 foreach my $moniker (keys %rr_map) {
928 $rr_map{$moniker} = [ $rr_map{$moniker} ] unless ref $rr_map{$moniker};
930 $self->result_roles_map(\%rr_map);
932 $self->result_roles_map({});
934 $self->_validate_result_roles_map;
936 if ($self->use_moose) {
937 if (not DBIx::Class::Schema::Loader::Optional::Dependencies->req_ok_for('use_moose')) {
938 die sprintf "You must install the following CPAN modules to enable the use_moose option: %s.\n",
939 DBIx::Class::Schema::Loader::Optional::Dependencies->req_missing_for('use_moose');
943 $self->{_tables} = {};
944 $self->{monikers} = {};
945 $self->{moniker_to_table} = {};
946 $self->{class_to_table} = {};
947 $self->{classes} = {};
948 $self->{_upgrading_classes} = {};
950 $self->{schema_class} ||= ( ref $self->{schema} || $self->{schema} );
951 $self->{schema} ||= $self->{schema_class};
952 $self->{table_comments_table} ||= 'table_comments';
953 $self->{column_comments_table} ||= 'column_comments';
955 croak "dump_overwrite is deprecated. Please read the"
956 . " DBIx::Class::Schema::Loader::Base documentation"
957 if $self->{dump_overwrite};
959 $self->{dynamic} = ! $self->{dump_directory};
960 $self->{temp_directory} ||= File::Temp::tempdir( 'dbicXXXX',
965 $self->{dump_directory} ||= $self->{temp_directory};
967 $self->real_dump_directory($self->{dump_directory});
969 $self->version_to_dump($DBIx::Class::Schema::Loader::VERSION);
970 $self->schema_version_to_dump($DBIx::Class::Schema::Loader::VERSION);
972 if (not defined $self->naming) {
973 $self->naming_set(0);
976 $self->naming_set(1);
979 if ((not ref $self->naming) && defined $self->naming) {
980 my $naming_ver = $self->naming;
982 relationships => $naming_ver,
983 monikers => $naming_ver,
984 column_accessors => $naming_ver,
987 elsif (ref $self->naming eq 'HASH' && exists $self->naming->{ALL}) {
988 my $val = delete $self->naming->{ALL};
990 $self->naming->{$_} = $val
991 foreach qw/relationships monikers column_accessors/;
995 foreach my $key (qw/relationships monikers column_accessors/) {
996 $self->naming->{$key} = $CURRENT_V if ($self->naming->{$key}||'') eq 'current';
999 $self->{naming} ||= {};
1001 if ($self->custom_column_info && ref $self->custom_column_info ne 'CODE') {
1002 croak 'custom_column_info must be a CODE ref';
1005 $self->_check_back_compat;
1007 $self->use_namespaces(1) unless defined $self->use_namespaces;
1008 $self->generate_pod(1) unless defined $self->generate_pod;
1009 $self->pod_comment_mode('auto') unless defined $self->pod_comment_mode;
1010 $self->pod_comment_spillover_length(60) unless defined $self->pod_comment_spillover_length;
1012 if (my $col_collision_map = $self->col_collision_map) {
1013 if (my $reftype = ref $col_collision_map) {
1014 if ($reftype ne 'HASH') {
1015 croak "Invalid type $reftype for option 'col_collision_map'";
1019 $self->col_collision_map({ '(.*)' => $col_collision_map });
1023 if (my $rel_collision_map = $self->rel_collision_map) {
1024 if (my $reftype = ref $rel_collision_map) {
1025 if ($reftype ne 'HASH') {
1026 croak "Invalid type $reftype for option 'rel_collision_map'";
1030 $self->rel_collision_map({ '(.*)' => $rel_collision_map });
1034 if (defined(my $rel_name_map = $self->rel_name_map)) {
1035 my $reftype = ref $rel_name_map;
1036 if ($reftype ne 'HASH' && $reftype ne 'CODE') {
1037 croak "Invalid type $reftype for option 'rel_name_map', must be HASH or CODE";
1041 if (defined(my $filter = $self->filter_generated_code)) {
1042 my $reftype = ref $filter;
1043 if ($reftype && $reftype ne 'CODE') {
1044 croak "Invalid type $reftype for option 'filter_generated_code, must be a scalar or a CODE reference";
1048 if (defined $self->db_schema) {
1049 if (ref $self->db_schema eq 'ARRAY') {
1050 if (@{ $self->db_schema } > 1) {
1051 $self->{qualify_objects} = 1;
1053 elsif (@{ $self->db_schema } == 0) {
1054 $self->{db_schema} = undef;
1057 elsif (not ref $self->db_schema) {
1058 if ($self->db_schema eq '%') {
1059 $self->{qualify_objects} = 1;
1062 $self->{db_schema} = [ $self->db_schema ];
1066 if (not $self->moniker_parts) {
1067 $self->moniker_parts(['name']);
1070 if (not ref $self->moniker_parts) {
1071 $self->moniker_parts([ $self->moniker_parts ]);
1073 if (ref $self->moniker_parts ne 'ARRAY') {
1074 croak 'moniker_parts must be an arrayref';
1076 if ((firstidx { $_ eq 'name' } @{ $self->moniker_parts }) == -1) {
1077 croak "moniker_parts option *must* contain 'name'";
1084 sub _check_back_compat {
1087 # dynamic schemas will always be in 0.04006 mode, unless overridden
1088 if ($self->dynamic) {
1089 # just in case, though no one is likely to dump a dynamic schema
1090 $self->schema_version_to_dump('0.04006');
1092 if (not $self->naming_set) {
1093 warn <<EOF unless $ENV{SCHEMA_LOADER_BACKCOMPAT};
1095 Dynamic schema detected, will run in 0.04006 mode.
1097 Set the 'naming' attribute or the SCHEMA_LOADER_BACKCOMPAT environment variable
1098 to disable this warning.
1100 See perldoc DBIx::Class::Schema::Loader::Manual::UpgradingFromV4 for more
1105 $self->_upgrading_from('v4');
1108 if ((not defined $self->use_namespaces) && ($self->naming_set)) {
1109 $self->use_namespaces(1);
1112 $self->naming->{relationships} ||= 'v4';
1113 $self->naming->{monikers} ||= 'v4';
1115 if ($self->use_namespaces) {
1116 $self->_upgrading_from_load_classes(1);
1119 $self->use_namespaces(0);
1125 # otherwise check if we need backcompat mode for a static schema
1126 my $filename = $self->get_dump_filename($self->schema_class);
1127 return unless -e $filename;
1129 my ($old_gen, $old_md5, $old_ver, $old_ts, $old_custom) =
1130 $self->_parse_generated_file($filename);
1132 return unless $old_ver;
1134 # determine if the existing schema was dumped with use_moose => 1
1135 if (! defined $self->use_moose) {
1136 $self->{use_moose} = 1 if $old_gen =~ /^ (?!\s*\#) use \s+ Moose/xm;
1139 my $load_classes = ($old_gen =~ /^__PACKAGE__->load_classes;/m) ? 1 : 0;
1141 my $result_namespace = do { ($old_gen =~ /result_namespace => (.+)/) ? $1 : '' };
1142 my $ds = eval $result_namespace;
1144 Could not eval expression '$result_namespace' for result_namespace from
1147 $result_namespace = $ds || '';
1149 if ($load_classes && (not defined $self->use_namespaces)) {
1150 warn <<"EOF" unless $ENV{SCHEMA_LOADER_BACKCOMPAT};
1152 'load_classes;' static schema detected, turning off 'use_namespaces'.
1154 Set the 'use_namespaces' attribute or the SCHEMA_LOADER_BACKCOMPAT environment
1155 variable to disable this warning.
1157 See perldoc DBIx::Class::Schema::Loader::Manual::UpgradingFromV4 for more
1160 $self->use_namespaces(0);
1162 elsif ($load_classes && $self->use_namespaces) {
1163 $self->_upgrading_from_load_classes(1);
1165 elsif ((not $load_classes) && defined $self->use_namespaces && ! $self->use_namespaces) {
1166 $self->_downgrading_to_load_classes(
1167 $result_namespace || 'Result'
1170 elsif ((not defined $self->use_namespaces) || $self->use_namespaces) {
1171 if (not $self->result_namespace) {
1172 $self->result_namespace($result_namespace || 'Result');
1174 elsif ($result_namespace ne $self->result_namespace) {
1175 $self->_rewriting_result_namespace(
1176 $result_namespace || 'Result'
1181 # XXX when we go past .0 this will need fixing
1182 my ($v) = $old_ver =~ /([1-9])/;
1185 return if ($v eq $CURRENT_V || $old_ver =~ /^0\.\d\d999/);
1187 if (not %{ $self->naming }) {
1188 warn <<"EOF" unless $ENV{SCHEMA_LOADER_BACKCOMPAT};
1190 Version $old_ver static schema detected, turning on backcompat mode.
1192 Set the 'naming' attribute or the SCHEMA_LOADER_BACKCOMPAT environment variable
1193 to disable this warning.
1195 See: 'naming' in perldoc DBIx::Class::Schema::Loader::Base .
1197 See perldoc DBIx::Class::Schema::Loader::Manual::UpgradingFromV4 if upgrading
1198 from version 0.04006.
1201 $self->naming->{relationships} ||= $v;
1202 $self->naming->{monikers} ||= $v;
1203 $self->naming->{column_accessors} ||= $v;
1205 $self->schema_version_to_dump($old_ver);
1208 $self->_upgrading_from($v);
1212 sub _validate_class_args {
1215 foreach my $k (@CLASS_ARGS) {
1216 next unless $self->$k;
1218 my @classes = ref $self->$k eq 'ARRAY' ? @{ $self->$k } : $self->$k;
1219 $self->_validate_classes($k, \@classes);
1223 sub _validate_result_components_map {
1226 foreach my $classes (values %{ $self->result_components_map }) {
1227 $self->_validate_classes('result_components_map', $classes);
1231 sub _validate_result_roles_map {
1234 foreach my $classes (values %{ $self->result_roles_map }) {
1235 $self->_validate_classes('result_roles_map', $classes);
1239 sub _validate_classes {
1242 my $classes = shift;
1244 # make a copy to not destroy original
1245 my @classes = @$classes;
1247 foreach my $c (@classes) {
1248 # components default to being under the DBIx::Class namespace unless they
1249 # are preceeded with a '+'
1250 if ( $key =~ m/component/ && $c !~ s/^\+// ) {
1251 $c = 'DBIx::Class::' . $c;
1254 # 1 == installed, 0 == not installed, undef == invalid classname
1255 my $installed = Class::Inspector->installed($c);
1256 if ( defined($installed) ) {
1257 if ( $installed == 0 ) {
1258 croak qq/$c, as specified in the loader option "$key", is not installed/;
1261 croak qq/$c, as specified in the loader option "$key", is an invalid class name/;
1267 sub _find_file_in_inc {
1268 my ($self, $file) = @_;
1270 foreach my $prefix (@INC) {
1271 my $fullpath = File::Spec->catfile($prefix, $file);
1272 return $fullpath if -f $fullpath
1273 # abs_path throws on Windows for nonexistant files
1274 and (try { Cwd::abs_path($fullpath) }) ne
1275 ((try { Cwd::abs_path(File::Spec->catfile($self->dump_directory, $file)) }) || '');
1281 sub _find_class_in_inc {
1282 my ($self, $class) = @_;
1284 return $self->_find_file_in_inc(class_path($class));
1290 return $self->_upgrading_from
1291 || $self->_upgrading_from_load_classes
1292 || $self->_downgrading_to_load_classes
1293 || $self->_rewriting_result_namespace
1297 sub _rewrite_old_classnames {
1298 my ($self, $code) = @_;
1300 return $code unless $self->_rewriting;
1302 my %old_classes = reverse %{ $self->_upgrading_classes };
1304 my $re = join '|', keys %old_classes;
1305 $re = qr/\b($re)\b/;
1307 $code =~ s/$re/$old_classes{$1} || $1/eg;
1312 sub _load_external {
1313 my ($self, $class) = @_;
1315 return if $self->{skip_load_external};
1317 # so that we don't load our own classes, under any circumstances
1318 local *INC = [ grep $_ ne $self->dump_directory, @INC ];
1320 my $real_inc_path = $self->_find_class_in_inc($class);
1322 my $old_class = $self->_upgrading_classes->{$class}
1323 if $self->_rewriting;
1325 my $old_real_inc_path = $self->_find_class_in_inc($old_class)
1326 if $old_class && $old_class ne $class;
1328 return unless $real_inc_path || $old_real_inc_path;
1330 if ($real_inc_path) {
1331 # If we make it to here, we loaded an external definition
1332 warn qq/# Loaded external class definition for '$class'\n/
1335 my $code = $self->_rewrite_old_classnames(slurp_file $real_inc_path);
1337 if ($self->dynamic) { # load the class too
1338 eval_package_without_redefine_warnings($class, $code);
1341 $self->_ext_stmt($class,
1342 qq|# These lines were loaded from '$real_inc_path' found in \@INC.\n|
1343 .qq|# They are now part of the custom portion of this file\n|
1344 .qq|# for you to hand-edit. If you do not either delete\n|
1345 .qq|# this section or remove that file from \@INC, this section\n|
1346 .qq|# will be repeated redundantly when you re-create this\n|
1347 .qq|# file again via Loader! See skip_load_external to disable\n|
1348 .qq|# this feature.\n|
1351 $self->_ext_stmt($class, $code);
1352 $self->_ext_stmt($class,
1353 qq|# End of lines loaded from '$real_inc_path' |
1357 if ($old_real_inc_path) {
1358 my $code = slurp_file $old_real_inc_path;
1360 $self->_ext_stmt($class, <<"EOF");
1362 # These lines were loaded from '$old_real_inc_path',
1363 # based on the Result class name that would have been created by an older
1364 # version of the Loader. For a static schema, this happens only once during
1365 # upgrade. See skip_load_external to disable this feature.
1368 $code = $self->_rewrite_old_classnames($code);
1370 if ($self->dynamic) {
1373 Detected external content in '$old_real_inc_path', a class name that would have
1374 been used by an older version of the Loader.
1376 * PLEASE RENAME THIS CLASS: from '$old_class' to '$class', as that is the
1377 new name of the Result.
1379 eval_package_without_redefine_warnings($class, $code);
1383 $self->_ext_stmt($class, $code);
1384 $self->_ext_stmt($class,
1385 qq|# End of lines loaded from '$old_real_inc_path' |
1392 Does the actual schema-construction work.
1399 $self->_load_tables(
1400 $self->_tables_list({ constraint => $self->constraint, exclude => $self->exclude })
1408 Rescan the database for changes. Returns a list of the newly added table
1411 The schema argument should be the schema class or object to be affected. It
1412 should probably be derived from the original schema_class used during L</load>.
1417 my ($self, $schema) = @_;
1419 $self->{schema} = $schema;
1420 $self->_relbuilder->{schema} = $schema;
1423 my @current = $self->_tables_list({ constraint => $self->constraint, exclude => $self->exclude });
1425 foreach my $table (@current) {
1426 if(!exists $self->_tables->{$table->sql_name}) {
1427 push(@created, $table);
1432 @current{map $_->sql_name, @current} = ();
1433 foreach my $table (values %{ $self->_tables }) {
1434 if (not exists $current{$table->sql_name}) {
1435 $self->_remove_table($table);
1439 delete @$self{qw/_dump_storage _relations_started _uniqs_started/};
1441 my $loaded = $self->_load_tables(@current);
1443 foreach my $table (@created) {
1444 $self->monikers->{$table->sql_name} = $self->_table2moniker($table);
1447 return map { $self->monikers->{$_->sql_name} } @created;
1453 return if $self->{skip_relationships};
1455 return $self->{relbuilder} ||= do {
1456 my $relbuilder_suff =
1463 ->{$self->naming->{relationships}||$CURRENT_V} || '';
1465 my $relbuilder_class = 'DBIx::Class::Schema::Loader::RelBuilder'.$relbuilder_suff;
1466 $self->ensure_class_loaded($relbuilder_class);
1467 $relbuilder_class->new($self);
1472 my ($self, @tables) = @_;
1474 # Save the new tables to the tables list
1476 $self->_tables->{$_->sql_name} = $_;
1479 $self->_make_src_class($_) for @tables;
1481 # sanity-check for moniker clashes
1482 my $inverse_moniker_idx;
1483 foreach my $table (values %{ $self->_tables }) {
1484 push @{ $inverse_moniker_idx->{$self->monikers->{$table->sql_name}} }, $table;
1488 foreach my $moniker (keys %$inverse_moniker_idx) {
1489 my $tables = $inverse_moniker_idx->{$moniker};
1491 push @clashes, sprintf ("tables %s reduced to the same source moniker '%s'",
1492 join (', ', map $_->sql_name, @$tables),
1499 die 'Unable to load schema - chosen moniker/class naming style results in moniker clashes. '
1500 . 'In multi db_schema configurations you may need to set moniker_parts, '
1501 . 'otherwise change the naming style, or supply an explicit moniker_map: '
1502 . join ('; ', @clashes)
1507 $self->_setup_src_meta($_) for @tables;
1509 if(!$self->skip_relationships) {
1510 # The relationship loader needs a working schema
1511 local $self->{quiet} = 1;
1512 local $self->{dump_directory} = $self->{temp_directory};
1513 $self->_reload_classes(\@tables);
1514 $self->_load_relationships(\@tables);
1516 # Remove that temp dir from INC so it doesn't get reloaded
1517 @INC = grep $_ ne $self->dump_directory, @INC;
1520 $self->_load_roles($_) for @tables;
1522 $self->_load_external($_)
1523 for map { $self->classes->{$_->sql_name} } @tables;
1525 # Reload without unloading first to preserve any symbols from external
1527 $self->_reload_classes(\@tables, { unload => 0 });
1529 # Drop temporary cache
1530 delete $self->{_cache};
1535 sub _reload_classes {
1536 my ($self, $tables, $opts) = @_;
1538 my @tables = @$tables;
1540 my $unload = $opts->{unload};
1541 $unload = 1 unless defined $unload;
1543 # so that we don't repeat custom sections
1544 @INC = grep $_ ne $self->dump_directory, @INC;
1546 $self->_dump_to_dir(map { $self->classes->{$_->sql_name} } @tables);
1548 unshift @INC, $self->dump_directory;
1551 my %have_source = map { $_ => $self->schema->source($_) }
1552 $self->schema->sources;
1554 for my $table (@tables) {
1555 my $moniker = $self->monikers->{$table->sql_name};
1556 my $class = $self->classes->{$table->sql_name};
1559 no warnings 'redefine';
1560 local *Class::C3::reinitialize = sub {}; # to speed things up, reinitialized below
1563 if (my $mc = $self->_moose_metaclass($class)) {
1566 Class::Unload->unload($class) if $unload;
1567 my ($source, $resultset_class);
1569 ($source = $have_source{$moniker})
1570 && ($resultset_class = $source->resultset_class)
1571 && ($resultset_class ne 'DBIx::Class::ResultSet')
1573 my $has_file = Class::Inspector->loaded_filename($resultset_class);
1574 if (my $mc = $self->_moose_metaclass($resultset_class)) {
1577 Class::Unload->unload($resultset_class) if $unload;
1578 $self->_reload_class($resultset_class) if $has_file;
1580 $self->_reload_class($class);
1582 push @to_register, [$moniker, $class];
1585 Class::C3->reinitialize;
1586 for (@to_register) {
1587 $self->schema->register_class(@$_);
1591 sub _moose_metaclass {
1592 return undef unless $INC{'Class/MOP.pm'}; # if CMOP is not loaded the class could not have loaded in the 1st place
1596 my $mc = try { Class::MOP::class_of($class) }
1599 return $mc->isa('Moose::Meta::Class') ? $mc : undef;
1602 # We use this instead of ensure_class_loaded when there are package symbols we
1605 my ($self, $class) = @_;
1607 delete $INC{ +class_path($class) };
1610 eval_package_without_redefine_warnings ($class, "require $class");
1613 my $source = slurp_file $self->_get_dump_filename($class);
1614 die "Failed to reload class $class: $_.\n\nCLASS SOURCE:\n\n$source";
1618 sub _get_dump_filename {
1619 my ($self, $class) = (@_);
1621 $class =~ s{::}{/}g;
1622 return $self->dump_directory . q{/} . $class . q{.pm};
1625 =head2 get_dump_filename
1629 Returns the full path to the file for a class that the class has been or will
1630 be dumped to. This is a file in a temp dir for a dynamic schema.
1634 sub get_dump_filename {
1635 my ($self, $class) = (@_);
1637 local $self->{dump_directory} = $self->real_dump_directory;
1639 return $self->_get_dump_filename($class);
1642 sub _ensure_dump_subdirs {
1643 my ($self, $class) = (@_);
1645 my @name_parts = split(/::/, $class);
1646 pop @name_parts; # we don't care about the very last element,
1647 # which is a filename
1649 my $dir = $self->dump_directory;
1652 mkdir($dir) or croak "mkdir('$dir') failed: $!";
1654 last if !@name_parts;
1655 $dir = File::Spec->catdir($dir, shift @name_parts);
1660 my ($self, @classes) = @_;
1662 my $schema_class = $self->schema_class;
1663 my $schema_base_class = $self->schema_base_class || 'DBIx::Class::Schema';
1665 my $target_dir = $self->dump_directory;
1666 warn "Dumping manual schema for $schema_class to directory $target_dir ...\n"
1667 unless $self->dynamic or $self->quiet;
1671 . qq|package $schema_class;\n\n|
1672 . qq|# Created by DBIx::Class::Schema::Loader\n|
1673 . qq|# DO NOT MODIFY THE FIRST PART OF THIS FILE\n\n|;
1676 = $self->only_autoclean
1677 ? 'namespace::autoclean'
1678 : 'MooseX::MarkAsMethods autoclean => 1'
1681 if ($self->use_moose) {
1683 $schema_text.= qq|use Moose;\nuse $autoclean;\nextends '$schema_base_class';\n\n|;
1686 $schema_text .= qq|use strict;\nuse warnings;\n\nuse base '$schema_base_class';\n\n|;
1689 my @schema_components = @{ $self->schema_components || [] };
1691 if (@schema_components) {
1692 my $schema_components = dump @schema_components;
1693 $schema_components = "($schema_components)" if @schema_components == 1;
1695 $schema_text .= "__PACKAGE__->load_components${schema_components};\n\n";
1698 if ($self->use_namespaces) {
1699 $schema_text .= qq|__PACKAGE__->load_namespaces|;
1700 my $namespace_options;
1702 my @attr = qw/resultset_namespace default_resultset_class/;
1704 unshift @attr, 'result_namespace' unless (not $self->result_namespace) || $self->result_namespace eq 'Result';
1706 for my $attr (@attr) {
1708 my $code = dumper_squashed $self->$attr;
1709 $namespace_options .= qq| $attr => $code,\n|
1712 $schema_text .= qq|(\n$namespace_options)| if $namespace_options;
1713 $schema_text .= qq|;\n|;
1716 $schema_text .= qq|__PACKAGE__->load_classes;\n|;
1720 local $self->{version_to_dump} = $self->schema_version_to_dump;
1721 $self->_write_classfile($schema_class, $schema_text, 1);
1724 my $result_base_class = $self->result_base_class || 'DBIx::Class::Core';
1726 foreach my $src_class (@classes) {
1729 . qq|package $src_class;\n\n|
1730 . qq|# Created by DBIx::Class::Schema::Loader\n|
1731 . qq|# DO NOT MODIFY THE FIRST PART OF THIS FILE\n\n|;
1733 $src_text .= $self->_make_pod_heading($src_class);
1735 $src_text .= qq|use strict;\nuse warnings;\n\n|;
1737 $src_text .= $self->_base_class_pod($result_base_class)
1738 unless $result_base_class eq 'DBIx::Class::Core';
1740 if ($self->use_moose) {
1741 $src_text.= qq|use Moose;\nuse MooseX::NonMoose;\nuse $autoclean;|;
1743 # these options 'use base' which is compile time
1744 if (@{ $self->left_base_classes } || @{ $self->additional_base_classes }) {
1745 $src_text .= qq|\nBEGIN { extends '$result_base_class' }\n|;
1748 $src_text .= qq|\nextends '$result_base_class';\n|;
1752 $src_text .= qq|use base '$result_base_class';\n|;
1755 $self->_write_classfile($src_class, $src_text);
1758 # remove Result dir if downgrading from use_namespaces, and there are no
1760 if (my $result_ns = $self->_downgrading_to_load_classes
1761 || $self->_rewriting_result_namespace) {
1762 my $result_namespace = $self->_result_namespace(
1767 (my $result_dir = $result_namespace) =~ s{::}{/}g;
1768 $result_dir = $self->dump_directory . '/' . $result_dir;
1770 unless (my @files = glob "$result_dir/*") {
1775 warn "Schema dump completed.\n" unless $self->dynamic or $self->quiet;
1779 my ($self, $version, $ts) = @_;
1780 return qq|\n\n# Created by DBIx::Class::Schema::Loader|
1783 . qq|\n# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:|;
1786 sub _write_classfile {
1787 my ($self, $class, $text, $is_schema) = @_;
1789 my $filename = $self->_get_dump_filename($class);
1790 $self->_ensure_dump_subdirs($class);
1792 if (-f $filename && $self->really_erase_my_files) {
1793 warn "Deleting existing file '$filename' due to "
1794 . "'really_erase_my_files' setting\n" unless $self->quiet;
1798 my ($old_gen, $old_md5, $old_ver, $old_ts, $old_custom)
1799 = $self->_parse_generated_file($filename);
1801 if (! $old_gen && -f $filename) {
1802 croak "Cannot overwrite '$filename' without 'really_erase_my_files',"
1803 . " it does not appear to have been generated by Loader"
1806 my $custom_content = $old_custom || '';
1808 # Use custom content from a renamed class, the class names in it are
1810 if (my $renamed_class = $self->_upgrading_classes->{$class}) {
1811 my $old_filename = $self->_get_dump_filename($renamed_class);
1813 if (-f $old_filename) {
1814 $custom_content = ($self->_parse_generated_file ($old_filename))[4];
1816 unlink $old_filename;
1820 $custom_content ||= $self->_default_custom_content($is_schema);
1822 # If upgrading to use_moose=1 replace default custom content with default Moose custom content.
1823 # If there is already custom content, which does not have the Moose content, add it.
1824 if ($self->use_moose) {
1826 my $non_moose_custom_content = do {
1827 local $self->{use_moose} = 0;
1828 $self->_default_custom_content;
1831 if ($custom_content eq $non_moose_custom_content) {
1832 $custom_content = $self->_default_custom_content($is_schema);
1834 elsif ($custom_content !~ /\Q@{[$self->_default_moose_custom_content($is_schema)]}\E/) {
1835 $custom_content .= $self->_default_custom_content($is_schema);
1838 elsif (defined $self->use_moose && $old_gen) {
1839 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'
1840 if $old_gen =~ /use \s+ MooseX?\b/x;
1843 $custom_content = $self->_rewrite_old_classnames($custom_content);
1846 for @{$self->{_dump_storage}->{$class} || []};
1848 if ($self->filter_generated_code) {
1849 my $filter = $self->filter_generated_code;
1851 if (ref $filter eq 'CODE') {
1853 ($is_schema ? 'schema' : 'result'),
1859 my ($fh, $temp_file) = tempfile();
1861 binmode $fh, ':encoding(UTF-8)';
1865 open my $out, qq{$filter < "$temp_file"|}
1866 or croak "Could not open pipe to $filter: $!";
1868 $text = decode('UTF-8', do { local $/; <$out> });
1870 $text =~ s/$CR?$LF/\n/g;
1874 my $exit_code = $? >> 8;
1877 or croak "Could not remove temporary file '$temp_file': $!";
1879 if ($exit_code != 0) {
1880 croak "filter '$filter' exited non-zero: $exit_code";
1883 if (not $text or not $text =~ /\bpackage\b/) {
1884 warn("$class skipped due to filter") if $self->debug;
1889 # Check and see if the dump is in fact different
1893 $compare_to = $text . $self->_sig_comment($old_ver, $old_ts);
1894 if (Digest::MD5::md5_base64(encode 'UTF-8', $compare_to) eq $old_md5) {
1895 return unless $self->_upgrading_from && $is_schema;
1899 $text .= $self->_sig_comment(
1900 $self->version_to_dump,
1901 POSIX::strftime('%Y-%m-%d %H:%M:%S', localtime)
1904 open(my $fh, '>:encoding(UTF-8)', $filename)
1905 or croak "Cannot open '$filename' for writing: $!";
1907 # Write the top half and its MD5 sum
1908 print $fh $text . Digest::MD5::md5_base64(encode 'UTF-8', $text) . "\n";
1910 # Write out anything loaded via external partial class file in @INC
1912 for @{$self->{_ext_storage}->{$class} || []};
1914 # Write out any custom content the user has added
1915 print $fh $custom_content;
1918 or croak "Error closing '$filename': $!";
1921 sub _default_moose_custom_content {
1922 my ($self, $is_schema) = @_;
1924 if (not $is_schema) {
1925 return qq|\n__PACKAGE__->meta->make_immutable;|;
1928 return qq|\n__PACKAGE__->meta->make_immutable(inline_constructor => 0);|;
1931 sub _default_custom_content {
1932 my ($self, $is_schema) = @_;
1933 my $default = qq|\n\n# You can replace this text with custom|
1934 . qq| code or comments, and it will be preserved on regeneration|;
1935 if ($self->use_moose) {
1936 $default .= $self->_default_moose_custom_content($is_schema);
1938 $default .= qq|\n1;\n|;
1942 sub _parse_generated_file {
1943 my ($self, $fn) = @_;
1945 return unless -f $fn;
1947 open(my $fh, '<:encoding(UTF-8)', $fn)
1948 or croak "Cannot open '$fn' for reading: $!";
1951 qr{^(# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:)([A-Za-z0-9/+]{22})\r?\n};
1953 my ($md5, $ts, $ver, $gen);
1959 # Pull out the version and timestamp from the line above
1960 ($ver, $ts) = $gen =~ m/^# Created by DBIx::Class::Schema::Loader v(.*?) @ (.*?)\r?\Z/m;
1963 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"
1964 if !$self->overwrite_modifications && Digest::MD5::md5_base64(encode 'UTF-8', $gen) ne $md5;
1973 my $custom = do { local $/; <$fh> }
1977 $custom =~ s/$CRLF|$LF/\n/g;
1981 return ($gen, $md5, $ver, $ts, $custom);
1989 warn "$target: use $_;" if $self->debug;
1990 $self->_raw_stmt($target, "use $_;");
1998 my $blist = join(q{ }, @_);
2000 return unless $blist;
2002 warn "$target: use base qw/$blist/;" if $self->debug;
2003 $self->_raw_stmt($target, "use base qw/$blist/;");
2010 my $rlist = join(q{, }, map { qq{'$_'} } @_);
2012 return unless $rlist;
2014 warn "$target: with $rlist;" if $self->debug;
2015 $self->_raw_stmt($target, "\nwith $rlist;");
2018 sub _result_namespace {
2019 my ($self, $schema_class, $ns) = @_;
2020 my @result_namespace;
2022 $ns = $ns->[0] if ref $ns;
2024 if ($ns =~ /^\+(.*)/) {
2025 # Fully qualified namespace
2026 @result_namespace = ($1)
2029 # Relative namespace
2030 @result_namespace = ($schema_class, $ns);
2033 return wantarray ? @result_namespace : join '::', @result_namespace;
2036 # Create class with applicable bases, setup monikers, etc
2037 sub _make_src_class {
2038 my ($self, $table) = @_;
2040 my $schema = $self->schema;
2041 my $schema_class = $self->schema_class;
2043 my $table_moniker = $self->_table2moniker($table);
2044 my @result_namespace = ($schema_class);
2045 if ($self->use_namespaces) {
2046 my $result_namespace = $self->result_namespace || 'Result';
2047 @result_namespace = $self->_result_namespace(
2052 my $table_class = join(q{::}, @result_namespace, $table_moniker);
2054 if ((my $upgrading_v = $self->_upgrading_from)
2055 || $self->_rewriting) {
2056 local $self->naming->{monikers} = $upgrading_v
2059 my @result_namespace = @result_namespace;
2060 if ($self->_upgrading_from_load_classes) {
2061 @result_namespace = ($schema_class);
2063 elsif (my $ns = $self->_downgrading_to_load_classes) {
2064 @result_namespace = $self->_result_namespace(
2069 elsif ($ns = $self->_rewriting_result_namespace) {
2070 @result_namespace = $self->_result_namespace(
2076 my $old_table_moniker = do {
2077 local $self->naming->{monikers} = $upgrading_v;
2078 $self->_table2moniker($table);
2081 my $old_class = join(q{::}, @result_namespace, $old_table_moniker);
2083 $self->_upgrading_classes->{$table_class} = $old_class
2084 unless $table_class eq $old_class;
2087 $self->classes->{$table->sql_name} = $table_class;
2088 $self->monikers->{$table->sql_name} = $table_moniker;
2089 $self->moniker_to_table->{$table_moniker} = $table;
2090 $self->class_to_table->{$table_class} = $table;
2092 $self->_pod_class_list($table_class, 'ADDITIONAL CLASSES USED', @{$self->additional_classes});
2094 $self->_use ($table_class, @{$self->additional_classes});
2096 $self->_pod_class_list($table_class, 'LEFT BASE CLASSES', @{$self->left_base_classes});
2098 $self->_inject($table_class, @{$self->left_base_classes});
2100 my @components = @{ $self->components || [] };
2102 push @components, @{ $self->result_components_map->{$table_moniker} }
2103 if exists $self->result_components_map->{$table_moniker};
2105 my @fq_components = @components;
2106 foreach my $component (@fq_components) {
2107 if ($component !~ s/^\+//) {
2108 $component = "DBIx::Class::$component";
2112 $self->_pod_class_list($table_class, 'COMPONENTS LOADED', @fq_components);
2114 $self->_dbic_stmt($table_class, 'load_components', @components) if @components;
2116 $self->_pod_class_list($table_class, 'ADDITIONAL BASE CLASSES', @{$self->additional_base_classes});
2118 $self->_inject($table_class, @{$self->additional_base_classes});
2121 sub _is_result_class_method {
2122 my ($self, $name, $table) = @_;
2124 my $table_moniker = $table ? $self->monikers->{$table->sql_name} : '';
2126 $self->_result_class_methods({})
2127 if not defined $self->_result_class_methods;
2129 if (not exists $self->_result_class_methods->{$table_moniker}) {
2130 my (@methods, %methods);
2131 my $base = $self->result_base_class || 'DBIx::Class::Core';
2133 my @components = @{ $self->components || [] };
2135 push @components, @{ $self->result_components_map->{$table_moniker} }
2136 if exists $self->result_components_map->{$table_moniker};
2138 for my $c (@components) {
2139 $c = $c =~ /^\+/ ? substr($c,1) : "DBIx::Class::$c";
2142 my @roles = @{ $self->result_roles || [] };
2144 push @roles, @{ $self->result_roles_map->{$table_moniker} }
2145 if exists $self->result_roles_map->{$table_moniker};
2147 for my $class ($base, @components,
2148 ($self->use_moose ? 'Moose::Object' : ()), @roles) {
2149 $self->ensure_class_loaded($class);
2151 push @methods, @{ Class::Inspector->methods($class) || [] };
2154 push @methods, @{ Class::Inspector->methods('UNIVERSAL') };
2156 @methods{@methods} = ();
2158 $self->_result_class_methods->{$table_moniker} = \%methods;
2160 my $result_methods = $self->_result_class_methods->{$table_moniker};
2162 return exists $result_methods->{$name};
2165 sub _resolve_col_accessor_collisions {
2166 my ($self, $table, $col_info) = @_;
2168 while (my ($col, $info) = each %$col_info) {
2169 my $accessor = $info->{accessor} || $col;
2171 next if $accessor eq 'id'; # special case (very common column)
2173 if ($self->_is_result_class_method($accessor, $table)) {
2176 if (my $map = $self->col_collision_map) {
2177 for my $re (keys %$map) {
2178 if (my @matches = $col =~ /$re/) {
2179 $info->{accessor} = sprintf $map->{$re}, @matches;
2187 Column '$col' in table '$table' collides with an inherited method.
2188 See "COLUMN ACCESSOR COLLISIONS" in perldoc DBIx::Class::Schema::Loader::Base .
2190 $info->{accessor} = undef;
2196 # use the same logic to run moniker_map, col_accessor_map
2198 my ( $self, $map, $default_code, $ident, @extra ) = @_;
2200 my $default_ident = $default_code->( $ident, @extra );
2202 if( $map && ref $map eq 'HASH' ) {
2203 $new_ident = $map->{ $ident };
2205 elsif( $map && ref $map eq 'CODE' ) {
2206 $new_ident = $map->( $ident, $default_ident, @extra );
2209 $new_ident ||= $default_ident;
2214 sub _default_column_accessor_name {
2215 my ( $self, $column_name ) = @_;
2217 my $preserve = ($self->naming->{column_accessors}||'') eq 'preserve';
2219 my $v = $self->_get_naming_v('column_accessors');
2221 my $accessor_name = $preserve ?
2222 $self->_to_identifier('column_accessors', $column_name) # assume CamelCase
2224 $self->_to_identifier('column_accessors', $column_name, '_');
2226 $accessor_name =~ s/\W+/_/g; # only if naming < v8, otherwise to_identifier
2230 return $accessor_name;
2232 elsif ($v < 7 || (not $self->preserve_case)) {
2233 # older naming just lc'd the col accessor and that's all.
2234 return lc $accessor_name;
2237 return join '_', map lc, split_name $column_name, $v;
2240 sub _make_column_accessor_name {
2241 my ($self, $column_name, $column_context_info ) = @_;
2243 my $accessor = $self->_run_user_map(
2244 $self->col_accessor_map,
2245 sub { $self->_default_column_accessor_name( shift ) },
2247 $column_context_info,
2253 # Set up metadata (cols, pks, etc)
2254 sub _setup_src_meta {
2255 my ($self, $table) = @_;
2257 my $schema = $self->schema;
2258 my $schema_class = $self->schema_class;
2260 my $table_class = $self->classes->{$table->sql_name};
2261 my $table_moniker = $self->monikers->{$table->sql_name};
2263 $self->_dbic_stmt($table_class, 'table', $table->dbic_name);
2265 my $cols = $self->_table_columns($table);
2266 my $col_info = $self->__columns_info_for($table);
2268 ### generate all the column accessor names
2269 while (my ($col, $info) = each %$col_info) {
2270 # hashref of other info that could be used by
2271 # user-defined accessor map functions
2273 table_class => $table_class,
2274 table_moniker => $table_moniker,
2275 table_name => $table,
2276 full_table_name => $table->dbic_name,
2277 schema_class => $schema_class,
2278 column_info => $info,
2281 $info->{accessor} = $self->_make_column_accessor_name( $col, $context );
2284 $self->_resolve_col_accessor_collisions($table, $col_info);
2286 # prune any redundant accessor names
2287 while (my ($col, $info) = each %$col_info) {
2288 no warnings 'uninitialized';
2289 delete $info->{accessor} if $info->{accessor} eq $col;
2292 my $fks = $self->_table_fk_info($table);
2294 foreach my $fkdef (@$fks) {
2295 for my $col (@{ $fkdef->{local_columns} }) {
2296 $col_info->{$col}{is_foreign_key} = 1;
2300 my $pks = $self->_table_pk_info($table) || [];
2302 my %uniq_tag; # used to eliminate duplicate uniqs
2304 $uniq_tag{ join("\0", @$pks) }++ if @$pks; # pk is a uniq
2306 my $uniqs = $self->_table_uniq_info($table) || [];
2309 foreach my $uniq (@$uniqs) {
2310 my ($name, $cols) = @$uniq;
2311 next if $uniq_tag{ join("\0", @$cols) }++; # skip duplicates
2312 push @uniqs, [$name, $cols];
2315 my @non_nullable_uniqs = grep {
2316 all { $col_info->{$_}{is_nullable} == 0 } @{ $_->[1] }
2319 if ($self->uniq_to_primary && (not @$pks) && @non_nullable_uniqs) {
2320 my @by_colnum = sort { $b->[0] <=> $a->[0] }
2321 map [ scalar @{ $_->[1] }, $_ ], @non_nullable_uniqs;
2323 if (not (@by_colnum > 1 && $by_colnum[0][0] == $by_colnum[1][0])) {
2324 my @keys = map $_->[1], @by_colnum;
2328 # remove the uniq from list
2329 @uniqs = grep { $_->[0] ne $pk->[0] } @uniqs;
2335 foreach my $pkcol (@$pks) {
2336 $col_info->{$pkcol}{is_nullable} = 0;
2342 map { $_, ($col_info->{$_}||{}) } @$cols
2345 $self->_dbic_stmt($table_class, 'set_primary_key', @$pks)
2348 # Sort unique constraints by constraint name for repeatable results (rels
2349 # are sorted as well elsewhere.)
2350 @uniqs = sort { $a->[0] cmp $b->[0] } @uniqs;
2352 foreach my $uniq (@uniqs) {
2353 my ($name, $cols) = @$uniq;
2354 $self->_dbic_stmt($table_class,'add_unique_constraint', $name, $cols);
2358 sub __columns_info_for {
2359 my ($self, $table) = @_;
2361 my $result = $self->_columns_info_for($table);
2363 while (my ($col, $info) = each %$result) {
2364 $info = { %$info, %{ $self->_custom_column_info ($table, $col, $info) } };
2365 $info = { %$info, %{ $self->_datetime_column_info($table, $col, $info) } };
2367 $result->{$col} = $info;
2375 Returns a sorted list of loaded tables, using the original database table
2383 return values %{$self->_tables};
2387 my ($self, $naming_key) = @_;
2391 if (($self->naming->{$naming_key}||'') =~ /^v(\d+)\z/) {
2395 ($v) = $CURRENT_V =~ /^v(\d+)\z/;
2401 sub _to_identifier {
2402 my ($self, $naming_key, $name, $sep_char, $force) = @_;
2404 my $v = $self->_get_naming_v($naming_key);
2406 my $to_identifier = $self->naming->{force_ascii} ?
2407 \&String::ToIdentifier::EN::to_identifier
2408 : \&String::ToIdentifier::EN::Unicode::to_identifier;
2410 return $v >= 8 || $force ? $to_identifier->($name, $sep_char) : $name;
2413 # Make a moniker from a table
2414 sub _default_table2moniker {
2415 my ($self, $table) = @_;
2417 my $v = $self->_get_naming_v('monikers');
2419 my @name_parts = map $table->$_, @{ $self->moniker_parts };
2421 my $name_idx = firstidx { $_ eq 'name' } @{ $self->moniker_parts };
2425 foreach my $i (0 .. $#name_parts) {
2426 my $part = $name_parts[$i];
2428 if ($i != $name_idx || $v >= 8) {
2429 $part = $self->_to_identifier('monikers', $part, '_', 1);
2432 if ($i == $name_idx && $v == 5) {
2433 $part = Lingua::EN::Inflect::Number::to_S($part);
2436 my @part_parts = map lc, $v > 6 ?
2437 # use v8 semantics for all moniker parts except name
2438 ($i == $name_idx ? split_name $part, $v : split_name $part)
2439 : split /[\W_]+/, $part;
2441 if ($i == $name_idx && $v >= 6) {
2442 my $as_phrase = join ' ', @part_parts;
2444 my $inflected = ($self->naming->{monikers}||'') eq 'plural' ?
2445 Lingua::EN::Inflect::Phrase::to_PL($as_phrase)
2447 ($self->naming->{monikers}||'') eq 'preserve' ?
2450 Lingua::EN::Inflect::Phrase::to_S($as_phrase);
2452 @part_parts = split /\s+/, $inflected;
2455 push @all_parts, map ucfirst, @part_parts;
2458 return join '', @all_parts;
2461 sub _table2moniker {
2462 my ( $self, $table ) = @_;
2464 $self->_run_user_map(
2466 sub { $self->_default_table2moniker( shift ) },
2471 sub _load_relationships {
2472 my ($self, $tables) = @_;
2476 foreach my $table (@$tables) {
2477 my $local_moniker = $self->monikers->{$table->sql_name};
2479 my $tbl_fk_info = $self->_table_fk_info($table);
2481 foreach my $fkdef (@$tbl_fk_info) {
2482 $fkdef->{local_table} = $table;
2483 $fkdef->{local_moniker} = $local_moniker;
2484 $fkdef->{remote_source} =
2485 $self->monikers->{$fkdef->{remote_table}->sql_name};
2487 my $tbl_uniq_info = $self->_table_uniq_info($table);
2489 push @tables, [ $local_moniker, $tbl_fk_info, $tbl_uniq_info ];
2492 my $rel_stmts = $self->_relbuilder->generate_code(\@tables);
2494 foreach my $src_class (sort keys %$rel_stmts) {
2496 my @src_stmts = map $_->[1],
2497 sort { $a->[0] cmp $b->[0] }
2498 map [ $_->{args}[0], $_ ], @{ $rel_stmts->{$src_class} };
2500 foreach my $stmt (@src_stmts) {
2501 $self->_dbic_stmt($src_class,$stmt->{method}, @{$stmt->{args}});
2507 my ($self, $table) = @_;
2509 my $table_moniker = $self->monikers->{$table->sql_name};
2510 my $table_class = $self->classes->{$table->sql_name};
2512 my @roles = @{ $self->result_roles || [] };
2513 push @roles, @{ $self->result_roles_map->{$table_moniker} }
2514 if exists $self->result_roles_map->{$table_moniker};
2517 $self->_pod_class_list($table_class, 'L<Moose> ROLES APPLIED', @roles);
2519 $self->_with($table_class, @roles);
2523 # Overload these in driver class:
2525 # Returns an arrayref of column names
2526 sub _table_columns { croak "ABSTRACT METHOD" }
2528 # Returns arrayref of pk col names
2529 sub _table_pk_info { croak "ABSTRACT METHOD" }
2531 # Returns an arrayref of uniqs [ [ foo => [ col1, col2 ] ], [ bar => [ ... ] ] ]
2532 sub _table_uniq_info { croak "ABSTRACT METHOD" }
2534 # Returns an arrayref of foreign key constraints, each
2535 # being a hashref with 3 keys:
2536 # local_columns (arrayref), remote_columns (arrayref), remote_table
2537 sub _table_fk_info { croak "ABSTRACT METHOD" }
2539 # Returns an array of lower case table names
2540 sub _tables_list { croak "ABSTRACT METHOD" }
2542 # Execute a constructive DBIC class method, with debug/dump_to_dir hooks.
2548 # generate the pod for this statement, storing it with $self->_pod
2549 $self->_make_pod( $class, $method, @_ ) if $self->generate_pod;
2551 my $args = dump(@_);
2552 $args = '(' . $args . ')' if @_ < 2;
2553 my $stmt = $method . $args . q{;};
2555 warn qq|$class\->$stmt\n| if $self->debug;
2556 $self->_raw_stmt($class, '__PACKAGE__->' . $stmt);
2560 sub _make_pod_heading {
2561 my ($self, $class) = @_;
2563 return '' if not $self->generate_pod;
2565 my $table = $self->class_to_table->{$class};
2568 my $pcm = $self->pod_comment_mode;
2569 my ($comment, $comment_overflows, $comment_in_name, $comment_in_desc);
2570 $comment = $self->__table_comment($table);
2571 $comment_overflows = ($comment and length $comment > $self->pod_comment_spillover_length);
2572 $comment_in_name = ($pcm eq 'name' or ($pcm eq 'auto' and !$comment_overflows));
2573 $comment_in_desc = ($pcm eq 'description' or ($pcm eq 'auto' and $comment_overflows));
2575 $pod .= "=head1 NAME\n\n";
2577 my $table_descr = $class;
2578 $table_descr .= " - " . $comment if $comment and $comment_in_name;
2580 $pod .= "$table_descr\n\n";
2582 if ($comment and $comment_in_desc) {
2583 $pod .= "=head1 DESCRIPTION\n\n${comment}\n\n";
2590 # generates the accompanying pod for a DBIC class method statement,
2591 # storing it with $self->_pod
2597 if ($method eq 'table') {
2599 $table = $$table if ref $table eq 'SCALAR';
2600 $self->_pod($class, "=head1 TABLE: C<$table>");
2601 $self->_pod_cut($class);
2603 elsif ( $method eq 'add_columns' ) {
2604 $self->_pod( $class, "=head1 ACCESSORS" );
2605 my $col_counter = 0;
2607 while( my ($name,$attrs) = splice @cols,0,2 ) {
2609 $self->_pod( $class, '=head2 ' . $name );
2610 $self->_pod( $class,
2612 my $s = $attrs->{$_};
2613 $s = !defined $s ? 'undef' :
2614 length($s) == 0 ? '(empty string)' :
2615 ref($s) eq 'SCALAR' ? $$s :
2616 ref($s) ? dumper_squashed $s :
2617 looks_like_number($s) ? $s : qq{'$s'};
2620 } sort keys %$attrs,
2622 if (my $comment = $self->__column_comment($self->class_to_table->{$class}, $col_counter, $name)) {
2623 $self->_pod( $class, $comment );
2626 $self->_pod_cut( $class );
2627 } elsif ( $method =~ /^(belongs_to|has_many|might_have)$/ ) {
2628 $self->_pod( $class, "=head1 RELATIONS" ) unless $self->{_relations_started} { $class } ;
2629 my ( $accessor, $rel_class ) = @_;
2630 $self->_pod( $class, "=head2 $accessor" );
2631 $self->_pod( $class, 'Type: ' . $method );
2632 $self->_pod( $class, "Related object: L<$rel_class>" );
2633 $self->_pod_cut( $class );
2634 $self->{_relations_started} { $class } = 1;
2636 elsif ($method eq 'add_unique_constraint') {
2637 $self->_pod($class, '=head1 UNIQUE CONSTRAINTS')
2638 unless $self->{_uniqs_started}{$class};
2640 my ($name, $cols) = @_;
2642 $self->_pod($class, "=head2 C<$name>");
2643 $self->_pod($class, '=over 4');
2645 foreach my $col (@$cols) {
2646 $self->_pod($class, "=item \* L</$col>");
2649 $self->_pod($class, '=back');
2650 $self->_pod_cut($class);
2652 $self->{_uniqs_started}{$class} = 1;
2654 elsif ($method eq 'set_primary_key') {
2655 $self->_pod($class, "=head1 PRIMARY KEY");
2656 $self->_pod($class, '=over 4');
2658 foreach my $col (@_) {
2659 $self->_pod($class, "=item \* L</$col>");
2662 $self->_pod($class, '=back');
2663 $self->_pod_cut($class);
2667 sub _pod_class_list {
2668 my ($self, $class, $title, @classes) = @_;
2670 return unless @classes && $self->generate_pod;
2672 $self->_pod($class, "=head1 $title");
2673 $self->_pod($class, '=over 4');
2675 foreach my $link (@classes) {
2676 $self->_pod($class, "=item * L<$link>");
2679 $self->_pod($class, '=back');
2680 $self->_pod_cut($class);
2683 sub _base_class_pod {
2684 my ($self, $base_class) = @_;
2686 return '' unless $self->generate_pod;
2689 =head1 BASE CLASS: L<$base_class>
2696 sub _filter_comment {
2697 my ($self, $txt) = @_;
2699 $txt = '' if not defined $txt;
2701 $txt =~ s/(?:\015?\012|\015\012?)/\n/g;
2706 sub __table_comment {
2709 if (my $code = $self->can('_table_comment')) {
2710 return $self->_filter_comment($self->$code(@_));
2716 sub __column_comment {
2719 if (my $code = $self->can('_column_comment')) {
2720 return $self->_filter_comment($self->$code(@_));
2726 # Stores a POD documentation
2728 my ($self, $class, $stmt) = @_;
2729 $self->_raw_stmt( $class, "\n" . $stmt );
2733 my ($self, $class ) = @_;
2734 $self->_raw_stmt( $class, "\n=cut\n" );
2737 # Store a raw source line for a class (for dumping purposes)
2739 my ($self, $class, $stmt) = @_;
2740 push(@{$self->{_dump_storage}->{$class}}, $stmt);
2743 # Like above, but separately for the externally loaded stuff
2745 my ($self, $class, $stmt) = @_;
2746 push(@{$self->{_ext_storage}->{$class}}, $stmt);
2749 sub _custom_column_info {
2750 my ( $self, $table_name, $column_name, $column_info ) = @_;
2752 if (my $code = $self->custom_column_info) {
2753 return $code->($table_name, $column_name, $column_info) || {};
2758 sub _datetime_column_info {
2759 my ( $self, $table_name, $column_name, $column_info ) = @_;
2761 my $type = $column_info->{data_type} || '';
2762 if ((grep $_, @{ $column_info }{map "inflate_$_", qw/date datetime timestamp/})
2763 or ($type =~ /date|timestamp/i)) {
2764 $result->{timezone} = $self->datetime_timezone if $self->datetime_timezone;
2765 $result->{locale} = $self->datetime_locale if $self->datetime_locale;
2771 my ($self, $name) = @_;
2773 return $self->preserve_case ? $name : lc($name);
2777 my ($self, $name) = @_;
2779 return $self->preserve_case ? $name : uc($name);
2783 my ($self, $table) = @_;
2786 my $schema = $self->schema;
2787 # in older DBIC it's a private method
2788 my $unregister = $schema->can('unregister_source') || $schema->can('_unregister_source');
2789 $schema->$unregister(delete $self->monikers->{$table->sql_name});
2790 delete $self->_upgrading_classes->{delete $self->classes->{$table->sql_name}};
2791 delete $self->_tables->{$table->sql_name};
2795 # remove the dump dir from @INC on destruction
2799 @INC = grep $_ ne $self->dump_directory, @INC;
2804 Returns a hashref of loaded table to moniker mappings. There will
2805 be two entries for each table, the original name and the "normalized"
2806 name, in the case that the two are different (such as databases
2807 that like uppercase table names, or preserve your original mixed-case
2808 definitions, or what-have-you).
2812 Returns a hashref of table to class mappings. In some cases it will
2813 contain multiple entries per table for the original and normalized table
2814 names, as above in L</monikers>.
2816 =head1 NON-ENGLISH DATABASES
2818 If you use the loader on a database with table and column names in a language
2819 other than English, you will want to turn off the English language specific
2822 To do so, use something like this in your loader options:
2824 naming => { monikers => 'v4' },
2825 inflect_singular => sub { "$_[0]_rel" },
2826 inflect_plural => sub { "$_[0]_rel" },
2828 =head1 COLUMN ACCESSOR COLLISIONS
2830 Occasionally you may have a column name that collides with a perl method, such
2831 as C<can>. In such cases, the default action is to set the C<accessor> of the
2832 column spec to C<undef>.
2834 You can then name the accessor yourself by placing code such as the following
2837 __PACKAGE__->add_column('+can' => { accessor => 'my_can' });
2839 Another option is to use the L</col_collision_map> option.
2841 =head1 RELATIONSHIP NAME COLLISIONS
2843 In very rare cases, you may get a collision between a generated relationship
2844 name and a method in your Result class, for example if you have a foreign key
2845 called C<belongs_to>.
2847 This is a problem because relationship names are also relationship accessor
2848 methods in L<DBIx::Class>.
2850 The default behavior is to append C<_rel> to the relationship name and print
2851 out a warning that refers to this text.
2853 You can also control the renaming with the L</rel_collision_map> option.
2857 L<DBIx::Class::Schema::Loader>, L<dbicdump>
2861 See L<DBIx::Class::Schema::Loader/AUTHOR> and L<DBIx::Class::Schema::Loader/CONTRIBUTORS>.
2865 This library is free software; you can redistribute it and/or modify it under
2866 the same terms as Perl itself.
2871 # vim:et sts=4 sw=4 tw=0: