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