rename column_accessor_map -> col_accessor_map
[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
3b71e53b 28our $VERSION = '0.07007';
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
3fea497f 43 col_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
3fea497f 313=head2 col_accessor_map
cfc5dce3 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
3fea497f 567 if (exists $args{column_accessor_map}) {
568 $args{col_accessor_map} = delete $args{column_accessor_map};
569 }
570
996be9ee 571 my $self = { %args };
572
8de81918 573 # don't lose undef options
574 for (values %$self) {
575 $_ = 0 unless defined $_;
576 }
577
996be9ee 578 bless $self => $class;
579
73099af4 580 if (my $config_file = $self->config_file) {
581 my $config_opts = do $config_file;
582
583 croak "Error reading config from $config_file: $@" if $@;
584
585 croak "Config file $config_file must be a hashref" unless ref($config_opts) eq 'HASH';
586
587 while (my ($k, $v) = each %$config_opts) {
588 $self->{$k} = $v unless exists $self->{$k};
589 }
590 }
591
996be9ee 592 $self->_ensure_arrayref(qw/additional_classes
593 additional_base_classes
594 left_base_classes
595 components
996be9ee 596 /);
597
8048320c 598 $self->_validate_class_args;
599
c9cf9b4d 600 if ($self->use_moose) {
ef8e9c69 601 if (not DBIx::Class::Schema::Loader::Optional::Dependencies->req_ok_for('use_moose')) {
53e721bc 602 die sprintf "You must install the following CPAN modules to enable the use_moose option: %s.\n",
ef8e9c69 603 DBIx::Class::Schema::Loader::Optional::Dependencies->req_missing_for('use_moose');
c9cf9b4d 604 }
605 }
606
996be9ee 607 $self->{monikers} = {};
608 $self->{classes} = {};
f53dcdf0 609 $self->{_upgrading_classes} = {};
996be9ee 610
996be9ee 611 $self->{schema_class} ||= ( ref $self->{schema} || $self->{schema} );
612 $self->{schema} ||= $self->{schema_class};
613
28b4691d 614 croak "dump_overwrite is deprecated. Please read the"
615 . " DBIx::Class::Schema::Loader::Base documentation"
616 if $self->{dump_overwrite};
617
af31090c 618 $self->{dynamic} = ! $self->{dump_directory};
79193756 619 $self->{temp_directory} ||= File::Temp::tempdir( 'dbicXXXX',
af31090c 620 TMPDIR => 1,
621 CLEANUP => 1,
622 );
623
79193756 624 $self->{dump_directory} ||= $self->{temp_directory};
625
1ad8e8c3 626 $self->real_dump_directory($self->{dump_directory});
627
01012543 628 $self->version_to_dump($DBIx::Class::Schema::Loader::VERSION);
1c95b304 629 $self->schema_version_to_dump($DBIx::Class::Schema::Loader::VERSION);
01012543 630
66afce69 631 if ((not ref $self->naming) && defined $self->naming) {
9cc8e7e1 632 my $naming_ver = $self->naming;
a8d229ff 633 $self->{naming} = {
634 relationships => $naming_ver,
635 monikers => $naming_ver,
f3a657ef 636 column_accessors => $naming_ver,
a8d229ff 637 };
638 }
639
66afce69 640 if ($self->naming) {
641 for (values %{ $self->naming }) {
c5df7397 642 $_ = $CURRENT_V if $_ eq 'current';
66afce69 643 }
644 }
645 $self->{naming} ||= {};
646
d67d058e 647 if ($self->custom_column_info && ref $self->custom_column_info ne 'CODE') {
648 croak 'custom_column_info must be a CODE ref';
649 }
650
7824616e 651 $self->_check_back_compat;
9c465d2c 652
f22644d7 653 $self->use_namespaces(1) unless defined $self->use_namespaces;
492dce8d 654 $self->generate_pod(1) unless defined $self->generate_pod;
43b982ea 655 $self->pod_comment_mode('auto') unless defined $self->pod_comment_mode;
656 $self->pod_comment_spillover_length(60) unless defined $self->pod_comment_spillover_length;
f22644d7 657
15c4393b 658 if (my $col_collision_map = $self->col_collision_map) {
659 if (my $reftype = ref $col_collision_map) {
660 if ($reftype ne 'HASH') {
661 croak "Invalid type $reftype for option 'col_collision_map'";
662 }
663 }
664 else {
665 $self->col_collision_map({ '(.*)' => $col_collision_map });
666 }
667 }
668
7824616e 669 $self;
670}
af31090c 671
7824616e 672sub _check_back_compat {
673 my ($self) = @_;
e8ad6491 674
a8d229ff 675# dynamic schemas will always be in 0.04006 mode, unless overridden
106a976a 676 if ($self->dynamic) {
fb3bb595 677# just in case, though no one is likely to dump a dynamic schema
1c95b304 678 $self->schema_version_to_dump('0.04006');
a8d229ff 679
66afce69 680 if (not %{ $self->naming }) {
681 warn <<EOF unless $ENV{SCHEMA_LOADER_BACKCOMPAT};
682
683Dynamic schema detected, will run in 0.04006 mode.
684
685Set the 'naming' attribute or the SCHEMA_LOADER_BACKCOMPAT environment variable
686to disable this warning.
a0e0a56a 687
805dbe0a 688Also consider setting 'use_namespaces => 1' if/when upgrading.
689
a0e0a56a 690See perldoc DBIx::Class::Schema::Loader::Manual::UpgradingFromV4 for more
691details.
66afce69 692EOF
693 }
f53dcdf0 694 else {
695 $self->_upgrading_from('v4');
696 }
66afce69 697
a8d229ff 698 $self->naming->{relationships} ||= 'v4';
699 $self->naming->{monikers} ||= 'v4';
700
805dbe0a 701 if ($self->use_namespaces) {
702 $self->_upgrading_from_load_classes(1);
703 }
704 else {
705 $self->use_namespaces(0);
706 }
f22644d7 707
01012543 708 return;
709 }
710
711# otherwise check if we need backcompat mode for a static schema
7824616e 712 my $filename = $self->_get_dump_filename($self->schema_class);
713 return unless -e $filename;
714
8de81918 715 my ($old_gen, $old_md5, $old_ver, $old_ts, $old_custom) =
716 $self->_parse_generated_file($filename);
7824616e 717
8de81918 718 return unless $old_ver;
719
720 # determine if the existing schema was dumped with use_moose => 1
721 if (! defined $self->use_moose) {
53e721bc 722 $self->{use_moose} = 1 if $old_gen =~ /^ (?!\s*\#) use \s+ Moose/xm;
8de81918 723 }
f22644d7 724
8de81918 725 my $load_classes = ($old_gen =~ /^__PACKAGE__->load_classes;/m) ? 1 : 0;
726 my $result_namespace = do { ($old_gen =~ /result_namespace => '([^']+)'/) ? $1 : '' };
805dbe0a 727
8de81918 728 if ($load_classes && (not defined $self->use_namespaces)) {
729 warn <<"EOF" unless $ENV{SCHEMA_LOADER_BACKCOMPAT};
805dbe0a 730
a1a91c42 731'load_classes;' static schema detected, turning off 'use_namespaces'.
805dbe0a 732
733Set the 'use_namespaces' attribute or the SCHEMA_LOADER_BACKCOMPAT environment
734variable to disable this warning.
735
736See perldoc DBIx::Class::Schema::Loader::Manual::UpgradingFromV4 for more
737details.
738EOF
8de81918 739 $self->use_namespaces(0);
740 }
741 elsif ($load_classes && $self->use_namespaces) {
742 $self->_upgrading_from_load_classes(1);
743 }
744 elsif ((not $load_classes) && defined $self->use_namespaces && ! $self->use_namespaces) {
745 $self->_downgrading_to_load_classes(
746 $result_namespace || 'Result'
747 );
748 }
749 elsif ((not defined $self->use_namespaces) || $self->use_namespaces) {
750 if (not $self->result_namespace) {
751 $self->result_namespace($result_namespace || 'Result');
752 }
753 elsif ($result_namespace ne $self->result_namespace) {
754 $self->_rewriting_result_namespace(
755 $result_namespace || 'Result'
756 );
757 }
758 }
a8d229ff 759
8de81918 760 # XXX when we go past .0 this will need fixing
761 my ($v) = $old_ver =~ /([1-9])/;
762 $v = "v$v";
a8d229ff 763
8de81918 764 return if ($v eq $CURRENT_V || $old_ver =~ /^0\.\d\d999/);
a0e0a56a 765
8de81918 766 if (not %{ $self->naming }) {
767 warn <<"EOF" unless $ENV{SCHEMA_LOADER_BACKCOMPAT};
a0e0a56a 768
8de81918 769Version $old_ver static schema detected, turning on backcompat mode.
a0e0a56a 770
771Set the 'naming' attribute or the SCHEMA_LOADER_BACKCOMPAT environment variable
772to disable this warning.
773
9990e58f 774See: 'naming' in perldoc DBIx::Class::Schema::Loader::Base .
775
2a8e93e9 776See perldoc DBIx::Class::Schema::Loader::Manual::UpgradingFromV4 if upgrading
777from version 0.04006.
a0e0a56a 778EOF
a8d229ff 779
8de81918 780 $self->naming->{relationships} ||= $v;
781 $self->naming->{monikers} ||= $v;
782 $self->naming->{column_accessors} ||= $v;
a0e0a56a 783
8de81918 784 $self->schema_version_to_dump($old_ver);
785 }
786 else {
787 $self->_upgrading_from($v);
7824616e 788 }
996be9ee 789}
790
8048320c 791sub _validate_class_args {
792 my $self = shift;
793 my $args = shift;
8de81918 794
c5df7397 795 foreach my $k (@CLASS_ARGS) {
8048320c 796 next unless $self->$k;
797
798 my @classes = ref $self->$k eq 'ARRAY' ? @{ $self->$k } : $self->$k;
799 foreach my $c (@classes) {
800 # components default to being under the DBIx::Class namespace unless they
801 # are preceeded with a '+'
802 if ( $k =~ m/components$/ && $c !~ s/^\+// ) {
803 $c = 'DBIx::Class::' . $c;
804 }
805
806 # 1 == installed, 0 == not installed, undef == invalid classname
807 my $installed = Class::Inspector->installed($c);
808 if ( defined($installed) ) {
809 if ( $installed == 0 ) {
810 croak qq/$c, as specified in the loader option "$k", is not installed/;
811 }
812 } else {
813 croak qq/$c, as specified in the loader option "$k", is an invalid class name/;
814 }
815 }
816 }
817}
818
419a2eeb 819sub _find_file_in_inc {
820 my ($self, $file) = @_;
821
822 foreach my $prefix (@INC) {
af31090c 823 my $fullpath = File::Spec->catfile($prefix, $file);
824 return $fullpath if -f $fullpath
281d0f3e 825 # abs_path throws on Windows for nonexistant files
1ad8e8c3 826 and (try { Cwd::abs_path($fullpath) }) ne
827 ((try { Cwd::abs_path(File::Spec->catfile($self->dump_directory, $file)) }) || '');
419a2eeb 828 }
829
830 return;
831}
832
fb3bb595 833sub _class_path {
f96ef30f 834 my ($self, $class) = @_;
835
836 my $class_path = $class;
837 $class_path =~ s{::}{/}g;
838 $class_path .= '.pm';
839
fb3bb595 840 return $class_path;
841}
842
843sub _find_class_in_inc {
844 my ($self, $class) = @_;
845
846 return $self->_find_file_in_inc($self->_class_path($class));
847}
848
a4b94090 849sub _rewriting {
850 my $self = shift;
851
852 return $self->_upgrading_from
853 || $self->_upgrading_from_load_classes
540a8149 854 || $self->_downgrading_to_load_classes
855 || $self->_rewriting_result_namespace
856 ;
a4b94090 857}
858
b24cb177 859sub _rewrite_old_classnames {
860 my ($self, $code) = @_;
861
a4b94090 862 return $code unless $self->_rewriting;
b24cb177 863
864 my %old_classes = reverse %{ $self->_upgrading_classes };
865
866 my $re = join '|', keys %old_classes;
867 $re = qr/\b($re)\b/;
868
68d49e50 869 $code =~ s/$re/$old_classes{$1} || $1/eg;
b24cb177 870
871 return $code;
872}
873
fb3bb595 874sub _load_external {
875 my ($self, $class) = @_;
876
0ca61324 877 return if $self->{skip_load_external};
878
ffc705f3 879 # so that we don't load our own classes, under any circumstances
880 local *INC = [ grep $_ ne $self->dump_directory, @INC ];
881
fb3bb595 882 my $real_inc_path = $self->_find_class_in_inc($class);
f96ef30f 883
ffc705f3 884 my $old_class = $self->_upgrading_classes->{$class}
a4b94090 885 if $self->_rewriting;
ffc705f3 886
887 my $old_real_inc_path = $self->_find_class_in_inc($old_class)
888 if $old_class && $old_class ne $class;
889
890 return unless $real_inc_path || $old_real_inc_path;
891
892 if ($real_inc_path) {
893 # If we make it to here, we loaded an external definition
894 warn qq/# Loaded external class definition for '$class'\n/
895 if $self->debug;
896
0dd4099e 897 my $code = $self->_rewrite_old_classnames(scalar slurp $real_inc_path);
ffc705f3 898
899 if ($self->dynamic) { # load the class too
c38ec663 900 eval_without_redefine_warnings($code);
ffc705f3 901 }
b24cb177 902
903 $self->_ext_stmt($class,
904 qq|# These lines were loaded from '$real_inc_path' found in \@INC.\n|
905 .qq|# They are now part of the custom portion of this file\n|
906 .qq|# for you to hand-edit. If you do not either delete\n|
907 .qq|# this section or remove that file from \@INC, this section\n|
908 .qq|# will be repeated redundantly when you re-create this\n|
e770e9ce 909 .qq|# file again via Loader! See skip_load_external to disable\n|
910 .qq|# this feature.\n|
b24cb177 911 );
912 chomp $code;
913 $self->_ext_stmt($class, $code);
914 $self->_ext_stmt($class,
915 qq|# End of lines loaded from '$real_inc_path' |
916 );
996be9ee 917 }
106a976a 918
ffc705f3 919 if ($old_real_inc_path) {
b511f36e 920 my $code = slurp $old_real_inc_path;
921
ffc705f3 922 $self->_ext_stmt($class, <<"EOF");
923
30a4c064 924# These lines were loaded from '$old_real_inc_path',
b08ea624 925# based on the Result class name that would have been created by an older
30a4c064 926# version of the Loader. For a static schema, this happens only once during
e770e9ce 927# upgrade. See skip_load_external to disable this feature.
ffc705f3 928EOF
b24cb177 929
b24cb177 930 $code = $self->_rewrite_old_classnames($code);
931
ffc705f3 932 if ($self->dynamic) {
933 warn <<"EOF";
934
935Detected external content in '$old_real_inc_path', a class name that would have
b08ea624 936been used by an older version of the Loader.
ffc705f3 937
938* PLEASE RENAME THIS CLASS: from '$old_class' to '$class', as that is the
939new name of the Result.
940EOF
c38ec663 941 eval_without_redefine_warnings($code);
ffc705f3 942 }
943
b24cb177 944 chomp $code;
945 $self->_ext_stmt($class, $code);
ffc705f3 946 $self->_ext_stmt($class,
947 qq|# End of lines loaded from '$old_real_inc_path' |
948 );
9e8033c1 949 }
996be9ee 950}
951
952=head2 load
953
954Does the actual schema-construction work.
955
956=cut
957
958sub load {
959 my $self = shift;
960
bfb43060 961 $self->_load_tables(
962 $self->_tables_list({ constraint => $self->constraint, exclude => $self->exclude })
963 );
b97c2c1e 964}
965
966=head2 rescan
967
a60b5b8d 968Arguments: schema
969
b511f36e 970Rescan the database for changes. Returns a list of the newly added table
971monikers.
a60b5b8d 972
b511f36e 973The schema argument should be the schema class or object to be affected. It
974should probably be derived from the original schema_class used during L</load>.
b97c2c1e 975
976=cut
977
978sub rescan {
a60b5b8d 979 my ($self, $schema) = @_;
980
981 $self->{schema} = $schema;
7824616e 982 $self->_relbuilder->{schema} = $schema;
b97c2c1e 983
984 my @created;
bfb43060 985 my @current = $self->_tables_list({ constraint => $self->constraint, exclude => $self->exclude });
0c1d5b47 986
bfb43060 987 foreach my $table (@current) {
b97c2c1e 988 if(!exists $self->{_tables}->{$table}) {
989 push(@created, $table);
990 }
991 }
992
0c1d5b47 993 my %current;
994 @current{@current} = ();
995 foreach my $table (keys %{ $self->{_tables} }) {
996 if (not exists $current{$table}) {
997 $self->_unregister_source_for_table($table);
998 }
999 }
1000
b511f36e 1001 delete $self->{_dump_storage};
1002 delete $self->{_relations_started};
1003
1004 my $loaded = $self->_load_tables(@current);
a60b5b8d 1005
b511f36e 1006 return map { $self->monikers->{$_} } @created;
b97c2c1e 1007}
1008
7824616e 1009sub _relbuilder {
1010 my ($self) = @_;
3fed44ca 1011
1012 return if $self->{skip_relationships};
1013
ef372cf4 1014 return $self->{relbuilder} ||= do {
1015
1016 no warnings 'uninitialized';
1017 my $relbuilder_suff =
1018 {qw{
1019 v4 ::Compat::v0_040
1020 v5 ::Compat::v0_05
1021 v6 ::Compat::v0_06
1022 }}
1023 ->{ $self->naming->{relationships}};
1024
1025 my $relbuilder_class = 'DBIx::Class::Schema::Loader::RelBuilder'.$relbuilder_suff;
b622b087 1026 load_class $relbuilder_class;
ef372cf4 1027 $relbuilder_class->new( $self );
a8d229ff 1028
ef372cf4 1029 };
7824616e 1030}
1031
b97c2c1e 1032sub _load_tables {
1033 my ($self, @tables) = @_;
1034
b97c2c1e 1035 # Save the new tables to the tables list
a60b5b8d 1036 foreach (@tables) {
1037 $self->{_tables}->{$_} = 1;
1038 }
f96ef30f 1039
af31090c 1040 $self->_make_src_class($_) for @tables;
27305cc1 1041
27305cc1 1042 # sanity-check for moniker clashes
1043 my $inverse_moniker_idx;
1044 for (keys %{$self->monikers}) {
1045 push @{$inverse_moniker_idx->{$self->monikers->{$_}}}, $_;
1046 }
1047
1048 my @clashes;
1049 for (keys %$inverse_moniker_idx) {
1050 my $tables = $inverse_moniker_idx->{$_};
1051 if (@$tables > 1) {
1052 push @clashes, sprintf ("tables %s reduced to the same source moniker '%s'",
1053 join (', ', map { "'$_'" } @$tables),
1054 $_,
1055 );
1056 }
1057 }
1058
1059 if (@clashes) {
1060 die 'Unable to load schema - chosen moniker/class naming style results in moniker clashes. '
1061 . 'Either change the naming style, or supply an explicit moniker_map: '
1062 . join ('; ', @clashes)
1063 . "\n"
1064 ;
1065 }
1066
1067
f96ef30f 1068 $self->_setup_src_meta($_) for @tables;
1069
e8ad6491 1070 if(!$self->skip_relationships) {
181cc907 1071 # The relationship loader needs a working schema
af31090c 1072 $self->{quiet} = 1;
79193756 1073 local $self->{dump_directory} = $self->{temp_directory};
106a976a 1074 $self->_reload_classes(\@tables);
e8ad6491 1075 $self->_load_relationships($_) for @tables;
8c70d2c7 1076 $self->_relbuilder->cleanup;
af31090c 1077 $self->{quiet} = 0;
79193756 1078
1079 # Remove that temp dir from INC so it doesn't get reloaded
ffc705f3 1080 @INC = grep $_ ne $self->dump_directory, @INC;
e8ad6491 1081 }
1082
f96ef30f 1083 $self->_load_external($_)
75451704 1084 for map { $self->classes->{$_} } @tables;
f96ef30f 1085
106a976a 1086 # Reload without unloading first to preserve any symbols from external
1087 # packages.
1ad8e8c3 1088 $self->_reload_classes(\@tables, { unload => 0 });
996be9ee 1089
5223f24a 1090 # Drop temporary cache
1091 delete $self->{_cache};
1092
c39e3507 1093 return \@tables;
996be9ee 1094}
1095
af31090c 1096sub _reload_classes {
1ad8e8c3 1097 my ($self, $tables, $opts) = @_;
106a976a 1098
1099 my @tables = @$tables;
1ad8e8c3 1100
1101 my $unload = $opts->{unload};
106a976a 1102 $unload = 1 unless defined $unload;
181cc907 1103
4daef04f 1104 # so that we don't repeat custom sections
1105 @INC = grep $_ ne $self->dump_directory, @INC;
1106
181cc907 1107 $self->_dump_to_dir(map { $self->classes->{$_} } @tables);
e9b8719e 1108
1109 unshift @INC, $self->dump_directory;
af31090c 1110
706ef173 1111 my @to_register;
1112 my %have_source = map { $_ => $self->schema->source($_) }
1113 $self->schema->sources;
1114
181cc907 1115 for my $table (@tables) {
1116 my $moniker = $self->monikers->{$table};
1117 my $class = $self->classes->{$table};
0ae6b65d 1118
1119 {
1120 no warnings 'redefine';
942bd5e0 1121 local *Class::C3::reinitialize = sub {}; # to speed things up, reinitialized below
0ae6b65d 1122 use warnings;
1123
01f93238 1124 if (my $mc = $self->_moose_metaclass($class)) {
1125 $mc->make_mutable;
c9cf9b4d 1126 }
106a976a 1127 Class::Unload->unload($class) if $unload;
706ef173 1128 my ($source, $resultset_class);
1129 if (
1130 ($source = $have_source{$moniker})
1131 && ($resultset_class = $source->resultset_class)
1132 && ($resultset_class ne 'DBIx::Class::ResultSet')
1133 ) {
1134 my $has_file = Class::Inspector->loaded_filename($resultset_class);
01f93238 1135 if (my $mc = $self->_moose_metaclass($resultset_class)) {
1136 $mc->make_mutable;
c9cf9b4d 1137 }
106a976a 1138 Class::Unload->unload($resultset_class) if $unload;
1139 $self->_reload_class($resultset_class) if $has_file;
0ae6b65d 1140 }
106a976a 1141 $self->_reload_class($class);
af31090c 1142 }
706ef173 1143 push @to_register, [$moniker, $class];
1144 }
af31090c 1145
706ef173 1146 Class::C3->reinitialize;
1147 for (@to_register) {
1148 $self->schema->register_class(@$_);
af31090c 1149 }
1150}
1151
01f93238 1152sub _moose_metaclass {
1153 return undef unless $INC{'Class/MOP.pm'}; # if CMOP is not loaded the class could not have loaded in the 1st place
1154
0dd4099e 1155 my $class = $_[1];
1156
1157 my $mc = try { Class::MOP::class_of($class) }
01f93238 1158 or return undef;
1159
1160 return $mc->isa('Moose::Meta::Class') ? $mc : undef;
1161}
1162
106a976a 1163# We use this instead of ensure_class_loaded when there are package symbols we
1164# want to preserve.
1165sub _reload_class {
1166 my ($self, $class) = @_;
1167
1168 my $class_path = $self->_class_path($class);
1169 delete $INC{ $class_path };
f53dcdf0 1170
1171# kill redefined warnings
1ad8e8c3 1172 try {
c38ec663 1173 eval_without_redefine_warnings ("require $class");
1ad8e8c3 1174 }
1175 catch {
61d1cca1 1176 my $source = slurp $self->_get_dump_filename($class);
1177 die "Failed to reload class $class: $_.\n\nCLASS SOURCE:\n\n$source";
f53dcdf0 1178 };
106a976a 1179}
1180
996be9ee 1181sub _get_dump_filename {
1182 my ($self, $class) = (@_);
1183
1184 $class =~ s{::}{/}g;
1185 return $self->dump_directory . q{/} . $class . q{.pm};
1186}
1187
1ad8e8c3 1188=head2 get_dump_filename
1189
1190Arguments: class
1191
1192Returns the full path to the file for a class that the class has been or will
1193be dumped to. This is a file in a temp dir for a dynamic schema.
1194
1195=cut
1196
1197sub get_dump_filename {
1198 my ($self, $class) = (@_);
1199
1200 local $self->{dump_directory} = $self->real_dump_directory;
1201
1202 return $self->_get_dump_filename($class);
1203}
1204
996be9ee 1205sub _ensure_dump_subdirs {
1206 my ($self, $class) = (@_);
1207
1208 my @name_parts = split(/::/, $class);
dd03ee1a 1209 pop @name_parts; # we don't care about the very last element,
1210 # which is a filename
1211
996be9ee 1212 my $dir = $self->dump_directory;
7cab3ab7 1213 while (1) {
1214 if(!-d $dir) {
25328cc4 1215 mkdir($dir) or croak "mkdir('$dir') failed: $!";
996be9ee 1216 }
7cab3ab7 1217 last if !@name_parts;
1218 $dir = File::Spec->catdir($dir, shift @name_parts);
996be9ee 1219 }
1220}
1221
1222sub _dump_to_dir {
af31090c 1223 my ($self, @classes) = @_;
996be9ee 1224
fc2b71fd 1225 my $schema_class = $self->schema_class;
9c9c2f2b 1226 my $schema_base_class = $self->schema_base_class || 'DBIx::Class::Schema';
996be9ee 1227
e9b8719e 1228 my $target_dir = $self->dump_directory;
af31090c 1229 warn "Dumping manual schema for $schema_class to directory $target_dir ...\n"
1230 unless $self->{dynamic} or $self->{quiet};
996be9ee 1231
7cab3ab7 1232 my $schema_text =
1233 qq|package $schema_class;\n\n|
b4dcbcc5 1234 . qq|# Created by DBIx::Class::Schema::Loader\n|
1ad8e8c3 1235 . qq|# DO NOT MODIFY THE FIRST PART OF THIS FILE\n\n|;
1236
dcaf302a 1237 if ($self->use_moose) {
49643e1d 1238 $schema_text.= qq|use Moose;\nuse namespace::autoclean;\nextends '$schema_base_class';\n\n|;
dcaf302a 1239 }
1240 else {
1ad8e8c3 1241 $schema_text .= qq|use strict;\nuse warnings;\n\nuse base '$schema_base_class';\n\n|;
dcaf302a 1242 }
f44ecc2f 1243
f44ecc2f 1244 if ($self->use_namespaces) {
1245 $schema_text .= qq|__PACKAGE__->load_namespaces|;
1246 my $namespace_options;
2a8e93e9 1247
1248 my @attr = qw/resultset_namespace default_resultset_class/;
1249
1250 unshift @attr, 'result_namespace' unless (not $self->result_namespace) || $self->result_namespace eq 'Result';
1251
1252 for my $attr (@attr) {
f44ecc2f 1253 if ($self->$attr) {
1254 $namespace_options .= qq| $attr => '| . $self->$attr . qq|',\n|
1255 }
1256 }
1257 $schema_text .= qq|(\n$namespace_options)| if $namespace_options;
1258 $schema_text .= qq|;\n|;
1259 }
1260 else {
1261 $schema_text .= qq|__PACKAGE__->load_classes;\n|;
f44ecc2f 1262 }
996be9ee 1263
1c95b304 1264 {
1265 local $self->{version_to_dump} = $self->schema_version_to_dump;
68d49e50 1266 $self->_write_classfile($schema_class, $schema_text, 1);
1c95b304 1267 }
996be9ee 1268
2229729e 1269 my $result_base_class = $self->result_base_class || 'DBIx::Class::Core';
9c9c2f2b 1270
af31090c 1271 foreach my $src_class (@classes) {
7cab3ab7 1272 my $src_text =
1273 qq|package $src_class;\n\n|
b4dcbcc5 1274 . qq|# Created by DBIx::Class::Schema::Loader\n|
1275 . qq|# DO NOT MODIFY THE FIRST PART OF THIS FILE\n\n|
dcaf302a 1276 . qq|use strict;\nuse warnings;\n\n|;
1277 if ($self->use_moose) {
6c2b21a5 1278 $src_text.= qq|use Moose;\nuse MooseX::NonMoose;\nuse namespace::autoclean;|;
1279
1280 # these options 'use base' which is compile time
2b74a06b 1281 if (@{ $self->left_base_classes } || @{ $self->additional_base_classes }) {
6c2b21a5 1282 $src_text .= qq|\nBEGIN { extends '$result_base_class' }\n\n|;
1283 }
1284 else {
1285 $src_text .= qq|\nextends '$result_base_class';\n\n|;
1286 }
dcaf302a 1287 }
1288 else {
1289 $src_text .= qq|use base '$result_base_class';\n\n|;
1290 }
7cab3ab7 1291 $self->_write_classfile($src_class, $src_text);
02356864 1292 }
996be9ee 1293
a4b94090 1294 # remove Result dir if downgrading from use_namespaces, and there are no
1295 # files left.
b5f1b43c 1296 if (my $result_ns = $self->_downgrading_to_load_classes
1297 || $self->_rewriting_result_namespace) {
540a8149 1298 my $result_namespace = $self->_result_namespace(
1299 $schema_class,
1300 $result_ns,
1301 );
a4b94090 1302
540a8149 1303 (my $result_dir = $result_namespace) =~ s{::}{/}g;
a4b94090 1304 $result_dir = $self->dump_directory . '/' . $result_dir;
1305
1306 unless (my @files = glob "$result_dir/*") {
1307 rmdir $result_dir;
1308 }
1309 }
1310
af31090c 1311 warn "Schema dump completed.\n" unless $self->{dynamic} or $self->{quiet};
1312
7cab3ab7 1313}
1314
79193756 1315sub _sig_comment {
1316 my ($self, $version, $ts) = @_;
1317 return qq|\n\n# Created by DBIx::Class::Schema::Loader|
1318 . qq| v| . $version
1319 . q| @ | . $ts
1320 . qq|\n# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:|;
1321}
1322
7cab3ab7 1323sub _write_classfile {
68d49e50 1324 my ($self, $class, $text, $is_schema) = @_;
7cab3ab7 1325
1326 my $filename = $self->_get_dump_filename($class);
1327 $self->_ensure_dump_subdirs($class);
1328
28b4691d 1329 if (-f $filename && $self->really_erase_my_files) {
7cab3ab7 1330 warn "Deleting existing file '$filename' due to "
af31090c 1331 . "'really_erase_my_files' setting\n" unless $self->{quiet};
7cab3ab7 1332 unlink($filename);
8de81918 1333 }
7cab3ab7 1334
8de81918 1335 my ($old_gen, $old_md5, $old_ver, $old_ts, $old_custom)
1336 = $self->_parse_generated_file($filename);
17ca645f 1337
8de81918 1338 if (! $old_gen && -f $filename) {
1339 croak "Cannot overwrite '$filename' without 'really_erase_my_files',"
1340 . " it does not appear to have been generated by Loader"
1341 }
c9cf9b4d 1342
8de81918 1343 my $custom_content = $old_custom || '';
c9cf9b4d 1344
8de81918 1345 # prepend extra custom content from a *renamed* class (singularization effect)
1346 if (my $renamed_class = $self->_upgrading_classes->{$class}) {
1347 my $old_filename = $self->_get_dump_filename($renamed_class);
c9cf9b4d 1348
8de81918 1349 if (-f $old_filename) {
1350 my $extra_custom = ($self->_parse_generated_file ($old_filename))[4];
1351
1352 $extra_custom =~ s/\n\n# You can replace.*\n1;\n//;
1353
1354 $custom_content = join ("\n", '', $extra_custom, $custom_content)
1355 if $extra_custom;
1356
1357 unlink $old_filename;
c9cf9b4d 1358 }
1359 }
1360
49643e1d 1361 $custom_content ||= $self->_default_custom_content($is_schema);
f53dcdf0 1362
8de81918 1363 # If upgrading to use_moose=1 replace default custom content with default Moose custom content.
1364 # If there is already custom content, which does not have the Moose content, add it.
1365 if ($self->use_moose) {
ffc705f3 1366
8de81918 1367 my $non_moose_custom_content = do {
1368 local $self->{use_moose} = 0;
1369 $self->_default_custom_content;
1370 };
f53dcdf0 1371
8de81918 1372 if ($custom_content eq $non_moose_custom_content) {
49643e1d 1373 $custom_content = $self->_default_custom_content($is_schema);
8de81918 1374 }
49643e1d 1375 elsif ($custom_content !~ /\Q@{[$self->_default_moose_custom_content($is_schema)]}\E/) {
1376 $custom_content .= $self->_default_custom_content($is_schema);
f53dcdf0 1377 }
1378 }
22edddda 1379 elsif (defined $self->use_moose && $old_gen) {
1380 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'
1381 if $old_gen =~ /use \s+ MooseX?\b/x;
1382 }
f53dcdf0 1383
b24cb177 1384 $custom_content = $self->_rewrite_old_classnames($custom_content);
1385
7cab3ab7 1386 $text .= qq|$_\n|
1387 for @{$self->{_dump_storage}->{$class} || []};
1388
79193756 1389 # Check and see if the dump is infact differnt
1390
1391 my $compare_to;
1392 if ($old_md5) {
1393 $compare_to = $text . $self->_sig_comment($old_ver, $old_ts);
79193756 1394 if (Digest::MD5::md5_base64($compare_to) eq $old_md5) {
68d49e50 1395 return unless $self->_upgrading_from && $is_schema;
79193756 1396 }
1397 }
1398
1399 $text .= $self->_sig_comment(
01012543 1400 $self->version_to_dump,
79193756 1401 POSIX::strftime('%Y-%m-%d %H:%M:%S', localtime)
1402 );
7cab3ab7 1403
1404 open(my $fh, '>', $filename)
1405 or croak "Cannot open '$filename' for writing: $!";
1406
1407 # Write the top half and its MD5 sum
a4476f41 1408 print $fh $text . Digest::MD5::md5_base64($text) . "\n";
7cab3ab7 1409
1410 # Write out anything loaded via external partial class file in @INC
1411 print $fh qq|$_\n|
1412 for @{$self->{_ext_storage}->{$class} || []};
1413
1eea4fb1 1414 # Write out any custom content the user has added
7cab3ab7 1415 print $fh $custom_content;
1416
1417 close($fh)
e9b8719e 1418 or croak "Error closing '$filename': $!";
7cab3ab7 1419}
1420
c9cf9b4d 1421sub _default_moose_custom_content {
49643e1d 1422 my ($self, $is_schema) = @_;
1423
1424 if (not $is_schema) {
1425 return qq|\n__PACKAGE__->meta->make_immutable;|;
1426 }
1427
1428 return qq|\n__PACKAGE__->meta->make_immutable(inline_constructor => 0);|;
c9cf9b4d 1429}
1430
79193756 1431sub _default_custom_content {
49643e1d 1432 my ($self, $is_schema) = @_;
dcaf302a 1433 my $default = qq|\n\n# You can replace this text with custom|
b8e1a9d5 1434 . qq| code or comments, and it will be preserved on regeneration|;
dcaf302a 1435 if ($self->use_moose) {
49643e1d 1436 $default .= $self->_default_moose_custom_content($is_schema);
dcaf302a 1437 }
1438 $default .= qq|\n1;\n|;
1439 return $default;
79193756 1440}
1441
8de81918 1442sub _parse_generated_file {
1443 my ($self, $fn) = @_;
7cab3ab7 1444
8de81918 1445 return unless -f $fn;
79193756 1446
8de81918 1447 open(my $fh, '<', $fn)
1448 or croak "Cannot open '$fn' for reading: $!";
7cab3ab7 1449
8de81918 1450 my $mark_re =
419a2eeb 1451 qr{^(# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:)([A-Za-z0-9/+]{22})\n};
7cab3ab7 1452
8de81918 1453 my ($md5, $ts, $ver, $gen);
7cab3ab7 1454 while(<$fh>) {
8de81918 1455 if(/$mark_re/) {
1456 my $pre_md5 = $1;
79193756 1457 $md5 = $2;
79193756 1458
8de81918 1459 # Pull out the version and timestamp from the line above
1460 ($ver, $ts) = $gen =~ m/^# Created by DBIx::Class::Schema::Loader v(.*?) @ (.*?)\Z/m;
79193756 1461
8de81918 1462 $gen .= $pre_md5;
1463 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"
1464 if !$self->overwrite_modifications && Digest::MD5::md5_base64($gen) ne $md5;
7cab3ab7 1465
8de81918 1466 last;
7cab3ab7 1467 }
1468 else {
8de81918 1469 $gen .= $_;
7cab3ab7 1470 }
996be9ee 1471 }
1472
8de81918 1473 my $custom = do { local $/; <$fh> }
1474 if $md5;
5ef3c771 1475
8de81918 1476 close ($fh);
5ef3c771 1477
8de81918 1478 return ($gen, $md5, $ver, $ts, $custom);
996be9ee 1479}
1480
1481sub _use {
1482 my $self = shift;
1483 my $target = shift;
1484
1485 foreach (@_) {
cb54990b 1486 warn "$target: use $_;" if $self->debug;
996be9ee 1487 $self->_raw_stmt($target, "use $_;");
996be9ee 1488 }
1489}
1490
1491sub _inject {
1492 my $self = shift;
1493 my $target = shift;
996be9ee 1494
af31090c 1495 my $blist = join(q{ }, @_);
6c2b21a5 1496
1497 return unless $blist;
1498
1499 warn "$target: use base qw/$blist/;" if $self->debug;
1500 $self->_raw_stmt($target, "use base qw/$blist/;");
996be9ee 1501}
1502
540a8149 1503sub _result_namespace {
1504 my ($self, $schema_class, $ns) = @_;
1505 my @result_namespace;
1506
1507 if ($ns =~ /^\+(.*)/) {
1508 # Fully qualified namespace
1509 @result_namespace = ($1)
1510 }
1511 else {
1512 # Relative namespace
1513 @result_namespace = ($schema_class, $ns);
1514 }
1515
1516 return wantarray ? @result_namespace : join '::', @result_namespace;
1517}
1518
f96ef30f 1519# Create class with applicable bases, setup monikers, etc
1520sub _make_src_class {
1521 my ($self, $table) = @_;
996be9ee 1522
a13b2803 1523 my $schema = $self->schema;
1524 my $schema_class = $self->schema_class;
996be9ee 1525
f96ef30f 1526 my $table_moniker = $self->_table2moniker($table);
f44ecc2f 1527 my @result_namespace = ($schema_class);
1528 if ($self->use_namespaces) {
1529 my $result_namespace = $self->result_namespace || 'Result';
540a8149 1530 @result_namespace = $self->_result_namespace(
1531 $schema_class,
1532 $result_namespace,
1533 );
f44ecc2f 1534 }
1535 my $table_class = join(q{::}, @result_namespace, $table_moniker);
996be9ee 1536
805dbe0a 1537 if ((my $upgrading_v = $self->_upgrading_from)
a4b94090 1538 || $self->_rewriting) {
805dbe0a 1539 local $self->naming->{monikers} = $upgrading_v
1540 if $upgrading_v;
1541
1542 my @result_namespace = @result_namespace;
a4b94090 1543 if ($self->_upgrading_from_load_classes) {
1544 @result_namespace = ($schema_class);
1545 }
1546 elsif (my $ns = $self->_downgrading_to_load_classes) {
540a8149 1547 @result_namespace = $self->_result_namespace(
1548 $schema_class,
1549 $ns,
1550 );
1551 }
1552 elsif ($ns = $self->_rewriting_result_namespace) {
1553 @result_namespace = $self->_result_namespace(
1554 $schema_class,
1555 $ns,
1556 );
a4b94090 1557 }
f53dcdf0 1558
1559 my $old_class = join(q{::}, @result_namespace,
1560 $self->_table2moniker($table));
1561
68d49e50 1562 $self->_upgrading_classes->{$table_class} = $old_class
1563 unless $table_class eq $old_class;
f53dcdf0 1564 }
1565
bfb43060 1566# this was a bad idea, should be ok now without it
1567# my $table_normalized = lc $table;
1568# $self->classes->{$table_normalized} = $table_class;
1569# $self->monikers->{$table_normalized} = $table_moniker;
1570
f96ef30f 1571 $self->classes->{$table} = $table_class;
f96ef30f 1572 $self->monikers->{$table} = $table_moniker;
996be9ee 1573
f96ef30f 1574 $self->_use ($table_class, @{$self->additional_classes});
af31090c 1575 $self->_inject($table_class, @{$self->left_base_classes});
996be9ee 1576
2229729e 1577 if (my @components = @{ $self->components }) {
1578 $self->_dbic_stmt($table_class, 'load_components', @components);
1579 }
996be9ee 1580
af31090c 1581 $self->_inject($table_class, @{$self->additional_base_classes});
f96ef30f 1582}
996be9ee 1583
26c54680 1584sub _is_result_class_method {
1585 my ($self, $name) = @_;
9fdf3d5b 1586
26c54680 1587 if (not $self->_result_class_methods) {
1588 my (@methods, %methods);
1589 my $base = $self->result_base_class || 'DBIx::Class::Core';
1590 my @components = map { /^\+/ ? substr($_,1) : "DBIx::Class::$_" } @{ $self->components || [] };
9fdf3d5b 1591
26c54680 1592 for my $class ($base, @components, $self->use_moose ? 'Moose::Object' : ()) {
1593 load_class $class;
15c4393b 1594
26c54680 1595 push @methods, @{ Class::Inspector->methods($class) || [] };
1596 }
9fdf3d5b 1597
26c54680 1598 push @methods, @{ Class::Inspector->methods('UNIVERSAL') };
9fdf3d5b 1599
26c54680 1600 @methods{@methods} = ();
9fdf3d5b 1601
26c54680 1602 # futureproof meta
1603 $methods{meta} = undef;
61d1cca1 1604
26c54680 1605 $self->_result_class_methods(\%methods);
a7116285 1606 }
26c54680 1607 my $result_methods = $self->_result_class_methods;
1608
1609 return exists $result_methods->{$name};
a7116285 1610}
1611
1612sub _resolve_col_accessor_collisions {
1613 my ($self, $table, $col_info) = @_;
1614
1615 my $table_name = ref $table ? $$table : $table;
6c2b21a5 1616
9fdf3d5b 1617 while (my ($col, $info) = each %$col_info) {
1618 my $accessor = $info->{accessor} || $col;
1619
c9486c78 1620 next if $accessor eq 'id'; # special case (very common column)
9fdf3d5b 1621
a7116285 1622 if ($self->_is_result_class_method($accessor)) {
15c4393b 1623 my $mapped = 0;
1624
1625 if (my $map = $self->col_collision_map) {
1626 for my $re (keys %$map) {
1627 if (my @matches = $col =~ /$re/) {
1628 $info->{accessor} = sprintf $map->{$re}, @matches;
1629 $mapped = 1;
1630 }
1631 }
1632 }
1633
1634 if (not $mapped) {
1635 warn <<"EOF";
a7116285 1636Column '$col' in table '$table_name' collides with an inherited method.
15c4393b 1637See "COLUMN ACCESSOR COLLISIONS" in perldoc DBIx::Class::Schema::Loader::Base .
1638EOF
1639 $info->{accessor} = undef;
1640 }
9fdf3d5b 1641 }
1642 }
1643}
1644
3fea497f 1645# use the same logic to run moniker_map, col_accessor_map, and
cfc5dce3 1646# relationship_name_map
1647sub _run_user_map {
1648 my ( $self, $map, $default_code, $ident, @extra ) = @_;
1649
1650 my $default_ident = $default_code->( $ident, @extra );
1651 my $new_ident;
1652 if( $map && ref $map eq 'HASH' ) {
1653 $new_ident = $map->{ $ident };
1654 }
1655 elsif( $map && ref $map eq 'CODE' ) {
1656 $new_ident = $map->( $ident, $default_ident, @extra );
1657 }
1658
1659 $new_ident ||= $default_ident;
1660
1661 return $new_ident;
1662}
1663
1664sub _default_column_accessor_name {
1665 my ( $self, $column_name ) = @_;
1666
1667 my $accessor_name = $column_name;
1668 $accessor_name =~ s/\W+/_/g;
1669
61d1cca1 1670 if ((($self->naming->{column_accessors}||'') =~ /(\d+)/ && $1 < 7) || (not $self->preserve_case)) {
cfc5dce3 1671 # older naming just lc'd the col accessor and that's all.
1672 return lc $accessor_name;
1673 }
f3a657ef 1674
cc4f11a2 1675 return join '_', map lc, split_name $column_name;
cfc5dce3 1676
1677}
61d1cca1 1678
cfc5dce3 1679sub _make_column_accessor_name {
1680 my ($self, $column_name, $column_context_info ) = @_;
1681
1682 my $accessor = $self->_run_user_map(
3fea497f 1683 $self->col_accessor_map,
cfc5dce3 1684 sub { $self->_default_column_accessor_name( shift ) },
1685 $column_name,
1686 $column_context_info,
1687 );
1688
1689 return $accessor;
f3a657ef 1690}
1691
af31090c 1692# Set up metadata (cols, pks, etc)
f96ef30f 1693sub _setup_src_meta {
1694 my ($self, $table) = @_;
996be9ee 1695
f96ef30f 1696 my $schema = $self->schema;
1697 my $schema_class = $self->schema_class;
a13b2803 1698
f96ef30f 1699 my $table_class = $self->classes->{$table};
1700 my $table_moniker = $self->monikers->{$table};
996be9ee 1701
ff30991a 1702 my $table_name = $table;
1703 my $name_sep = $self->schema->storage->sql_maker->name_sep;
1704
c177d483 1705 if ($name_sep && $table_name =~ /\Q$name_sep\E/) {
ff30991a 1706 $table_name = \ $self->_quote_table_name($table_name);
1707 }
1708
b1d11550 1709 my $full_table_name = ($self->qualify_objects ? ($self->db_schema . '.') : '') . (ref $table_name ? $$table_name : $table_name);
1710
1711 # be careful to not create refs Data::Dump can "optimize"
1712 $full_table_name = \do {"".$full_table_name} if ref $table_name;
1713
1714 $self->_dbic_stmt($table_class, 'table', $full_table_name);
996be9ee 1715
cfc5dce3 1716 my $cols = $self->_table_columns($table);
45be2ce7 1717 my $col_info = $self->__columns_info_for($table);
df55c5fa 1718
cfc5dce3 1719 ### generate all the column accessor names
df55c5fa 1720 while (my ($col, $info) = each %$col_info) {
cfc5dce3 1721 # hashref of other info that could be used by
1722 # user-defined accessor map functions
1723 my $context = {
1724 table_class => $table_class,
1725 table_moniker => $table_moniker,
1726 table_name => $table_name,
1727 full_table_name => $full_table_name,
1728 schema_class => $schema_class,
1729 column_info => $info,
1730 };
df55c5fa 1731
cfc5dce3 1732 $info->{accessor} = $self->_make_column_accessor_name( $col, $context );
45be2ce7 1733 }
c9373b79 1734
15c4393b 1735 $self->_resolve_col_accessor_collisions($full_table_name, $col_info);
9fdf3d5b 1736
cfc5dce3 1737 # prune any redundant accessor names
1738 while (my ($col, $info) = each %$col_info) {
1739 no warnings 'uninitialized';
1740 delete $info->{accessor} if $info->{accessor} eq $col;
1741 }
1742
45be2ce7 1743 my $fks = $self->_table_fk_info($table);
565335e6 1744
10c0c4f3 1745 foreach my $fkdef (@$fks) {
45be2ce7 1746 for my $col (@{ $fkdef->{local_columns} }) {
1747 $col_info->{$col}{is_foreign_key} = 1;
e7213f4f 1748 }
996be9ee 1749 }
10c0c4f3 1750
1751 my $pks = $self->_table_pk_info($table) || [];
1752
1753 foreach my $pkcol (@$pks) {
1754 $col_info->{$pkcol}{is_nullable} = 0;
1755 }
1756
45be2ce7 1757 $self->_dbic_stmt(
1758 $table_class,
1759 'add_columns',
1760 map { $_, ($col_info->{$_}||{}) } @$cols
1761 );
996be9ee 1762
d70c335f 1763 my %uniq_tag; # used to eliminate duplicate uniqs
1764
f96ef30f 1765 @$pks ? $self->_dbic_stmt($table_class,'set_primary_key',@$pks)
1766 : carp("$table has no primary key");
d70c335f 1767 $uniq_tag{ join("\0", @$pks) }++ if @$pks; # pk is a uniq
996be9ee 1768
f96ef30f 1769 my $uniqs = $self->_table_uniq_info($table) || [];
d70c335f 1770 for (@$uniqs) {
1771 my ($name, $cols) = @$_;
1772 next if $uniq_tag{ join("\0", @$cols) }++; # skip duplicates
1773 $self->_dbic_stmt($table_class,'add_unique_constraint', $name, $cols);
1774 }
1775
996be9ee 1776}
1777
d67d058e 1778sub __columns_info_for {
1779 my ($self, $table) = @_;
1780
1781 my $result = $self->_columns_info_for($table);
1782
1783 while (my ($col, $info) = each %$result) {
1784 $info = { %$info, %{ $self->_custom_column_info ($table, $col, $info) } };
1785 $info = { %$info, %{ $self->_datetime_column_info($table, $col, $info) } };
1786
1787 $result->{$col} = $info;
1788 }
1789
1790 return $result;
1791}
1792
996be9ee 1793=head2 tables
1794
1795Returns a sorted list of loaded tables, using the original database table
1796names.
1797
1798=cut
1799
1800sub tables {
1801 my $self = shift;
1802
b97c2c1e 1803 return keys %{$self->_tables};
996be9ee 1804}
1805
1806# Make a moniker from a table
c39e403e 1807sub _default_table2moniker {
66afce69 1808 no warnings 'uninitialized';
c39e403e 1809 my ($self, $table) = @_;
1810
a8d229ff 1811 if ($self->naming->{monikers} eq 'v4') {
1812 return join '', map ucfirst, split /[\W_]+/, lc $table;
1813 }
ecf930e6 1814 elsif ($self->naming->{monikers} eq 'v5') {
1815 return join '', map ucfirst, split /[\W_]+/,
1816 Lingua::EN::Inflect::Number::to_S(lc $table);
1817 }
9990e58f 1818 elsif ($self->naming->{monikers} eq 'v6') {
1819 (my $as_phrase = lc $table) =~ s/_+/ /g;
1820 my $inflected = Lingua::EN::Inflect::Phrase::to_S($as_phrase);
1821
1822 return join '', map ucfirst, split /\W+/, $inflected;
1823 }
1824
cc4f11a2 1825 my @words = map lc, split_name $table;
9990e58f 1826 my $as_phrase = join ' ', @words;
ecf930e6 1827
ecf930e6 1828 my $inflected = Lingua::EN::Inflect::Phrase::to_S($as_phrase);
a8d229ff 1829
ecf930e6 1830 return join '', map ucfirst, split /\W+/, $inflected;
c39e403e 1831}
1832
996be9ee 1833sub _table2moniker {
1834 my ( $self, $table ) = @_;
1835
cfc5dce3 1836 $self->_run_user_map(
1837 $self->moniker_map,
1838 sub { $self->_default_table2moniker( shift ) },
1839 $table
1840 );
996be9ee 1841}
1842
1843sub _load_relationships {
e8ad6491 1844 my ($self, $table) = @_;
996be9ee 1845
e8ad6491 1846 my $tbl_fk_info = $self->_table_fk_info($table);
1847 foreach my $fkdef (@$tbl_fk_info) {
1848 $fkdef->{remote_source} =
1849 $self->monikers->{delete $fkdef->{remote_table}};
996be9ee 1850 }
26f1c8c9 1851 my $tbl_uniq_info = $self->_table_uniq_info($table);
996be9ee 1852
e8ad6491 1853 my $local_moniker = $self->monikers->{$table};
7824616e 1854 my $rel_stmts = $self->_relbuilder->generate_code($local_moniker, $tbl_fk_info, $tbl_uniq_info);
996be9ee 1855
996be9ee 1856 foreach my $src_class (sort keys %$rel_stmts) {
1857 my $src_stmts = $rel_stmts->{$src_class};
1858 foreach my $stmt (@$src_stmts) {
1859 $self->_dbic_stmt($src_class,$stmt->{method},@{$stmt->{args}});
1860 }
1861 }
1862}
1863
1864# Overload these in driver class:
1865
1866# Returns an arrayref of column names
1867sub _table_columns { croak "ABSTRACT METHOD" }
1868
1869# Returns arrayref of pk col names
1870sub _table_pk_info { croak "ABSTRACT METHOD" }
1871
1872# Returns an arrayref of uniqs [ [ foo => [ col1, col2 ] ], [ bar => [ ... ] ] ]
1873sub _table_uniq_info { croak "ABSTRACT METHOD" }
1874
1875# Returns an arrayref of foreign key constraints, each
1876# being a hashref with 3 keys:
1877# local_columns (arrayref), remote_columns (arrayref), remote_table
1878sub _table_fk_info { croak "ABSTRACT METHOD" }
1879
1880# Returns an array of lower case table names
1881sub _tables_list { croak "ABSTRACT METHOD" }
1882
1883# Execute a constructive DBIC class method, with debug/dump_to_dir hooks.
1884sub _dbic_stmt {
bf654ab9 1885 my $self = shift;
1886 my $class = shift;
996be9ee 1887 my $method = shift;
bf654ab9 1888
1889 # generate the pod for this statement, storing it with $self->_pod
43b982ea 1890 $self->_make_pod( $class, $method, @_ ) if $self->generate_pod;
bf654ab9 1891
1892 my $args = dump(@_);
1893 $args = '(' . $args . ')' if @_ < 2;
1894 my $stmt = $method . $args . q{;};
1895
1896 warn qq|$class\->$stmt\n| if $self->debug;
1897 $self->_raw_stmt($class, '__PACKAGE__->' . $stmt);
1898 return;
1899}
1900
1901# generates the accompanying pod for a DBIC class method statement,
1902# storing it with $self->_pod
1903sub _make_pod {
1904 my $self = shift;
1905 my $class = shift;
1906 my $method = shift;
1907
fbcfebdd 1908 if ( $method eq 'table' ) {
1909 my ($table) = @_;
43b982ea 1910 my $pcm = $self->pod_comment_mode;
1911 my ($comment, $comment_overflows, $comment_in_name, $comment_in_desc);
fd97abca 1912 $comment = $self->__table_comment($table);
1913 $comment_overflows = ($comment and length $comment > $self->pod_comment_spillover_length);
1914 $comment_in_name = ($pcm eq 'name' or ($pcm eq 'auto' and !$comment_overflows));
1915 $comment_in_desc = ($pcm eq 'description' or ($pcm eq 'auto' and $comment_overflows));
43b982ea 1916 $self->_pod( $class, "=head1 NAME" );
1917 my $table_descr = $class;
1918 $table_descr .= " - " . $comment if $comment and $comment_in_name;
fbcfebdd 1919 $self->{_class2table}{ $class } = $table;
1920 $self->_pod( $class, $table_descr );
43b982ea 1921 if ($comment and $comment_in_desc) {
1922 $self->_pod( $class, "=head1 DESCRIPTION" );
1923 $self->_pod( $class, $comment );
1924 }
fbcfebdd 1925 $self->_pod_cut( $class );
1926 } elsif ( $method eq 'add_columns' ) {
1927 $self->_pod( $class, "=head1 ACCESSORS" );
79a00530 1928 my $col_counter = 0;
ceb009d3 1929 my @cols = @_;
79a00530 1930 while( my ($name,$attrs) = splice @cols,0,2 ) {
ceb009d3 1931 $col_counter++;
79a00530 1932 $self->_pod( $class, '=head2 ' . $name );
ceb009d3 1933 $self->_pod( $class,
1934 join "\n", map {
1935 my $s = $attrs->{$_};
1936 $s = !defined $s ? 'undef' :
1937 length($s) == 0 ? '(empty string)' :
1938 ref($s) eq 'SCALAR' ? $$s :
1939 ref($s) ? dumper_squashed $s :
1940 looks_like_number($s) ? $s : qq{'$s'};
1941
1942 " $_: $s"
1943 } sort keys %$attrs,
1944 );
4cd5155b 1945 if (my $comment = $self->__column_comment($self->{_class2table}{$class}, $col_counter, $name)) {
ceb009d3 1946 $self->_pod( $class, $comment );
1947 }
fbcfebdd 1948 }
1949 $self->_pod_cut( $class );
1950 } elsif ( $method =~ /^(belongs_to|has_many|might_have)$/ ) {
1951 $self->_pod( $class, "=head1 RELATIONS" ) unless $self->{_relations_started} { $class } ;
1952 my ( $accessor, $rel_class ) = @_;
1953 $self->_pod( $class, "=head2 $accessor" );
1954 $self->_pod( $class, 'Type: ' . $method );
1955 $self->_pod( $class, "Related object: L<$rel_class>" );
1956 $self->_pod_cut( $class );
1957 $self->{_relations_started} { $class } = 1;
1958 }
996be9ee 1959}
1960
fd97abca 1961sub _filter_comment {
1962 my ($self, $txt) = @_;
1963
1964 $txt = '' if not defined $txt;
1965
1966 $txt =~ s/(?:\015?\012|\015\012?)/\n/g;
1967
1968 return $txt;
1969}
1970
1971sub __table_comment {
1972 my $self = shift;
1973
1974 if (my $code = $self->can('_table_comment')) {
1975 return $self->_filter_comment($self->$code(@_));
1976 }
1977
1978 return '';
1979}
1980
1981sub __column_comment {
1982 my $self = shift;
1983
1984 if (my $code = $self->can('_column_comment')) {
1985 return $self->_filter_comment($self->$code(@_));
1986 }
1987
1988 return '';
1989}
1990
fbcfebdd 1991# Stores a POD documentation
1992sub _pod {
1993 my ($self, $class, $stmt) = @_;
1994 $self->_raw_stmt( $class, "\n" . $stmt );
1995}
1996
1997sub _pod_cut {
1998 my ($self, $class ) = @_;
1999 $self->_raw_stmt( $class, "\n=cut\n" );
2000}
2001
996be9ee 2002# Store a raw source line for a class (for dumping purposes)
2003sub _raw_stmt {
2004 my ($self, $class, $stmt) = @_;
af31090c 2005 push(@{$self->{_dump_storage}->{$class}}, $stmt);
996be9ee 2006}
2007
7cab3ab7 2008# Like above, but separately for the externally loaded stuff
2009sub _ext_stmt {
2010 my ($self, $class, $stmt) = @_;
af31090c 2011 push(@{$self->{_ext_storage}->{$class}}, $stmt);
7cab3ab7 2012}
2013
565335e6 2014sub _quote_table_name {
2015 my ($self, $table) = @_;
2016
2017 my $qt = $self->schema->storage->sql_maker->quote_char;
2018
c177d483 2019 return $table unless $qt;
2020
565335e6 2021 if (ref $qt) {
2022 return $qt->[0] . $table . $qt->[1];
2023 }
2024
2025 return $qt . $table . $qt;
2026}
2027
b639d969 2028sub _custom_column_info {
23d1f36b 2029 my ( $self, $table_name, $column_name, $column_info ) = @_;
b639d969 2030
d67d058e 2031 if (my $code = $self->custom_column_info) {
2032 return $code->($table_name, $column_name, $column_info) || {};
b639d969 2033 }
3a368709 2034 return {};
b639d969 2035}
2036
42e785fa 2037sub _datetime_column_info {
23d1f36b 2038 my ( $self, $table_name, $column_name, $column_info ) = @_;
d67d058e 2039 my $result = {};
2040 my $type = $column_info->{data_type} || '';
2041 if ((grep $_, @{ $column_info }{map "inflate_$_", qw/date datetime timestamp/})
2042 or ($type =~ /date|timestamp/i)) {
2043 $result->{timezone} = $self->datetime_timezone if $self->datetime_timezone;
2044 $result->{locale} = $self->datetime_locale if $self->datetime_locale;
42e785fa 2045 }
d67d058e 2046 return $result;
42e785fa 2047}
2048
bc1cb85e 2049sub _lc {
2050 my ($self, $name) = @_;
2051
2052 return $self->preserve_case ? $name : lc($name);
2053}
2054
2055sub _uc {
2056 my ($self, $name) = @_;
2057
2058 return $self->preserve_case ? $name : uc($name);
2059}
2060
0c1d5b47 2061sub _unregister_source_for_table {
2062 my ($self, $table) = @_;
2063
1ad8e8c3 2064 try {
0c1d5b47 2065 local $@;
2066 my $schema = $self->schema;
2067 # in older DBIC it's a private method
2068 my $unregister = $schema->can('unregister_source') || $schema->can('_unregister_source');
2069 $schema->$unregister($self->_table2moniker($table));
2070 delete $self->monikers->{$table};
2071 delete $self->classes->{$table};
2072 delete $self->_upgrading_classes->{$table};
2073 delete $self->{_tables}{$table};
2074 };
2075}
2076
ffc705f3 2077# remove the dump dir from @INC on destruction
2078sub DESTROY {
2079 my $self = shift;
2080
2081 @INC = grep $_ ne $self->dump_directory, @INC;
2082}
2083
996be9ee 2084=head2 monikers
2085
8f9d7ce5 2086Returns a hashref of loaded table to moniker mappings. There will
996be9ee 2087be two entries for each table, the original name and the "normalized"
2088name, in the case that the two are different (such as databases
2089that like uppercase table names, or preserve your original mixed-case
2090definitions, or what-have-you).
2091
2092=head2 classes
2093
8f9d7ce5 2094Returns a hashref of table to class mappings. In some cases it will
996be9ee 2095contain multiple entries per table for the original and normalized table
2096names, as above in L</monikers>.
2097
15c4393b 2098=head1 COLUMN ACCESSOR COLLISIONS
2099
2100Occasionally you may have a column name that collides with a perl method, such
2101as C<can>. In such cases, the default action is to set the C<accessor> of the
2102column spec to C<undef>.
2103
2104You can then name the accessor yourself by placing code such as the following
2105below the md5:
2106
2107 __PACKAGE__->add_column('+can' => { accessor => 'my_can' });
2108
2109Another option is to use the L</col_collision_map> option.
2110
a7116285 2111=head1 RELATIONSHIP NAME COLLISIONS
2112
2113In very rare cases, you may get a collision between a generated relationship
2114name and a method in your Result class, for example if you have a foreign key
2115called C<belongs_to>.
2116
2117This is a problem because relationship names are also relationship accessor
2118methods in L<DBIx::Class>.
2119
2120The default behavior is to append C<_rel> to the relationship name and print
2121out a warning that refers to this text.
2122
2123You can also control the renaming with the L</rel_collision_map> option.
2124
996be9ee 2125=head1 SEE ALSO
2126
2127L<DBIx::Class::Schema::Loader>
2128
be80bba7 2129=head1 AUTHOR
2130
9cc8e7e1 2131See L<DBIx::Class::Schema::Loader/AUTHOR> and L<DBIx::Class::Schema::Loader/CONTRIBUTORS>.
be80bba7 2132
2133=head1 LICENSE
2134
2135This library is free software; you can redistribute it and/or modify it under
2136the same terms as Perl itself.
2137
996be9ee 2138=cut
2139
21401;
bfb43060 2141# vim:et sts=4 sw=4 tw=0: