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