credits
[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;
5use base qw/Class::Accessor::Fast/;
6use Class::C3;
fa994d3c 7use Carp::Clan qw/^DBIx::Class/;
996be9ee 8use UNIVERSAL::require;
9use DBIx::Class::Schema::Loader::RelBuilder;
10use Data::Dump qw/ dump /;
11use POSIX qw//;
dd03ee1a 12use File::Spec qw//;
419a2eeb 13use Cwd qw//;
7cab3ab7 14use Digest::MD5 qw//;
996be9ee 15require DBIx::Class;
16
28b4691d 17our $VERSION = '0.04001';
32f784fc 18
996be9ee 19__PACKAGE__->mk_ro_accessors(qw/
20 schema
21 schema_class
22
23 exclude
24 constraint
25 additional_classes
26 additional_base_classes
27 left_base_classes
28 components
29 resultset_components
59cfa251 30 skip_relationships
996be9ee 31 moniker_map
32 inflect_singular
33 inflect_plural
34 debug
35 dump_directory
d65cda9e 36 dump_overwrite
28b4691d 37 really_erase_my_files
996be9ee 38
996be9ee 39 db_schema
40 _tables
41 classes
42 monikers
43 /);
44
45=head1 NAME
46
47DBIx::Class::Schema::Loader::Base - Base DBIx::Class::Schema::Loader Implementation.
48
49=head1 SYNOPSIS
50
51See L<DBIx::Class::Schema::Loader>
52
53=head1 DESCRIPTION
54
55This is the base class for the storage-specific C<DBIx::Class::Schema::*>
56classes, and implements the common functionality between them.
57
58=head1 CONSTRUCTOR OPTIONS
59
60These constructor options are the base options for
61L<DBIx::Class::Schema::Loader/loader_opts>. Available constructor options are:
62
59cfa251 63=head2 skip_relationships
996be9ee 64
59cfa251 65Skip setting up relationships. The default is to attempt the loading
66of relationships.
996be9ee 67
68=head2 debug
69
70If set to true, each constructive L<DBIx::Class> statement the loader
71decides to execute will be C<warn>-ed before execution.
72
d65cda9e 73=head2 db_schema
74
75Set the name of the schema to load (schema in the sense that your database
76vendor means it). Does not currently support loading more than one schema
77name.
78
996be9ee 79=head2 constraint
80
81Only load tables matching regex. Best specified as a qr// regex.
82
83=head2 exclude
84
85Exclude tables matching regex. Best specified as a qr// regex.
86
87=head2 moniker_map
88
8f9d7ce5 89Overrides the default table name to moniker translation. Can be either
90a hashref of table keys and moniker values, or a coderef for a translator
996be9ee 91function taking a single scalar table name argument and returning
92a scalar moniker. If the hash entry does not exist, or the function
93returns a false value, the code falls back to default behavior
94for that table name.
95
96The default behavior is: C<join '', map ucfirst, split /[\W_]+/, lc $table>,
97which is to say: lowercase everything, split up the table name into chunks
98anywhere a non-alpha-numeric character occurs, change the case of first letter
99of each chunk to upper case, and put the chunks back together. Examples:
100
101 Table Name | Moniker Name
102 ---------------------------
103 luser | Luser
104 luser_group | LuserGroup
105 luser-opts | LuserOpts
106
107=head2 inflect_plural
108
109Just like L</moniker_map> above (can be hash/code-ref, falls back to default
110if hash key does not exist or coderef returns false), but acts as a map
111for pluralizing relationship names. The default behavior is to utilize
112L<Lingua::EN::Inflect::Number/to_PL>.
113
114=head2 inflect_singular
115
116As L</inflect_plural> above, but for singularizing relationship names.
117Default behavior is to utilize L<Lingua::EN::Inflect::Number/to_S>.
118
119=head2 additional_base_classes
120
121List of additional base classes all of your table classes will use.
122
123=head2 left_base_classes
124
125List of additional base classes all of your table classes will use
126that need to be leftmost.
127
128=head2 additional_classes
129
130List of additional classes which all of your table classes will use.
131
132=head2 components
133
134List of additional components to be loaded into all of your table
135classes. A good example would be C<ResultSetManager>.
136
137=head2 resultset_components
138
8f9d7ce5 139List of additional ResultSet components to be loaded into your table
996be9ee 140classes. A good example would be C<AlwaysRS>. Component
141C<ResultSetManager> will be automatically added to the above
142C<components> list if this option is set.
143
996be9ee 144=head2 dump_directory
145
146This option is designed to be a tool to help you transition from this
147loader to a manually-defined schema when you decide it's time to do so.
148
149The value of this option is a perl libdir pathname. Within
150that directory this module will create a baseline manual
151L<DBIx::Class::Schema> module set, based on what it creates at runtime
152in memory.
153
154The created schema class will have the same classname as the one on
155which you are setting this option (and the ResultSource classes will be
7cab3ab7 156based on this name as well).
996be9ee 157
8f9d7ce5 158Normally you wouldn't hard-code this setting in your schema class, as it
996be9ee 159is meant for one-time manual usage.
160
161See L<DBIx::Class::Schema::Loader/dump_to_dir> for examples of the
162recommended way to access this functionality.
163
d65cda9e 164=head2 dump_overwrite
165
28b4691d 166Deprecated. See L</really_erase_my_files> below, which does *not* mean
167the same thing as the old C<dump_overwrite> setting from previous releases.
168
169=head2 really_erase_my_files
170
7cab3ab7 171Default false. If true, Loader will unconditionally delete any existing
172files before creating the new ones from scratch when dumping a schema to disk.
173
174The default behavior is instead to only replace the top portion of the
175file, up to and including the final stanza which contains
176C<# DO NOT MODIFY THIS OR ANYTHING ABOVE!>
177leaving any customizations you placed after that as they were.
178
28b4691d 179When C<really_erase_my_files> is not set, if the output file already exists,
7cab3ab7 180but the aforementioned final stanza is not found, or the checksum
181contained there does not match the generated contents, Loader will
182croak and not touch the file.
d65cda9e 183
28b4691d 184You should really be using version control on your schema classes (and all
185of the rest of your code for that matter). Don't blame me if a bug in this
186code wipes something out when it shouldn't have, you've been warned.
187
996be9ee 188=head1 METHODS
189
190None of these methods are intended for direct invocation by regular
191users of L<DBIx::Class::Schema::Loader>. Anything you can find here
192can also be found via standard L<DBIx::Class::Schema> methods somehow.
193
194=cut
195
196# ensure that a peice of object data is a valid arrayref, creating
197# an empty one or encapsulating whatever's there.
198sub _ensure_arrayref {
199 my $self = shift;
200
201 foreach (@_) {
202 $self->{$_} ||= [];
203 $self->{$_} = [ $self->{$_} ]
204 unless ref $self->{$_} eq 'ARRAY';
205 }
206}
207
208=head2 new
209
210Constructor for L<DBIx::Class::Schema::Loader::Base>, used internally
211by L<DBIx::Class::Schema::Loader>.
212
213=cut
214
215sub new {
216 my ( $class, %args ) = @_;
217
218 my $self = { %args };
219
220 bless $self => $class;
221
996be9ee 222 $self->_ensure_arrayref(qw/additional_classes
223 additional_base_classes
224 left_base_classes
225 components
226 resultset_components
227 /);
228
229 push(@{$self->{components}}, 'ResultSetManager')
230 if @{$self->{resultset_components}};
231
232 $self->{monikers} = {};
233 $self->{classes} = {};
234
996be9ee 235 $self->{schema_class} ||= ( ref $self->{schema} || $self->{schema} );
236 $self->{schema} ||= $self->{schema_class};
237
28b4691d 238 croak "dump_overwrite is deprecated. Please read the"
239 . " DBIx::Class::Schema::Loader::Base documentation"
240 if $self->{dump_overwrite};
241
e8ad6491 242 $self->{relbuilder} = DBIx::Class::Schema::Loader::RelBuilder->new(
243 $self->schema_class, $self->inflect_plural, $self->inflect_singular
244 ) if !$self->{skip_relationships};
245
996be9ee 246 $self;
247}
248
419a2eeb 249sub _find_file_in_inc {
250 my ($self, $file) = @_;
251
252 foreach my $prefix (@INC) {
253 my $fullpath = $prefix . '/' . $file;
254 return $fullpath if -f $fullpath;
255 }
256
257 return;
258}
259
996be9ee 260sub _load_external {
f96ef30f 261 my ($self, $class) = @_;
262
263 my $class_path = $class;
264 $class_path =~ s{::}{/}g;
265 $class_path .= '.pm';
266
267 my $inc_path = $self->_find_file_in_inc($class_path);
268
269 return if !$inc_path;
270
271 my $real_dump_path = $self->dump_directory
272 ? Cwd::abs_path(
273 File::Spec->catfile($self->dump_directory, $class_path)
274 )
275 : '';
276 my $real_inc_path = Cwd::abs_path($inc_path);
277 return if $real_inc_path eq $real_dump_path;
278
279 $class->require;
280 croak "Failed to load external class definition"
281 . " for '$class': $@"
282 if $@;
283
284 # If we make it to here, we loaded an external definition
285 warn qq/# Loaded external class definition for '$class'\n/
286 if $self->debug;
287
288 # The rest is only relevant when dumping
289 return if !$self->dump_directory;
290
291 croak 'Failed to locate actual external module file for '
292 . "'$class'"
293 if !$real_inc_path;
294 open(my $fh, '<', $real_inc_path)
295 or croak "Failed to open '$real_inc_path' for reading: $!";
296 $self->_ext_stmt($class,
297 qq|# These lines were loaded from '$real_inc_path' found in \@INC.|
298 .q|# They are now part of the custom portion of this file|
299 .q|# for you to hand-edit. If you do not either delete|
300 .q|# this section or remove that file from @INC, this section|
301 .q|# will be repeated redundantly when you re-create this|
302 .q|# file again via Loader!|
303 );
304 while(<$fh>) {
305 chomp;
306 $self->_ext_stmt($class, $_);
996be9ee 307 }
f96ef30f 308 $self->_ext_stmt($class,
70b72fab 309 qq|# End of lines loaded from '$real_inc_path' |
f96ef30f 310 );
311 close($fh)
312 or croak "Failed to close $real_inc_path: $!";
996be9ee 313}
314
315=head2 load
316
317Does the actual schema-construction work.
318
319=cut
320
321sub load {
322 my $self = shift;
323
b97c2c1e 324 $self->_load_tables($self->_tables_list);
325}
326
327=head2 rescan
328
a60b5b8d 329Arguments: schema
330
b97c2c1e 331Rescan the database for newly added tables. Does
a60b5b8d 332not process drops or changes. Returns a list of
333the newly added table monikers.
334
335The schema argument should be the schema class
336or object to be affected. It should probably
337be derived from the original schema_class used
338during L</load>.
b97c2c1e 339
340=cut
341
342sub rescan {
a60b5b8d 343 my ($self, $schema) = @_;
344
345 $self->{schema} = $schema;
b97c2c1e 346
347 my @created;
348 my @current = $self->_tables_list;
349 foreach my $table ($self->_tables_list) {
350 if(!exists $self->{_tables}->{$table}) {
351 push(@created, $table);
352 }
353 }
354
355 $self->_load_tables(@created);
a60b5b8d 356
357 return map { $self->monikers->{$_} } @created;
b97c2c1e 358}
359
360sub _load_tables {
361 my ($self, @tables) = @_;
362
f96ef30f 363 # First, use _tables_list with constraint and exclude
364 # to get a list of tables to operate on
365
366 my $constraint = $self->constraint;
367 my $exclude = $self->exclude;
f96ef30f 368
b97c2c1e 369 @tables = grep { /$constraint/ } @tables if $constraint;
370 @tables = grep { ! /$exclude/ } @tables if $exclude;
f96ef30f 371
b97c2c1e 372 # Save the new tables to the tables list
a60b5b8d 373 foreach (@tables) {
374 $self->{_tables}->{$_} = 1;
375 }
f96ef30f 376
377 # Set up classes/monikers
378 {
379 no warnings 'redefine';
380 local *Class::C3::reinitialize = sub { };
381 use warnings;
382
383 $self->_make_src_class($_) for @tables;
384 }
385
386 Class::C3::reinitialize;
387
388 $self->_setup_src_meta($_) for @tables;
389
e8ad6491 390 if(!$self->skip_relationships) {
391 $self->_load_relationships($_) for @tables;
392 }
393
f96ef30f 394 $self->_load_external($_)
75451704 395 for map { $self->classes->{$_} } @tables;
f96ef30f 396
996be9ee 397 $self->_dump_to_dir if $self->dump_directory;
398
5223f24a 399 # Drop temporary cache
400 delete $self->{_cache};
401
996be9ee 402 1;
403}
404
405sub _get_dump_filename {
406 my ($self, $class) = (@_);
407
408 $class =~ s{::}{/}g;
409 return $self->dump_directory . q{/} . $class . q{.pm};
410}
411
412sub _ensure_dump_subdirs {
413 my ($self, $class) = (@_);
414
415 my @name_parts = split(/::/, $class);
dd03ee1a 416 pop @name_parts; # we don't care about the very last element,
417 # which is a filename
418
996be9ee 419 my $dir = $self->dump_directory;
7cab3ab7 420 while (1) {
421 if(!-d $dir) {
25328cc4 422 mkdir($dir) or croak "mkdir('$dir') failed: $!";
996be9ee 423 }
7cab3ab7 424 last if !@name_parts;
425 $dir = File::Spec->catdir($dir, shift @name_parts);
996be9ee 426 }
427}
428
429sub _dump_to_dir {
430 my ($self) = @_;
431
432 my $target_dir = $self->dump_directory;
d65cda9e 433
fc2b71fd 434 my $schema_class = $self->schema_class;
996be9ee 435
25328cc4 436 croak "Must specify target directory for dumping!" if ! $target_dir;
996be9ee 437
fc2b71fd 438 warn "Dumping manual schema for $schema_class to directory $target_dir ...\n";
996be9ee 439
7cab3ab7 440 my $schema_text =
441 qq|package $schema_class;\n\n|
442 . qq|use strict;\nuse warnings;\n\n|
443 . qq|use base 'DBIx::Class::Schema';\n\n|
444 . qq|__PACKAGE__->load_classes;\n|;
996be9ee 445
7cab3ab7 446 $self->_write_classfile($schema_class, $schema_text);
996be9ee 447
7cab3ab7 448 foreach my $src_class (sort keys %{$self->{_dump_storage}}) {
449 my $src_text =
450 qq|package $src_class;\n\n|
451 . qq|use strict;\nuse warnings;\n\n|
452 . qq|use base 'DBIx::Class';\n\n|;
996be9ee 453
7cab3ab7 454 $self->_write_classfile($src_class, $src_text);
02356864 455 }
996be9ee 456
7cab3ab7 457 warn "Schema dump completed.\n";
458}
459
460sub _write_classfile {
461 my ($self, $class, $text) = @_;
462
463 my $filename = $self->_get_dump_filename($class);
464 $self->_ensure_dump_subdirs($class);
465
28b4691d 466 if (-f $filename && $self->really_erase_my_files) {
7cab3ab7 467 warn "Deleting existing file '$filename' due to "
28b4691d 468 . "'really_erase_my_files' setting\n";
7cab3ab7 469 unlink($filename);
470 }
471
419a2eeb 472 my $custom_content = $self->_get_custom_content($class, $filename);
7cab3ab7 473
474 $custom_content ||= qq|\n# You can replace this text with custom|
475 . qq| content, and it will be preserved on regeneration|
476 . qq|\n1;\n|;
477
478 $text .= qq|$_\n|
479 for @{$self->{_dump_storage}->{$class} || []};
480
481 $text .= qq|\n\n# Created by DBIx::Class::Schema::Loader|
482 . qq| v| . $DBIx::Class::Schema::Loader::VERSION
483 . q| @ | . POSIX::strftime('%Y-%m-%d %H:%M:%S', localtime)
484 . qq|\n# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:|;
485
486 open(my $fh, '>', $filename)
487 or croak "Cannot open '$filename' for writing: $!";
488
489 # Write the top half and its MD5 sum
490 print $fh $text . Digest::MD5::md5_base64($text) . "\n\n";
491
492 # Write out anything loaded via external partial class file in @INC
493 print $fh qq|$_\n|
494 for @{$self->{_ext_storage}->{$class} || []};
495
496 print $fh $custom_content;
497
498 close($fh)
499 or croak "Cannot close '$filename': $!";
500}
501
502sub _get_custom_content {
503 my ($self, $class, $filename) = @_;
504
505 return if ! -f $filename;
506 open(my $fh, '<', $filename)
507 or croak "Cannot open '$filename' for reading: $!";
508
509 my $mark_re =
419a2eeb 510 qr{^(# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:)([A-Za-z0-9/+]{22})\n};
7cab3ab7 511
512 my $found = 0;
513 my $buffer = '';
514 while(<$fh>) {
515 if(!$found && /$mark_re/) {
516 $found = 1;
517 $buffer .= $1;
7cab3ab7 518 croak "Checksum mismatch in '$filename'"
419a2eeb 519 if Digest::MD5::md5_base64($buffer) ne $2;
7cab3ab7 520
521 $buffer = '';
522 }
523 else {
524 $buffer .= $_;
525 }
996be9ee 526 }
527
28b4691d 528 croak "Cannot not overwrite '$filename' without 'really_erase_my_files',"
419a2eeb 529 . " it does not appear to have been generated by Loader"
5ef3c771 530 if !$found;
531
7cab3ab7 532 return $buffer;
996be9ee 533}
534
535sub _use {
536 my $self = shift;
537 my $target = shift;
cb54990b 538 my $evalstr;
996be9ee 539
540 foreach (@_) {
cb54990b 541 warn "$target: use $_;" if $self->debug;
996be9ee 542 $self->_raw_stmt($target, "use $_;");
cb54990b 543 $_->require or croak ($_ . "->require: $@");
544 $evalstr .= "package $target; use $_;";
996be9ee 545 }
cb54990b 546 eval $evalstr if $evalstr;
547 croak $@ if $@;
996be9ee 548}
549
550sub _inject {
551 my $self = shift;
552 my $target = shift;
553 my $schema_class = $self->schema_class;
554
555 my $blist = join(q{ }, @_);
cb54990b 556 warn "$target: use base qw/ $blist /;" if $self->debug && @_;
996be9ee 557 $self->_raw_stmt($target, "use base qw/ $blist /;") if @_;
996be9ee 558 foreach (@_) {
559 $_->require or croak ($_ . "->require: $@");
560 $schema_class->inject_base($target, $_);
561 }
562}
563
f96ef30f 564# Create class with applicable bases, setup monikers, etc
565sub _make_src_class {
566 my ($self, $table) = @_;
996be9ee 567
a13b2803 568 my $schema = $self->schema;
569 my $schema_class = $self->schema_class;
996be9ee 570
f96ef30f 571 my $table_moniker = $self->_table2moniker($table);
572 my $table_class = $schema_class . q{::} . $table_moniker;
996be9ee 573
f96ef30f 574 my $table_normalized = lc $table;
575 $self->classes->{$table} = $table_class;
576 $self->classes->{$table_normalized} = $table_class;
577 $self->monikers->{$table} = $table_moniker;
578 $self->monikers->{$table_normalized} = $table_moniker;
996be9ee 579
f96ef30f 580 { no strict 'refs'; @{"${table_class}::ISA"} = qw/DBIx::Class/ }
996be9ee 581
f96ef30f 582 $self->_use ($table_class, @{$self->additional_classes});
583 $self->_inject($table_class, @{$self->additional_base_classes});
996be9ee 584
605fcea8 585 $self->_dbic_stmt($table_class, 'load_components', @{$self->components}, 'Core');
996be9ee 586
f96ef30f 587 $self->_dbic_stmt($table_class, 'load_resultset_components', @{$self->resultset_components})
588 if @{$self->resultset_components};
589 $self->_inject($table_class, @{$self->left_base_classes});
590}
996be9ee 591
f96ef30f 592# Set up metadata (cols, pks, etc) and register the class with the schema
593sub _setup_src_meta {
594 my ($self, $table) = @_;
996be9ee 595
f96ef30f 596 my $schema = $self->schema;
597 my $schema_class = $self->schema_class;
a13b2803 598
f96ef30f 599 my $table_class = $self->classes->{$table};
600 my $table_moniker = $self->monikers->{$table};
996be9ee 601
f96ef30f 602 $self->_dbic_stmt($table_class,'table',$table);
996be9ee 603
f96ef30f 604 my $cols = $self->_table_columns($table);
605 my $col_info;
606 eval { $col_info = $self->_columns_info_for($table) };
607 if($@) {
608 $self->_dbic_stmt($table_class,'add_columns',@$cols);
609 }
610 else {
611 my %col_info_lc = map { lc($_), $col_info->{$_} } keys %$col_info;
612 $self->_dbic_stmt(
613 $table_class,
614 'add_columns',
615 map { $_, ($col_info_lc{$_}||{}) } @$cols
616 );
996be9ee 617 }
618
f96ef30f 619 my $pks = $self->_table_pk_info($table) || [];
620 @$pks ? $self->_dbic_stmt($table_class,'set_primary_key',@$pks)
621 : carp("$table has no primary key");
996be9ee 622
f96ef30f 623 my $uniqs = $self->_table_uniq_info($table) || [];
624 $self->_dbic_stmt($table_class,'add_unique_constraint',@$_) for (@$uniqs);
996be9ee 625
f96ef30f 626 $schema_class->register_class($table_moniker, $table_class);
627 $schema->register_class($table_moniker, $table_class) if $schema ne $schema_class;
996be9ee 628}
629
630=head2 tables
631
632Returns a sorted list of loaded tables, using the original database table
633names.
634
635=cut
636
637sub tables {
638 my $self = shift;
639
b97c2c1e 640 return keys %{$self->_tables};
996be9ee 641}
642
643# Make a moniker from a table
644sub _table2moniker {
645 my ( $self, $table ) = @_;
646
647 my $moniker;
648
649 if( ref $self->moniker_map eq 'HASH' ) {
650 $moniker = $self->moniker_map->{$table};
651 }
652 elsif( ref $self->moniker_map eq 'CODE' ) {
653 $moniker = $self->moniker_map->($table);
654 }
655
656 $moniker ||= join '', map ucfirst, split /[\W_]+/, lc $table;
657
658 return $moniker;
659}
660
661sub _load_relationships {
e8ad6491 662 my ($self, $table) = @_;
996be9ee 663
e8ad6491 664 my $tbl_fk_info = $self->_table_fk_info($table);
665 foreach my $fkdef (@$tbl_fk_info) {
666 $fkdef->{remote_source} =
667 $self->monikers->{delete $fkdef->{remote_table}};
996be9ee 668 }
669
e8ad6491 670 my $local_moniker = $self->monikers->{$table};
671 my $rel_stmts = $self->{relbuilder}->generate_code($local_moniker, $tbl_fk_info);
996be9ee 672
996be9ee 673 foreach my $src_class (sort keys %$rel_stmts) {
674 my $src_stmts = $rel_stmts->{$src_class};
675 foreach my $stmt (@$src_stmts) {
676 $self->_dbic_stmt($src_class,$stmt->{method},@{$stmt->{args}});
677 }
678 }
679}
680
681# Overload these in driver class:
682
683# Returns an arrayref of column names
684sub _table_columns { croak "ABSTRACT METHOD" }
685
686# Returns arrayref of pk col names
687sub _table_pk_info { croak "ABSTRACT METHOD" }
688
689# Returns an arrayref of uniqs [ [ foo => [ col1, col2 ] ], [ bar => [ ... ] ] ]
690sub _table_uniq_info { croak "ABSTRACT METHOD" }
691
692# Returns an arrayref of foreign key constraints, each
693# being a hashref with 3 keys:
694# local_columns (arrayref), remote_columns (arrayref), remote_table
695sub _table_fk_info { croak "ABSTRACT METHOD" }
696
697# Returns an array of lower case table names
698sub _tables_list { croak "ABSTRACT METHOD" }
699
700# Execute a constructive DBIC class method, with debug/dump_to_dir hooks.
701sub _dbic_stmt {
702 my $self = shift;
703 my $class = shift;
704 my $method = shift;
705
706 if(!$self->debug && !$self->dump_directory) {
707 $class->$method(@_);
708 return;
709 }
710
711 my $args = dump(@_);
712 $args = '(' . $args . ')' if @_ < 2;
713 my $stmt = $method . $args . q{;};
714
715 warn qq|$class\->$stmt\n| if $self->debug;
716 $class->$method(@_);
717 $self->_raw_stmt($class, '__PACKAGE__->' . $stmt);
718}
719
720# Store a raw source line for a class (for dumping purposes)
721sub _raw_stmt {
722 my ($self, $class, $stmt) = @_;
723 push(@{$self->{_dump_storage}->{$class}}, $stmt) if $self->dump_directory;
724}
725
7cab3ab7 726# Like above, but separately for the externally loaded stuff
727sub _ext_stmt {
728 my ($self, $class, $stmt) = @_;
729 push(@{$self->{_ext_storage}->{$class}}, $stmt) if $self->dump_directory;
730}
731
996be9ee 732=head2 monikers
733
8f9d7ce5 734Returns a hashref of loaded table to moniker mappings. There will
996be9ee 735be two entries for each table, the original name and the "normalized"
736name, in the case that the two are different (such as databases
737that like uppercase table names, or preserve your original mixed-case
738definitions, or what-have-you).
739
740=head2 classes
741
8f9d7ce5 742Returns a hashref of table to class mappings. In some cases it will
996be9ee 743contain multiple entries per table for the original and normalized table
744names, as above in L</monikers>.
745
746=head1 SEE ALSO
747
748L<DBIx::Class::Schema::Loader>
749
750=cut
751
7521;