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