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