Merge branch 'master' into column_callback
[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 Class::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 File::Temp qw//;
16 use Class::Unload;
17 use Class::Inspector ();
18 require DBIx::Class;
19
20 our $VERSION = '0.05002';
21
22 __PACKAGE__->mk_group_ro_accessors('simple', qw/
23                                 schema
24                                 schema_class
25
26                                 exclude
27                                 constraint
28                                 additional_classes
29                                 additional_base_classes
30                                 left_base_classes
31                                 components
32                                 resultset_components
33                                 skip_relationships
34                                 skip_load_external
35                                 moniker_map
36                                 custom_column_info
37                                 inflect_singular
38                                 inflect_plural
39                                 debug
40                                 dump_directory
41                                 dump_overwrite
42                                 really_erase_my_files
43                                 resultset_namespace
44                                 default_resultset_class
45                                 schema_base_class
46                                 result_base_class
47                                 overwrite_modifications
48
49                                 relationship_attrs
50
51                                 db_schema
52                                 _tables
53                                 classes
54                                 _upgrading_classes
55                                 monikers
56                                 dynamic
57                                 naming
58 /);
59
60
61 __PACKAGE__->mk_group_accessors('simple', qw/
62                                 version_to_dump
63                                 schema_version_to_dump
64                                 _upgrading_from
65                                 _upgrading_from_load_classes
66                                 _downgrading_to_load_classes
67                                 _rewriting_result_namespace
68                                 use_namespaces
69                                 result_namespace
70                                 generate_pod
71                                 pod_comment_mode
72                                 pod_comment_spillover_length
73 /);
74
75 =head1 NAME
76
77 DBIx::Class::Schema::Loader::Base - Base DBIx::Class::Schema::Loader Implementation.
78
79 =head1 SYNOPSIS
80
81 See L<DBIx::Class::Schema::Loader>
82
83 =head1 DESCRIPTION
84
85 This is the base class for the storage-specific C<DBIx::Class::Schema::*>
86 classes, and implements the common functionality between them.
87
88 =head1 CONSTRUCTOR OPTIONS
89
90 These constructor options are the base options for
91 L<DBIx::Class::Schema::Loader/loader_options>.  Available constructor options are:
92
93 =head2 skip_relationships
94
95 Skip setting up relationships.  The default is to attempt the loading
96 of relationships.
97
98 =head2 skip_load_external
99
100 Skip loading of other classes in @INC. The default is to merge all other classes
101 with the same name found in @INC into the schema file we are creating.
102
103 =head2 naming
104
105 Static schemas (ones dumped to disk) will, by default, use the new-style 0.05XXX
106 relationship names and singularized Results, unless you're overwriting an
107 existing dump made by a 0.04XXX version of L<DBIx::Class::Schema::Loader>, in
108 which case the backward compatible RelBuilder will be activated, and
109 singularization will be turned off.
110
111 Specifying
112
113     naming => 'v5'
114
115 will disable the backward-compatible RelBuilder and use
116 the new-style relationship names along with singularized Results, even when
117 overwriting a dump made with an earlier version.
118
119 The option also takes a hashref:
120
121     naming => { relationships => 'v5', monikers => 'v4' }
122
123 The keys are:
124
125 =over 4
126
127 =item relationships
128
129 How to name relationship accessors.
130
131 =item monikers
132
133 How to name Result classes.
134
135 =back
136
137 The values can be:
138
139 =over 4
140
141 =item current
142
143 Latest default style, whatever that happens to be.
144
145 =item v5
146
147 Version 0.05XXX style.
148
149 =item v4
150
151 Version 0.04XXX style.
152
153 =back
154
155 Dynamic schemas will always default to the 0.04XXX relationship names and won't
156 singularize Results for backward compatibility, to activate the new RelBuilder
157 and singularization put this in your C<Schema.pm> file:
158
159     __PACKAGE__->naming('current');
160
161 Or if you prefer to use 0.05XXX features but insure that nothing breaks in the
162 next major version upgrade:
163
164     __PACKAGE__->naming('v5');
165
166 =head2 generate_pod
167
168 By default POD will be generated for columns and relationships, using database
169 metadata for the text if available and supported.
170
171 Reading database metadata (e.g. C<COMMENT ON TABLE some_table ...>) is only
172 supported for Postgres right now.
173
174 Set this to C<0> to turn off all POD generation.
175
176 =head2 pod_comment_mode
177
178 Controls where table comments appear in the generated POD. Smaller table
179 comments are appended to the C<NAME> section of the documentation, and larger
180 ones are inserted into C<DESCRIPTION> instead. You can force a C<DESCRIPTION>
181 section to be generated with the comment always, only use C<NAME>, or choose
182 the length threshold at which the comment is forced into the description.
183
184 =over 4
185
186 =item name
187
188 Use C<NAME> section only.
189
190 =item description
191
192 Force C<DESCRIPTION> always.
193
194 =item auto
195
196 Use C<DESCRIPTION> if length > L</pod_comment_spillover_length>, this is the
197 default.
198
199 =back
200
201 =head2 pod_comment_spillover_length
202
203 When pod_comment_mode is set to C<auto>, this is the length of the comment at
204 which it will be forced into a separate description section.
205
206 The default is C<60>
207
208 =head2 relationship_attrs
209
210 Hashref of attributes to pass to each generated relationship, listed
211 by type.  Also supports relationship type 'all', containing options to
212 pass to all generated relationships.  Attributes set for more specific
213 relationship types override those set in 'all'.
214
215 For example:
216
217   relationship_attrs => {
218     all      => { cascade_delete => 0 },
219     has_many => { cascade_delete => 1 },
220   },
221
222 will set the C<cascade_delete> option to 0 for all generated relationships,
223 except for C<has_many>, which will have cascade_delete as 1.
224
225 NOTE: this option is not supported if v4 backward-compatible naming is
226 set either globally (naming => 'v4') or just for relationships.
227
228 =head2 debug
229
230 If set to true, each constructive L<DBIx::Class> statement the loader
231 decides to execute will be C<warn>-ed before execution.
232
233 =head2 db_schema
234
235 Set the name of the schema to load (schema in the sense that your database
236 vendor means it).  Does not currently support loading more than one schema
237 name.
238
239 =head2 constraint
240
241 Only load tables matching regex.  Best specified as a qr// regex.
242
243 =head2 exclude
244
245 Exclude tables matching regex.  Best specified as a qr// regex.
246
247 =head2 moniker_map
248
249 Overrides the default table name to moniker translation.  Can be either
250 a hashref of table keys and moniker values, or a coderef for a translator
251 function taking a single scalar table name argument and returning
252 a scalar moniker.  If the hash entry does not exist, or the function
253 returns a false value, the code falls back to default behavior
254 for that table name.
255
256 The default behavior is to singularize the table name, and: C<join '', map
257 ucfirst, split /[\W_]+/, lc $table>, which is to say: lowercase everything,
258 split up the table name into chunks anywhere a non-alpha-numeric character
259 occurs, change the case of first letter of each chunk to upper case, and put
260 the chunks back together.  Examples:
261
262     Table Name  | Moniker Name
263     ---------------------------
264     luser       | Luser
265     luser_group | LuserGroup
266     luser-opts  | LuserOpt
267
268 =head2 inflect_plural
269
270 Just like L</moniker_map> above (can be hash/code-ref, falls back to default
271 if hash key does not exist or coderef returns false), but acts as a map
272 for pluralizing relationship names.  The default behavior is to utilize
273 L<Lingua::EN::Inflect::Number/to_PL>.
274
275 =head2 inflect_singular
276
277 As L</inflect_plural> above, but for singularizing relationship names.
278 Default behavior is to utilize L<Lingua::EN::Inflect::Number/to_S>.
279
280 =head2 schema_base_class
281
282 Base class for your schema classes. Defaults to 'DBIx::Class::Schema'.
283
284 =head2 result_base_class
285
286 Base class for your table classes (aka result classes). Defaults to
287 'DBIx::Class::Core'.
288
289 =head2 additional_base_classes
290
291 List of additional base classes all of your table classes will use.
292
293 =head2 left_base_classes
294
295 List of additional base classes all of your table classes will use
296 that need to be leftmost.
297
298 =head2 additional_classes
299
300 List of additional classes which all of your table classes will use.
301
302 =head2 components
303
304 List of additional components to be loaded into all of your table
305 classes.  A good example would be C<ResultSetManager>.
306
307 =head2 resultset_components
308
309 List of additional ResultSet components to be loaded into your table
310 classes.  A good example would be C<AlwaysRS>.  Component
311 C<ResultSetManager> will be automatically added to the above
312 C<components> list if this option is set.
313
314 =head2 use_namespaces
315
316 This is now the default, to go back to L<DBIx::Class::Schema/load_classes> pass
317 a C<0>.
318
319 Generate result class names suitable for
320 L<DBIx::Class::Schema/load_namespaces> and call that instead of
321 L<DBIx::Class::Schema/load_classes>. When using this option you can also
322 specify any of the options for C<load_namespaces> (i.e. C<result_namespace>,
323 C<resultset_namespace>, C<default_resultset_class>), and they will be added
324 to the call (and the generated result class names adjusted appropriately).
325
326 =head2 dump_directory
327
328 This option is designed to be a tool to help you transition from this
329 loader to a manually-defined schema when you decide it's time to do so.
330
331 The value of this option is a perl libdir pathname.  Within
332 that directory this module will create a baseline manual
333 L<DBIx::Class::Schema> module set, based on what it creates at runtime
334 in memory.
335
336 The created schema class will have the same classname as the one on
337 which you are setting this option (and the ResultSource classes will be
338 based on this name as well).
339
340 Normally you wouldn't hard-code this setting in your schema class, as it
341 is meant for one-time manual usage.
342
343 See L<DBIx::Class::Schema::Loader/dump_to_dir> for examples of the
344 recommended way to access this functionality.
345
346 =head2 dump_overwrite
347
348 Deprecated.  See L</really_erase_my_files> below, which does *not* mean
349 the same thing as the old C<dump_overwrite> setting from previous releases.
350
351 =head2 really_erase_my_files
352
353 Default false.  If true, Loader will unconditionally delete any existing
354 files before creating the new ones from scratch when dumping a schema to disk.
355
356 The default behavior is instead to only replace the top portion of the
357 file, up to and including the final stanza which contains
358 C<# DO NOT MODIFY THIS OR ANYTHING ABOVE!>
359 leaving any customizations you placed after that as they were.
360
361 When C<really_erase_my_files> is not set, if the output file already exists,
362 but the aforementioned final stanza is not found, or the checksum
363 contained there does not match the generated contents, Loader will
364 croak and not touch the file.
365
366 You should really be using version control on your schema classes (and all
367 of the rest of your code for that matter).  Don't blame me if a bug in this
368 code wipes something out when it shouldn't have, you've been warned.
369
370 =head2 overwrite_modifications
371
372 Default false.  If false, when updating existing files, Loader will
373 refuse to modify any Loader-generated code that has been modified
374 since its last run (as determined by the checksum Loader put in its
375 comment lines).
376
377 If true, Loader will discard any manual modifications that have been
378 made to Loader-generated code.
379
380 Again, you should be using version control on your schema classes.  Be
381 careful with this option.
382
383 =head1 METHODS
384
385 None of these methods are intended for direct invocation by regular
386 users of L<DBIx::Class::Schema::Loader>.  Anything you can find here
387 can also be found via standard L<DBIx::Class::Schema> methods somehow.
388
389 =cut
390
391 use constant CURRENT_V  => 'v5';
392
393 use constant CLASS_ARGS => qw(
394     schema_base_class result_base_class additional_base_classes
395     left_base_classes additional_classes components resultset_components
396 );
397
398 # ensure that a peice of object data is a valid arrayref, creating
399 # an empty one or encapsulating whatever's there.
400 sub _ensure_arrayref {
401     my $self = shift;
402
403     foreach (@_) {
404         $self->{$_} ||= [];
405         $self->{$_} = [ $self->{$_} ]
406             unless ref $self->{$_} eq 'ARRAY';
407     }
408 }
409
410 =head2 new
411
412 Constructor for L<DBIx::Class::Schema::Loader::Base>, used internally
413 by L<DBIx::Class::Schema::Loader>.
414
415 =cut
416
417 sub new {
418     my ( $class, %args ) = @_;
419
420     my $self = { %args };
421
422     bless $self => $class;
423
424     $self->_ensure_arrayref(qw/additional_classes
425                                additional_base_classes
426                                left_base_classes
427                                components
428                                resultset_components
429                               /);
430
431     $self->_validate_class_args;
432
433     push(@{$self->{components}}, 'ResultSetManager')
434         if @{$self->{resultset_components}};
435
436     $self->{monikers} = {};
437     $self->{classes} = {};
438     $self->{_upgrading_classes} = {};
439
440     $self->{schema_class} ||= ( ref $self->{schema} || $self->{schema} );
441     $self->{schema} ||= $self->{schema_class};
442
443     croak "dump_overwrite is deprecated.  Please read the"
444         . " DBIx::Class::Schema::Loader::Base documentation"
445             if $self->{dump_overwrite};
446
447     $self->{dynamic} = ! $self->{dump_directory};
448     $self->{temp_directory} ||= File::Temp::tempdir( 'dbicXXXX',
449                                                      TMPDIR  => 1,
450                                                      CLEANUP => 1,
451                                                    );
452
453     $self->{dump_directory} ||= $self->{temp_directory};
454
455     $self->version_to_dump($DBIx::Class::Schema::Loader::VERSION);
456     $self->schema_version_to_dump($DBIx::Class::Schema::Loader::VERSION);
457
458     if ((not ref $self->naming) && defined $self->naming) {
459         my $naming_ver = $self->naming;
460         $self->{naming} = {
461             relationships => $naming_ver,
462             monikers => $naming_ver,
463         };
464     }
465
466     if ($self->naming) {
467         for (values %{ $self->naming }) {
468             $_ = CURRENT_V if $_ eq 'current';
469         }
470     }
471     $self->{naming} ||= {};
472
473     $self->_check_back_compat;
474
475     $self->use_namespaces(1) unless defined $self->use_namespaces;
476     $self->generate_pod(1)   unless defined $self->generate_pod;
477     $self->pod_comment_mode('auto')         unless defined $self->pod_comment_mode;
478     $self->pod_comment_spillover_length(60) unless defined $self->pod_comment_spillover_length;
479
480     $self;
481 }
482
483 sub _check_back_compat {
484     my ($self) = @_;
485
486 # dynamic schemas will always be in 0.04006 mode, unless overridden
487     if ($self->dynamic) {
488 # just in case, though no one is likely to dump a dynamic schema
489         $self->schema_version_to_dump('0.04006');
490
491         if (not %{ $self->naming }) {
492             warn <<EOF unless $ENV{SCHEMA_LOADER_BACKCOMPAT};
493
494 Dynamic schema detected, will run in 0.04006 mode.
495
496 Set the 'naming' attribute or the SCHEMA_LOADER_BACKCOMPAT environment variable
497 to disable this warning.
498
499 Also consider setting 'use_namespaces => 1' if/when upgrading.
500
501 See perldoc DBIx::Class::Schema::Loader::Manual::UpgradingFromV4 for more
502 details.
503 EOF
504         }
505         else {
506             $self->_upgrading_from('v4');
507         }
508
509         $self->naming->{relationships} ||= 'v4';
510         $self->naming->{monikers}      ||= 'v4';
511
512         if ($self->use_namespaces) {
513             $self->_upgrading_from_load_classes(1);
514         }
515         else {
516             $self->use_namespaces(0);
517         }
518
519         return;
520     }
521
522 # otherwise check if we need backcompat mode for a static schema
523     my $filename = $self->_get_dump_filename($self->schema_class);
524     return unless -e $filename;
525
526     open(my $fh, '<', $filename)
527         or croak "Cannot open '$filename' for reading: $!";
528
529     my $load_classes     = 0;
530     my $result_namespace = '';
531
532     while (<$fh>) {
533         if (/^__PACKAGE__->load_classes;/) {
534             $load_classes = 1;
535         } elsif (/result_namespace => '([^']+)'/) {
536             $result_namespace = $1;
537         } elsif (my ($real_ver) =
538                 /^# Created by DBIx::Class::Schema::Loader v(\d+\.\d+)/) {
539
540             if ($load_classes && (not defined $self->use_namespaces)) {
541                 warn <<"EOF"  unless $ENV{SCHEMA_LOADER_BACKCOMPAT};
542
543 'load_classes;' static schema detected, turning off 'use_namespaces'.
544
545 Set the 'use_namespaces' attribute or the SCHEMA_LOADER_BACKCOMPAT environment
546 variable to disable this warning.
547
548 See perldoc DBIx::Class::Schema::Loader::Manual::UpgradingFromV4 for more
549 details.
550 EOF
551                 $self->use_namespaces(0);
552             }
553             elsif ($load_classes && $self->use_namespaces) {
554                 $self->_upgrading_from_load_classes(1);
555             }
556             elsif ((not $load_classes) && defined $self->use_namespaces
557                                        && (not $self->use_namespaces)) {
558                 $self->_downgrading_to_load_classes(
559                     $result_namespace || 'Result'
560                 );
561             }
562             elsif ((not defined $self->use_namespaces)
563                    || $self->use_namespaces) {
564                 if (not $self->result_namespace) {
565                     $self->result_namespace($result_namespace || 'Result');
566                 }
567                 elsif ($result_namespace ne $self->result_namespace) {
568                     $self->_rewriting_result_namespace(
569                         $result_namespace || 'Result'
570                     );
571                 }
572             }
573
574             # XXX when we go past .0 this will need fixing
575             my ($v) = $real_ver =~ /([1-9])/;
576             $v = "v$v";
577
578             last if $v eq CURRENT_V || $real_ver =~ /^0\.\d\d999/;
579
580             if (not %{ $self->naming }) {
581                 warn <<"EOF" unless $ENV{SCHEMA_LOADER_BACKCOMPAT};
582
583 Version $real_ver static schema detected, turning on backcompat mode.
584
585 Set the 'naming' attribute or the SCHEMA_LOADER_BACKCOMPAT environment variable
586 to disable this warning.
587
588 See perldoc DBIx::Class::Schema::Loader::Manual::UpgradingFromV4 for more
589 details.
590 EOF
591             }
592             else {
593                 $self->_upgrading_from($v);
594                 last;
595             }
596
597             $self->naming->{relationships} ||= $v;
598             $self->naming->{monikers}      ||= $v;
599
600             $self->schema_version_to_dump($real_ver);
601
602             last;
603         }
604     }
605     close $fh;
606 }
607
608 sub _validate_class_args {
609     my $self = shift;
610     my $args = shift;
611     
612     foreach my $k (CLASS_ARGS) {
613         next unless $self->$k;
614
615         my @classes = ref $self->$k eq 'ARRAY' ? @{ $self->$k } : $self->$k;
616         foreach my $c (@classes) {
617             # components default to being under the DBIx::Class namespace unless they
618             # are preceeded with a '+'
619             if ( $k =~ m/components$/ && $c !~ s/^\+// ) {
620                 $c = 'DBIx::Class::' . $c;
621             }
622
623             # 1 == installed, 0 == not installed, undef == invalid classname
624             my $installed = Class::Inspector->installed($c);
625             if ( defined($installed) ) {
626                 if ( $installed == 0 ) {
627                     croak qq/$c, as specified in the loader option "$k", is not installed/;
628                 }
629             } else {
630                 croak qq/$c, as specified in the loader option "$k", is an invalid class name/;
631             }
632         }
633     }
634 }
635
636 sub _find_file_in_inc {
637     my ($self, $file) = @_;
638
639     foreach my $prefix (@INC) {
640         my $fullpath = File::Spec->catfile($prefix, $file);
641         return $fullpath if -f $fullpath
642             # abs_path throws on Windows for nonexistant files
643             and eval { Cwd::abs_path($fullpath) } ne
644                (eval { Cwd::abs_path(File::Spec->catfile($self->dump_directory, $file)) } || '');
645     }
646
647     return;
648 }
649
650 sub _class_path {
651     my ($self, $class) = @_;
652
653     my $class_path = $class;
654     $class_path =~ s{::}{/}g;
655     $class_path .= '.pm';
656
657     return $class_path;
658 }
659
660 sub _find_class_in_inc {
661     my ($self, $class) = @_;
662
663     return $self->_find_file_in_inc($self->_class_path($class));
664 }
665
666 sub _rewriting {
667     my $self = shift;
668
669     return $self->_upgrading_from
670         || $self->_upgrading_from_load_classes
671         || $self->_downgrading_to_load_classes
672         || $self->_rewriting_result_namespace
673     ;
674 }
675
676 sub _rewrite_old_classnames {
677     my ($self, $code) = @_;
678
679     return $code unless $self->_rewriting;
680
681     my %old_classes = reverse %{ $self->_upgrading_classes };
682
683     my $re = join '|', keys %old_classes;
684     $re = qr/\b($re)\b/;
685
686     $code =~ s/$re/$old_classes{$1} || $1/eg;
687
688     return $code;
689 }
690
691 sub _load_external {
692     my ($self, $class) = @_;
693
694     return if $self->{skip_load_external};
695
696     # so that we don't load our own classes, under any circumstances
697     local *INC = [ grep $_ ne $self->dump_directory, @INC ];
698
699     my $real_inc_path = $self->_find_class_in_inc($class);
700
701     my $old_class = $self->_upgrading_classes->{$class}
702         if $self->_rewriting;
703
704     my $old_real_inc_path = $self->_find_class_in_inc($old_class)
705         if $old_class && $old_class ne $class;
706
707     return unless $real_inc_path || $old_real_inc_path;
708
709     if ($real_inc_path) {
710         # If we make it to here, we loaded an external definition
711         warn qq/# Loaded external class definition for '$class'\n/
712             if $self->debug;
713
714         open(my $fh, '<', $real_inc_path)
715             or croak "Failed to open '$real_inc_path' for reading: $!";
716         my $code = do { local $/; <$fh> };
717         close($fh)
718             or croak "Failed to close $real_inc_path: $!";
719         $code = $self->_rewrite_old_classnames($code);
720
721         if ($self->dynamic) { # load the class too
722             # kill redefined warnings
723             my $warn_handler = $SIG{__WARN__} || sub { warn @_ };
724             local $SIG{__WARN__} = sub {
725                 $warn_handler->(@_)
726                     unless $_[0] =~ /^Subroutine \S+ redefined/;
727             };
728             eval $code;
729             die $@ if $@;
730         }
731
732         $self->_ext_stmt($class,
733           qq|# These lines were loaded from '$real_inc_path' found in \@INC.\n|
734          .qq|# They are now part of the custom portion of this file\n|
735          .qq|# for you to hand-edit.  If you do not either delete\n|
736          .qq|# this section or remove that file from \@INC, this section\n|
737          .qq|# will be repeated redundantly when you re-create this\n|
738          .qq|# file again via Loader!  See skip_load_external to disable\n|
739          .qq|# this feature.\n|
740         );
741         chomp $code;
742         $self->_ext_stmt($class, $code);
743         $self->_ext_stmt($class,
744             qq|# End of lines loaded from '$real_inc_path' |
745         );
746     }
747
748     if ($old_real_inc_path) {
749         open(my $fh, '<', $old_real_inc_path)
750             or croak "Failed to open '$old_real_inc_path' for reading: $!";
751         $self->_ext_stmt($class, <<"EOF");
752
753 # These lines were loaded from '$old_real_inc_path',
754 # based on the Result class name that would have been created by an 0.04006
755 # version of the Loader. For a static schema, this happens only once during
756 # upgrade. See skip_load_external to disable this feature.
757 EOF
758
759         my $code = do {
760             local ($/, @ARGV) = (undef, $old_real_inc_path); <>
761         };
762         $code = $self->_rewrite_old_classnames($code);
763
764         if ($self->dynamic) {
765             warn <<"EOF";
766
767 Detected external content in '$old_real_inc_path', a class name that would have
768 been used by an 0.04006 version of the Loader.
769
770 * PLEASE RENAME THIS CLASS: from '$old_class' to '$class', as that is the
771 new name of the Result.
772 EOF
773             # kill redefined warnings
774             my $warn_handler = $SIG{__WARN__} || sub { warn @_ };
775             local $SIG{__WARN__} = sub {
776                 $warn_handler->(@_)
777                     unless $_[0] =~ /^Subroutine \S+ redefined/;
778             };
779             eval $code;
780             die $@ if $@;
781         }
782
783         chomp $code;
784         $self->_ext_stmt($class, $code);
785         $self->_ext_stmt($class,
786             qq|# End of lines loaded from '$old_real_inc_path' |
787         );
788     }
789 }
790
791 =head2 load
792
793 Does the actual schema-construction work.
794
795 =cut
796
797 sub load {
798     my $self = shift;
799
800     $self->_load_tables($self->_tables_list);
801 }
802
803 =head2 rescan
804
805 Arguments: schema
806
807 Rescan the database for newly added tables.  Does
808 not process drops or changes.  Returns a list of
809 the newly added table monikers.
810
811 The schema argument should be the schema class
812 or object to be affected.  It should probably
813 be derived from the original schema_class used
814 during L</load>.
815
816 =cut
817
818 sub rescan {
819     my ($self, $schema) = @_;
820
821     $self->{schema} = $schema;
822     $self->_relbuilder->{schema} = $schema;
823
824     my @created;
825     my @current = $self->_tables_list;
826     foreach my $table ($self->_tables_list) {
827         if(!exists $self->{_tables}->{$table}) {
828             push(@created, $table);
829         }
830     }
831
832     my $loaded = $self->_load_tables(@created);
833
834     return map { $self->monikers->{$_} } @$loaded;
835 }
836
837 sub _relbuilder {
838     no warnings 'uninitialized';
839     my ($self) = @_;
840
841     return if $self->{skip_relationships};
842
843     if ($self->naming->{relationships} eq 'v4') {
844         require DBIx::Class::Schema::Loader::RelBuilder::Compat::v0_040;
845         return $self->{relbuilder} ||=
846             DBIx::Class::Schema::Loader::RelBuilder::Compat::v0_040->new(
847                 $self->schema, $self->inflect_plural, $self->inflect_singular
848             );
849     }
850
851     $self->{relbuilder} ||= DBIx::Class::Schema::Loader::RelBuilder->new (
852          $self->schema,
853          $self->inflect_plural,
854          $self->inflect_singular,
855          $self->relationship_attrs,
856     );
857 }
858
859 sub _load_tables {
860     my ($self, @tables) = @_;
861
862     # First, use _tables_list with constraint and exclude
863     #  to get a list of tables to operate on
864
865     my $constraint   = $self->constraint;
866     my $exclude      = $self->exclude;
867
868     @tables = grep { /$constraint/ } @tables if $constraint;
869     @tables = grep { ! /$exclude/ } @tables if $exclude;
870
871     # Save the new tables to the tables list
872     foreach (@tables) {
873         $self->{_tables}->{$_} = 1;
874     }
875
876     $self->_make_src_class($_) for @tables;
877     $self->_setup_src_meta($_) for @tables;
878
879     if(!$self->skip_relationships) {
880         # The relationship loader needs a working schema
881         $self->{quiet} = 1;
882         local $self->{dump_directory} = $self->{temp_directory};
883         $self->_reload_classes(\@tables);
884         $self->_load_relationships($_) for @tables;
885         $self->{quiet} = 0;
886
887         # Remove that temp dir from INC so it doesn't get reloaded
888         @INC = grep $_ ne $self->dump_directory, @INC;
889     }
890
891     $self->_load_external($_)
892         for map { $self->classes->{$_} } @tables;
893
894     # Reload without unloading first to preserve any symbols from external
895     # packages.
896     $self->_reload_classes(\@tables, 0);
897
898     # Drop temporary cache
899     delete $self->{_cache};
900
901     return \@tables;
902 }
903
904 sub _reload_classes {
905     my ($self, $tables, $unload) = @_;
906
907     my @tables = @$tables;
908     $unload = 1 unless defined $unload;
909
910     # so that we don't repeat custom sections
911     @INC = grep $_ ne $self->dump_directory, @INC;
912
913     $self->_dump_to_dir(map { $self->classes->{$_} } @tables);
914
915     unshift @INC, $self->dump_directory;
916     
917     my @to_register;
918     my %have_source = map { $_ => $self->schema->source($_) }
919         $self->schema->sources;
920
921     for my $table (@tables) {
922         my $moniker = $self->monikers->{$table};
923         my $class = $self->classes->{$table};
924         
925         {
926             no warnings 'redefine';
927             local *Class::C3::reinitialize = sub {};
928             use warnings;
929
930             Class::Unload->unload($class) if $unload;
931             my ($source, $resultset_class);
932             if (
933                 ($source = $have_source{$moniker})
934                 && ($resultset_class = $source->resultset_class)
935                 && ($resultset_class ne 'DBIx::Class::ResultSet')
936             ) {
937                 my $has_file = Class::Inspector->loaded_filename($resultset_class);
938                 Class::Unload->unload($resultset_class) if $unload;
939                 $self->_reload_class($resultset_class) if $has_file;
940             }
941             $self->_reload_class($class);
942         }
943         push @to_register, [$moniker, $class];
944     }
945
946     Class::C3->reinitialize;
947     for (@to_register) {
948         $self->schema->register_class(@$_);
949     }
950 }
951
952 # We use this instead of ensure_class_loaded when there are package symbols we
953 # want to preserve.
954 sub _reload_class {
955     my ($self, $class) = @_;
956
957     my $class_path = $self->_class_path($class);
958     delete $INC{ $class_path };
959
960 # kill redefined warnings
961     my $warn_handler = $SIG{__WARN__} || sub { warn @_ };
962     local $SIG{__WARN__} = sub {
963         $warn_handler->(@_)
964             unless $_[0] =~ /^Subroutine \S+ redefined/;
965     };
966     eval "require $class;";
967 }
968
969 sub _get_dump_filename {
970     my ($self, $class) = (@_);
971
972     $class =~ s{::}{/}g;
973     return $self->dump_directory . q{/} . $class . q{.pm};
974 }
975
976 sub _ensure_dump_subdirs {
977     my ($self, $class) = (@_);
978
979     my @name_parts = split(/::/, $class);
980     pop @name_parts; # we don't care about the very last element,
981                      # which is a filename
982
983     my $dir = $self->dump_directory;
984     while (1) {
985         if(!-d $dir) {
986             mkdir($dir) or croak "mkdir('$dir') failed: $!";
987         }
988         last if !@name_parts;
989         $dir = File::Spec->catdir($dir, shift @name_parts);
990     }
991 }
992
993 sub _dump_to_dir {
994     my ($self, @classes) = @_;
995
996     my $schema_class = $self->schema_class;
997     my $schema_base_class = $self->schema_base_class || 'DBIx::Class::Schema';
998
999     my $target_dir = $self->dump_directory;
1000     warn "Dumping manual schema for $schema_class to directory $target_dir ...\n"
1001         unless $self->{dynamic} or $self->{quiet};
1002
1003     my $schema_text =
1004           qq|package $schema_class;\n\n|
1005         . qq|# Created by DBIx::Class::Schema::Loader\n|
1006         . qq|# DO NOT MODIFY THE FIRST PART OF THIS FILE\n\n|
1007         . qq|use strict;\nuse warnings;\n\n|
1008         . qq|use base '$schema_base_class';\n\n|;
1009
1010     if ($self->use_namespaces) {
1011         $schema_text .= qq|__PACKAGE__->load_namespaces|;
1012         my $namespace_options;
1013         for my $attr (qw(result_namespace
1014                          resultset_namespace
1015                          default_resultset_class)) {
1016             if ($self->$attr) {
1017                 $namespace_options .= qq|    $attr => '| . $self->$attr . qq|',\n|
1018             }
1019         }
1020         $schema_text .= qq|(\n$namespace_options)| if $namespace_options;
1021         $schema_text .= qq|;\n|;
1022     }
1023     else {
1024         $schema_text .= qq|__PACKAGE__->load_classes;\n|;
1025     }
1026
1027     {
1028         local $self->{version_to_dump} = $self->schema_version_to_dump;
1029         $self->_write_classfile($schema_class, $schema_text, 1);
1030     }
1031
1032     my $result_base_class = $self->result_base_class || 'DBIx::Class::Core';
1033
1034     foreach my $src_class (@classes) {
1035         my $src_text = 
1036               qq|package $src_class;\n\n|
1037             . qq|# Created by DBIx::Class::Schema::Loader\n|
1038             . qq|# DO NOT MODIFY THE FIRST PART OF THIS FILE\n\n|
1039             . qq|use strict;\nuse warnings;\n\n|
1040             . qq|use base '$result_base_class';\n\n|;
1041
1042         $self->_write_classfile($src_class, $src_text);
1043     }
1044
1045     # remove Result dir if downgrading from use_namespaces, and there are no
1046     # files left.
1047     if (my $result_ns = $self->_downgrading_to_load_classes
1048                         || $self->_rewriting_result_namespace) {
1049         my $result_namespace = $self->_result_namespace(
1050             $schema_class,
1051             $result_ns,
1052         );
1053
1054         (my $result_dir = $result_namespace) =~ s{::}{/}g;
1055         $result_dir = $self->dump_directory . '/' . $result_dir;
1056
1057         unless (my @files = glob "$result_dir/*") {
1058             rmdir $result_dir;
1059         }
1060     }
1061
1062     warn "Schema dump completed.\n" unless $self->{dynamic} or $self->{quiet};
1063
1064 }
1065
1066 sub _sig_comment {
1067     my ($self, $version, $ts) = @_;
1068     return qq|\n\n# Created by DBIx::Class::Schema::Loader|
1069          . qq| v| . $version
1070          . q| @ | . $ts 
1071          . qq|\n# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:|;
1072 }
1073
1074 sub _write_classfile {
1075     my ($self, $class, $text, $is_schema) = @_;
1076
1077     my $filename = $self->_get_dump_filename($class);
1078     $self->_ensure_dump_subdirs($class);
1079
1080     if (-f $filename && $self->really_erase_my_files) {
1081         warn "Deleting existing file '$filename' due to "
1082             . "'really_erase_my_files' setting\n" unless $self->{quiet};
1083         unlink($filename);
1084     }    
1085
1086     my ($custom_content, $old_md5, $old_ver, $old_ts) = $self->_get_custom_content($class, $filename);
1087
1088     if (my $old_class = $self->_upgrading_classes->{$class}) {
1089         my $old_filename = $self->_get_dump_filename($old_class);
1090
1091         my ($old_custom_content) = $self->_get_custom_content(
1092             $old_class, $old_filename, 0 # do not add default comment
1093         );
1094
1095         $old_custom_content =~ s/\n\n# You can replace.*\n1;\n//;
1096
1097         if ($old_custom_content) {
1098             $custom_content =
1099                 "\n" . $old_custom_content . "\n" . $custom_content;
1100         }
1101
1102         unlink $old_filename;
1103     }
1104
1105     $custom_content = $self->_rewrite_old_classnames($custom_content);
1106
1107     $text .= qq|$_\n|
1108         for @{$self->{_dump_storage}->{$class} || []};
1109
1110     # Check and see if the dump is infact differnt
1111
1112     my $compare_to;
1113     if ($old_md5) {
1114       $compare_to = $text . $self->_sig_comment($old_ver, $old_ts);
1115       
1116
1117       if (Digest::MD5::md5_base64($compare_to) eq $old_md5) {
1118         return unless $self->_upgrading_from && $is_schema;
1119       }
1120     }
1121
1122     $text .= $self->_sig_comment(
1123       $self->version_to_dump,
1124       POSIX::strftime('%Y-%m-%d %H:%M:%S', localtime)
1125     );
1126
1127     open(my $fh, '>', $filename)
1128         or croak "Cannot open '$filename' for writing: $!";
1129
1130     # Write the top half and its MD5 sum
1131     print $fh $text . Digest::MD5::md5_base64($text) . "\n";
1132
1133     # Write out anything loaded via external partial class file in @INC
1134     print $fh qq|$_\n|
1135         for @{$self->{_ext_storage}->{$class} || []};
1136
1137     # Write out any custom content the user has added
1138     print $fh $custom_content;
1139
1140     close($fh)
1141         or croak "Error closing '$filename': $!";
1142 }
1143
1144 sub _default_custom_content {
1145     return qq|\n\n# You can replace this text with custom|
1146          . qq| content, and it will be preserved on regeneration|
1147          . qq|\n1;\n|;
1148 }
1149
1150 sub _get_custom_content {
1151     my ($self, $class, $filename, $add_default) = @_;
1152
1153     $add_default = 1 unless defined $add_default;
1154
1155     return ($self->_default_custom_content) if ! -f $filename;
1156
1157     open(my $fh, '<', $filename)
1158         or croak "Cannot open '$filename' for reading: $!";
1159
1160     my $mark_re = 
1161         qr{^(# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:)([A-Za-z0-9/+]{22})\n};
1162
1163     my $buffer = '';
1164     my ($md5, $ts, $ver);
1165     while(<$fh>) {
1166         if(!$md5 && /$mark_re/) {
1167             $md5 = $2;
1168             my $line = $1;
1169
1170             # Pull out the previous version and timestamp
1171             ($ver, $ts) = $buffer =~ m/# Created by DBIx::Class::Schema::Loader v(.*?) @ (.*?)$/s;
1172
1173             $buffer .= $line;
1174             croak "Checksum mismatch in '$filename', 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"
1175                 if !$self->overwrite_modifications && Digest::MD5::md5_base64($buffer) ne $md5;
1176
1177             $buffer = '';
1178         }
1179         else {
1180             $buffer .= $_;
1181         }
1182     }
1183
1184     croak "Cannot not overwrite '$filename' without 'really_erase_my_files',"
1185         . " it does not appear to have been generated by Loader"
1186             if !$md5;
1187
1188     # Default custom content:
1189     $buffer ||= $self->_default_custom_content if $add_default;
1190
1191     return ($buffer, $md5, $ver, $ts);
1192 }
1193
1194 sub _use {
1195     my $self = shift;
1196     my $target = shift;
1197
1198     foreach (@_) {
1199         warn "$target: use $_;" if $self->debug;
1200         $self->_raw_stmt($target, "use $_;");
1201     }
1202 }
1203
1204 sub _inject {
1205     my $self = shift;
1206     my $target = shift;
1207     my $schema_class = $self->schema_class;
1208
1209     my $blist = join(q{ }, @_);
1210     warn "$target: use base qw/ $blist /;" if $self->debug && @_;
1211     $self->_raw_stmt($target, "use base qw/ $blist /;") if @_;
1212 }
1213
1214 sub _result_namespace {
1215     my ($self, $schema_class, $ns) = @_;
1216     my @result_namespace;
1217
1218     if ($ns =~ /^\+(.*)/) {
1219         # Fully qualified namespace
1220         @result_namespace = ($1)
1221     }
1222     else {
1223         # Relative namespace
1224         @result_namespace = ($schema_class, $ns);
1225     }
1226
1227     return wantarray ? @result_namespace : join '::', @result_namespace;
1228 }
1229
1230 # Create class with applicable bases, setup monikers, etc
1231 sub _make_src_class {
1232     my ($self, $table) = @_;
1233
1234     my $schema       = $self->schema;
1235     my $schema_class = $self->schema_class;
1236
1237     my $table_moniker = $self->_table2moniker($table);
1238     my @result_namespace = ($schema_class);
1239     if ($self->use_namespaces) {
1240         my $result_namespace = $self->result_namespace || 'Result';
1241         @result_namespace = $self->_result_namespace(
1242             $schema_class,
1243             $result_namespace,
1244         );
1245     }
1246     my $table_class = join(q{::}, @result_namespace, $table_moniker);
1247
1248     if ((my $upgrading_v = $self->_upgrading_from)
1249             || $self->_rewriting) {
1250         local $self->naming->{monikers} = $upgrading_v
1251             if $upgrading_v;
1252
1253         my @result_namespace = @result_namespace;
1254         if ($self->_upgrading_from_load_classes) {
1255             @result_namespace = ($schema_class);
1256         }
1257         elsif (my $ns = $self->_downgrading_to_load_classes) {
1258             @result_namespace = $self->_result_namespace(
1259                 $schema_class,
1260                 $ns,
1261             );
1262         }
1263         elsif ($ns = $self->_rewriting_result_namespace) {
1264             @result_namespace = $self->_result_namespace(
1265                 $schema_class,
1266                 $ns,
1267             );
1268         }
1269
1270         my $old_class = join(q{::}, @result_namespace,
1271             $self->_table2moniker($table));
1272
1273         $self->_upgrading_classes->{$table_class} = $old_class
1274             unless $table_class eq $old_class;
1275     }
1276
1277     my $table_normalized = lc $table;
1278     $self->classes->{$table} = $table_class;
1279     $self->classes->{$table_normalized} = $table_class;
1280     $self->monikers->{$table} = $table_moniker;
1281     $self->monikers->{$table_normalized} = $table_moniker;
1282
1283     $self->_use   ($table_class, @{$self->additional_classes});
1284     $self->_inject($table_class, @{$self->left_base_classes});
1285
1286     if (my @components = @{ $self->components }) {
1287         $self->_dbic_stmt($table_class, 'load_components', @components);
1288     }
1289
1290     $self->_dbic_stmt($table_class, 'load_resultset_components', @{$self->resultset_components})
1291         if @{$self->resultset_components};
1292     $self->_inject($table_class, @{$self->additional_base_classes});
1293 }
1294
1295 # Set up metadata (cols, pks, etc)
1296 sub _setup_src_meta {
1297     my ($self, $table) = @_;
1298
1299     my $schema       = $self->schema;
1300     my $schema_class = $self->schema_class;
1301
1302     my $table_class = $self->classes->{$table};
1303     my $table_moniker = $self->monikers->{$table};
1304
1305     my $table_name = $table;
1306     my $name_sep   = $self->schema->storage->sql_maker->name_sep;
1307
1308     if ($name_sep && $table_name =~ /\Q$name_sep\E/) {
1309         $table_name = \ $self->_quote_table_name($table_name);
1310     }
1311
1312     $self->_dbic_stmt($table_class,'table',$table_name);
1313
1314     my $cols = $self->_table_columns($table);
1315     my $col_info;
1316     eval { $col_info = $self->_columns_info_for($table) };
1317     if($@) {
1318         $self->_dbic_stmt($table_class,'add_columns',@$cols);
1319     }
1320     else {
1321         if ($self->_is_case_sensitive) {
1322             for my $col (keys %$col_info) {
1323                 $col_info->{$col}{accessor} = lc $col
1324                     if $col ne lc($col);
1325             }
1326         } else {
1327             $col_info = { map { lc($_), $col_info->{$_} } keys %$col_info };
1328         }
1329
1330         my $fks = $self->_table_fk_info($table);
1331
1332         for my $fkdef (@$fks) {
1333             for my $col (@{ $fkdef->{local_columns} }) {
1334                 $col_info->{$col}{is_foreign_key} = 1;
1335             }
1336         }
1337         $self->_dbic_stmt(
1338             $table_class,
1339             'add_columns',
1340             map { $_, ($col_info->{$_}||{}) } @$cols
1341         );
1342     }
1343
1344     my %uniq_tag; # used to eliminate duplicate uniqs
1345
1346     my $pks = $self->_table_pk_info($table) || [];
1347     @$pks ? $self->_dbic_stmt($table_class,'set_primary_key',@$pks)
1348           : carp("$table has no primary key");
1349     $uniq_tag{ join("\0", @$pks) }++ if @$pks; # pk is a uniq
1350
1351     my $uniqs = $self->_table_uniq_info($table) || [];
1352     for (@$uniqs) {
1353         my ($name, $cols) = @$_;
1354         next if $uniq_tag{ join("\0", @$cols) }++; # skip duplicates
1355         $self->_dbic_stmt($table_class,'add_unique_constraint', $name, $cols);
1356     }
1357
1358 }
1359
1360 =head2 tables
1361
1362 Returns a sorted list of loaded tables, using the original database table
1363 names.
1364
1365 =cut
1366
1367 sub tables {
1368     my $self = shift;
1369
1370     return keys %{$self->_tables};
1371 }
1372
1373 # Make a moniker from a table
1374 sub _default_table2moniker {
1375     no warnings 'uninitialized';
1376     my ($self, $table) = @_;
1377
1378     if ($self->naming->{monikers} eq 'v4') {
1379         return join '', map ucfirst, split /[\W_]+/, lc $table;
1380     }
1381
1382     return join '', map ucfirst, split /[\W_]+/,
1383         Lingua::EN::Inflect::Number::to_S(lc $table);
1384 }
1385
1386 sub _table2moniker {
1387     my ( $self, $table ) = @_;
1388
1389     my $moniker;
1390
1391     if( ref $self->moniker_map eq 'HASH' ) {
1392         $moniker = $self->moniker_map->{$table};
1393     }
1394     elsif( ref $self->moniker_map eq 'CODE' ) {
1395         $moniker = $self->moniker_map->($table);
1396     }
1397
1398     $moniker ||= $self->_default_table2moniker($table);
1399
1400     return $moniker;
1401 }
1402
1403 sub _load_relationships {
1404     my ($self, $table) = @_;
1405
1406     my $tbl_fk_info = $self->_table_fk_info($table);
1407     foreach my $fkdef (@$tbl_fk_info) {
1408         $fkdef->{remote_source} =
1409             $self->monikers->{delete $fkdef->{remote_table}};
1410     }
1411     my $tbl_uniq_info = $self->_table_uniq_info($table);
1412
1413     my $local_moniker = $self->monikers->{$table};
1414     my $rel_stmts = $self->_relbuilder->generate_code($local_moniker, $tbl_fk_info, $tbl_uniq_info);
1415
1416     foreach my $src_class (sort keys %$rel_stmts) {
1417         my $src_stmts = $rel_stmts->{$src_class};
1418         foreach my $stmt (@$src_stmts) {
1419             $self->_dbic_stmt($src_class,$stmt->{method},@{$stmt->{args}});
1420         }
1421     }
1422 }
1423
1424 # Overload these in driver class:
1425
1426 # Returns an arrayref of column names
1427 sub _table_columns { croak "ABSTRACT METHOD" }
1428
1429 # Returns arrayref of pk col names
1430 sub _table_pk_info { croak "ABSTRACT METHOD" }
1431
1432 # Returns an arrayref of uniqs [ [ foo => [ col1, col2 ] ], [ bar => [ ... ] ] ]
1433 sub _table_uniq_info { croak "ABSTRACT METHOD" }
1434
1435 # Returns an arrayref of foreign key constraints, each
1436 #   being a hashref with 3 keys:
1437 #   local_columns (arrayref), remote_columns (arrayref), remote_table
1438 sub _table_fk_info { croak "ABSTRACT METHOD" }
1439
1440 # Returns an array of lower case table names
1441 sub _tables_list { croak "ABSTRACT METHOD" }
1442
1443 # Execute a constructive DBIC class method, with debug/dump_to_dir hooks.
1444 sub _dbic_stmt {
1445     my $self   = shift;
1446     my $class  = shift;
1447     my $method = shift;
1448
1449     # generate the pod for this statement, storing it with $self->_pod
1450     $self->_make_pod( $class, $method, @_ ) if $self->generate_pod;
1451
1452     my $args = dump(@_);
1453     $args = '(' . $args . ')' if @_ < 2;
1454     my $stmt = $method . $args . q{;};
1455
1456     warn qq|$class\->$stmt\n| if $self->debug;
1457     $self->_raw_stmt($class, '__PACKAGE__->' . $stmt);
1458     return;
1459 }
1460
1461 # generates the accompanying pod for a DBIC class method statement,
1462 # storing it with $self->_pod
1463 sub _make_pod {
1464     my $self   = shift;
1465     my $class  = shift;
1466     my $method = shift;
1467
1468     if ( $method eq 'table' ) {
1469         my ($table) = @_;
1470         my $pcm = $self->pod_comment_mode;
1471         my ($comment, $comment_overflows, $comment_in_name, $comment_in_desc);
1472         if ( $self->can('_table_comment') ) {
1473             $comment = $self->_table_comment($table);
1474             $comment_overflows = ($comment and length $comment > $self->pod_comment_spillover_length);
1475             $comment_in_name   = ($pcm eq 'name' or ($pcm eq 'auto' and !$comment_overflows));
1476             $comment_in_desc   = ($pcm eq 'description' or ($pcm eq 'auto' and $comment_overflows));
1477         }
1478         $self->_pod( $class, "=head1 NAME" );
1479         my $table_descr = $class;
1480         $table_descr .= " - " . $comment if $comment and $comment_in_name;
1481         $self->{_class2table}{ $class } = $table;
1482         $self->_pod( $class, $table_descr );
1483         if ($comment and $comment_in_desc) {
1484             $self->_pod( $class, "=head1 DESCRIPTION" );
1485             $self->_pod( $class, $comment );
1486         }
1487         $self->_pod_cut( $class );
1488     } elsif ( $method eq 'add_columns' ) {
1489         $self->_pod( $class, "=head1 ACCESSORS" );
1490         my $col_counter = 0;
1491         my @cols = @_;
1492         while( my ($name,$attrs) = splice @cols,0,2 ) {
1493             $col_counter++;
1494             $self->_pod( $class, '=head2 ' . $name  );
1495             $self->_pod( $class,
1496                          join "\n", map {
1497                              my $s = $attrs->{$_};
1498                              $s = !defined $s      ? 'undef'          :
1499                                   length($s) == 0  ? '(empty string)' :
1500                                                      $s;
1501
1502                              "  $_: $s"
1503                          } sort keys %$attrs,
1504                        );
1505
1506             if( $self->can('_column_comment')
1507                 and my $comment = $self->_column_comment( $self->{_class2table}{$class}, $col_counter)
1508               ) {
1509                 $self->_pod( $class, $comment );
1510             }
1511         }
1512         $self->_pod_cut( $class );
1513     } elsif ( $method =~ /^(belongs_to|has_many|might_have)$/ ) {
1514         $self->_pod( $class, "=head1 RELATIONS" ) unless $self->{_relations_started} { $class } ;
1515         my ( $accessor, $rel_class ) = @_;
1516         $self->_pod( $class, "=head2 $accessor" );
1517         $self->_pod( $class, 'Type: ' . $method );
1518         $self->_pod( $class, "Related object: L<$rel_class>" );
1519         $self->_pod_cut( $class );
1520         $self->{_relations_started} { $class } = 1;
1521     }
1522 }
1523
1524 # Stores a POD documentation
1525 sub _pod {
1526     my ($self, $class, $stmt) = @_;
1527     $self->_raw_stmt( $class, "\n" . $stmt  );
1528 }
1529
1530 sub _pod_cut {
1531     my ($self, $class ) = @_;
1532     $self->_raw_stmt( $class, "\n=cut\n" );
1533 }
1534
1535 # Store a raw source line for a class (for dumping purposes)
1536 sub _raw_stmt {
1537     my ($self, $class, $stmt) = @_;
1538     push(@{$self->{_dump_storage}->{$class}}, $stmt);
1539 }
1540
1541 # Like above, but separately for the externally loaded stuff
1542 sub _ext_stmt {
1543     my ($self, $class, $stmt) = @_;
1544     push(@{$self->{_ext_storage}->{$class}}, $stmt);
1545 }
1546
1547 sub _quote_table_name {
1548     my ($self, $table) = @_;
1549
1550     my $qt = $self->schema->storage->sql_maker->quote_char;
1551
1552     return $table unless $qt;
1553
1554     if (ref $qt) {
1555         return $qt->[0] . $table . $qt->[1];
1556     }
1557
1558     return $qt . $table . $qt;
1559 }
1560
1561 sub _is_case_sensitive { 0 }
1562
1563 sub _custom_column_info {
1564     my ( $self, $info ) = @_;
1565
1566     if( ref $self->custom_column_info eq 'HASH' ) {
1567         
1568     } elsif( ref $self->custom_column_info eq 'CODE' ) {
1569         return $self->custom_column_info->($info);
1570     }
1571 }
1572
1573 # remove the dump dir from @INC on destruction
1574 sub DESTROY {
1575     my $self = shift;
1576
1577     @INC = grep $_ ne $self->dump_directory, @INC;
1578 }
1579
1580 =head2 monikers
1581
1582 Returns a hashref of loaded table to moniker mappings.  There will
1583 be two entries for each table, the original name and the "normalized"
1584 name, in the case that the two are different (such as databases
1585 that like uppercase table names, or preserve your original mixed-case
1586 definitions, or what-have-you).
1587
1588 =head2 classes
1589
1590 Returns a hashref of table to class mappings.  In some cases it will
1591 contain multiple entries per table for the original and normalized table
1592 names, as above in L</monikers>.
1593
1594 =head1 SEE ALSO
1595
1596 L<DBIx::Class::Schema::Loader>
1597
1598 =head1 AUTHOR
1599
1600 See L<DBIx::Class::Schema::Loader/AUTHOR> and L<DBIx::Class::Schema::Loader/CONTRIBUTORS>.
1601
1602 =head1 LICENSE
1603
1604 This library is free software; you can redistribute it and/or modify it under
1605 the same terms as Perl itself.
1606
1607 =cut
1608
1609 1;