remove MooseX::NonMoose from Schema files under use_moose=1
[dbsrgits/DBIx-Class-Schema-Loader.git] / lib / DBIx / Class / Schema / Loader / Base.pm
1 package DBIx::Class::Schema::Loader::Base;
2
3 use strict;
4 use warnings;
5 use base qw/Class::Accessor::Grouped Class::C3::Componentised/;
6 use mro 'c3';
7 use Carp::Clan qw/^DBIx::Class/;
8 use DBIx::Class::Schema::Loader::RelBuilder;
9 use Data::Dump qw/ dump /;
10 use POSIX qw//;
11 use File::Spec qw//;
12 use Cwd qw//;
13 use Digest::MD5 qw//;
14 use Lingua::EN::Inflect::Number qw//;
15 use Lingua::EN::Inflect::Phrase qw//;
16 use File::Temp qw//;
17 use Class::Unload;
18 use Class::Inspector ();
19 use Scalar::Util 'looks_like_number';
20 use File::Slurp 'slurp';
21 use DBIx::Class::Schema::Loader::Utils qw/split_name dumper_squashed eval_without_redefine_warnings/;
22 use DBIx::Class::Schema::Loader::Optional::Dependencies ();
23 use Try::Tiny;
24 use DBIx::Class ();
25 use namespace::clean;
26
27 our $VERSION = '0.07002';
28
29 __PACKAGE__->mk_group_ro_accessors('simple', qw/
30                                 schema
31                                 schema_class
32
33                                 exclude
34                                 constraint
35                                 additional_classes
36                                 additional_base_classes
37                                 left_base_classes
38                                 components
39                                 skip_relationships
40                                 skip_load_external
41                                 moniker_map
42                                 column_accessor_map
43                                 custom_column_info
44                                 inflect_singular
45                                 inflect_plural
46                                 debug
47                                 dump_directory
48                                 dump_overwrite
49                                 really_erase_my_files
50                                 resultset_namespace
51                                 default_resultset_class
52                                 schema_base_class
53                                 result_base_class
54                                 use_moose
55                                 overwrite_modifications
56
57                                 relationship_attrs
58
59                                 db_schema
60                                 _tables
61                                 classes
62                                 _upgrading_classes
63                                 monikers
64                                 dynamic
65                                 naming
66                                 datetime_timezone
67                                 datetime_locale
68                                 config_file
69                                 loader_class
70                                 qualify_objects
71 /);
72
73
74 __PACKAGE__->mk_group_accessors('simple', qw/
75                                 version_to_dump
76                                 schema_version_to_dump
77                                 _upgrading_from
78                                 _upgrading_from_load_classes
79                                 _downgrading_to_load_classes
80                                 _rewriting_result_namespace
81                                 use_namespaces
82                                 result_namespace
83                                 generate_pod
84                                 pod_comment_mode
85                                 pod_comment_spillover_length
86                                 preserve_case
87                                 col_collision_map
88                                 real_dump_directory
89                                 datetime_undef_if_invalid
90 /);
91
92 =head1 NAME
93
94 DBIx::Class::Schema::Loader::Base - Base DBIx::Class::Schema::Loader Implementation.
95
96 =head1 SYNOPSIS
97
98 See L<DBIx::Class::Schema::Loader>
99
100 =head1 DESCRIPTION
101
102 This is the base class for the storage-specific C<DBIx::Class::Schema::*>
103 classes, and implements the common functionality between them.
104
105 =head1 CONSTRUCTOR OPTIONS
106
107 These constructor options are the base options for
108 L<DBIx::Class::Schema::Loader/loader_options>.  Available constructor options are:
109
110 =head2 skip_relationships
111
112 Skip setting up relationships.  The default is to attempt the loading
113 of relationships.
114
115 =head2 skip_load_external
116
117 Skip loading of other classes in @INC. The default is to merge all other classes
118 with the same name found in @INC into the schema file we are creating.
119
120 =head2 naming
121
122 Static schemas (ones dumped to disk) will, by default, use the new-style
123 relationship names and singularized Results, unless you're overwriting an
124 existing dump made by an older version of L<DBIx::Class::Schema::Loader>, in
125 which case the backward compatible RelBuilder will be activated, and the
126 appropriate monikerization used.
127
128 Specifying
129
130     naming => 'current'
131
132 will disable the backward-compatible RelBuilder and use
133 the new-style relationship names along with singularized Results, even when
134 overwriting a dump made with an earlier version.
135
136 The option also takes a hashref:
137
138     naming => { relationships => 'v7', monikers => 'v7' }
139
140 The keys are:
141
142 =over 4
143
144 =item relationships
145
146 How to name relationship accessors.
147
148 =item monikers
149
150 How to name Result classes.
151
152 =item column_accessors
153
154 How to name column accessors in Result classes.
155
156 =back
157
158 The values can be:
159
160 =over 4
161
162 =item current
163
164 Latest style, whatever that happens to be.
165
166 =item v4
167
168 Unsingularlized monikers, C<has_many> only relationships with no _id stripping.
169
170 =item v5
171
172 Monikers singularized as whole words, C<might_have> relationships for FKs on
173 C<UNIQUE> constraints, C<_id> stripping for belongs_to relationships.
174
175 Some of the C<_id> stripping edge cases in C<0.05003> have been reverted for
176 the v5 RelBuilder.
177
178 =item v6
179
180 All monikers and relationships are inflected using
181 L<Lingua::EN::Inflect::Phrase>, and there is more aggressive C<_id> stripping
182 from relationship names.
183
184 In general, there is very little difference between v5 and v6 schemas.
185
186 =item v7
187
188 This mode is identical to C<v6> mode, except that monikerization of CamelCase
189 table names is also done correctly.
190
191 CamelCase column names in case-preserving mode will also be handled correctly
192 for relationship name inflection. See L</preserve_case>.
193
194 In this mode, CamelCase L</column_accessors> are normalized based on case
195 transition instead of just being lowercased, so C<FooId> becomes C<foo_id>.
196
197 If you don't have any CamelCase table or column names, you can upgrade without
198 breaking any of your code.
199
200 =back
201
202 Dynamic schemas will always default to the 0.04XXX relationship names and won't
203 singularize Results for backward compatibility, to activate the new RelBuilder
204 and singularization put this in your C<Schema.pm> file:
205
206     __PACKAGE__->naming('current');
207
208 Or if you prefer to use 0.07XXX features but insure that nothing breaks in the
209 next major version upgrade:
210
211     __PACKAGE__->naming('v7');
212
213 =head2 generate_pod
214
215 By default POD will be generated for columns and relationships, using database
216 metadata for the text if available and supported.
217
218 Reading database metadata (e.g. C<COMMENT ON TABLE some_table ...>) is only
219 supported for Postgres right now.
220
221 Set this to C<0> to turn off all POD generation.
222
223 =head2 pod_comment_mode
224
225 Controls where table comments appear in the generated POD. Smaller table
226 comments are appended to the C<NAME> section of the documentation, and larger
227 ones are inserted into C<DESCRIPTION> instead. You can force a C<DESCRIPTION>
228 section to be generated with the comment always, only use C<NAME>, or choose
229 the length threshold at which the comment is forced into the description.
230
231 =over 4
232
233 =item name
234
235 Use C<NAME> section only.
236
237 =item description
238
239 Force C<DESCRIPTION> always.
240
241 =item auto
242
243 Use C<DESCRIPTION> if length > L</pod_comment_spillover_length>, this is the
244 default.
245
246 =back
247
248 =head2 pod_comment_spillover_length
249
250 When pod_comment_mode is set to C<auto>, this is the length of the comment at
251 which it will be forced into a separate description section.
252
253 The default is C<60>
254
255 =head2 relationship_attrs
256
257 Hashref of attributes to pass to each generated relationship, listed
258 by type.  Also supports relationship type 'all', containing options to
259 pass to all generated relationships.  Attributes set for more specific
260 relationship types override those set in 'all'.
261
262 For example:
263
264   relationship_attrs => {
265     belongs_to => { is_deferrable => 0 },
266   },
267
268 use this to turn off DEFERRABLE on your foreign key constraints.
269
270 =head2 debug
271
272 If set to true, each constructive L<DBIx::Class> statement the loader
273 decides to execute will be C<warn>-ed before execution.
274
275 =head2 db_schema
276
277 Set the name of the schema to load (schema in the sense that your database
278 vendor means it).  Does not currently support loading more than one schema
279 name.
280
281 =head2 constraint
282
283 Only load tables matching regex.  Best specified as a qr// regex.
284
285 =head2 exclude
286
287 Exclude tables matching regex.  Best specified as a qr// regex.
288
289 =head2 moniker_map
290
291 Overrides the default table name to moniker translation.  Can be either
292 a hashref of table keys and moniker values, or a coderef for a translator
293 function taking a single scalar table name argument and returning
294 a scalar moniker.  If the hash entry does not exist, or the function
295 returns a false value, the code falls back to default behavior
296 for that table name.
297
298 The default behavior is to split on case transition and non-alphanumeric
299 boundaries, singularize the resulting phrase, then join the titlecased words
300 together. Examples:
301
302     Table Name       | Moniker Name
303     ---------------------------------
304     luser            | Luser
305     luser_group      | LuserGroup
306     luser-opts       | LuserOpt
307     stations_visited | StationVisited
308     routeChange      | RouteChange
309
310 =head2 column_accessor_map
311
312 Same as moniker_map, but for column accessor names.  If a coderef is
313 passed, the code is called with arguments of
314
315    the name of the column in the underlying database,
316    default accessor name that DBICSL would ordinarily give this column,
317    {
318       table_class     => name of the DBIC class we are building,
319       table_moniker   => calculated moniker for this table (after moniker_map if present),
320       table_name      => name of the database table,
321       full_table_name => schema-qualified name of the database table (RDBMS specific),
322       schema_class    => name of the schema class we are building,
323       column_info     => hashref of column info (data_type, is_nullable, etc),
324     }
325
326 =head2 inflect_plural
327
328 Just like L</moniker_map> above (can be hash/code-ref, falls back to default
329 if hash key does not exist or coderef returns false), but acts as a map
330 for pluralizing relationship names.  The default behavior is to utilize
331 L<Lingua::EN::Inflect::Phrase/to_PL>.
332
333 =head2 inflect_singular
334
335 As L</inflect_plural> above, but for singularizing relationship names.
336 Default behavior is to utilize L<Lingua::EN::Inflect::Phrase/to_S>.
337
338 =head2 schema_base_class
339
340 Base class for your schema classes. Defaults to 'DBIx::Class::Schema'.
341
342 =head2 result_base_class
343
344 Base class for your table classes (aka result classes). Defaults to
345 'DBIx::Class::Core'.
346
347 =head2 additional_base_classes
348
349 List of additional base classes all of your table classes will use.
350
351 =head2 left_base_classes
352
353 List of additional base classes all of your table classes will use
354 that need to be leftmost.
355
356 =head2 additional_classes
357
358 List of additional classes which all of your table classes will use.
359
360 =head2 components
361
362 List of additional components to be loaded into all of your table
363 classes.  A good example would be
364 L<InflateColumn::DateTime|DBIx::Class::InflateColumn::DateTime>
365
366 =head2 use_namespaces
367
368 This is now the default, to go back to L<DBIx::Class::Schema/load_classes> pass
369 a C<0>.
370
371 Generate result class names suitable for
372 L<DBIx::Class::Schema/load_namespaces> and call that instead of
373 L<DBIx::Class::Schema/load_classes>. When using this option you can also
374 specify any of the options for C<load_namespaces> (i.e. C<result_namespace>,
375 C<resultset_namespace>, C<default_resultset_class>), and they will be added
376 to the call (and the generated result class names adjusted appropriately).
377
378 =head2 dump_directory
379
380 The value of this option is a perl libdir pathname.  Within
381 that directory this module will create a baseline manual
382 L<DBIx::Class::Schema> module set, based on what it creates at runtime.
383
384 The created schema class will have the same classname as the one on
385 which you are setting this option (and the ResultSource classes will be
386 based on this name as well).
387
388 Normally you wouldn't hard-code this setting in your schema class, as it
389 is meant for one-time manual usage.
390
391 See L<DBIx::Class::Schema::Loader/dump_to_dir> for examples of the
392 recommended way to access this functionality.
393
394 =head2 dump_overwrite
395
396 Deprecated.  See L</really_erase_my_files> below, which does *not* mean
397 the same thing as the old C<dump_overwrite> setting from previous releases.
398
399 =head2 really_erase_my_files
400
401 Default false.  If true, Loader will unconditionally delete any existing
402 files before creating the new ones from scratch when dumping a schema to disk.
403
404 The default behavior is instead to only replace the top portion of the
405 file, up to and including the final stanza which contains
406 C<# DO NOT MODIFY THE FIRST PART OF THIS FILE>
407 leaving any customizations you placed after that as they were.
408
409 When C<really_erase_my_files> is not set, if the output file already exists,
410 but the aforementioned final stanza is not found, or the checksum
411 contained there does not match the generated contents, Loader will
412 croak and not touch the file.
413
414 You should really be using version control on your schema classes (and all
415 of the rest of your code for that matter).  Don't blame me if a bug in this
416 code wipes something out when it shouldn't have, you've been warned.
417
418 =head2 overwrite_modifications
419
420 Default false.  If false, when updating existing files, Loader will
421 refuse to modify any Loader-generated code that has been modified
422 since its last run (as determined by the checksum Loader put in its
423 comment lines).
424
425 If true, Loader will discard any manual modifications that have been
426 made to Loader-generated code.
427
428 Again, you should be using version control on your schema classes.  Be
429 careful with this option.
430
431 =head2 custom_column_info
432
433 Hook for adding extra attributes to the
434 L<column_info|DBIx::Class::ResultSource/column_info> for a column.
435
436 Must be a coderef that returns a hashref with the extra attributes.
437
438 Receives the table name, column name and column_info.
439
440 For example:
441
442   custom_column_info => sub {
443       my ($table_name, $column_name, $column_info) = @_;
444
445       if ($column_name eq 'dog' && $column_info->{default_value} eq 'snoopy') {
446           return { is_snoopy => 1 };
447       }
448   },
449
450 This attribute can also be used to set C<inflate_datetime> on a non-datetime
451 column so it also receives the L</datetime_timezone> and/or L</datetime_locale>.
452
453 =head2 datetime_timezone
454
455 Sets the timezone attribute for L<DBIx::Class::InflateColumn::DateTime> for all
456 columns with the DATE/DATETIME/TIMESTAMP data_types.
457
458 =head2 datetime_locale
459
460 Sets the locale attribute for L<DBIx::Class::InflateColumn::DateTime> for all
461 columns with the DATE/DATETIME/TIMESTAMP data_types.
462
463 =head2 datetime_undef_if_invalid
464
465 Pass a C<0> for this option when using MySQL if you B<DON'T> want C<<
466 datetime_undef_if_invalid => 1 >> in your column info for DATE, DATETIME and
467 TIMESTAMP columns.
468
469 The default is recommended to deal with data such as C<00/00/00> which
470 sometimes ends up in such columns in MySQL.
471
472 =head2 config_file
473
474 File in Perl format, which should return a HASH reference, from which to read
475 loader options.
476
477 =head2 preserve_case
478
479 Usually column names are lowercased, to make them easier to work with in
480 L<DBIx::Class>. This option lets you turn this behavior off, if the driver
481 supports it.
482
483 Drivers for case sensitive databases like Sybase ASE or MSSQL with a
484 case-sensitive collation will turn this option on unconditionally.
485
486 Currently the drivers for SQLite, mysql, MSSQL and Firebird/InterBase support
487 setting this option.
488
489 =head2 qualify_objects
490
491 Set to true to prepend the L</db_schema> to table names for C<<
492 __PACKAGE__->table >> calls, and to some other things like Oracle sequences.
493
494 =head2 use_moose
495
496 Creates Schema and Result classes that use L<Moose>, L<MooseX::NonMoose> and
497 L<namespace::autoclean>. The default content after the md5 sum also makes the
498 classes immutable.
499
500 It is safe to upgrade your existing Schema to this option.
501
502 =head2 col_collision_map
503
504 This option controls how accessors for column names which collide with perl
505 methods are named. See L</COLUMN ACCESSOR COLLISIONS> for more information.
506
507 This option takes either a single L<sprintf|perlfunc/sprintf> format or a hashref of
508 strings which are compiled to regular expressions that map to
509 L<sprintf|perlfunc/sprintf> formats.
510
511 Examples:
512
513     col_collision_map => 'column_%s'
514
515     col_collision_map => { '(.*)' => 'column_%s' }
516
517     col_collision_map => { '(foo).*(bar)' => 'column_%s_%s' }
518
519 =head1 METHODS
520
521 None of these methods are intended for direct invocation by regular
522 users of L<DBIx::Class::Schema::Loader>. Some are proxied via
523 L<DBIx::Class::Schema::Loader>.
524
525 =cut
526
527 my $CURRENT_V = 'v7';
528
529 my @CLASS_ARGS = qw(
530     schema_base_class result_base_class additional_base_classes
531     left_base_classes additional_classes components
532 );
533
534 # ensure that a peice of object data is a valid arrayref, creating
535 # an empty one or encapsulating whatever's there.
536 sub _ensure_arrayref {
537     my $self = shift;
538
539     foreach (@_) {
540         $self->{$_} ||= [];
541         $self->{$_} = [ $self->{$_} ]
542             unless ref $self->{$_} eq 'ARRAY';
543     }
544 }
545
546 =head2 new
547
548 Constructor for L<DBIx::Class::Schema::Loader::Base>, used internally
549 by L<DBIx::Class::Schema::Loader>.
550
551 =cut
552
553 sub new {
554     my ( $class, %args ) = @_;
555
556     my $self = { %args };
557
558     # don't lose undef options
559     for (values %$self) {
560         $_ = 0 unless defined $_;
561     }
562
563     bless $self => $class;
564
565     if (my $config_file = $self->config_file) {
566         my $config_opts = do $config_file;
567
568         croak "Error reading config from $config_file: $@" if $@;
569
570         croak "Config file $config_file must be a hashref" unless ref($config_opts) eq 'HASH';
571
572         while (my ($k, $v) = each %$config_opts) {
573             $self->{$k} = $v unless exists $self->{$k};
574         }
575     }
576
577     $self->_ensure_arrayref(qw/additional_classes
578                                additional_base_classes
579                                left_base_classes
580                                components
581                               /);
582
583     $self->_validate_class_args;
584
585     if ($self->use_moose) {
586         if (not DBIx::Class::Schema::Loader::Optional::Dependencies->req_ok_for('use_moose')) {
587             die sprintf "You must install the following CPAN modules to enable the use_moose option: %s.\n",
588                 DBIx::Class::Schema::Loader::Optional::Dependencies->req_missing_for('use_moose');
589         }
590     }
591
592     $self->{monikers} = {};
593     $self->{classes} = {};
594     $self->{_upgrading_classes} = {};
595
596     $self->{schema_class} ||= ( ref $self->{schema} || $self->{schema} );
597     $self->{schema} ||= $self->{schema_class};
598
599     croak "dump_overwrite is deprecated.  Please read the"
600         . " DBIx::Class::Schema::Loader::Base documentation"
601             if $self->{dump_overwrite};
602
603     $self->{dynamic} = ! $self->{dump_directory};
604     $self->{temp_directory} ||= File::Temp::tempdir( 'dbicXXXX',
605                                                      TMPDIR  => 1,
606                                                      CLEANUP => 1,
607                                                    );
608
609     $self->{dump_directory} ||= $self->{temp_directory};
610
611     $self->real_dump_directory($self->{dump_directory});
612
613     $self->version_to_dump($DBIx::Class::Schema::Loader::VERSION);
614     $self->schema_version_to_dump($DBIx::Class::Schema::Loader::VERSION);
615
616     if ((not ref $self->naming) && defined $self->naming) {
617         my $naming_ver = $self->naming;
618         $self->{naming} = {
619             relationships => $naming_ver,
620             monikers => $naming_ver,
621             column_accessors => $naming_ver,
622         };
623     }
624
625     if ($self->naming) {
626         for (values %{ $self->naming }) {
627             $_ = $CURRENT_V if $_ eq 'current';
628         }
629     }
630     $self->{naming} ||= {};
631
632     if ($self->custom_column_info && ref $self->custom_column_info ne 'CODE') {
633         croak 'custom_column_info must be a CODE ref';
634     }
635
636     $self->_check_back_compat;
637
638     $self->use_namespaces(1) unless defined $self->use_namespaces;
639     $self->generate_pod(1)   unless defined $self->generate_pod;
640     $self->pod_comment_mode('auto')         unless defined $self->pod_comment_mode;
641     $self->pod_comment_spillover_length(60) unless defined $self->pod_comment_spillover_length;
642
643     if (my $col_collision_map = $self->col_collision_map) {
644         if (my $reftype = ref $col_collision_map) {
645             if ($reftype ne 'HASH') {
646                 croak "Invalid type $reftype for option 'col_collision_map'";
647             }
648         }
649         else {
650             $self->col_collision_map({ '(.*)' => $col_collision_map });
651         }
652     }
653
654     $self;
655 }
656
657 sub _check_back_compat {
658     my ($self) = @_;
659
660 # dynamic schemas will always be in 0.04006 mode, unless overridden
661     if ($self->dynamic) {
662 # just in case, though no one is likely to dump a dynamic schema
663         $self->schema_version_to_dump('0.04006');
664
665         if (not %{ $self->naming }) {
666             warn <<EOF unless $ENV{SCHEMA_LOADER_BACKCOMPAT};
667
668 Dynamic schema detected, will run in 0.04006 mode.
669
670 Set the 'naming' attribute or the SCHEMA_LOADER_BACKCOMPAT environment variable
671 to disable this warning.
672
673 Also consider setting 'use_namespaces => 1' if/when upgrading.
674
675 See perldoc DBIx::Class::Schema::Loader::Manual::UpgradingFromV4 for more
676 details.
677 EOF
678         }
679         else {
680             $self->_upgrading_from('v4');
681         }
682
683         $self->naming->{relationships} ||= 'v4';
684         $self->naming->{monikers}      ||= 'v4';
685
686         if ($self->use_namespaces) {
687             $self->_upgrading_from_load_classes(1);
688         }
689         else {
690             $self->use_namespaces(0);
691         }
692
693         return;
694     }
695
696 # otherwise check if we need backcompat mode for a static schema
697     my $filename = $self->_get_dump_filename($self->schema_class);
698     return unless -e $filename;
699
700     my ($old_gen, $old_md5, $old_ver, $old_ts, $old_custom) =
701       $self->_parse_generated_file($filename);
702
703     return unless $old_ver;
704
705     # determine if the existing schema was dumped with use_moose => 1
706     if (! defined $self->use_moose) {
707         $self->{use_moose} = 1 if $old_gen =~ /^ (?!\s*\#) use \s+ Moose/xm;
708     }
709
710     my $load_classes = ($old_gen =~ /^__PACKAGE__->load_classes;/m) ? 1 : 0;
711     my $result_namespace = do { ($old_gen =~ /result_namespace => '([^']+)'/) ? $1 : '' };
712
713     if ($load_classes && (not defined $self->use_namespaces)) {
714         warn <<"EOF"  unless $ENV{SCHEMA_LOADER_BACKCOMPAT};
715
716 'load_classes;' static schema detected, turning off 'use_namespaces'.
717
718 Set the 'use_namespaces' attribute or the SCHEMA_LOADER_BACKCOMPAT environment
719 variable to disable this warning.
720
721 See perldoc DBIx::Class::Schema::Loader::Manual::UpgradingFromV4 for more
722 details.
723 EOF
724         $self->use_namespaces(0);
725     }
726     elsif ($load_classes && $self->use_namespaces) {
727         $self->_upgrading_from_load_classes(1);
728     }
729     elsif ((not $load_classes) && defined $self->use_namespaces && ! $self->use_namespaces) {
730         $self->_downgrading_to_load_classes(
731             $result_namespace || 'Result'
732         );
733     }
734     elsif ((not defined $self->use_namespaces) || $self->use_namespaces) {
735         if (not $self->result_namespace) {
736             $self->result_namespace($result_namespace || 'Result');
737         }
738         elsif ($result_namespace ne $self->result_namespace) {
739             $self->_rewriting_result_namespace(
740                 $result_namespace || 'Result'
741             );
742         }
743     }
744
745     # XXX when we go past .0 this will need fixing
746     my ($v) = $old_ver =~ /([1-9])/;
747     $v = "v$v";
748
749     return if ($v eq $CURRENT_V || $old_ver =~ /^0\.\d\d999/);
750
751     if (not %{ $self->naming }) {
752         warn <<"EOF" unless $ENV{SCHEMA_LOADER_BACKCOMPAT};
753
754 Version $old_ver static schema detected, turning on backcompat mode.
755
756 Set the 'naming' attribute or the SCHEMA_LOADER_BACKCOMPAT environment variable
757 to disable this warning.
758
759 See: 'naming' in perldoc DBIx::Class::Schema::Loader::Base .
760
761 See perldoc DBIx::Class::Schema::Loader::Manual::UpgradingFromV4 if upgrading
762 from version 0.04006.
763 EOF
764
765         $self->naming->{relationships}    ||= $v;
766         $self->naming->{monikers}         ||= $v;
767         $self->naming->{column_accessors} ||= $v;
768
769         $self->schema_version_to_dump($old_ver);
770     }
771     else {
772         $self->_upgrading_from($v);
773     }
774 }
775
776 sub _validate_class_args {
777     my $self = shift;
778     my $args = shift;
779
780     foreach my $k (@CLASS_ARGS) {
781         next unless $self->$k;
782
783         my @classes = ref $self->$k eq 'ARRAY' ? @{ $self->$k } : $self->$k;
784         foreach my $c (@classes) {
785             # components default to being under the DBIx::Class namespace unless they
786             # are preceeded with a '+'
787             if ( $k =~ m/components$/ && $c !~ s/^\+// ) {
788                 $c = 'DBIx::Class::' . $c;
789             }
790
791             # 1 == installed, 0 == not installed, undef == invalid classname
792             my $installed = Class::Inspector->installed($c);
793             if ( defined($installed) ) {
794                 if ( $installed == 0 ) {
795                     croak qq/$c, as specified in the loader option "$k", is not installed/;
796                 }
797             } else {
798                 croak qq/$c, as specified in the loader option "$k", is an invalid class name/;
799             }
800         }
801     }
802 }
803
804 sub _find_file_in_inc {
805     my ($self, $file) = @_;
806
807     foreach my $prefix (@INC) {
808         my $fullpath = File::Spec->catfile($prefix, $file);
809         return $fullpath if -f $fullpath
810             # abs_path throws on Windows for nonexistant files
811             and (try { Cwd::abs_path($fullpath) }) ne
812                ((try { Cwd::abs_path(File::Spec->catfile($self->dump_directory, $file)) }) || '');
813     }
814
815     return;
816 }
817
818 sub _class_path {
819     my ($self, $class) = @_;
820
821     my $class_path = $class;
822     $class_path =~ s{::}{/}g;
823     $class_path .= '.pm';
824
825     return $class_path;
826 }
827
828 sub _find_class_in_inc {
829     my ($self, $class) = @_;
830
831     return $self->_find_file_in_inc($self->_class_path($class));
832 }
833
834 sub _rewriting {
835     my $self = shift;
836
837     return $self->_upgrading_from
838         || $self->_upgrading_from_load_classes
839         || $self->_downgrading_to_load_classes
840         || $self->_rewriting_result_namespace
841     ;
842 }
843
844 sub _rewrite_old_classnames {
845     my ($self, $code) = @_;
846
847     return $code unless $self->_rewriting;
848
849     my %old_classes = reverse %{ $self->_upgrading_classes };
850
851     my $re = join '|', keys %old_classes;
852     $re = qr/\b($re)\b/;
853
854     $code =~ s/$re/$old_classes{$1} || $1/eg;
855
856     return $code;
857 }
858
859 sub _load_external {
860     my ($self, $class) = @_;
861
862     return if $self->{skip_load_external};
863
864     # so that we don't load our own classes, under any circumstances
865     local *INC = [ grep $_ ne $self->dump_directory, @INC ];
866
867     my $real_inc_path = $self->_find_class_in_inc($class);
868
869     my $old_class = $self->_upgrading_classes->{$class}
870         if $self->_rewriting;
871
872     my $old_real_inc_path = $self->_find_class_in_inc($old_class)
873         if $old_class && $old_class ne $class;
874
875     return unless $real_inc_path || $old_real_inc_path;
876
877     if ($real_inc_path) {
878         # If we make it to here, we loaded an external definition
879         warn qq/# Loaded external class definition for '$class'\n/
880             if $self->debug;
881
882         my $code = $self->_rewrite_old_classnames(scalar slurp $real_inc_path);
883
884         if ($self->dynamic) { # load the class too
885             eval_without_redefine_warnings($code);
886         }
887
888         $self->_ext_stmt($class,
889           qq|# These lines were loaded from '$real_inc_path' found in \@INC.\n|
890          .qq|# They are now part of the custom portion of this file\n|
891          .qq|# for you to hand-edit.  If you do not either delete\n|
892          .qq|# this section or remove that file from \@INC, this section\n|
893          .qq|# will be repeated redundantly when you re-create this\n|
894          .qq|# file again via Loader!  See skip_load_external to disable\n|
895          .qq|# this feature.\n|
896         );
897         chomp $code;
898         $self->_ext_stmt($class, $code);
899         $self->_ext_stmt($class,
900             qq|# End of lines loaded from '$real_inc_path' |
901         );
902     }
903
904     if ($old_real_inc_path) {
905         my $code = slurp $old_real_inc_path;
906
907         $self->_ext_stmt($class, <<"EOF");
908
909 # These lines were loaded from '$old_real_inc_path',
910 # based on the Result class name that would have been created by an older
911 # version of the Loader. For a static schema, this happens only once during
912 # upgrade. See skip_load_external to disable this feature.
913 EOF
914
915         $code = $self->_rewrite_old_classnames($code);
916
917         if ($self->dynamic) {
918             warn <<"EOF";
919
920 Detected external content in '$old_real_inc_path', a class name that would have
921 been used by an older version of the Loader.
922
923 * PLEASE RENAME THIS CLASS: from '$old_class' to '$class', as that is the
924 new name of the Result.
925 EOF
926             eval_without_redefine_warnings($code);
927         }
928
929         chomp $code;
930         $self->_ext_stmt($class, $code);
931         $self->_ext_stmt($class,
932             qq|# End of lines loaded from '$old_real_inc_path' |
933         );
934     }
935 }
936
937 =head2 load
938
939 Does the actual schema-construction work.
940
941 =cut
942
943 sub load {
944     my $self = shift;
945
946     $self->_load_tables(
947         $self->_tables_list({ constraint => $self->constraint, exclude => $self->exclude })
948     );
949 }
950
951 =head2 rescan
952
953 Arguments: schema
954
955 Rescan the database for changes. Returns a list of the newly added table
956 monikers.
957
958 The schema argument should be the schema class or object to be affected.  It
959 should probably be derived from the original schema_class used during L</load>.
960
961 =cut
962
963 sub rescan {
964     my ($self, $schema) = @_;
965
966     $self->{schema} = $schema;
967     $self->_relbuilder->{schema} = $schema;
968
969     my @created;
970     my @current = $self->_tables_list({ constraint => $self->constraint, exclude => $self->exclude });
971
972     foreach my $table (@current) {
973         if(!exists $self->{_tables}->{$table}) {
974             push(@created, $table);
975         }
976     }
977
978     my %current;
979     @current{@current} = ();
980     foreach my $table (keys %{ $self->{_tables} }) {
981         if (not exists $current{$table}) {
982             $self->_unregister_source_for_table($table);
983         }
984     }
985
986     delete $self->{_dump_storage};
987     delete $self->{_relations_started};
988
989     my $loaded = $self->_load_tables(@current);
990
991     return map { $self->monikers->{$_} } @created;
992 }
993
994 sub _relbuilder {
995     my ($self) = @_;
996
997     return if $self->{skip_relationships};
998
999     return $self->{relbuilder} ||= do {
1000
1001         no warnings 'uninitialized';
1002         my $relbuilder_suff =
1003             {qw{
1004                 v4  ::Compat::v0_040
1005                 v5  ::Compat::v0_05
1006                 v6  ::Compat::v0_06
1007             }}
1008             ->{ $self->naming->{relationships}};
1009
1010         my $relbuilder_class = 'DBIx::Class::Schema::Loader::RelBuilder'.$relbuilder_suff;
1011         eval "require $relbuilder_class"; die $@ if $@;
1012         $relbuilder_class->new( $self );
1013
1014     };
1015 }
1016
1017 sub _load_tables {
1018     my ($self, @tables) = @_;
1019
1020     # Save the new tables to the tables list
1021     foreach (@tables) {
1022         $self->{_tables}->{$_} = 1;
1023     }
1024
1025     $self->_make_src_class($_) for @tables;
1026
1027     # sanity-check for moniker clashes
1028     my $inverse_moniker_idx;
1029     for (keys %{$self->monikers}) {
1030       push @{$inverse_moniker_idx->{$self->monikers->{$_}}}, $_;
1031     }
1032
1033     my @clashes;
1034     for (keys %$inverse_moniker_idx) {
1035       my $tables = $inverse_moniker_idx->{$_};
1036       if (@$tables > 1) {
1037         push @clashes, sprintf ("tables %s reduced to the same source moniker '%s'",
1038           join (', ', map { "'$_'" } @$tables),
1039           $_,
1040         );
1041       }
1042     }
1043
1044     if (@clashes) {
1045       die   'Unable to load schema - chosen moniker/class naming style results in moniker clashes. '
1046           . 'Either change the naming style, or supply an explicit moniker_map: '
1047           . join ('; ', @clashes)
1048           . "\n"
1049       ;
1050     }
1051
1052
1053     $self->_setup_src_meta($_) for @tables;
1054
1055     if(!$self->skip_relationships) {
1056         # The relationship loader needs a working schema
1057         $self->{quiet} = 1;
1058         local $self->{dump_directory} = $self->{temp_directory};
1059         $self->_reload_classes(\@tables);
1060         $self->_load_relationships($_) for @tables;
1061         $self->_relbuilder->cleanup;
1062         $self->{quiet} = 0;
1063
1064         # Remove that temp dir from INC so it doesn't get reloaded
1065         @INC = grep $_ ne $self->dump_directory, @INC;
1066     }
1067
1068     $self->_load_external($_)
1069         for map { $self->classes->{$_} } @tables;
1070
1071     # Reload without unloading first to preserve any symbols from external
1072     # packages.
1073     $self->_reload_classes(\@tables, { unload => 0 });
1074
1075     # Drop temporary cache
1076     delete $self->{_cache};
1077
1078     return \@tables;
1079 }
1080
1081 sub _reload_classes {
1082     my ($self, $tables, $opts) = @_;
1083
1084     my @tables = @$tables;
1085
1086     my $unload = $opts->{unload};
1087     $unload = 1 unless defined $unload;
1088
1089     # so that we don't repeat custom sections
1090     @INC = grep $_ ne $self->dump_directory, @INC;
1091
1092     $self->_dump_to_dir(map { $self->classes->{$_} } @tables);
1093
1094     unshift @INC, $self->dump_directory;
1095     
1096     my @to_register;
1097     my %have_source = map { $_ => $self->schema->source($_) }
1098         $self->schema->sources;
1099
1100     for my $table (@tables) {
1101         my $moniker = $self->monikers->{$table};
1102         my $class = $self->classes->{$table};
1103         
1104         {
1105             no warnings 'redefine';
1106             local *Class::C3::reinitialize = sub {};  # to speed things up, reinitialized below
1107             use warnings;
1108
1109             if (my $mc = $self->_moose_metaclass($class)) {
1110                 $mc->make_mutable;
1111             }
1112             Class::Unload->unload($class) if $unload;
1113             my ($source, $resultset_class);
1114             if (
1115                 ($source = $have_source{$moniker})
1116                 && ($resultset_class = $source->resultset_class)
1117                 && ($resultset_class ne 'DBIx::Class::ResultSet')
1118             ) {
1119                 my $has_file = Class::Inspector->loaded_filename($resultset_class);
1120                 if (my $mc = $self->_moose_metaclass($resultset_class)) {
1121                     $mc->make_mutable;
1122                 }
1123                 Class::Unload->unload($resultset_class) if $unload;
1124                 $self->_reload_class($resultset_class) if $has_file;
1125             }
1126             $self->_reload_class($class);
1127         }
1128         push @to_register, [$moniker, $class];
1129     }
1130
1131     Class::C3->reinitialize;
1132     for (@to_register) {
1133         $self->schema->register_class(@$_);
1134     }
1135 }
1136
1137 sub _moose_metaclass {
1138   return undef unless $INC{'Class/MOP.pm'};   # if CMOP is not loaded the class could not have loaded in the 1st place
1139
1140   my $class = $_[1];
1141
1142   my $mc = try { Class::MOP::class_of($class) }
1143     or return undef;
1144
1145   return $mc->isa('Moose::Meta::Class') ? $mc : undef;
1146 }
1147
1148 # We use this instead of ensure_class_loaded when there are package symbols we
1149 # want to preserve.
1150 sub _reload_class {
1151     my ($self, $class) = @_;
1152
1153     my $class_path = $self->_class_path($class);
1154     delete $INC{ $class_path };
1155
1156 # kill redefined warnings
1157     try {
1158         eval_without_redefine_warnings ("require $class");
1159     }
1160     catch {
1161         my $source = slurp $self->_get_dump_filename($class);
1162         die "Failed to reload class $class: $_.\n\nCLASS SOURCE:\n\n$source";
1163     };
1164 }
1165
1166 sub _get_dump_filename {
1167     my ($self, $class) = (@_);
1168
1169     $class =~ s{::}{/}g;
1170     return $self->dump_directory . q{/} . $class . q{.pm};
1171 }
1172
1173 =head2 get_dump_filename
1174
1175 Arguments: class
1176
1177 Returns the full path to the file for a class that the class has been or will
1178 be dumped to. This is a file in a temp dir for a dynamic schema.
1179
1180 =cut
1181
1182 sub get_dump_filename {
1183     my ($self, $class) = (@_);
1184
1185     local $self->{dump_directory} = $self->real_dump_directory;
1186
1187     return $self->_get_dump_filename($class);
1188 }
1189
1190 sub _ensure_dump_subdirs {
1191     my ($self, $class) = (@_);
1192
1193     my @name_parts = split(/::/, $class);
1194     pop @name_parts; # we don't care about the very last element,
1195                      # which is a filename
1196
1197     my $dir = $self->dump_directory;
1198     while (1) {
1199         if(!-d $dir) {
1200             mkdir($dir) or croak "mkdir('$dir') failed: $!";
1201         }
1202         last if !@name_parts;
1203         $dir = File::Spec->catdir($dir, shift @name_parts);
1204     }
1205 }
1206
1207 sub _dump_to_dir {
1208     my ($self, @classes) = @_;
1209
1210     my $schema_class = $self->schema_class;
1211     my $schema_base_class = $self->schema_base_class || 'DBIx::Class::Schema';
1212
1213     my $target_dir = $self->dump_directory;
1214     warn "Dumping manual schema for $schema_class to directory $target_dir ...\n"
1215         unless $self->{dynamic} or $self->{quiet};
1216
1217     my $schema_text =
1218           qq|package $schema_class;\n\n|
1219         . qq|# Created by DBIx::Class::Schema::Loader\n|
1220         . qq|# DO NOT MODIFY THE FIRST PART OF THIS FILE\n\n|;
1221
1222     if ($self->use_moose) {
1223         $schema_text.= qq|use Moose;\nuse namespace::autoclean;\nextends '$schema_base_class';\n\n|;
1224     }
1225     else {
1226         $schema_text .= qq|use strict;\nuse warnings;\n\nuse base '$schema_base_class';\n\n|;
1227     }
1228
1229     if ($self->use_namespaces) {
1230         $schema_text .= qq|__PACKAGE__->load_namespaces|;
1231         my $namespace_options;
1232
1233         my @attr = qw/resultset_namespace default_resultset_class/;
1234
1235         unshift @attr, 'result_namespace' unless (not $self->result_namespace) || $self->result_namespace eq 'Result';
1236
1237         for my $attr (@attr) {
1238             if ($self->$attr) {
1239                 $namespace_options .= qq|    $attr => '| . $self->$attr . qq|',\n|
1240             }
1241         }
1242         $schema_text .= qq|(\n$namespace_options)| if $namespace_options;
1243         $schema_text .= qq|;\n|;
1244     }
1245     else {
1246         $schema_text .= qq|__PACKAGE__->load_classes;\n|;
1247     }
1248
1249     {
1250         local $self->{version_to_dump} = $self->schema_version_to_dump;
1251         $self->_write_classfile($schema_class, $schema_text, 1);
1252     }
1253
1254     my $result_base_class = $self->result_base_class || 'DBIx::Class::Core';
1255
1256     foreach my $src_class (@classes) {
1257         my $src_text = 
1258               qq|package $src_class;\n\n|
1259             . qq|# Created by DBIx::Class::Schema::Loader\n|
1260             . qq|# DO NOT MODIFY THE FIRST PART OF THIS FILE\n\n|
1261             . qq|use strict;\nuse warnings;\n\n|;
1262         if ($self->use_moose) {
1263             $src_text.= qq|use Moose;\nuse MooseX::NonMoose;\nuse namespace::autoclean;|;
1264
1265             # these options 'use base' which is compile time
1266             if (@{ $self->left_base_classes } || @{ $self->additional_base_classes }) {
1267                 $src_text .= qq|\nBEGIN { extends '$result_base_class' }\n\n|;
1268             }
1269             else {
1270                 $src_text .= qq|\nextends '$result_base_class';\n\n|;
1271             }
1272         }
1273         else {
1274              $src_text .= qq|use base '$result_base_class';\n\n|;
1275         }
1276         $self->_write_classfile($src_class, $src_text);
1277     }
1278
1279     # remove Result dir if downgrading from use_namespaces, and there are no
1280     # files left.
1281     if (my $result_ns = $self->_downgrading_to_load_classes
1282                         || $self->_rewriting_result_namespace) {
1283         my $result_namespace = $self->_result_namespace(
1284             $schema_class,
1285             $result_ns,
1286         );
1287
1288         (my $result_dir = $result_namespace) =~ s{::}{/}g;
1289         $result_dir = $self->dump_directory . '/' . $result_dir;
1290
1291         unless (my @files = glob "$result_dir/*") {
1292             rmdir $result_dir;
1293         }
1294     }
1295
1296     warn "Schema dump completed.\n" unless $self->{dynamic} or $self->{quiet};
1297
1298 }
1299
1300 sub _sig_comment {
1301     my ($self, $version, $ts) = @_;
1302     return qq|\n\n# Created by DBIx::Class::Schema::Loader|
1303          . qq| v| . $version
1304          . q| @ | . $ts 
1305          . qq|\n# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:|;
1306 }
1307
1308 sub _write_classfile {
1309     my ($self, $class, $text, $is_schema) = @_;
1310
1311     my $filename = $self->_get_dump_filename($class);
1312     $self->_ensure_dump_subdirs($class);
1313
1314     if (-f $filename && $self->really_erase_my_files) {
1315         warn "Deleting existing file '$filename' due to "
1316             . "'really_erase_my_files' setting\n" unless $self->{quiet};
1317         unlink($filename);
1318     }
1319
1320     my ($old_gen, $old_md5, $old_ver, $old_ts, $old_custom)
1321         = $self->_parse_generated_file($filename);
1322
1323     if (! $old_gen && -f $filename) {
1324         croak "Cannot overwrite '$filename' without 'really_erase_my_files',"
1325             . " it does not appear to have been generated by Loader"
1326     }
1327
1328     my $custom_content = $old_custom || '';
1329
1330     # prepend extra custom content from a *renamed* class (singularization effect)
1331     if (my $renamed_class = $self->_upgrading_classes->{$class}) {
1332         my $old_filename = $self->_get_dump_filename($renamed_class);
1333
1334         if (-f $old_filename) {
1335             my $extra_custom = ($self->_parse_generated_file ($old_filename))[4];
1336
1337             $extra_custom =~ s/\n\n# You can replace.*\n1;\n//;
1338
1339             $custom_content = join ("\n", '', $extra_custom, $custom_content)
1340                 if $extra_custom;
1341
1342             unlink $old_filename;
1343         }
1344     }
1345
1346     $custom_content ||= $self->_default_custom_content($is_schema);
1347
1348     # If upgrading to use_moose=1 replace default custom content with default Moose custom content.
1349     # If there is already custom content, which does not have the Moose content, add it.
1350     if ($self->use_moose) {
1351
1352         my $non_moose_custom_content = do {
1353             local $self->{use_moose} = 0;
1354             $self->_default_custom_content;
1355         };
1356
1357         if ($custom_content eq $non_moose_custom_content) {
1358             $custom_content = $self->_default_custom_content($is_schema);
1359         }
1360         elsif ($custom_content !~ /\Q@{[$self->_default_moose_custom_content($is_schema)]}\E/) {
1361             $custom_content .= $self->_default_custom_content($is_schema);
1362         }
1363     }
1364     elsif (defined $self->use_moose && $old_gen) {
1365         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'
1366             if $old_gen =~ /use \s+ MooseX?\b/x;
1367     }
1368
1369     $custom_content = $self->_rewrite_old_classnames($custom_content);
1370
1371     $text .= qq|$_\n|
1372         for @{$self->{_dump_storage}->{$class} || []};
1373
1374     # Check and see if the dump is infact differnt
1375
1376     my $compare_to;
1377     if ($old_md5) {
1378       $compare_to = $text . $self->_sig_comment($old_ver, $old_ts);
1379       if (Digest::MD5::md5_base64($compare_to) eq $old_md5) {
1380         return unless $self->_upgrading_from && $is_schema;
1381       }
1382     }
1383
1384     $text .= $self->_sig_comment(
1385       $self->version_to_dump,
1386       POSIX::strftime('%Y-%m-%d %H:%M:%S', localtime)
1387     );
1388
1389     open(my $fh, '>', $filename)
1390         or croak "Cannot open '$filename' for writing: $!";
1391
1392     # Write the top half and its MD5 sum
1393     print $fh $text . Digest::MD5::md5_base64($text) . "\n";
1394
1395     # Write out anything loaded via external partial class file in @INC
1396     print $fh qq|$_\n|
1397         for @{$self->{_ext_storage}->{$class} || []};
1398
1399     # Write out any custom content the user has added
1400     print $fh $custom_content;
1401
1402     close($fh)
1403         or croak "Error closing '$filename': $!";
1404 }
1405
1406 sub _default_moose_custom_content {
1407     my ($self, $is_schema) = @_;
1408
1409     if (not $is_schema) {
1410         return qq|\n__PACKAGE__->meta->make_immutable;|;
1411     }
1412     
1413     return qq|\n__PACKAGE__->meta->make_immutable(inline_constructor => 0);|;
1414 }
1415
1416 sub _default_custom_content {
1417     my ($self, $is_schema) = @_;
1418     my $default = qq|\n\n# You can replace this text with custom|
1419          . qq| code or comments, and it will be preserved on regeneration|;
1420     if ($self->use_moose) {
1421         $default .= $self->_default_moose_custom_content($is_schema);
1422     }
1423     $default .= qq|\n1;\n|;
1424     return $default;
1425 }
1426
1427 sub _parse_generated_file {
1428     my ($self, $fn) = @_;
1429
1430     return unless -f $fn;
1431
1432     open(my $fh, '<', $fn)
1433         or croak "Cannot open '$fn' for reading: $!";
1434
1435     my $mark_re =
1436         qr{^(# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:)([A-Za-z0-9/+]{22})\n};
1437
1438     my ($md5, $ts, $ver, $gen);
1439     while(<$fh>) {
1440         if(/$mark_re/) {
1441             my $pre_md5 = $1;
1442             $md5 = $2;
1443
1444             # Pull out the version and timestamp from the line above
1445             ($ver, $ts) = $gen =~ m/^# Created by DBIx::Class::Schema::Loader v(.*?) @ (.*?)\Z/m;
1446
1447             $gen .= $pre_md5;
1448             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"
1449                 if !$self->overwrite_modifications && Digest::MD5::md5_base64($gen) ne $md5;
1450
1451             last;
1452         }
1453         else {
1454             $gen .= $_;
1455         }
1456     }
1457
1458     my $custom = do { local $/; <$fh> }
1459         if $md5;
1460
1461     close ($fh);
1462
1463     return ($gen, $md5, $ver, $ts, $custom);
1464 }
1465
1466 sub _use {
1467     my $self = shift;
1468     my $target = shift;
1469
1470     foreach (@_) {
1471         warn "$target: use $_;" if $self->debug;
1472         $self->_raw_stmt($target, "use $_;");
1473     }
1474 }
1475
1476 sub _inject {
1477     my $self = shift;
1478     my $target = shift;
1479
1480     my $blist = join(q{ }, @_);
1481
1482     return unless $blist;
1483
1484     warn "$target: use base qw/$blist/;" if $self->debug;
1485     $self->_raw_stmt($target, "use base qw/$blist/;");
1486 }
1487
1488 sub _result_namespace {
1489     my ($self, $schema_class, $ns) = @_;
1490     my @result_namespace;
1491
1492     if ($ns =~ /^\+(.*)/) {
1493         # Fully qualified namespace
1494         @result_namespace = ($1)
1495     }
1496     else {
1497         # Relative namespace
1498         @result_namespace = ($schema_class, $ns);
1499     }
1500
1501     return wantarray ? @result_namespace : join '::', @result_namespace;
1502 }
1503
1504 # Create class with applicable bases, setup monikers, etc
1505 sub _make_src_class {
1506     my ($self, $table) = @_;
1507
1508     my $schema       = $self->schema;
1509     my $schema_class = $self->schema_class;
1510
1511     my $table_moniker = $self->_table2moniker($table);
1512     my @result_namespace = ($schema_class);
1513     if ($self->use_namespaces) {
1514         my $result_namespace = $self->result_namespace || 'Result';
1515         @result_namespace = $self->_result_namespace(
1516             $schema_class,
1517             $result_namespace,
1518         );
1519     }
1520     my $table_class = join(q{::}, @result_namespace, $table_moniker);
1521
1522     if ((my $upgrading_v = $self->_upgrading_from)
1523             || $self->_rewriting) {
1524         local $self->naming->{monikers} = $upgrading_v
1525             if $upgrading_v;
1526
1527         my @result_namespace = @result_namespace;
1528         if ($self->_upgrading_from_load_classes) {
1529             @result_namespace = ($schema_class);
1530         }
1531         elsif (my $ns = $self->_downgrading_to_load_classes) {
1532             @result_namespace = $self->_result_namespace(
1533                 $schema_class,
1534                 $ns,
1535             );
1536         }
1537         elsif ($ns = $self->_rewriting_result_namespace) {
1538             @result_namespace = $self->_result_namespace(
1539                 $schema_class,
1540                 $ns,
1541             );
1542         }
1543
1544         my $old_class = join(q{::}, @result_namespace,
1545             $self->_table2moniker($table));
1546
1547         $self->_upgrading_classes->{$table_class} = $old_class
1548             unless $table_class eq $old_class;
1549     }
1550
1551 # this was a bad idea, should be ok now without it
1552 #    my $table_normalized = lc $table;
1553 #    $self->classes->{$table_normalized} = $table_class;
1554 #    $self->monikers->{$table_normalized} = $table_moniker;
1555
1556     $self->classes->{$table} = $table_class;
1557     $self->monikers->{$table} = $table_moniker;
1558
1559     $self->_use   ($table_class, @{$self->additional_classes});
1560     $self->_inject($table_class, @{$self->left_base_classes});
1561
1562     if (my @components = @{ $self->components }) {
1563         $self->_dbic_stmt($table_class, 'load_components', @components);
1564     }
1565
1566     $self->_inject($table_class, @{$self->additional_base_classes});
1567 }
1568
1569 sub _resolve_col_accessor_collisions {
1570     my ($self, $table, $col_info) = @_;
1571
1572     my $base       = $self->result_base_class || 'DBIx::Class::Core';
1573     my @components = map "DBIx::Class::$_", @{ $self->components || [] };
1574
1575     my $table_name = ref $table ? $$table : $table;
1576
1577     my @methods;
1578
1579     for my $class ($base, @components, $self->use_moose ? 'Moose::Object' : ()) {
1580         eval "require ${class};";
1581         die $@ if $@;
1582
1583         push @methods, @{ Class::Inspector->methods($class) || [] };
1584     }
1585
1586     push @methods, @{ Class::Inspector->methods('UNIVERSAL') };
1587
1588     my %methods;
1589     @methods{@methods} = ();
1590
1591     # futureproof meta
1592     $methods{meta} = undef;
1593
1594     while (my ($col, $info) = each %$col_info) {
1595         my $accessor = $info->{accessor} || $col;
1596
1597         next if $accessor eq 'id'; # special case (very common column)
1598
1599         if (exists $methods{$accessor}) {
1600             my $mapped = 0;
1601
1602             if (my $map = $self->col_collision_map) {
1603                 for my $re (keys %$map) {
1604                     if (my @matches = $col =~ /$re/) {
1605                         $info->{accessor} = sprintf $map->{$re}, @matches;
1606                         $mapped = 1;
1607                     }
1608                 }
1609             }
1610
1611             if (not $mapped) {
1612                 warn <<"EOF";
1613 Column $col in table $table_name collides with an inherited method.
1614 See "COLUMN ACCESSOR COLLISIONS" in perldoc DBIx::Class::Schema::Loader::Base .
1615 EOF
1616                 $info->{accessor} = undef;
1617             }
1618         }
1619     }
1620 }
1621
1622 # use the same logic to run moniker_map, column_accessor_map, and
1623 # relationship_name_map
1624 sub _run_user_map {
1625     my ( $self, $map, $default_code, $ident, @extra ) = @_;
1626
1627     my $default_ident = $default_code->( $ident, @extra );
1628     my $new_ident;
1629     if( $map && ref $map eq 'HASH' ) {
1630         $new_ident = $map->{ $ident };
1631     }
1632     elsif( $map && ref $map eq 'CODE' ) {
1633         $new_ident = $map->( $ident, $default_ident, @extra );
1634     }
1635
1636     $new_ident ||= $default_ident;
1637
1638     return $new_ident;
1639 }
1640
1641 sub _default_column_accessor_name {
1642     my ( $self, $column_name ) = @_;
1643
1644     my $accessor_name = $column_name;
1645     $accessor_name =~ s/\W+/_/g;
1646
1647     if ((($self->naming->{column_accessors}||'') =~ /(\d+)/ && $1 < 7) || (not $self->preserve_case)) {
1648         # older naming just lc'd the col accessor and that's all.
1649         return lc $accessor_name;
1650     }
1651
1652     return join '_', map lc, split_name $column_name;
1653
1654 }
1655
1656 sub _make_column_accessor_name {
1657     my ($self, $column_name, $column_context_info ) = @_;
1658
1659     my $accessor = $self->_run_user_map(
1660         $self->column_accessor_map,
1661         sub { $self->_default_column_accessor_name( shift ) },
1662         $column_name,
1663         $column_context_info,
1664        );
1665
1666     return $accessor;
1667 }
1668
1669 # Set up metadata (cols, pks, etc)
1670 sub _setup_src_meta {
1671     my ($self, $table) = @_;
1672
1673     my $schema       = $self->schema;
1674     my $schema_class = $self->schema_class;
1675
1676     my $table_class = $self->classes->{$table};
1677     my $table_moniker = $self->monikers->{$table};
1678
1679     my $table_name = $table;
1680     my $name_sep   = $self->schema->storage->sql_maker->name_sep;
1681
1682     if ($name_sep && $table_name =~ /\Q$name_sep\E/) {
1683         $table_name = \ $self->_quote_table_name($table_name);
1684     }
1685
1686     my $full_table_name = ($self->qualify_objects ? ($self->db_schema . '.') : '') . (ref $table_name ? $$table_name : $table_name);
1687
1688     # be careful to not create refs Data::Dump can "optimize"
1689     $full_table_name    = \do {"".$full_table_name} if ref $table_name;
1690
1691     $self->_dbic_stmt($table_class, 'table', $full_table_name);
1692
1693     my $cols     = $self->_table_columns($table);
1694     my $col_info = $self->__columns_info_for($table);
1695
1696     ### generate all the column accessor names
1697     while (my ($col, $info) = each %$col_info) {
1698         # hashref of other info that could be used by
1699         # user-defined accessor map functions
1700         my $context = {
1701             table_class     => $table_class,
1702             table_moniker   => $table_moniker,
1703             table_name      => $table_name,
1704             full_table_name => $full_table_name,
1705             schema_class    => $schema_class,
1706             column_info     => $info,
1707         };
1708
1709         $info->{accessor} = $self->_make_column_accessor_name( $col, $context );
1710     }
1711
1712     $self->_resolve_col_accessor_collisions($full_table_name, $col_info);
1713
1714     # prune any redundant accessor names
1715     while (my ($col, $info) = each %$col_info) {
1716         no warnings 'uninitialized';
1717         delete $info->{accessor} if $info->{accessor} eq $col;
1718     }
1719
1720     my $fks = $self->_table_fk_info($table);
1721
1722     foreach my $fkdef (@$fks) {
1723         for my $col (@{ $fkdef->{local_columns} }) {
1724             $col_info->{$col}{is_foreign_key} = 1;
1725         }
1726     }
1727
1728     my $pks = $self->_table_pk_info($table) || [];
1729
1730     foreach my $pkcol (@$pks) {
1731         $col_info->{$pkcol}{is_nullable} = 0;
1732     }
1733
1734     $self->_dbic_stmt(
1735         $table_class,
1736         'add_columns',
1737         map { $_, ($col_info->{$_}||{}) } @$cols
1738     );
1739
1740     my %uniq_tag; # used to eliminate duplicate uniqs
1741
1742     @$pks ? $self->_dbic_stmt($table_class,'set_primary_key',@$pks)
1743           : carp("$table has no primary key");
1744     $uniq_tag{ join("\0", @$pks) }++ if @$pks; # pk is a uniq
1745
1746     my $uniqs = $self->_table_uniq_info($table) || [];
1747     for (@$uniqs) {
1748         my ($name, $cols) = @$_;
1749         next if $uniq_tag{ join("\0", @$cols) }++; # skip duplicates
1750         $self->_dbic_stmt($table_class,'add_unique_constraint', $name, $cols);
1751     }
1752
1753 }
1754
1755 sub __columns_info_for {
1756     my ($self, $table) = @_;
1757
1758     my $result = $self->_columns_info_for($table);
1759
1760     while (my ($col, $info) = each %$result) {
1761         $info = { %$info, %{ $self->_custom_column_info  ($table, $col, $info) } };
1762         $info = { %$info, %{ $self->_datetime_column_info($table, $col, $info) } };
1763
1764         $result->{$col} = $info;
1765     }
1766
1767     return $result;
1768 }
1769
1770 =head2 tables
1771
1772 Returns a sorted list of loaded tables, using the original database table
1773 names.
1774
1775 =cut
1776
1777 sub tables {
1778     my $self = shift;
1779
1780     return keys %{$self->_tables};
1781 }
1782
1783 # Make a moniker from a table
1784 sub _default_table2moniker {
1785     no warnings 'uninitialized';
1786     my ($self, $table) = @_;
1787
1788     if ($self->naming->{monikers} eq 'v4') {
1789         return join '', map ucfirst, split /[\W_]+/, lc $table;
1790     }
1791     elsif ($self->naming->{monikers} eq 'v5') {
1792         return join '', map ucfirst, split /[\W_]+/,
1793             Lingua::EN::Inflect::Number::to_S(lc $table);
1794     }
1795     elsif ($self->naming->{monikers} eq 'v6') {
1796         (my $as_phrase = lc $table) =~ s/_+/ /g;
1797         my $inflected = Lingua::EN::Inflect::Phrase::to_S($as_phrase);
1798
1799         return join '', map ucfirst, split /\W+/, $inflected;
1800     }
1801
1802     my @words = map lc, split_name $table;
1803     my $as_phrase = join ' ', @words;
1804
1805     my $inflected = Lingua::EN::Inflect::Phrase::to_S($as_phrase);
1806
1807     return join '', map ucfirst, split /\W+/, $inflected;
1808 }
1809
1810 sub _table2moniker {
1811     my ( $self, $table ) = @_;
1812
1813     $self->_run_user_map(
1814         $self->moniker_map,
1815         sub { $self->_default_table2moniker( shift ) },
1816         $table
1817        );
1818 }
1819
1820 sub _load_relationships {
1821     my ($self, $table) = @_;
1822
1823     my $tbl_fk_info = $self->_table_fk_info($table);
1824     foreach my $fkdef (@$tbl_fk_info) {
1825         $fkdef->{remote_source} =
1826             $self->monikers->{delete $fkdef->{remote_table}};
1827     }
1828     my $tbl_uniq_info = $self->_table_uniq_info($table);
1829
1830     my $local_moniker = $self->monikers->{$table};
1831     my $rel_stmts = $self->_relbuilder->generate_code($local_moniker, $tbl_fk_info, $tbl_uniq_info);
1832
1833     foreach my $src_class (sort keys %$rel_stmts) {
1834         my $src_stmts = $rel_stmts->{$src_class};
1835         foreach my $stmt (@$src_stmts) {
1836             $self->_dbic_stmt($src_class,$stmt->{method},@{$stmt->{args}});
1837         }
1838     }
1839 }
1840
1841 # Overload these in driver class:
1842
1843 # Returns an arrayref of column names
1844 sub _table_columns { croak "ABSTRACT METHOD" }
1845
1846 # Returns arrayref of pk col names
1847 sub _table_pk_info { croak "ABSTRACT METHOD" }
1848
1849 # Returns an arrayref of uniqs [ [ foo => [ col1, col2 ] ], [ bar => [ ... ] ] ]
1850 sub _table_uniq_info { croak "ABSTRACT METHOD" }
1851
1852 # Returns an arrayref of foreign key constraints, each
1853 #   being a hashref with 3 keys:
1854 #   local_columns (arrayref), remote_columns (arrayref), remote_table
1855 sub _table_fk_info { croak "ABSTRACT METHOD" }
1856
1857 # Returns an array of lower case table names
1858 sub _tables_list { croak "ABSTRACT METHOD" }
1859
1860 # Execute a constructive DBIC class method, with debug/dump_to_dir hooks.
1861 sub _dbic_stmt {
1862     my $self   = shift;
1863     my $class  = shift;
1864     my $method = shift;
1865
1866     # generate the pod for this statement, storing it with $self->_pod
1867     $self->_make_pod( $class, $method, @_ ) if $self->generate_pod;
1868
1869     my $args = dump(@_);
1870     $args = '(' . $args . ')' if @_ < 2;
1871     my $stmt = $method . $args . q{;};
1872
1873     warn qq|$class\->$stmt\n| if $self->debug;
1874     $self->_raw_stmt($class, '__PACKAGE__->' . $stmt);
1875     return;
1876 }
1877
1878 # generates the accompanying pod for a DBIC class method statement,
1879 # storing it with $self->_pod
1880 sub _make_pod {
1881     my $self   = shift;
1882     my $class  = shift;
1883     my $method = shift;
1884
1885     if ( $method eq 'table' ) {
1886         my ($table) = @_;
1887         my $pcm = $self->pod_comment_mode;
1888         my ($comment, $comment_overflows, $comment_in_name, $comment_in_desc);
1889         $comment = $self->__table_comment($table);
1890         $comment_overflows = ($comment and length $comment > $self->pod_comment_spillover_length);
1891         $comment_in_name   = ($pcm eq 'name' or ($pcm eq 'auto' and !$comment_overflows));
1892         $comment_in_desc   = ($pcm eq 'description' or ($pcm eq 'auto' and $comment_overflows));
1893         $self->_pod( $class, "=head1 NAME" );
1894         my $table_descr = $class;
1895         $table_descr .= " - " . $comment if $comment and $comment_in_name;
1896         $self->{_class2table}{ $class } = $table;
1897         $self->_pod( $class, $table_descr );
1898         if ($comment and $comment_in_desc) {
1899             $self->_pod( $class, "=head1 DESCRIPTION" );
1900             $self->_pod( $class, $comment );
1901         }
1902         $self->_pod_cut( $class );
1903     } elsif ( $method eq 'add_columns' ) {
1904         $self->_pod( $class, "=head1 ACCESSORS" );
1905         my $col_counter = 0;
1906         my @cols = @_;
1907         while( my ($name,$attrs) = splice @cols,0,2 ) {
1908             $col_counter++;
1909             $self->_pod( $class, '=head2 ' . $name  );
1910             $self->_pod( $class,
1911                 join "\n", map {
1912                     my $s = $attrs->{$_};
1913                     $s = !defined $s          ? 'undef'             :
1914                         length($s) == 0       ? '(empty string)'    :
1915                         ref($s) eq 'SCALAR'   ? $$s                 :
1916                         ref($s)               ? dumper_squashed $s  :
1917                         looks_like_number($s) ? $s                  : qq{'$s'};
1918
1919                     "  $_: $s"
1920                  } sort keys %$attrs,
1921             );
1922             if (my $comment = $self->__column_comment($self->{_class2table}{$class}, $col_counter, $name)) {
1923                 $self->_pod( $class, $comment );
1924             }
1925         }
1926         $self->_pod_cut( $class );
1927     } elsif ( $method =~ /^(belongs_to|has_many|might_have)$/ ) {
1928         $self->_pod( $class, "=head1 RELATIONS" ) unless $self->{_relations_started} { $class } ;
1929         my ( $accessor, $rel_class ) = @_;
1930         $self->_pod( $class, "=head2 $accessor" );
1931         $self->_pod( $class, 'Type: ' . $method );
1932         $self->_pod( $class, "Related object: L<$rel_class>" );
1933         $self->_pod_cut( $class );
1934         $self->{_relations_started} { $class } = 1;
1935     }
1936 }
1937
1938 sub _filter_comment {
1939     my ($self, $txt) = @_;
1940
1941     $txt = '' if not defined $txt;
1942
1943     $txt =~ s/(?:\015?\012|\015\012?)/\n/g;
1944
1945     return $txt;
1946 }
1947
1948 sub __table_comment {
1949     my $self = shift;
1950
1951     if (my $code = $self->can('_table_comment')) {
1952         return $self->_filter_comment($self->$code(@_));
1953     }
1954     
1955     return '';
1956 }
1957
1958 sub __column_comment {
1959     my $self = shift;
1960
1961     if (my $code = $self->can('_column_comment')) {
1962         return $self->_filter_comment($self->$code(@_));
1963     }
1964
1965     return '';
1966 }
1967
1968 # Stores a POD documentation
1969 sub _pod {
1970     my ($self, $class, $stmt) = @_;
1971     $self->_raw_stmt( $class, "\n" . $stmt  );
1972 }
1973
1974 sub _pod_cut {
1975     my ($self, $class ) = @_;
1976     $self->_raw_stmt( $class, "\n=cut\n" );
1977 }
1978
1979 # Store a raw source line for a class (for dumping purposes)
1980 sub _raw_stmt {
1981     my ($self, $class, $stmt) = @_;
1982     push(@{$self->{_dump_storage}->{$class}}, $stmt);
1983 }
1984
1985 # Like above, but separately for the externally loaded stuff
1986 sub _ext_stmt {
1987     my ($self, $class, $stmt) = @_;
1988     push(@{$self->{_ext_storage}->{$class}}, $stmt);
1989 }
1990
1991 sub _quote_table_name {
1992     my ($self, $table) = @_;
1993
1994     my $qt = $self->schema->storage->sql_maker->quote_char;
1995
1996     return $table unless $qt;
1997
1998     if (ref $qt) {
1999         return $qt->[0] . $table . $qt->[1];
2000     }
2001
2002     return $qt . $table . $qt;
2003 }
2004
2005 sub _custom_column_info {
2006     my ( $self, $table_name, $column_name, $column_info ) = @_;
2007
2008     if (my $code = $self->custom_column_info) {
2009         return $code->($table_name, $column_name, $column_info) || {};
2010     }
2011     return {};
2012 }
2013
2014 sub _datetime_column_info {
2015     my ( $self, $table_name, $column_name, $column_info ) = @_;
2016     my $result = {};
2017     my $type = $column_info->{data_type} || '';
2018     if ((grep $_, @{ $column_info }{map "inflate_$_", qw/date datetime timestamp/})
2019             or ($type =~ /date|timestamp/i)) {
2020         $result->{timezone} = $self->datetime_timezone if $self->datetime_timezone;
2021         $result->{locale}   = $self->datetime_locale   if $self->datetime_locale;
2022     }
2023     return $result;
2024 }
2025
2026 sub _lc {
2027     my ($self, $name) = @_;
2028
2029     return $self->preserve_case ? $name : lc($name);
2030 }
2031
2032 sub _uc {
2033     my ($self, $name) = @_;
2034
2035     return $self->preserve_case ? $name : uc($name);
2036 }
2037
2038 sub _unregister_source_for_table {
2039     my ($self, $table) = @_;
2040
2041     try {
2042         local $@;
2043         my $schema = $self->schema;
2044         # in older DBIC it's a private method
2045         my $unregister = $schema->can('unregister_source') || $schema->can('_unregister_source');
2046         $schema->$unregister($self->_table2moniker($table));
2047         delete $self->monikers->{$table};
2048         delete $self->classes->{$table};
2049         delete $self->_upgrading_classes->{$table};
2050         delete $self->{_tables}{$table};
2051     };
2052 }
2053
2054 # remove the dump dir from @INC on destruction
2055 sub DESTROY {
2056     my $self = shift;
2057
2058     @INC = grep $_ ne $self->dump_directory, @INC;
2059 }
2060
2061 =head2 monikers
2062
2063 Returns a hashref of loaded table to moniker mappings.  There will
2064 be two entries for each table, the original name and the "normalized"
2065 name, in the case that the two are different (such as databases
2066 that like uppercase table names, or preserve your original mixed-case
2067 definitions, or what-have-you).
2068
2069 =head2 classes
2070
2071 Returns a hashref of table to class mappings.  In some cases it will
2072 contain multiple entries per table for the original and normalized table
2073 names, as above in L</monikers>.
2074
2075 =head1 COLUMN ACCESSOR COLLISIONS
2076
2077 Occasionally you may have a column name that collides with a perl method, such
2078 as C<can>. In such cases, the default action is to set the C<accessor> of the
2079 column spec to C<undef>.
2080
2081 You can then name the accessor yourself by placing code such as the following
2082 below the md5:
2083
2084     __PACKAGE__->add_column('+can' => { accessor => 'my_can' });
2085
2086 Another option is to use the L</col_collision_map> option.
2087
2088 =head1 SEE ALSO
2089
2090 L<DBIx::Class::Schema::Loader>
2091
2092 =head1 AUTHOR
2093
2094 See L<DBIx::Class::Schema::Loader/AUTHOR> and L<DBIx::Class::Schema::Loader/CONTRIBUTORS>.
2095
2096 =head1 LICENSE
2097
2098 This library is free software; you can redistribute it and/or modify it under
2099 the same terms as Perl itself.
2100
2101 =cut
2102
2103 1;
2104 # vim:et sts=4 sw=4 tw=0: