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