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/;
32 our $VERSION = '0.07010';
34 __PACKAGE__->mk_group_ro_accessors('simple', qw/
41 additional_base_classes
57 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 For relationships, belongs_to accessors are made from column names by stripping
266 postfixes other than C<_id> as well, just C<id>, C<_?ref>, C<_?cd>, C<_?code>
271 For L</monikers>, this option does not inflect the table names but makes
272 monikers based on the actual name. For L</column_accessors> this option does
273 not normalize CamelCase column names to lowercase column accessors, but makes
274 accessors that are the same names as the columns (with any non-\w chars
275 replaced with underscores.)
279 For L</monikers>, singularizes the names using the most current inflector. This
280 is the same as setting the option to L</current>.
284 For L</monikers>, pluralizes the names, using the most current inflector.
288 Dynamic schemas will always default to the 0.04XXX relationship names and won't
289 singularize Results for backward compatibility, to activate the new RelBuilder
290 and singularization put this in your C<Schema.pm> file:
292 __PACKAGE__->naming('current');
294 Or if you prefer to use 0.07XXX features but insure that nothing breaks in the
295 next major version upgrade:
297 __PACKAGE__->naming('v7');
301 If true, will not print the usual C<Dumping manual schema ... Schema dump
302 completed.> messages. Does not affect warnings (except for warnings related to
303 L</really_erase_my_files>.)
307 By default POD will be generated for columns and relationships, using database
308 metadata for the text if available and supported.
310 Comment metadata can be stored in two ways.
312 The first is that you can create two tables named C<table_comments> and
313 C<column_comments> respectively. These tables must exist in the same database
314 and schema as the tables they describe. They both need to have columns named
315 C<table_name> and C<comment_text>. The second one needs to have a column named
316 C<column_name>. Then data stored in these tables will be used as a source of
317 metadata about tables and comments.
319 (If you wish you can change the name of these tables with the parameters
320 L</table_comments_table> and L</column_comments_table>.)
322 As a fallback you can use built-in commenting mechanisms. Currently this is
323 only supported for PostgreSQL, Oracle and MySQL. To create comments in
324 PostgreSQL you add statements of the form C<COMMENT ON TABLE some_table IS
325 '...'>, the same syntax is used in Oracle. To create comments in MySQL you add
326 C<COMMENT '...'> to the end of the column or table definition. Note that MySQL
327 restricts the length of comments, and also does not handle complex Unicode
330 Set this to C<0> to turn off all POD generation.
332 =head2 pod_comment_mode
334 Controls where table comments appear in the generated POD. Smaller table
335 comments are appended to the C<NAME> section of the documentation, and larger
336 ones are inserted into C<DESCRIPTION> instead. You can force a C<DESCRIPTION>
337 section to be generated with the comment always, only use C<NAME>, or choose
338 the length threshold at which the comment is forced into the description.
344 Use C<NAME> section only.
348 Force C<DESCRIPTION> always.
352 Use C<DESCRIPTION> if length > L</pod_comment_spillover_length>, this is the
357 =head2 pod_comment_spillover_length
359 When pod_comment_mode is set to C<auto>, this is the length of the comment at
360 which it will be forced into a separate description section.
364 =head2 table_comments_table
366 The table to look for comments about tables in. By default C<table_comments>.
367 See L</generate_pod> for details.
369 This must not be a fully qualified name, the table will be looked for in the
370 same database and schema as the table whose comment is being retrieved.
372 =head2 column_comments_table
374 The table to look for comments about columns in. By default C<column_comments>.
375 See L</generate_pod> for details.
377 This must not be a fully qualified name, the table will be looked for in the
378 same database and schema as the table/column whose comment is being retrieved.
380 =head2 relationship_attrs
382 Hashref of attributes to pass to each generated relationship, listed
383 by type. Also supports relationship type 'all', containing options to
384 pass to all generated relationships. Attributes set for more specific
385 relationship types override those set in 'all'.
389 relationship_attrs => {
390 belongs_to => { is_deferrable => 0 },
393 use this to turn off DEFERRABLE on your foreign key constraints.
397 If set to true, each constructive L<DBIx::Class> statement the loader
398 decides to execute will be C<warn>-ed before execution.
402 Set the name of the schema to load (schema in the sense that your database
405 Can be set to an arrayref of schema names for multiple schemas, or the special
406 value C<%> for all schemas.
408 For MSSQL, Sybase ASE, and Informix can be set to a hashref of databases as
409 keys and arrays of owners as values, set to the value:
413 for all owners in all databases.
415 You may need to control naming of monikers with L</moniker_parts> if you have
416 name clashes for tables in different schemas/databases.
420 The database table names are represented by the
421 L<DBIx::Class::Schema::Loader::Table> class in the loader, the
422 L<DBIx::Class::Schema::Loader::Table::Sybase> class for Sybase ASE and
423 L<DBIx::Class::Schema::Loader::Table::Informix> for Informix.
425 Monikers are created normally based on just the
426 L<name|DBIx::Class::Schema::Loader::DBObject/name> property, corresponding to
427 the table name, but can consist of other parts of the fully qualified name of
430 The L</moniker_parts> option is an arrayref of methods on the table class
431 corresponding to parts of the fully qualified table name, defaulting to
432 C<['name']>, in the order those parts are used to create the moniker name.
434 The C<'name'> entry B<must> be present.
436 Below is a table of supported databases and possible L</moniker_parts>.
440 =item * DB2, Firebird, mysql, Oracle, Pg, SQLAnywhere, SQLite, MS Access
444 =item * Informix, MSSQL, Sybase ASE
446 C<database>, C<schema>, C<name>
452 Only load tables matching regex. Best specified as a qr// regex.
456 Exclude tables matching regex. Best specified as a qr// regex.
460 Overrides the default table name to moniker translation. Can be either
461 a hashref of table keys and moniker values, or a coderef for a translator
462 function taking a single scalar table name argument and returning
463 a scalar moniker. If the hash entry does not exist, or the function
464 returns a false value, the code falls back to default behavior
467 The default behavior is to split on case transition and non-alphanumeric
468 boundaries, singularize the resulting phrase, then join the titlecased words
471 Table Name | Moniker Name
472 ---------------------------------
474 luser_group | LuserGroup
475 luser-opts | LuserOpt
476 stations_visited | StationVisited
477 routeChange | RouteChange
479 =head2 col_accessor_map
481 Same as moniker_map, but for column accessor names. If a coderef is
482 passed, the code is called with arguments of
484 the name of the column in the underlying database,
485 default accessor name that DBICSL would ordinarily give this column,
487 table_class => name of the DBIC class we are building,
488 table_moniker => calculated moniker for this table (after moniker_map if present),
489 table_name => name of the database table,
490 full_table_name => schema-qualified name of the database table (RDBMS specific),
491 schema_class => name of the schema class we are building,
492 column_info => hashref of column info (data_type, is_nullable, etc),
497 Similar in idea to moniker_map, but different in the details. It can be
498 a hashref or a code ref.
500 If it is a hashref, keys can be either the default relationship name, or the
501 moniker. The keys that are the default relationship name should map to the
502 name you want to change the relationship to. Keys that are monikers should map
503 to hashes mapping relationship names to their translation. You can do both at
504 once, and the more specific moniker version will be picked up first. So, for
505 instance, you could have
514 and relationships that would have been named C<bar> will now be named C<baz>
515 except that in the table whose moniker is C<Foo> it will be named C<blat>.
517 If it is a coderef, the argument passed will be a hashref of this form:
520 name => default relationship name,
521 type => the relationship type eg: C<has_many>,
522 local_class => name of the DBIC class we are building,
523 local_moniker => moniker of the DBIC class we are building,
524 local_columns => columns in this table in the relationship,
525 remote_class => name of the DBIC class we are related to,
526 remote_moniker => moniker of the DBIC class we are related to,
527 remote_columns => columns in the other table in the relationship,
530 DBICSL will try to use the value returned as the relationship name.
532 =head2 inflect_plural
534 Just like L</moniker_map> above (can be hash/code-ref, falls back to default
535 if hash key does not exist or coderef returns false), but acts as a map
536 for pluralizing relationship names. The default behavior is to utilize
537 L<Lingua::EN::Inflect::Phrase/to_PL>.
539 =head2 inflect_singular
541 As L</inflect_plural> above, but for singularizing relationship names.
542 Default behavior is to utilize L<Lingua::EN::Inflect::Phrase/to_S>.
544 =head2 schema_base_class
546 Base class for your schema classes. Defaults to 'DBIx::Class::Schema'.
548 B<WARNING>: if you define schema_base_class for a dynamic schema, you cannot
549 define a L<connection|DBIx::Class::Schema/connection> method in your schema
550 class, it must be in the schema base class, due to the limits of L<mro>.
552 =head2 schema_components
554 List of components to load into the Schema class.
556 B<WARNING>: if you define schema_components for a dynamic schema, you cannot
557 define a L<connection|DBIx::Class::Schema/connection> method in your schema
558 class, it must be in L</schema_base_class> or a component, due to the limits of
561 =head2 result_base_class
563 Base class for your table classes (aka result classes). Defaults to
566 =head2 additional_base_classes
568 List of additional base classes all of your table classes will use.
570 =head2 left_base_classes
572 List of additional base classes all of your table classes will use
573 that need to be leftmost.
575 =head2 additional_classes
577 List of additional classes which all of your table classes will use.
581 List of additional components to be loaded into all of your Result
582 classes. A good example would be
583 L<InflateColumn::DateTime|DBIx::Class::InflateColumn::DateTime>
585 =head2 result_components_map
587 A hashref of moniker keys and component values. Unlike L</components>, which
588 loads the given components into every Result class, this option allows you to
589 load certain components for specified Result classes. For example:
591 result_components_map => {
592 StationVisited => '+YourApp::Schema::Component::StationVisited',
594 '+YourApp::Schema::Component::RouteChange',
595 'InflateColumn::DateTime',
599 You may use this in conjunction with L</components>.
603 List of L<Moose> roles to be applied to all of your Result classes.
605 =head2 result_roles_map
607 A hashref of moniker keys and role values. Unlike L</result_roles>, which
608 applies the given roles to every Result class, this option allows you to apply
609 certain roles for specified Result classes. For example:
611 result_roles_map => {
613 'YourApp::Role::Building',
614 'YourApp::Role::Destination',
616 RouteChange => 'YourApp::Role::TripEvent',
619 You may use this in conjunction with L</result_roles>.
621 =head2 use_namespaces
623 This is now the default, to go back to L<DBIx::Class::Schema/load_classes> pass
626 Generate result class names suitable for
627 L<DBIx::Class::Schema/load_namespaces> and call that instead of
628 L<DBIx::Class::Schema/load_classes>. When using this option you can also
629 specify any of the options for C<load_namespaces> (i.e. C<result_namespace>,
630 C<resultset_namespace>, C<default_resultset_class>), and they will be added
631 to the call (and the generated result class names adjusted appropriately).
633 =head2 dump_directory
635 The value of this option is a perl libdir pathname. Within
636 that directory this module will create a baseline manual
637 L<DBIx::Class::Schema> module set, based on what it creates at runtime.
639 The created schema class will have the same classname as the one on
640 which you are setting this option (and the ResultSource classes will be
641 based on this name as well).
643 Normally you wouldn't hard-code this setting in your schema class, as it
644 is meant for one-time manual usage.
646 See L<DBIx::Class::Schema::Loader/dump_to_dir> for examples of the
647 recommended way to access this functionality.
649 =head2 dump_overwrite
651 Deprecated. See L</really_erase_my_files> below, which does *not* mean
652 the same thing as the old C<dump_overwrite> setting from previous releases.
654 =head2 really_erase_my_files
656 Default false. If true, Loader will unconditionally delete any existing
657 files before creating the new ones from scratch when dumping a schema to disk.
659 The default behavior is instead to only replace the top portion of the
660 file, up to and including the final stanza which contains
661 C<# DO NOT MODIFY THE FIRST PART OF THIS FILE>
662 leaving any customizations you placed after that as they were.
664 When C<really_erase_my_files> is not set, if the output file already exists,
665 but the aforementioned final stanza is not found, or the checksum
666 contained there does not match the generated contents, Loader will
667 croak and not touch the file.
669 You should really be using version control on your schema classes (and all
670 of the rest of your code for that matter). Don't blame me if a bug in this
671 code wipes something out when it shouldn't have, you've been warned.
673 =head2 overwrite_modifications
675 Default false. If false, when updating existing files, Loader will
676 refuse to modify any Loader-generated code that has been modified
677 since its last run (as determined by the checksum Loader put in its
680 If true, Loader will discard any manual modifications that have been
681 made to Loader-generated code.
683 Again, you should be using version control on your schema classes. Be
684 careful with this option.
686 =head2 custom_column_info
688 Hook for adding extra attributes to the
689 L<column_info|DBIx::Class::ResultSource/column_info> for a column.
691 Must be a coderef that returns a hashref with the extra attributes.
693 Receives the table name, column name and column_info.
697 custom_column_info => sub {
698 my ($table_name, $column_name, $column_info) = @_;
700 if ($column_name eq 'dog' && $column_info->{default_value} eq 'snoopy') {
701 return { is_snoopy => 1 };
705 This attribute can also be used to set C<inflate_datetime> on a non-datetime
706 column so it also receives the L</datetime_timezone> and/or L</datetime_locale>.
708 =head2 datetime_timezone
710 Sets the timezone attribute for L<DBIx::Class::InflateColumn::DateTime> for all
711 columns with the DATE/DATETIME/TIMESTAMP data_types.
713 =head2 datetime_locale
715 Sets the locale attribute for L<DBIx::Class::InflateColumn::DateTime> for all
716 columns with the DATE/DATETIME/TIMESTAMP data_types.
718 =head2 datetime_undef_if_invalid
720 Pass a C<0> for this option when using MySQL if you B<DON'T> want C<<
721 datetime_undef_if_invalid => 1 >> in your column info for DATE, DATETIME and
724 The default is recommended to deal with data such as C<00/00/00> which
725 sometimes ends up in such columns in MySQL.
729 File in Perl format, which should return a HASH reference, from which to read
734 Usually column names are lowercased, to make them easier to work with in
735 L<DBIx::Class>. This option lets you turn this behavior off, if the driver
738 Drivers for case sensitive databases like Sybase ASE or MSSQL with a
739 case-sensitive collation will turn this option on unconditionally.
741 Currently the drivers for SQLite, mysql, MSSQL and Firebird/InterBase support
744 =head2 qualify_objects
746 Set to true to prepend the L</db_schema> to table names for C<<
747 __PACKAGE__->table >> calls, and to some other things like Oracle sequences.
751 Creates Schema and Result classes that use L<Moose>, L<MooseX::NonMoose> and
752 L<namespace::autoclean>. The default content after the md5 sum also makes the
755 It is safe to upgrade your existing Schema to this option.
757 =head2 col_collision_map
759 This option controls how accessors for column names which collide with perl
760 methods are named. See L</COLUMN ACCESSOR COLLISIONS> for more information.
762 This option takes either a single L<sprintf|perlfunc/sprintf> format or a hashref of
763 strings which are compiled to regular expressions that map to
764 L<sprintf|perlfunc/sprintf> formats.
768 col_collision_map => 'column_%s'
770 col_collision_map => { '(.*)' => 'column_%s' }
772 col_collision_map => { '(foo).*(bar)' => 'column_%s_%s' }
774 =head2 rel_collision_map
776 Works just like L</col_collision_map>, but for relationship names/accessors
777 rather than column names/accessors.
779 The default is to just append C<_rel> to the relationship name, see
780 L</RELATIONSHIP NAME COLLISIONS>.
782 =head2 uniq_to_primary
784 Automatically promotes the largest unique constraints with non-nullable columns
785 on tables to primary keys, assuming there is only one largest unique
788 =head2 filter_generated_code
790 An optional hook that lets you filter the generated text for various classes
791 through a function that change it in any way that you want. The function will
792 receive the type of file, C<schema> or C<result>, class and code; and returns
793 the new code to use instead. For instance you could add custom comments, or do
794 anything else that you want.
796 The option can also be set to a string, which is then used as a filter program,
799 If this exists but fails to return text matching C</\bpackage\b/>, no file will
802 filter_generated_code => sub {
803 my ($type, $class, $text) = @_;
810 None of these methods are intended for direct invocation by regular
811 users of L<DBIx::Class::Schema::Loader>. Some are proxied via
812 L<DBIx::Class::Schema::Loader>.
816 # ensure that a peice of object data is a valid arrayref, creating
817 # an empty one or encapsulating whatever's there.
818 sub _ensure_arrayref {
823 $self->{$_} = [ $self->{$_} ]
824 unless ref $self->{$_} eq 'ARRAY';
830 Constructor for L<DBIx::Class::Schema::Loader::Base>, used internally
831 by L<DBIx::Class::Schema::Loader>.
836 my ( $class, %args ) = @_;
838 if (exists $args{column_accessor_map}) {
839 $args{col_accessor_map} = delete $args{column_accessor_map};
842 my $self = { %args };
844 # don't lose undef options
845 for (values %$self) {
846 $_ = 0 unless defined $_;
849 bless $self => $class;
851 if (my $config_file = $self->config_file) {
852 my $config_opts = do $config_file;
854 croak "Error reading config from $config_file: $@" if $@;
856 croak "Config file $config_file must be a hashref" unless ref($config_opts) eq 'HASH';
858 while (my ($k, $v) = each %$config_opts) {
859 $self->{$k} = $v unless exists $self->{$k};
863 if (defined $self->{result_component_map}) {
864 if (defined $self->result_components_map) {
865 croak "Specify only one of result_components_map or result_component_map";
867 $self->result_components_map($self->{result_component_map})
870 if (defined $self->{result_role_map}) {
871 if (defined $self->result_roles_map) {
872 croak "Specify only one of result_roles_map or result_role_map";
874 $self->result_roles_map($self->{result_role_map})
877 croak "the result_roles and result_roles_map options may only be used in conjunction with use_moose=1"
878 if ((not defined $self->use_moose) || (not $self->use_moose))
879 && ((defined $self->result_roles) || (defined $self->result_roles_map));
881 $self->_ensure_arrayref(qw/schema_components
883 additional_base_classes
889 $self->_validate_class_args;
891 croak "result_components_map must be a hash"
892 if defined $self->result_components_map
893 && ref $self->result_components_map ne 'HASH';
895 if ($self->result_components_map) {
896 my %rc_map = %{ $self->result_components_map };
897 foreach my $moniker (keys %rc_map) {
898 $rc_map{$moniker} = [ $rc_map{$moniker} ] unless ref $rc_map{$moniker};
900 $self->result_components_map(\%rc_map);
903 $self->result_components_map({});
905 $self->_validate_result_components_map;
907 croak "result_roles_map must be a hash"
908 if defined $self->result_roles_map
909 && ref $self->result_roles_map ne 'HASH';
911 if ($self->result_roles_map) {
912 my %rr_map = %{ $self->result_roles_map };
913 foreach my $moniker (keys %rr_map) {
914 $rr_map{$moniker} = [ $rr_map{$moniker} ] unless ref $rr_map{$moniker};
916 $self->result_roles_map(\%rr_map);
918 $self->result_roles_map({});
920 $self->_validate_result_roles_map;
922 if ($self->use_moose) {
923 if (not DBIx::Class::Schema::Loader::Optional::Dependencies->req_ok_for('use_moose')) {
924 die sprintf "You must install the following CPAN modules to enable the use_moose option: %s.\n",
925 DBIx::Class::Schema::Loader::Optional::Dependencies->req_missing_for('use_moose');
929 $self->{_tables} = {};
930 $self->{monikers} = {};
931 $self->{moniker_to_table} = {};
932 $self->{class_to_table} = {};
933 $self->{classes} = {};
934 $self->{_upgrading_classes} = {};
936 $self->{schema_class} ||= ( ref $self->{schema} || $self->{schema} );
937 $self->{schema} ||= $self->{schema_class};
938 $self->{table_comments_table} ||= 'table_comments';
939 $self->{column_comments_table} ||= 'column_comments';
941 croak "dump_overwrite is deprecated. Please read the"
942 . " DBIx::Class::Schema::Loader::Base documentation"
943 if $self->{dump_overwrite};
945 $self->{dynamic} = ! $self->{dump_directory};
946 $self->{temp_directory} ||= File::Temp::tempdir( 'dbicXXXX',
951 $self->{dump_directory} ||= $self->{temp_directory};
953 $self->real_dump_directory($self->{dump_directory});
955 $self->version_to_dump($DBIx::Class::Schema::Loader::VERSION);
956 $self->schema_version_to_dump($DBIx::Class::Schema::Loader::VERSION);
958 if (not defined $self->naming) {
959 $self->naming_set(0);
962 $self->naming_set(1);
965 if ((not ref $self->naming) && defined $self->naming) {
966 my $naming_ver = $self->naming;
968 relationships => $naming_ver,
969 monikers => $naming_ver,
970 column_accessors => $naming_ver,
973 elsif (ref $self->naming eq 'HASH' && exists $self->naming->{ALL}) {
974 my $val = delete $self->naming->{ALL};
976 $self->naming->{$_} = $val
977 foreach qw/relationships monikers column_accessors/;
981 foreach my $key (qw/relationships monikers column_accessors/) {
982 $self->naming->{$key} = $CURRENT_V if $self->naming->{$key} eq 'current';
985 $self->{naming} ||= {};
987 if ($self->custom_column_info && ref $self->custom_column_info ne 'CODE') {
988 croak 'custom_column_info must be a CODE ref';
991 $self->_check_back_compat;
993 $self->use_namespaces(1) unless defined $self->use_namespaces;
994 $self->generate_pod(1) unless defined $self->generate_pod;
995 $self->pod_comment_mode('auto') unless defined $self->pod_comment_mode;
996 $self->pod_comment_spillover_length(60) unless defined $self->pod_comment_spillover_length;
998 if (my $col_collision_map = $self->col_collision_map) {
999 if (my $reftype = ref $col_collision_map) {
1000 if ($reftype ne 'HASH') {
1001 croak "Invalid type $reftype for option 'col_collision_map'";
1005 $self->col_collision_map({ '(.*)' => $col_collision_map });
1009 if (my $rel_collision_map = $self->rel_collision_map) {
1010 if (my $reftype = ref $rel_collision_map) {
1011 if ($reftype ne 'HASH') {
1012 croak "Invalid type $reftype for option 'rel_collision_map'";
1016 $self->rel_collision_map({ '(.*)' => $rel_collision_map });
1020 if (defined(my $rel_name_map = $self->rel_name_map)) {
1021 my $reftype = ref $rel_name_map;
1022 if ($reftype ne 'HASH' && $reftype ne 'CODE') {
1023 croak "Invalid type $reftype for option 'rel_name_map', must be HASH or CODE";
1027 if (defined(my $filter = $self->filter_generated_code)) {
1028 my $reftype = ref $filter;
1029 if ($reftype && $reftype ne 'CODE') {
1030 croak "Invalid type $reftype for option 'filter_generated_code, must be a scalar or a CODE reference";
1034 if (defined $self->db_schema) {
1035 if (ref $self->db_schema eq 'ARRAY') {
1036 if (@{ $self->db_schema } > 1) {
1037 $self->{qualify_objects} = 1;
1039 elsif (@{ $self->db_schema } == 0) {
1040 $self->{db_schema} = undef;
1043 elsif (not ref $self->db_schema) {
1044 if ($self->db_schema eq '%') {
1045 $self->{qualify_objects} = 1;
1048 $self->{db_schema} = [ $self->db_schema ];
1052 if (not $self->moniker_parts) {
1053 $self->moniker_parts(['name']);
1056 if (not ref $self->moniker_parts) {
1057 $self->moniker_parts([ $self->moniker_parts ]);
1059 if (ref $self->moniker_parts ne 'ARRAY') {
1060 croak 'moniker_parts must be an arrayref';
1062 if ((firstidx { $_ eq 'name' } @{ $self->moniker_parts }) == -1) {
1063 croak "moniker_parts option *must* contain 'name'";
1070 sub _check_back_compat {
1073 # dynamic schemas will always be in 0.04006 mode, unless overridden
1074 if ($self->dynamic) {
1075 # just in case, though no one is likely to dump a dynamic schema
1076 $self->schema_version_to_dump('0.04006');
1078 if (not $self->naming_set) {
1079 warn <<EOF unless $ENV{SCHEMA_LOADER_BACKCOMPAT};
1081 Dynamic schema detected, will run in 0.04006 mode.
1083 Set the 'naming' attribute or the SCHEMA_LOADER_BACKCOMPAT environment variable
1084 to disable this warning.
1086 See perldoc DBIx::Class::Schema::Loader::Manual::UpgradingFromV4 for more
1091 $self->_upgrading_from('v4');
1094 if ((not defined $self->use_namespaces) && ($self->naming_set)) {
1095 $self->use_namespaces(1);
1098 $self->naming->{relationships} ||= 'v4';
1099 $self->naming->{monikers} ||= 'v4';
1101 if ($self->use_namespaces) {
1102 $self->_upgrading_from_load_classes(1);
1105 $self->use_namespaces(0);
1111 # otherwise check if we need backcompat mode for a static schema
1112 my $filename = $self->get_dump_filename($self->schema_class);
1113 return unless -e $filename;
1115 my ($old_gen, $old_md5, $old_ver, $old_ts, $old_custom) =
1116 $self->_parse_generated_file($filename);
1118 return unless $old_ver;
1120 # determine if the existing schema was dumped with use_moose => 1
1121 if (! defined $self->use_moose) {
1122 $self->{use_moose} = 1 if $old_gen =~ /^ (?!\s*\#) use \s+ Moose/xm;
1125 my $load_classes = ($old_gen =~ /^__PACKAGE__->load_classes;/m) ? 1 : 0;
1127 my $result_namespace = do { ($old_gen =~ /result_namespace => (.+)/) ? $1 : '' };
1128 my $ds = eval $result_namespace;
1130 Could not eval expression '$result_namespace' for result_namespace from
1133 $result_namespace = $ds || '';
1135 if ($load_classes && (not defined $self->use_namespaces)) {
1136 warn <<"EOF" unless $ENV{SCHEMA_LOADER_BACKCOMPAT};
1138 'load_classes;' static schema detected, turning off 'use_namespaces'.
1140 Set the 'use_namespaces' attribute or the SCHEMA_LOADER_BACKCOMPAT environment
1141 variable to disable this warning.
1143 See perldoc DBIx::Class::Schema::Loader::Manual::UpgradingFromV4 for more
1146 $self->use_namespaces(0);
1148 elsif ($load_classes && $self->use_namespaces) {
1149 $self->_upgrading_from_load_classes(1);
1151 elsif ((not $load_classes) && defined $self->use_namespaces && ! $self->use_namespaces) {
1152 $self->_downgrading_to_load_classes(
1153 $result_namespace || 'Result'
1156 elsif ((not defined $self->use_namespaces) || $self->use_namespaces) {
1157 if (not $self->result_namespace) {
1158 $self->result_namespace($result_namespace || 'Result');
1160 elsif ($result_namespace ne $self->result_namespace) {
1161 $self->_rewriting_result_namespace(
1162 $result_namespace || 'Result'
1167 # XXX when we go past .0 this will need fixing
1168 my ($v) = $old_ver =~ /([1-9])/;
1171 return if ($v eq $CURRENT_V || $old_ver =~ /^0\.\d\d999/);
1173 if (not %{ $self->naming }) {
1174 warn <<"EOF" unless $ENV{SCHEMA_LOADER_BACKCOMPAT};
1176 Version $old_ver static schema detected, turning on backcompat mode.
1178 Set the 'naming' attribute or the SCHEMA_LOADER_BACKCOMPAT environment variable
1179 to disable this warning.
1181 See: 'naming' in perldoc DBIx::Class::Schema::Loader::Base .
1183 See perldoc DBIx::Class::Schema::Loader::Manual::UpgradingFromV4 if upgrading
1184 from version 0.04006.
1187 $self->naming->{relationships} ||= $v;
1188 $self->naming->{monikers} ||= $v;
1189 $self->naming->{column_accessors} ||= $v;
1191 $self->schema_version_to_dump($old_ver);
1194 $self->_upgrading_from($v);
1198 sub _validate_class_args {
1201 foreach my $k (@CLASS_ARGS) {
1202 next unless $self->$k;
1204 my @classes = ref $self->$k eq 'ARRAY' ? @{ $self->$k } : $self->$k;
1205 $self->_validate_classes($k, \@classes);
1209 sub _validate_result_components_map {
1212 foreach my $classes (values %{ $self->result_components_map }) {
1213 $self->_validate_classes('result_components_map', $classes);
1217 sub _validate_result_roles_map {
1220 foreach my $classes (values %{ $self->result_roles_map }) {
1221 $self->_validate_classes('result_roles_map', $classes);
1225 sub _validate_classes {
1228 my $classes = shift;
1230 # make a copy to not destroy original
1231 my @classes = @$classes;
1233 foreach my $c (@classes) {
1234 # components default to being under the DBIx::Class namespace unless they
1235 # are preceeded with a '+'
1236 if ( $key =~ m/component/ && $c !~ s/^\+// ) {
1237 $c = 'DBIx::Class::' . $c;
1240 # 1 == installed, 0 == not installed, undef == invalid classname
1241 my $installed = Class::Inspector->installed($c);
1242 if ( defined($installed) ) {
1243 if ( $installed == 0 ) {
1244 croak qq/$c, as specified in the loader option "$key", is not installed/;
1247 croak qq/$c, as specified in the loader option "$key", is an invalid class name/;
1253 sub _find_file_in_inc {
1254 my ($self, $file) = @_;
1256 foreach my $prefix (@INC) {
1257 my $fullpath = File::Spec->catfile($prefix, $file);
1258 return $fullpath if -f $fullpath
1259 # abs_path throws on Windows for nonexistant files
1260 and (try { Cwd::abs_path($fullpath) }) ne
1261 ((try { Cwd::abs_path(File::Spec->catfile($self->dump_directory, $file)) }) || '');
1267 sub _find_class_in_inc {
1268 my ($self, $class) = @_;
1270 return $self->_find_file_in_inc(class_path($class));
1276 return $self->_upgrading_from
1277 || $self->_upgrading_from_load_classes
1278 || $self->_downgrading_to_load_classes
1279 || $self->_rewriting_result_namespace
1283 sub _rewrite_old_classnames {
1284 my ($self, $code) = @_;
1286 return $code unless $self->_rewriting;
1288 my %old_classes = reverse %{ $self->_upgrading_classes };
1290 my $re = join '|', keys %old_classes;
1291 $re = qr/\b($re)\b/;
1293 $code =~ s/$re/$old_classes{$1} || $1/eg;
1298 sub _load_external {
1299 my ($self, $class) = @_;
1301 return if $self->{skip_load_external};
1303 # so that we don't load our own classes, under any circumstances
1304 local *INC = [ grep $_ ne $self->dump_directory, @INC ];
1306 my $real_inc_path = $self->_find_class_in_inc($class);
1308 my $old_class = $self->_upgrading_classes->{$class}
1309 if $self->_rewriting;
1311 my $old_real_inc_path = $self->_find_class_in_inc($old_class)
1312 if $old_class && $old_class ne $class;
1314 return unless $real_inc_path || $old_real_inc_path;
1316 if ($real_inc_path) {
1317 # If we make it to here, we loaded an external definition
1318 warn qq/# Loaded external class definition for '$class'\n/
1321 my $code = $self->_rewrite_old_classnames(slurp_file $real_inc_path);
1323 if ($self->dynamic) { # load the class too
1324 eval_package_without_redefine_warnings($class, $code);
1327 $self->_ext_stmt($class,
1328 qq|# These lines were loaded from '$real_inc_path' found in \@INC.\n|
1329 .qq|# They are now part of the custom portion of this file\n|
1330 .qq|# for you to hand-edit. If you do not either delete\n|
1331 .qq|# this section or remove that file from \@INC, this section\n|
1332 .qq|# will be repeated redundantly when you re-create this\n|
1333 .qq|# file again via Loader! See skip_load_external to disable\n|
1334 .qq|# this feature.\n|
1337 $self->_ext_stmt($class, $code);
1338 $self->_ext_stmt($class,
1339 qq|# End of lines loaded from '$real_inc_path' |
1343 if ($old_real_inc_path) {
1344 my $code = slurp_file $old_real_inc_path;
1346 $self->_ext_stmt($class, <<"EOF");
1348 # These lines were loaded from '$old_real_inc_path',
1349 # based on the Result class name that would have been created by an older
1350 # version of the Loader. For a static schema, this happens only once during
1351 # upgrade. See skip_load_external to disable this feature.
1354 $code = $self->_rewrite_old_classnames($code);
1356 if ($self->dynamic) {
1359 Detected external content in '$old_real_inc_path', a class name that would have
1360 been used by an older version of the Loader.
1362 * PLEASE RENAME THIS CLASS: from '$old_class' to '$class', as that is the
1363 new name of the Result.
1365 eval_package_without_redefine_warnings($class, $code);
1369 $self->_ext_stmt($class, $code);
1370 $self->_ext_stmt($class,
1371 qq|# End of lines loaded from '$old_real_inc_path' |
1378 Does the actual schema-construction work.
1385 $self->_load_tables(
1386 $self->_tables_list({ constraint => $self->constraint, exclude => $self->exclude })
1394 Rescan the database for changes. Returns a list of the newly added table
1397 The schema argument should be the schema class or object to be affected. It
1398 should probably be derived from the original schema_class used during L</load>.
1403 my ($self, $schema) = @_;
1405 $self->{schema} = $schema;
1406 $self->_relbuilder->{schema} = $schema;
1409 my @current = $self->_tables_list({ constraint => $self->constraint, exclude => $self->exclude });
1411 foreach my $table (@current) {
1412 if(!exists $self->_tables->{$table->sql_name}) {
1413 push(@created, $table);
1418 @current{map $_->sql_name, @current} = ();
1419 foreach my $table (values %{ $self->_tables }) {
1420 if (not exists $current{$table->sql_name}) {
1421 $self->_remove_table($table);
1425 delete @$self{qw/_dump_storage _relations_started _uniqs_started/};
1427 my $loaded = $self->_load_tables(@current);
1429 foreach my $table (@created) {
1430 $self->monikers->{$table->sql_name} = $self->_table2moniker($table);
1433 return map { $self->monikers->{$_->sql_name} } @created;
1439 return if $self->{skip_relationships};
1441 return $self->{relbuilder} ||= do {
1442 my $relbuilder_suff =
1449 ->{$self->naming->{relationships}||$CURRENT_V} || '';
1451 my $relbuilder_class = 'DBIx::Class::Schema::Loader::RelBuilder'.$relbuilder_suff;
1452 $self->ensure_class_loaded($relbuilder_class);
1453 $relbuilder_class->new($self);
1458 my ($self, @tables) = @_;
1460 # Save the new tables to the tables list
1462 $self->_tables->{$_->sql_name} = $_;
1465 $self->_make_src_class($_) for @tables;
1467 # sanity-check for moniker clashes
1468 my $inverse_moniker_idx;
1469 foreach my $table (values %{ $self->_tables }) {
1470 push @{ $inverse_moniker_idx->{$self->monikers->{$table->sql_name}} }, $table;
1474 foreach my $moniker (keys %$inverse_moniker_idx) {
1475 my $tables = $inverse_moniker_idx->{$moniker};
1477 push @clashes, sprintf ("tables %s reduced to the same source moniker '%s'",
1478 join (', ', map $_->sql_name, @$tables),
1485 die 'Unable to load schema - chosen moniker/class naming style results in moniker clashes. '
1486 . 'In multi db_schema configurations you may need to set moniker_parts, '
1487 . 'otherwise change the naming style, or supply an explicit moniker_map: '
1488 . join ('; ', @clashes)
1493 $self->_setup_src_meta($_) for @tables;
1495 if(!$self->skip_relationships) {
1496 # The relationship loader needs a working schema
1497 local $self->{quiet} = 1;
1498 local $self->{dump_directory} = $self->{temp_directory};
1499 $self->_reload_classes(\@tables);
1500 $self->_load_relationships(\@tables);
1502 # Remove that temp dir from INC so it doesn't get reloaded
1503 @INC = grep $_ ne $self->dump_directory, @INC;
1506 $self->_load_roles($_) for @tables;
1508 $self->_load_external($_)
1509 for map { $self->classes->{$_->sql_name} } @tables;
1511 # Reload without unloading first to preserve any symbols from external
1513 $self->_reload_classes(\@tables, { unload => 0 });
1515 # Drop temporary cache
1516 delete $self->{_cache};
1521 sub _reload_classes {
1522 my ($self, $tables, $opts) = @_;
1524 my @tables = @$tables;
1526 my $unload = $opts->{unload};
1527 $unload = 1 unless defined $unload;
1529 # so that we don't repeat custom sections
1530 @INC = grep $_ ne $self->dump_directory, @INC;
1532 $self->_dump_to_dir(map { $self->classes->{$_->sql_name} } @tables);
1534 unshift @INC, $self->dump_directory;
1537 my %have_source = map { $_ => $self->schema->source($_) }
1538 $self->schema->sources;
1540 for my $table (@tables) {
1541 my $moniker = $self->monikers->{$table->sql_name};
1542 my $class = $self->classes->{$table->sql_name};
1545 no warnings 'redefine';
1546 local *Class::C3::reinitialize = sub {}; # to speed things up, reinitialized below
1549 if (my $mc = $self->_moose_metaclass($class)) {
1552 Class::Unload->unload($class) if $unload;
1553 my ($source, $resultset_class);
1555 ($source = $have_source{$moniker})
1556 && ($resultset_class = $source->resultset_class)
1557 && ($resultset_class ne 'DBIx::Class::ResultSet')
1559 my $has_file = Class::Inspector->loaded_filename($resultset_class);
1560 if (my $mc = $self->_moose_metaclass($resultset_class)) {
1563 Class::Unload->unload($resultset_class) if $unload;
1564 $self->_reload_class($resultset_class) if $has_file;
1566 $self->_reload_class($class);
1568 push @to_register, [$moniker, $class];
1571 Class::C3->reinitialize;
1572 for (@to_register) {
1573 $self->schema->register_class(@$_);
1577 sub _moose_metaclass {
1578 return undef unless $INC{'Class/MOP.pm'}; # if CMOP is not loaded the class could not have loaded in the 1st place
1582 my $mc = try { Class::MOP::class_of($class) }
1585 return $mc->isa('Moose::Meta::Class') ? $mc : undef;
1588 # We use this instead of ensure_class_loaded when there are package symbols we
1591 my ($self, $class) = @_;
1593 delete $INC{ +class_path($class) };
1596 eval_package_without_redefine_warnings ($class, "require $class");
1599 my $source = slurp_file $self->_get_dump_filename($class);
1600 die "Failed to reload class $class: $_.\n\nCLASS SOURCE:\n\n$source";
1604 sub _get_dump_filename {
1605 my ($self, $class) = (@_);
1607 $class =~ s{::}{/}g;
1608 return $self->dump_directory . q{/} . $class . q{.pm};
1611 =head2 get_dump_filename
1615 Returns the full path to the file for a class that the class has been or will
1616 be dumped to. This is a file in a temp dir for a dynamic schema.
1620 sub get_dump_filename {
1621 my ($self, $class) = (@_);
1623 local $self->{dump_directory} = $self->real_dump_directory;
1625 return $self->_get_dump_filename($class);
1628 sub _ensure_dump_subdirs {
1629 my ($self, $class) = (@_);
1631 my @name_parts = split(/::/, $class);
1632 pop @name_parts; # we don't care about the very last element,
1633 # which is a filename
1635 my $dir = $self->dump_directory;
1638 mkdir($dir) or croak "mkdir('$dir') failed: $!";
1640 last if !@name_parts;
1641 $dir = File::Spec->catdir($dir, shift @name_parts);
1646 my ($self, @classes) = @_;
1648 my $schema_class = $self->schema_class;
1649 my $schema_base_class = $self->schema_base_class || 'DBIx::Class::Schema';
1651 my $target_dir = $self->dump_directory;
1652 warn "Dumping manual schema for $schema_class to directory $target_dir ...\n"
1653 unless $self->dynamic or $self->quiet;
1657 . qq|package $schema_class;\n\n|
1658 . qq|# Created by DBIx::Class::Schema::Loader\n|
1659 . qq|# DO NOT MODIFY THE FIRST PART OF THIS FILE\n\n|;
1661 if ($self->use_moose) {
1662 $schema_text.= qq|use Moose;\nuse namespace::autoclean;\nextends '$schema_base_class';\n\n|;
1665 $schema_text .= qq|use strict;\nuse warnings;\n\nuse base '$schema_base_class';\n\n|;
1668 my @schema_components = @{ $self->schema_components || [] };
1670 if (@schema_components) {
1671 my $schema_components = dump @schema_components;
1672 $schema_components = "($schema_components)" if @schema_components == 1;
1674 $schema_text .= "__PACKAGE__->load_components${schema_components};\n\n";
1677 if ($self->use_namespaces) {
1678 $schema_text .= qq|__PACKAGE__->load_namespaces|;
1679 my $namespace_options;
1681 my @attr = qw/resultset_namespace default_resultset_class/;
1683 unshift @attr, 'result_namespace' unless (not $self->result_namespace) || $self->result_namespace eq 'Result';
1685 for my $attr (@attr) {
1687 my $code = dumper_squashed $self->$attr;
1688 $namespace_options .= qq| $attr => $code,\n|
1691 $schema_text .= qq|(\n$namespace_options)| if $namespace_options;
1692 $schema_text .= qq|;\n|;
1695 $schema_text .= qq|__PACKAGE__->load_classes;\n|;
1699 local $self->{version_to_dump} = $self->schema_version_to_dump;
1700 $self->_write_classfile($schema_class, $schema_text, 1);
1703 my $result_base_class = $self->result_base_class || 'DBIx::Class::Core';
1705 foreach my $src_class (@classes) {
1708 . qq|package $src_class;\n\n|
1709 . qq|# Created by DBIx::Class::Schema::Loader\n|
1710 . qq|# DO NOT MODIFY THE FIRST PART OF THIS FILE\n\n|;
1712 $src_text .= $self->_make_pod_heading($src_class);
1714 $src_text .= qq|use strict;\nuse warnings;\n\n|;
1716 $src_text .= $self->_base_class_pod($result_base_class)
1717 unless $result_base_class eq 'DBIx::Class::Core';
1719 if ($self->use_moose) {
1720 $src_text.= qq|use Moose;\nuse MooseX::NonMoose;\nuse namespace::autoclean;|;
1722 # these options 'use base' which is compile time
1723 if (@{ $self->left_base_classes } || @{ $self->additional_base_classes }) {
1724 $src_text .= qq|\nBEGIN { extends '$result_base_class' }\n|;
1727 $src_text .= qq|\nextends '$result_base_class';\n|;
1731 $src_text .= qq|use base '$result_base_class';\n|;
1734 $self->_write_classfile($src_class, $src_text);
1737 # remove Result dir if downgrading from use_namespaces, and there are no
1739 if (my $result_ns = $self->_downgrading_to_load_classes
1740 || $self->_rewriting_result_namespace) {
1741 my $result_namespace = $self->_result_namespace(
1746 (my $result_dir = $result_namespace) =~ s{::}{/}g;
1747 $result_dir = $self->dump_directory . '/' . $result_dir;
1749 unless (my @files = glob "$result_dir/*") {
1754 warn "Schema dump completed.\n" unless $self->dynamic or $self->quiet;
1758 my ($self, $version, $ts) = @_;
1759 return qq|\n\n# Created by DBIx::Class::Schema::Loader|
1762 . qq|\n# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:|;
1765 sub _write_classfile {
1766 my ($self, $class, $text, $is_schema) = @_;
1768 my $filename = $self->_get_dump_filename($class);
1769 $self->_ensure_dump_subdirs($class);
1771 if (-f $filename && $self->really_erase_my_files) {
1772 warn "Deleting existing file '$filename' due to "
1773 . "'really_erase_my_files' setting\n" unless $self->quiet;
1777 my ($old_gen, $old_md5, $old_ver, $old_ts, $old_custom)
1778 = $self->_parse_generated_file($filename);
1780 if (! $old_gen && -f $filename) {
1781 croak "Cannot overwrite '$filename' without 'really_erase_my_files',"
1782 . " it does not appear to have been generated by Loader"
1785 my $custom_content = $old_custom || '';
1787 # prepend extra custom content from a *renamed* class (singularization effect)
1788 if (my $renamed_class = $self->_upgrading_classes->{$class}) {
1789 my $old_filename = $self->_get_dump_filename($renamed_class);
1791 if (-f $old_filename) {
1792 my $extra_custom = ($self->_parse_generated_file ($old_filename))[4];
1794 $extra_custom =~ s/\n\n# You can replace.*\n1;\n//;
1796 $custom_content = join ("\n", '', $extra_custom, $custom_content)
1799 unlink $old_filename;
1803 $custom_content ||= $self->_default_custom_content($is_schema);
1805 # If upgrading to use_moose=1 replace default custom content with default Moose custom content.
1806 # If there is already custom content, which does not have the Moose content, add it.
1807 if ($self->use_moose) {
1809 my $non_moose_custom_content = do {
1810 local $self->{use_moose} = 0;
1811 $self->_default_custom_content;
1814 if ($custom_content eq $non_moose_custom_content) {
1815 $custom_content = $self->_default_custom_content($is_schema);
1817 elsif ($custom_content !~ /\Q@{[$self->_default_moose_custom_content($is_schema)]}\E/) {
1818 $custom_content .= $self->_default_custom_content($is_schema);
1821 elsif (defined $self->use_moose && $old_gen) {
1822 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'
1823 if $old_gen =~ /use \s+ MooseX?\b/x;
1826 $custom_content = $self->_rewrite_old_classnames($custom_content);
1829 for @{$self->{_dump_storage}->{$class} || []};
1831 if ($self->filter_generated_code) {
1832 my $filter = $self->filter_generated_code;
1834 if (ref $filter eq 'CODE') {
1836 ($is_schema ? 'schema' : 'result'),
1842 my ($out, $in) = (gensym, gensym);
1844 my $pid = open2($out, $in, $filter)
1845 or croak "Could not open pipe to $filter: $!";
1851 $text = decode('UTF-8', do { local $/; <$out> });
1853 $text =~ s/$CR?$LF/\n/g;
1857 my $exit_code = $? >> 8;
1859 if ($exit_code != 0) {
1860 croak "filter '$filter' exited non-zero: $exit_code";
1863 if (not $text or not $text =~ /\bpackage\b/) {
1864 warn("$class skipped due to filter") if $self->debug;
1869 # Check and see if the dump is in fact different
1873 $compare_to = $text . $self->_sig_comment($old_ver, $old_ts);
1874 if (Digest::MD5::md5_base64(encode 'UTF-8', $compare_to) eq $old_md5) {
1875 return unless $self->_upgrading_from && $is_schema;
1879 $text .= $self->_sig_comment(
1880 $self->version_to_dump,
1881 POSIX::strftime('%Y-%m-%d %H:%M:%S', localtime)
1884 open(my $fh, '>:encoding(UTF-8)', $filename)
1885 or croak "Cannot open '$filename' for writing: $!";
1887 # Write the top half and its MD5 sum
1888 print $fh $text . Digest::MD5::md5_base64(encode 'UTF-8', $text) . "\n";
1890 # Write out anything loaded via external partial class file in @INC
1892 for @{$self->{_ext_storage}->{$class} || []};
1894 # Write out any custom content the user has added
1895 print $fh $custom_content;
1898 or croak "Error closing '$filename': $!";
1901 sub _default_moose_custom_content {
1902 my ($self, $is_schema) = @_;
1904 if (not $is_schema) {
1905 return qq|\n__PACKAGE__->meta->make_immutable;|;
1908 return qq|\n__PACKAGE__->meta->make_immutable(inline_constructor => 0);|;
1911 sub _default_custom_content {
1912 my ($self, $is_schema) = @_;
1913 my $default = qq|\n\n# You can replace this text with custom|
1914 . qq| code or comments, and it will be preserved on regeneration|;
1915 if ($self->use_moose) {
1916 $default .= $self->_default_moose_custom_content($is_schema);
1918 $default .= qq|\n1;\n|;
1922 sub _parse_generated_file {
1923 my ($self, $fn) = @_;
1925 return unless -f $fn;
1927 open(my $fh, '<:encoding(UTF-8)', $fn)
1928 or croak "Cannot open '$fn' for reading: $!";
1931 qr{^(# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:)([A-Za-z0-9/+]{22})\r?\n};
1933 my ($md5, $ts, $ver, $gen);
1939 # Pull out the version and timestamp from the line above
1940 ($ver, $ts) = $gen =~ m/^# Created by DBIx::Class::Schema::Loader v(.*?) @ (.*?)\r?\Z/m;
1943 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"
1944 if !$self->overwrite_modifications && Digest::MD5::md5_base64(encode 'UTF-8', $gen) ne $md5;
1953 my $custom = do { local $/; <$fh> }
1957 $custom =~ s/$CRLF|$LF/\n/g;
1961 return ($gen, $md5, $ver, $ts, $custom);
1969 warn "$target: use $_;" if $self->debug;
1970 $self->_raw_stmt($target, "use $_;");
1978 my $blist = join(q{ }, @_);
1980 return unless $blist;
1982 warn "$target: use base qw/$blist/;" if $self->debug;
1983 $self->_raw_stmt($target, "use base qw/$blist/;");
1990 my $rlist = join(q{, }, map { qq{'$_'} } @_);
1992 return unless $rlist;
1994 warn "$target: with $rlist;" if $self->debug;
1995 $self->_raw_stmt($target, "\nwith $rlist;");
1998 sub _result_namespace {
1999 my ($self, $schema_class, $ns) = @_;
2000 my @result_namespace;
2002 $ns = $ns->[0] if ref $ns;
2004 if ($ns =~ /^\+(.*)/) {
2005 # Fully qualified namespace
2006 @result_namespace = ($1)
2009 # Relative namespace
2010 @result_namespace = ($schema_class, $ns);
2013 return wantarray ? @result_namespace : join '::', @result_namespace;
2016 # Create class with applicable bases, setup monikers, etc
2017 sub _make_src_class {
2018 my ($self, $table) = @_;
2020 my $schema = $self->schema;
2021 my $schema_class = $self->schema_class;
2023 my $table_moniker = $self->_table2moniker($table);
2024 my @result_namespace = ($schema_class);
2025 if ($self->use_namespaces) {
2026 my $result_namespace = $self->result_namespace || 'Result';
2027 @result_namespace = $self->_result_namespace(
2032 my $table_class = join(q{::}, @result_namespace, $table_moniker);
2034 if ((my $upgrading_v = $self->_upgrading_from)
2035 || $self->_rewriting) {
2036 local $self->naming->{monikers} = $upgrading_v
2039 my @result_namespace = @result_namespace;
2040 if ($self->_upgrading_from_load_classes) {
2041 @result_namespace = ($schema_class);
2043 elsif (my $ns = $self->_downgrading_to_load_classes) {
2044 @result_namespace = $self->_result_namespace(
2049 elsif ($ns = $self->_rewriting_result_namespace) {
2050 @result_namespace = $self->_result_namespace(
2056 my $old_table_moniker = do {
2057 local $self->naming->{monikers} = $upgrading_v;
2058 $self->_table2moniker($table);
2061 my $old_class = join(q{::}, @result_namespace, $old_table_moniker);
2063 $self->_upgrading_classes->{$table_class} = $old_class
2064 unless $table_class eq $old_class;
2067 $self->classes->{$table->sql_name} = $table_class;
2068 $self->monikers->{$table->sql_name} = $table_moniker;
2069 $self->moniker_to_table->{$table_moniker} = $table;
2070 $self->class_to_table->{$table_class} = $table;
2072 $self->_pod_class_list($table_class, 'ADDITIONAL CLASSES USED', @{$self->additional_classes});
2074 $self->_use ($table_class, @{$self->additional_classes});
2076 $self->_pod_class_list($table_class, 'LEFT BASE CLASSES', @{$self->left_base_classes});
2078 $self->_inject($table_class, @{$self->left_base_classes});
2080 my @components = @{ $self->components || [] };
2082 push @components, @{ $self->result_components_map->{$table_moniker} }
2083 if exists $self->result_components_map->{$table_moniker};
2085 my @fq_components = @components;
2086 foreach my $component (@fq_components) {
2087 if ($component !~ s/^\+//) {
2088 $component = "DBIx::Class::$component";
2092 $self->_pod_class_list($table_class, 'COMPONENTS LOADED', @fq_components);
2094 $self->_dbic_stmt($table_class, 'load_components', @components) if @components;
2096 $self->_pod_class_list($table_class, 'ADDITIONAL BASE CLASSES', @{$self->additional_base_classes});
2098 $self->_inject($table_class, @{$self->additional_base_classes});
2101 sub _is_result_class_method {
2102 my ($self, $name, $table) = @_;
2104 my $table_moniker = $table ? $self->monikers->{$table->sql_name} : '';
2106 $self->_result_class_methods({})
2107 if not defined $self->_result_class_methods;
2109 if (not exists $self->_result_class_methods->{$table_moniker}) {
2110 my (@methods, %methods);
2111 my $base = $self->result_base_class || 'DBIx::Class::Core';
2113 my @components = @{ $self->components || [] };
2115 push @components, @{ $self->result_components_map->{$table_moniker} }
2116 if exists $self->result_components_map->{$table_moniker};
2118 for my $c (@components) {
2119 $c = $c =~ /^\+/ ? substr($c,1) : "DBIx::Class::$c";
2122 my @roles = @{ $self->result_roles || [] };
2124 push @roles, @{ $self->result_roles_map->{$table_moniker} }
2125 if exists $self->result_roles_map->{$table_moniker};
2127 for my $class ($base, @components,
2128 ($self->use_moose ? 'Moose::Object' : ()), @roles) {
2129 $self->ensure_class_loaded($class);
2131 push @methods, @{ Class::Inspector->methods($class) || [] };
2134 push @methods, @{ Class::Inspector->methods('UNIVERSAL') };
2136 @methods{@methods} = ();
2138 $self->_result_class_methods->{$table_moniker} = \%methods;
2140 my $result_methods = $self->_result_class_methods->{$table_moniker};
2142 return exists $result_methods->{$name};
2145 sub _resolve_col_accessor_collisions {
2146 my ($self, $table, $col_info) = @_;
2148 while (my ($col, $info) = each %$col_info) {
2149 my $accessor = $info->{accessor} || $col;
2151 next if $accessor eq 'id'; # special case (very common column)
2153 if ($self->_is_result_class_method($accessor, $table)) {
2156 if (my $map = $self->col_collision_map) {
2157 for my $re (keys %$map) {
2158 if (my @matches = $col =~ /$re/) {
2159 $info->{accessor} = sprintf $map->{$re}, @matches;
2167 Column '$col' in table '$table' collides with an inherited method.
2168 See "COLUMN ACCESSOR COLLISIONS" in perldoc DBIx::Class::Schema::Loader::Base .
2170 $info->{accessor} = undef;
2176 # use the same logic to run moniker_map, col_accessor_map
2178 my ( $self, $map, $default_code, $ident, @extra ) = @_;
2180 my $default_ident = $default_code->( $ident, @extra );
2182 if( $map && ref $map eq 'HASH' ) {
2183 $new_ident = $map->{ $ident };
2185 elsif( $map && ref $map eq 'CODE' ) {
2186 $new_ident = $map->( $ident, $default_ident, @extra );
2189 $new_ident ||= $default_ident;
2194 sub _default_column_accessor_name {
2195 my ( $self, $column_name ) = @_;
2197 my $accessor_name = $self->_to_identifier('column_accessors', $column_name, '_');
2199 $accessor_name =~ s/\W+/_/g; # only if naming < v8, otherwise to_identifier
2202 if ((($self->naming->{column_accessors}||'') =~ /(\d+)/ && $1 < 7) || (not $self->preserve_case)) {
2203 # older naming just lc'd the col accessor and that's all.
2204 return lc $accessor_name;
2206 elsif (($self->naming->{column_accessors}||'') eq 'preserve') {
2207 return $accessor_name;
2210 return join '_', map lc, split_name $column_name;
2213 sub _make_column_accessor_name {
2214 my ($self, $column_name, $column_context_info ) = @_;
2216 my $accessor = $self->_run_user_map(
2217 $self->col_accessor_map,
2218 sub { $self->_default_column_accessor_name( shift ) },
2220 $column_context_info,
2226 # Set up metadata (cols, pks, etc)
2227 sub _setup_src_meta {
2228 my ($self, $table) = @_;
2230 my $schema = $self->schema;
2231 my $schema_class = $self->schema_class;
2233 my $table_class = $self->classes->{$table->sql_name};
2234 my $table_moniker = $self->monikers->{$table->sql_name};
2236 $self->_dbic_stmt($table_class, 'table', $table->dbic_name);
2238 my $cols = $self->_table_columns($table);
2239 my $col_info = $self->__columns_info_for($table);
2241 ### generate all the column accessor names
2242 while (my ($col, $info) = each %$col_info) {
2243 # hashref of other info that could be used by
2244 # user-defined accessor map functions
2246 table_class => $table_class,
2247 table_moniker => $table_moniker,
2248 table_name => $table,
2249 full_table_name => $table->dbic_name,
2250 schema_class => $schema_class,
2251 column_info => $info,
2254 $info->{accessor} = $self->_make_column_accessor_name( $col, $context );
2257 $self->_resolve_col_accessor_collisions($table, $col_info);
2259 # prune any redundant accessor names
2260 while (my ($col, $info) = each %$col_info) {
2261 no warnings 'uninitialized';
2262 delete $info->{accessor} if $info->{accessor} eq $col;
2265 my $fks = $self->_table_fk_info($table);
2267 foreach my $fkdef (@$fks) {
2268 for my $col (@{ $fkdef->{local_columns} }) {
2269 $col_info->{$col}{is_foreign_key} = 1;
2273 my $pks = $self->_table_pk_info($table) || [];
2275 my %uniq_tag; # used to eliminate duplicate uniqs
2277 $uniq_tag{ join("\0", @$pks) }++ if @$pks; # pk is a uniq
2279 my $uniqs = $self->_table_uniq_info($table) || [];
2282 foreach my $uniq (@$uniqs) {
2283 my ($name, $cols) = @$uniq;
2284 next if $uniq_tag{ join("\0", @$cols) }++; # skip duplicates
2285 push @uniqs, [$name, $cols];
2288 my @non_nullable_uniqs = grep {
2289 all { $col_info->{$_}{is_nullable} == 0 } @{ $_->[1] }
2292 if ($self->uniq_to_primary && (not @$pks) && @non_nullable_uniqs) {
2293 my @by_colnum = sort { $b->[0] <=> $a->[0] }
2294 map [ scalar @{ $_->[1] }, $_ ], @non_nullable_uniqs;
2296 if (not (@by_colnum > 1 && $by_colnum[0][0] == $by_colnum[1][0])) {
2297 my @keys = map $_->[1], @by_colnum;
2301 # remove the uniq from list
2302 @uniqs = grep { $_->[0] ne $pk->[0] } @uniqs;
2308 foreach my $pkcol (@$pks) {
2309 $col_info->{$pkcol}{is_nullable} = 0;
2315 map { $_, ($col_info->{$_}||{}) } @$cols
2318 $self->_dbic_stmt($table_class, 'set_primary_key', @$pks)
2321 # Sort unique constraints by constraint name for repeatable results (rels
2322 # are sorted as well elsewhere.)
2323 @uniqs = sort { $a->[0] cmp $b->[0] } @uniqs;
2325 foreach my $uniq (@uniqs) {
2326 my ($name, $cols) = @$uniq;
2327 $self->_dbic_stmt($table_class,'add_unique_constraint', $name, $cols);
2331 sub __columns_info_for {
2332 my ($self, $table) = @_;
2334 my $result = $self->_columns_info_for($table);
2336 while (my ($col, $info) = each %$result) {
2337 $info = { %$info, %{ $self->_custom_column_info ($table, $col, $info) } };
2338 $info = { %$info, %{ $self->_datetime_column_info($table, $col, $info) } };
2340 $result->{$col} = $info;
2348 Returns a sorted list of loaded tables, using the original database table
2356 return values %{$self->_tables};
2359 sub _to_identifier {
2360 my ($self, $naming_key, $name, $sep_char) = @_;
2362 my ($v) = ($self->naming->{$naming_key}||$CURRENT_V) =~ /^v(\d+)\z/;
2364 my $to_identifier = $self->naming->{force_ascii} ?
2365 \&String::ToIdentifier::EN::to_identifier
2366 : \&String::ToIdentifier::EN::Unicode::to_identifier;
2368 return $v >= 8 ? $to_identifier->($name, $sep_char) : $name;
2371 # Make a moniker from a table
2372 sub _default_table2moniker {
2373 my ($self, $table) = @_;
2375 my ($v) = ($self->naming->{monikers}||$CURRENT_V) =~ /^v(\d+)\z/;
2377 my @name_parts = map $table->$_, @{ $self->moniker_parts };
2379 my $name_idx = firstidx { $_ eq 'name' } @{ $self->moniker_parts };
2383 foreach my $i (0 .. $#name_parts) {
2384 my $part = $name_parts[$i];
2386 if ($i != $name_idx || $v >= 8) {
2387 $part = $self->_to_identifier->('monikers', $part, '_');
2390 if ($i == $name_idx && $v == 5) {
2391 $part = Lingua::EN::Inflect::Number::to_S($part);
2394 my @part_parts = map lc, $v > 6 ? split_name $part : split /[\W_]+/, $part;
2396 if ($i == $name_idx && $v >= 6) {
2397 my $as_phrase = join ' ', @part_parts;
2399 my $inflected = ($self->naming->{monikers}||'') eq 'plural' ?
2400 Lingua::EN::Inflect::Phrase::to_PL($as_phrase)
2402 ($self->naming->{monikers}||'') eq 'preserve' ?
2405 Lingua::EN::Inflect::Phrase::to_S($as_phrase);
2407 @part_parts = split /\s+/, $inflected;
2410 push @all_parts, map ucfirst, @part_parts;
2413 return join '', @all_parts;
2416 sub _table2moniker {
2417 my ( $self, $table ) = @_;
2419 $self->_run_user_map(
2421 sub { $self->_default_table2moniker( shift ) },
2426 sub _load_relationships {
2427 my ($self, $tables) = @_;
2431 foreach my $table (@$tables) {
2432 my $local_moniker = $self->monikers->{$table->sql_name};
2434 my $tbl_fk_info = $self->_table_fk_info($table);
2436 foreach my $fkdef (@$tbl_fk_info) {
2437 $fkdef->{local_table} = $table;
2438 $fkdef->{local_moniker} = $local_moniker;
2439 $fkdef->{remote_source} =
2440 $self->monikers->{$fkdef->{remote_table}->sql_name};
2442 my $tbl_uniq_info = $self->_table_uniq_info($table);
2444 push @tables, [ $local_moniker, $tbl_fk_info, $tbl_uniq_info ];
2447 my $rel_stmts = $self->_relbuilder->generate_code(\@tables);
2449 foreach my $src_class (sort keys %$rel_stmts) {
2451 my @src_stmts = map $_->[1],
2452 sort { $a->[0] cmp $b->[0] }
2453 map [ $_->{args}[0], $_ ], @{ $rel_stmts->{$src_class} };
2455 foreach my $stmt (@src_stmts) {
2456 $self->_dbic_stmt($src_class,$stmt->{method}, @{$stmt->{args}});
2462 my ($self, $table) = @_;
2464 my $table_moniker = $self->monikers->{$table->sql_name};
2465 my $table_class = $self->classes->{$table->sql_name};
2467 my @roles = @{ $self->result_roles || [] };
2468 push @roles, @{ $self->result_roles_map->{$table_moniker} }
2469 if exists $self->result_roles_map->{$table_moniker};
2472 $self->_pod_class_list($table_class, 'L<Moose> ROLES APPLIED', @roles);
2474 $self->_with($table_class, @roles);
2478 # Overload these in driver class:
2480 # Returns an arrayref of column names
2481 sub _table_columns { croak "ABSTRACT METHOD" }
2483 # Returns arrayref of pk col names
2484 sub _table_pk_info { croak "ABSTRACT METHOD" }
2486 # Returns an arrayref of uniqs [ [ foo => [ col1, col2 ] ], [ bar => [ ... ] ] ]
2487 sub _table_uniq_info { croak "ABSTRACT METHOD" }
2489 # Returns an arrayref of foreign key constraints, each
2490 # being a hashref with 3 keys:
2491 # local_columns (arrayref), remote_columns (arrayref), remote_table
2492 sub _table_fk_info { croak "ABSTRACT METHOD" }
2494 # Returns an array of lower case table names
2495 sub _tables_list { croak "ABSTRACT METHOD" }
2497 # Execute a constructive DBIC class method, with debug/dump_to_dir hooks.
2503 # generate the pod for this statement, storing it with $self->_pod
2504 $self->_make_pod( $class, $method, @_ ) if $self->generate_pod;
2506 my $args = dump(@_);
2507 $args = '(' . $args . ')' if @_ < 2;
2508 my $stmt = $method . $args . q{;};
2510 warn qq|$class\->$stmt\n| if $self->debug;
2511 $self->_raw_stmt($class, '__PACKAGE__->' . $stmt);
2515 sub _make_pod_heading {
2516 my ($self, $class) = @_;
2518 return '' if not $self->generate_pod;
2520 my $table = $self->class_to_table->{$class};
2523 my $pcm = $self->pod_comment_mode;
2524 my ($comment, $comment_overflows, $comment_in_name, $comment_in_desc);
2525 $comment = $self->__table_comment($table);
2526 $comment_overflows = ($comment and length $comment > $self->pod_comment_spillover_length);
2527 $comment_in_name = ($pcm eq 'name' or ($pcm eq 'auto' and !$comment_overflows));
2528 $comment_in_desc = ($pcm eq 'description' or ($pcm eq 'auto' and $comment_overflows));
2530 $pod .= "=head1 NAME\n\n";
2532 my $table_descr = $class;
2533 $table_descr .= " - " . $comment if $comment and $comment_in_name;
2535 $pod .= "$table_descr\n\n";
2537 if ($comment and $comment_in_desc) {
2538 $pod .= "=head1 DESCRIPTION\n\n${comment}\n\n";
2545 # generates the accompanying pod for a DBIC class method statement,
2546 # storing it with $self->_pod
2552 if ($method eq 'table') {
2554 $table = $$table if ref $table eq 'SCALAR';
2555 $self->_pod($class, "=head1 TABLE: C<$table>");
2556 $self->_pod_cut($class);
2558 elsif ( $method eq 'add_columns' ) {
2559 $self->_pod( $class, "=head1 ACCESSORS" );
2560 my $col_counter = 0;
2562 while( my ($name,$attrs) = splice @cols,0,2 ) {
2564 $self->_pod( $class, '=head2 ' . $name );
2565 $self->_pod( $class,
2567 my $s = $attrs->{$_};
2568 $s = !defined $s ? 'undef' :
2569 length($s) == 0 ? '(empty string)' :
2570 ref($s) eq 'SCALAR' ? $$s :
2571 ref($s) ? dumper_squashed $s :
2572 looks_like_number($s) ? $s : qq{'$s'};
2575 } sort keys %$attrs,
2577 if (my $comment = $self->__column_comment($self->class_to_table->{$class}, $col_counter, $name)) {
2578 $self->_pod( $class, $comment );
2581 $self->_pod_cut( $class );
2582 } elsif ( $method =~ /^(belongs_to|has_many|might_have)$/ ) {
2583 $self->_pod( $class, "=head1 RELATIONS" ) unless $self->{_relations_started} { $class } ;
2584 my ( $accessor, $rel_class ) = @_;
2585 $self->_pod( $class, "=head2 $accessor" );
2586 $self->_pod( $class, 'Type: ' . $method );
2587 $self->_pod( $class, "Related object: L<$rel_class>" );
2588 $self->_pod_cut( $class );
2589 $self->{_relations_started} { $class } = 1;
2591 elsif ($method eq 'add_unique_constraint') {
2592 $self->_pod($class, '=head1 UNIQUE CONSTRAINTS')
2593 unless $self->{_uniqs_started}{$class};
2595 my ($name, $cols) = @_;
2597 $self->_pod($class, "=head2 C<$name>");
2598 $self->_pod($class, '=over 4');
2600 foreach my $col (@$cols) {
2601 $self->_pod($class, "=item \* L</$col>");
2604 $self->_pod($class, '=back');
2605 $self->_pod_cut($class);
2607 $self->{_uniqs_started}{$class} = 1;
2609 elsif ($method eq 'set_primary_key') {
2610 $self->_pod($class, "=head1 PRIMARY KEY");
2611 $self->_pod($class, '=over 4');
2613 foreach my $col (@_) {
2614 $self->_pod($class, "=item \* L</$col>");
2617 $self->_pod($class, '=back');
2618 $self->_pod_cut($class);
2622 sub _pod_class_list {
2623 my ($self, $class, $title, @classes) = @_;
2625 return unless @classes && $self->generate_pod;
2627 $self->_pod($class, "=head1 $title");
2628 $self->_pod($class, '=over 4');
2630 foreach my $link (@classes) {
2631 $self->_pod($class, "=item * L<$link>");
2634 $self->_pod($class, '=back');
2635 $self->_pod_cut($class);
2638 sub _base_class_pod {
2639 my ($self, $base_class) = @_;
2641 return '' unless $self->generate_pod;
2644 =head1 BASE CLASS: L<$base_class>
2651 sub _filter_comment {
2652 my ($self, $txt) = @_;
2654 $txt = '' if not defined $txt;
2656 $txt =~ s/(?:\015?\012|\015\012?)/\n/g;
2661 sub __table_comment {
2664 if (my $code = $self->can('_table_comment')) {
2665 return $self->_filter_comment($self->$code(@_));
2671 sub __column_comment {
2674 if (my $code = $self->can('_column_comment')) {
2675 return $self->_filter_comment($self->$code(@_));
2681 # Stores a POD documentation
2683 my ($self, $class, $stmt) = @_;
2684 $self->_raw_stmt( $class, "\n" . $stmt );
2688 my ($self, $class ) = @_;
2689 $self->_raw_stmt( $class, "\n=cut\n" );
2692 # Store a raw source line for a class (for dumping purposes)
2694 my ($self, $class, $stmt) = @_;
2695 push(@{$self->{_dump_storage}->{$class}}, $stmt);
2698 # Like above, but separately for the externally loaded stuff
2700 my ($self, $class, $stmt) = @_;
2701 push(@{$self->{_ext_storage}->{$class}}, $stmt);
2704 sub _custom_column_info {
2705 my ( $self, $table_name, $column_name, $column_info ) = @_;
2707 if (my $code = $self->custom_column_info) {
2708 return $code->($table_name, $column_name, $column_info) || {};
2713 sub _datetime_column_info {
2714 my ( $self, $table_name, $column_name, $column_info ) = @_;
2716 my $type = $column_info->{data_type} || '';
2717 if ((grep $_, @{ $column_info }{map "inflate_$_", qw/date datetime timestamp/})
2718 or ($type =~ /date|timestamp/i)) {
2719 $result->{timezone} = $self->datetime_timezone if $self->datetime_timezone;
2720 $result->{locale} = $self->datetime_locale if $self->datetime_locale;
2726 my ($self, $name) = @_;
2728 return $self->preserve_case ? $name : lc($name);
2732 my ($self, $name) = @_;
2734 return $self->preserve_case ? $name : uc($name);
2738 my ($self, $table) = @_;
2741 my $schema = $self->schema;
2742 # in older DBIC it's a private method
2743 my $unregister = $schema->can('unregister_source') || $schema->can('_unregister_source');
2744 $schema->$unregister(delete $self->monikers->{$table->sql_name});
2745 delete $self->_upgrading_classes->{delete $self->classes->{$table->sql_name}};
2746 delete $self->_tables->{$table->sql_name};
2750 # remove the dump dir from @INC on destruction
2754 @INC = grep $_ ne $self->dump_directory, @INC;
2759 Returns a hashref of loaded table to moniker mappings. There will
2760 be two entries for each table, the original name and the "normalized"
2761 name, in the case that the two are different (such as databases
2762 that like uppercase table names, or preserve your original mixed-case
2763 definitions, or what-have-you).
2767 Returns a hashref of table to class mappings. In some cases it will
2768 contain multiple entries per table for the original and normalized table
2769 names, as above in L</monikers>.
2771 =head1 NON-ENGLISH DATABASES
2773 If you use the loader on a database with table and column names in a language
2774 other than English, you will want to turn off the English language specific
2777 To do so, use something like this in your laoder options:
2779 naming => { monikers => 'v4' },
2780 inflect_singular => sub { "$_[0]_rel" },
2781 inflect_plural => sub { "$_[0]_rel" },
2783 =head1 COLUMN ACCESSOR COLLISIONS
2785 Occasionally you may have a column name that collides with a perl method, such
2786 as C<can>. In such cases, the default action is to set the C<accessor> of the
2787 column spec to C<undef>.
2789 You can then name the accessor yourself by placing code such as the following
2792 __PACKAGE__->add_column('+can' => { accessor => 'my_can' });
2794 Another option is to use the L</col_collision_map> option.
2796 =head1 RELATIONSHIP NAME COLLISIONS
2798 In very rare cases, you may get a collision between a generated relationship
2799 name and a method in your Result class, for example if you have a foreign key
2800 called C<belongs_to>.
2802 This is a problem because relationship names are also relationship accessor
2803 methods in L<DBIx::Class>.
2805 The default behavior is to append C<_rel> to the relationship name and print
2806 out a warning that refers to this text.
2808 You can also control the renaming with the L</rel_collision_map> option.
2812 L<DBIx::Class::Schema::Loader>
2816 See L<DBIx::Class::Schema::Loader/AUTHOR> and L<DBIx::Class::Schema::Loader/CONTRIBUTORS>.
2820 This library is free software; you can redistribute it and/or modify it under
2821 the same terms as Perl itself.
2826 # vim:et sts=4 sw=4 tw=0: