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