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