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