Use newly refactored code for DB interaction
[dbsrgits/DBIx-Class-DeploymentHandler.git] / lib / DBIx / Class / DeploymentHandler / DeployMethod / SQL / Translator.pm
1 package DBIx::Class::DeploymentHandler::DeployMethod::SQL::Translator;
2 use Moose;
3
4 # ABSTRACT: Manage your SQL and Perl migrations in nicely laid out directories
5
6 use autodie;
7 use Carp qw( carp croak );
8 use DBIx::Class::DeploymentHandler::Logger;
9 use Log::Contextual qw(:log :dlog), -default_logger =>
10   DBIx::Class::DeploymentHandler::Logger->new({
11     env_prefix => 'DBICDH'
12   });
13
14 use Method::Signatures::Simple;
15 use Try::Tiny;
16
17 use SQL::Translator;
18 require SQL::Translator::Diff;
19
20 require DBIx::Class::Storage;   # loaded for type constraint
21 use DBIx::Class::DeploymentHandler::Types;
22
23 use File::Path 'mkpath';
24 use File::Spec::Functions;
25
26 with 'DBIx::Class::DeploymentHandler::HandlesDeploy';
27
28 has ignore_ddl => (
29   isa      => 'Bool',
30   is       => 'ro',
31   default  => undef,
32 );
33
34 has schema => (
35   isa      => 'DBIx::Class::Schema',
36   is       => 'ro',
37   required => 1,
38 );
39
40 has storage => (
41   isa        => 'DBIx::Class::Storage',
42   is         => 'ro',
43   lazy_build => 1,
44 );
45
46 method _build_storage {
47   my $s = $self->schema->storage;
48   $s->_determine_driver;
49   $s
50 }
51
52 has sql_translator_args => (
53   isa => 'HashRef',
54   is  => 'ro',
55   default => sub { {} },
56 );
57 has script_directory => (
58   isa      => 'Str',
59   is       => 'ro',
60   required => 1,
61   default  => 'sql',
62 );
63
64 has databases => (
65   coerce  => 1,
66   isa     => 'DBIx::Class::DeploymentHandler::Databases',
67   is      => 'ro',
68   default => sub { [qw( MySQL SQLite PostgreSQL )] },
69 );
70
71 has txn_wrap => (
72   is => 'ro',
73   isa => 'Bool',
74   default => 1,
75 );
76
77 has schema_version => (
78   is => 'ro',
79   isa => 'Str',
80   lazy_build => 1,
81 );
82
83 # this will probably never get called as the DBICDH
84 # will be passing down a schema_version normally, which
85 # is built the same way, but we leave this in place
86 method _build_schema_version { $self->schema->schema_version }
87
88 method __ddl_consume_with_prefix($type, $versions, $prefix) {
89   my $base_dir = $self->script_directory;
90
91   my $main    = catfile( $base_dir, $type      );
92   my $generic = catfile( $base_dir, '_generic' );
93   my $common  =
94     catfile( $base_dir, '_common', $prefix, join q(-), @{$versions} );
95
96   my $dir;
97   if (-d $main) {
98     $dir = catfile($main, $prefix, join q(-), @{$versions})
99   } elsif (-d $generic) {
100     $dir = catfile($generic, $prefix, join q(-), @{$versions});
101   } else {
102     croak "neither $main or $generic exist; please write/generate some SQL";
103   }
104
105   my %files;
106   try {
107      opendir my($dh), $dir;
108      %files =
109        map { $_ => "$dir/$_" }
110        grep { /\.(?:sql|pl|sql-\w+)$/ && -f "$dir/$_" }
111        readdir $dh;
112      closedir $dh;
113   } catch {
114     die $_ unless $self->ignore_ddl;
115   };
116   if (-d $common) {
117     opendir my($dh), $common;
118     for my $filename (grep { /\.(?:sql|pl)$/ && -f catfile($common,$_) } readdir $dh) {
119       unless ($files{$filename}) {
120         $files{$filename} = catfile($common,$filename);
121       }
122     }
123     closedir $dh;
124   }
125
126   return [@files{sort keys %files}]
127 }
128
129 method _ddl_preinstall_consume_filenames($type, $version) {
130   $self->__ddl_consume_with_prefix($type, [ $version ], 'preinstall')
131 }
132
133 method _ddl_schema_consume_filenames($type, $version) {
134   $self->__ddl_consume_with_prefix($type, [ $version ], 'schema')
135 }
136
137 method _ddl_protoschema_produce_filename($version) {
138   my $dirname = catfile( $self->script_directory, '_protoschema', $version );
139   mkpath($dirname) unless -d $dirname;
140
141   return catfile( $dirname, '001-auto.yml' );
142 }
143
144 method _ddl_schema_produce_filename($type, $version) {
145   my $dirname = catfile( $self->script_directory, $type, 'schema', $version );
146   mkpath($dirname) unless -d $dirname;
147
148   return catfile( $dirname, '001-auto.sql' );
149 }
150
151 method _ddl_schema_up_consume_filenames($type, $versions) {
152   $self->__ddl_consume_with_prefix($type, $versions, 'up')
153 }
154
155 method _ddl_schema_down_consume_filenames($type, $versions) {
156   $self->__ddl_consume_with_prefix($type, $versions, 'down')
157 }
158
159 method _ddl_schema_up_produce_filename($type, $versions) {
160   my $dir = $self->script_directory;
161
162   my $dirname = catfile( $dir, $type, 'up', join q(-), @{$versions});
163   mkpath($dirname) unless -d $dirname;
164
165   return catfile( $dirname, '001-auto.sql' );
166 }
167
168 method _ddl_schema_down_produce_filename($type, $versions, $dir) {
169   my $dirname = catfile( $dir, $type, 'down', join q(-), @{$versions} );
170   mkpath($dirname) unless -d $dirname;
171
172   return catfile( $dirname, '001-auto.sql');
173 }
174
175 method _run_sql_array($sql) {
176   my $storage = $self->storage;
177
178   $sql = [grep {
179     $_ && # remove blank lines
180     !/^(BEGIN|BEGIN TRANSACTION|COMMIT)/ # strip txn's
181   } map {
182     s/^\s+//; s/\s+$//; # trim whitespace
183     join '', grep { !/^--/ } split /\n/ # remove comments
184   } @$sql];
185
186   Dlog_trace { "Running SQL $_" } $sql;
187   foreach my $line (@{$sql}) {
188     $storage->_query_start($line);
189     # the whole reason we do this is so that we can see the line that was run
190     try {
191       $storage->dbh_do (sub { $_[1]->do($line) });
192     }
193     catch {
194       die "$_ (running line '$line')"
195     }
196     $storage->_query_end($line);
197   }
198   return join "\n", @$sql
199 }
200
201 method _run_sql($filename) {
202   log_debug { "Running SQL from $filename" };
203   return $self->_run_sql_array($self->_read_sql_file($filename));
204 }
205
206 method _run_perl($filename) {
207   log_debug { "Running Perl from $filename" };
208   my $filedata = do { local( @ARGV, $/ ) = $filename; <> };
209
210   no warnings 'redefine';
211   my $fn = eval "$filedata";
212   use warnings;
213   Dlog_trace { "Running Perl $_" } $fn;
214
215   if ($@) {
216     carp "$filename failed to compile: $@";
217   } elsif (ref $fn eq 'CODE') {
218     $fn->($self->schema)
219   } else {
220     carp "$filename should define an anonymouse sub that takes a schema but it didn't!";
221   }
222 }
223
224 method _run_sql_and_perl($filenames, $sql_to_run) {
225   my @files   = @{$filenames};
226   my $guard   = $self->schema->txn_scope_guard if $self->txn_wrap;
227
228   $self->_run_sql_array($sql_to_run) if $self->ignore_ddl;
229
230   my $sql = ($sql_to_run)?join ";\n", @$sql_to_run:'';
231   FILENAME:
232   for my $filename (@files) {
233     if ($self->ignore_ddl && $filename =~ /^[^_]*-auto.*\.sql$/) {
234       next FILENAME
235     } elsif ($filename =~ /\.sql$/) {
236        $sql .= $self->_run_sql($filename)
237     } elsif ( $filename =~ /\.pl$/ ) {
238        $self->_run_perl($filename)
239     } else {
240       croak "A file ($filename) got to deploy that wasn't sql or perl!";
241     }
242   }
243
244   $guard->commit if $self->txn_wrap;
245
246   return $sql;
247 }
248
249 sub deploy {
250   my $self = shift;
251   my $version = (shift @_ || {})->{version} || $self->schema_version;
252   log_info { "deploying version $version" };
253   my $sqlt_type = $self->storage->sqlt_type;
254   my $sql;
255   if ($self->ignore_ddl) {
256      $sql = $self->_sql_from_yaml({},
257        '_ddl_protoschema_produce_filename', $sqlt_type
258      );
259   }
260   return $self->_run_sql_and_perl($self->_ddl_schema_consume_filenames(
261     $sqlt_type,
262     $version,
263   ), $sql);
264 }
265
266 sub preinstall {
267   my $self         = shift;
268   my $args         = shift;
269   my $version      = $args->{version}      || $self->schema_version;
270   log_info { "preinstalling version $version" };
271   my $storage_type = $args->{storage_type} || $self->storage->sqlt_type;
272
273   my @files = @{$self->_ddl_preinstall_consume_filenames(
274     $storage_type,
275     $version,
276   )};
277
278   for my $filename (@files) {
279     # We ignore sql for now (till I figure out what to do with it)
280     if ( $filename =~ /^(.+)\.pl$/ ) {
281       my $filedata = do { local( @ARGV, $/ ) = $filename; <> };
282
283       no warnings 'redefine';
284       my $fn = eval "$filedata";
285       use warnings;
286
287       if ($@) {
288         carp "$filename failed to compile: $@";
289       } elsif (ref $fn eq 'CODE') {
290         $fn->()
291       } else {
292         carp "$filename should define an anonymous sub but it didn't!";
293       }
294     } else {
295       croak "A file ($filename) got to preinstall_scripts that wasn't sql or perl!";
296     }
297   }
298 }
299
300 method _sqldiff_from_yaml($from_version, $to_version, $db) {
301   my $dir       = $self->script_directory;
302   my $sqltargs = {
303     add_drop_table => 1,
304     ignore_constraint_names => 1,
305     ignore_index_names => 1,
306     %{$self->sql_translator_args}
307   };
308
309   my $source_schema;
310   {
311     my $prefilename = $self->_ddl_protoschema_produce_filename($from_version, $dir);
312
313     # should probably be a croak
314     carp("No previous schema file found ($prefilename)")
315        unless -e $prefilename;
316
317     my $t = SQL::Translator->new({
318        %{$sqltargs},
319        debug => 0,
320        trace => 0,
321        parser => 'SQL::Translator::Parser::YAML',
322     });
323
324     my $out = $t->translate( $prefilename )
325       or croak($t->error);
326
327     $source_schema = $t->schema;
328
329     $source_schema->name( $prefilename )
330       unless  $source_schema->name;
331   }
332
333   my $dest_schema;
334   {
335     my $filename = $self->_ddl_protoschema_produce_filename($to_version, $dir);
336
337     # should probably be a croak
338     carp("No next schema file found ($filename)")
339        unless -e $filename;
340
341     my $t = SQL::Translator->new({
342        %{$sqltargs},
343        debug => 0,
344        trace => 0,
345        parser => 'SQL::Translator::Parser::YAML',
346     });
347
348     my $out = $t->translate( $filename )
349       or croak($t->error);
350
351     $dest_schema = $t->schema;
352
353     $dest_schema->name( $filename )
354       unless $dest_schema->name;
355   }
356   return [SQL::Translator::Diff::schema_diff(
357      $source_schema, $db,
358      $dest_schema,   $db,
359      $sqltargs
360   )];
361 }
362
363 method _sql_from_yaml($sqltargs, $from_file, $db) {
364   my $schema    = $self->schema;
365   my $version   = $self->schema_version;
366
367   my $sqlt = SQL::Translator->new({
368     add_drop_table          => 0,
369     parser                  => 'SQL::Translator::Parser::YAML',
370     %{$sqltargs},
371     producer => $db,
372   });
373
374   my $yaml_filename = $self->$from_file($version);
375
376   my @sql = $sqlt->translate($yaml_filename);
377   if(!@sql) {
378     carp("Failed to translate to $db, skipping. (" . $sqlt->error . ")");
379     return undef;
380   }
381   return \@sql;
382 }
383
384 sub _prepare_install {
385   my $self      = shift;
386   my $sqltargs  = { %{$self->sql_translator_args}, %{shift @_} };
387   my $from_file = shift;
388   my $to_file   = shift;
389   my $dir       = $self->script_directory;
390   my $databases = $self->databases;
391   my $version   = $self->schema_version;
392
393   foreach my $db (@$databases) {
394     my $sql = $self->_sql_from_yaml($sqltargs, $from_file, $db ) or next;
395
396     my $filename = $self->$to_file($db, $version, $dir);
397     if (-e $filename ) {
398       carp "Overwriting existing DDL file - $filename";
399       unlink $filename;
400     }
401     open my $file, q(>), $filename;
402     print {$file} join ";\n", @$sql;
403     close $file;
404   }
405 }
406
407 sub _resultsource_install_filename {
408   my ($self, $source_name) = @_;
409   return sub {
410     my ($self, $type, $version) = @_;
411     my $dirname = catfile( $self->script_directory, $type, 'schema', $version );
412     mkpath($dirname) unless -d $dirname;
413
414     return catfile( $dirname, "001-auto-$source_name.sql" );
415   }
416 }
417
418 sub _resultsource_protoschema_filename {
419   my ($self, $source_name) = @_;
420   return sub {
421     my ($self, $version) = @_;
422     my $dirname = catfile( $self->script_directory, '_protoschema', $version );
423     mkpath($dirname) unless -d $dirname;
424
425     return catfile( $dirname, "001-auto-$source_name.yml" );
426   }
427 }
428
429 sub install_resultsource {
430   my ($self, $args) = @_;
431   my $source          = $args->{result_source};
432   my $version         = $args->{version};
433   log_info { 'installing_resultsource ' . $source->source_name . ", version $version" };
434   my $rs_install_file =
435     $self->_resultsource_install_filename($source->source_name);
436
437   my $files = [
438      $self->$rs_install_file(
439       $self->storage->sqlt_type,
440       $version,
441     )
442   ];
443   $self->_run_sql_and_perl($files);
444 }
445
446 sub prepare_resultsource_install {
447   my $self = shift;
448   my $source = (shift @_)->{result_source};
449   log_info { 'preparing install for resultsource ' . $source->source_name };
450
451   my $install_filename = $self->_resultsource_install_filename($source->source_name);
452   my $proto_filename = $self->_resultsource_protoschema_filename($source->source_name);
453   $self->prepare_protoschema({
454       parser_args => { sources => [$source->source_name], }
455   }, $proto_filename);
456   $self->_prepare_install({}, $proto_filename, $install_filename);
457 }
458
459 sub prepare_deploy {
460   log_info { 'preparing deploy' };
461   my $self = shift;
462   $self->prepare_protoschema({}, '_ddl_protoschema_produce_filename');
463   $self->_prepare_install({}, '_ddl_protoschema_produce_filename', '_ddl_schema_produce_filename');
464 }
465
466 sub prepare_upgrade {
467   my ($self, $args) = @_;
468   log_info {
469      "preparing upgrade from $args->{from_version} to $args->{to_version}"
470   };
471   $self->_prepare_changegrade(
472     $args->{from_version}, $args->{to_version}, $args->{version_set}, 'up'
473   );
474 }
475
476 sub prepare_downgrade {
477   my ($self, $args) = @_;
478   log_info {
479      "preparing downgrade from $args->{from_version} to $args->{to_version}"
480   };
481   $self->_prepare_changegrade(
482     $args->{from_version}, $args->{to_version}, $args->{version_set}, 'down'
483   );
484 }
485
486 method _prepare_changegrade($from_version, $to_version, $version_set, $direction) {
487   my $schema    = $self->schema;
488   my $databases = $self->databases;
489   my $dir       = $self->script_directory;
490
491   my $schema_version = $self->schema_version;
492   my $diff_file_method = "_ddl_schema_${direction}_produce_filename";
493   foreach my $db (@$databases) {
494     my $diff_file = $self->$diff_file_method($db, $version_set, $dir );
495     if(-e $diff_file) {
496       carp("Overwriting existing $direction-diff file - $diff_file");
497       unlink $diff_file;
498     }
499
500     open my $file, q(>), $diff_file;
501     print {$file} join ";\n", @{$self->_sqldiff_from_yaml($from_version, $to_version, $db)};
502     close $file;
503   }
504 }
505
506 method _read_sql_file($file) {
507   return unless $file;
508
509   open my $fh, '<', $file;
510   my @data = split /;\n/, join '', <$fh>;
511   close $fh;
512
513   @data = grep {
514     $_ && # remove blank lines
515     !/^(BEGIN|BEGIN TRANSACTION|COMMIT)/ # strip txn's
516   } map {
517     s/^\s+//; s/\s+$//; # trim whitespace
518     join '', grep { !/^--/ } split /\n/ # remove comments
519   } @data;
520
521   return \@data;
522 }
523
524 sub downgrade_single_step {
525   my $self = shift;
526   my $version_set = (shift @_)->{version_set};
527   Dlog_info { "downgrade_single_step'ing $_" } $version_set;
528
529   my $sqlt_type = $self->storage->sqlt_type;
530   my $sql_to_run;
531   if ($self->ignore_ddl) {
532      $sql_to_run = $self->_sqldiff_from_yaml(
533        $version_set->[0], $version_set->[1], $sqlt_type
534      );
535   }
536   my $sql = $self->_run_sql_and_perl($self->_ddl_schema_down_consume_filenames(
537     $sqlt_type,
538     $version_set,
539   ), $sql_to_run);
540
541   return ['', $sql];
542 }
543
544 sub upgrade_single_step {
545   my $self = shift;
546   my $version_set = (shift @_)->{version_set};
547   Dlog_info { "upgrade_single_step'ing $_" } $version_set;
548
549   my $sqlt_type = $self->storage->sqlt_type;
550   my $sql_to_run;
551   if ($self->ignore_ddl) {
552      $sql_to_run = $self->_sqldiff_from_yaml(
553        $version_set->[0], $version_set->[1], $sqlt_type
554      );
555   }
556   my $sql = $self->_run_sql_and_perl($self->_ddl_schema_up_consume_filenames(
557     $sqlt_type,
558     $version_set,
559   ), $sql_to_run);
560   return ['', $sql];
561 }
562
563 sub prepare_protoschema {
564   my $self      = shift;
565   my $sqltargs  = { %{$self->sql_translator_args}, %{shift @_} };
566   my $to_file   = shift;
567   my $filename
568     = $self->$to_file($self->schema_version);
569
570   # we do this because the code that uses this sets parser args,
571   # so we just need to merge in the package
572   $sqltargs->{parser_args}{package} = $self->schema;
573   my $sqlt = SQL::Translator->new({
574     parser                  => 'SQL::Translator::Parser::DBIx::Class',
575     producer                => 'SQL::Translator::Producer::YAML',
576     %{ $sqltargs },
577   });
578
579   my $yml = $sqlt->translate;
580
581   croak("Failed to translate to YAML: " . $sqlt->error)
582     unless $yml;
583
584   if (-e $filename ) {
585     carp "Overwriting existing DDL-YML file - $filename";
586     unlink $filename;
587   }
588
589   open my $file, q(>), $filename;
590   print {$file} $yml;
591   close $file;
592 }
593
594 __PACKAGE__->meta->make_immutable;
595
596 1;
597
598 # vim: ts=2 sw=2 expandtab
599
600 __END__
601
602 =head1 DESCRIPTION
603
604 This class is the meat of L<DBIx::Class::DeploymentHandler>.  It takes care
605 of generating serialized schemata  as well as sql files to move from one
606 version of a schema to the rest.  One of the hallmark features of this class
607 is that it allows for multiple sql files for deploy and upgrade, allowing
608 developers to fine tune deployment.  In addition it also allows for perl
609 files to be run at any stage of the process.
610
611 For basic usage see L<DBIx::Class::DeploymentHandler::HandlesDeploy>.  What's
612 documented here is extra fun stuff or private methods.
613
614 =head1 DIRECTORY LAYOUT
615
616 Arguably this is the best feature of L<DBIx::Class::DeploymentHandler>.  It's
617 heavily based upon L<DBIx::Migration::Directories>, but has some extensions and
618 modifications, so even if you are familiar with it, please read this.  I feel
619 like the best way to describe the layout is with the following example:
620
621  $sql_migration_dir
622  |- SQLite
623  |  |- down
624  |  |  `- 2-1
625  |  |     `- 001-auto.sql
626  |  |- schema
627  |  |  `- 1
628  |  |     `- 001-auto.sql
629  |  `- up
630  |     |- 1-2
631  |     |  `- 001-auto.sql
632  |     `- 2-3
633  |        `- 001-auto.sql
634  |- _common
635  |  |- down
636  |  |  `- 2-1
637  |  |     `- 002-remove-customers.pl
638  |  `- up
639  |     `- 1-2
640  |        `- 002-generate-customers.pl
641  |- _generic
642  |  |- down
643  |  |  `- 2-1
644  |  |     `- 001-auto.sql
645  |  |- schema
646  |  |  `- 1
647  |  |     `- 001-auto.sql
648  |  `- up
649  |     `- 1-2
650  |        |- 001-auto.sql
651  |        `- 002-create-stored-procedures.sql
652  `- MySQL
653     |- down
654     |  `- 2-1
655     |     `- 001-auto.sql
656     |- preinstall
657     |  `- 1
658     |     |- 001-create_database.pl
659     |     `- 002-create_users_and_permissions.pl
660     |- schema
661     |  `- 1
662     |     `- 001-auto.sql
663     `- up
664        `- 1-2
665           `- 001-auto.sql
666
667 So basically, the code
668
669  $dm->deploy(1)
670
671 on an C<SQLite> database that would simply run
672 C<$sql_migration_dir/SQLite/schema/1/001-auto.sql>.  Next,
673
674  $dm->upgrade_single_step([1,2])
675
676 would run C<$sql_migration_dir/SQLite/up/1-2/001-auto.sql> followed by
677 C<$sql_migration_dir/_common/up/1-2/002-generate-customers.pl>.
678
679 C<.pl> files don't have to be in the C<_common> directory, but most of the time
680 they should be, because perl scripts are generally be database independent.
681
682 C<_generic> exists for when you for some reason are sure that your SQL is
683 generic enough to run on all databases.  Good luck with that one.
684
685 Note that unlike most steps in the process, C<preinstall> will not run SQL, as
686 there may not even be an database at preinstall time.  It will run perl scripts
687 just like the other steps in the process, but nothing is passed to them.
688 Until people have used this more it will remain freeform, but a recommended use
689 of preinstall is to have it prompt for username and password, and then call the
690 appropriate C<< CREATE DATABASE >> commands etc.
691
692 =head1 PERL SCRIPTS
693
694 A perl script for this tool is very simple.  It merely needs to contain an
695 anonymous sub that takes a L<DBIx::Class::Schema> as it's only argument.
696 A very basic perl script might look like:
697
698  #!perl
699
700  use strict;
701  use warnings;
702
703  sub {
704    my $schema = shift;
705
706    $schema->resultset('Users')->create({
707      name => 'root',
708      password => 'root',
709    })
710  }
711
712 =attr schema
713
714 The L<DBIx::Class::Schema> (B<required>) that is used to talk to the database
715 and generate the DDL.
716
717 =attr storage
718
719 The L<DBIx::Class::Storage> that is I<actually> used to talk to the database
720 and generate the DDL.  This is automatically created with L</_build_storage>.
721
722 =attr sql_translator_args
723
724 The arguments that get passed to L<SQL::Translator> when it's used.
725
726 =attr script_directory
727
728 The directory (default C<'sql'>) that scripts are stored in
729
730 =attr databases
731
732 The types of databases (default C<< [qw( MySQL SQLite PostgreSQL )] >>) to
733 generate files for
734
735 =attr txn_wrap
736
737 Set to true (which is the default) to wrap all upgrades and deploys in a single
738 transaction.
739
740 =attr schema_version
741
742 The version the schema on your harddrive is at.  Defaults to
743 C<< $self->schema->schema_version >>.
744
745 =begin comment
746
747 =head2 __ddl_consume_with_prefix
748
749  $dm->__ddl_consume_with_prefix( 'SQLite', [qw( 1.00 1.01 )], 'up' )
750
751 This is the meat of the multi-file upgrade/deploy stuff.  It returns a list of
752 files in the order that they should be run for a generic "type" of upgrade.
753 You should not be calling this in user code.
754
755 =head2 _ddl_schema_consume_filenames
756
757  $dm->__ddl_schema_consume_filenames( 'SQLite', [qw( 1.00 )] )
758
759 Just a curried L</__ddl_consume_with_prefix>.  Get's a list of files for an
760 initial deploy.
761
762 =head2 _ddl_schema_produce_filename
763
764  $dm->__ddl_schema_produce_filename( 'SQLite', [qw( 1.00 )] )
765
766 Returns a single file in which an initial schema will be stored.
767
768 =head2 _ddl_schema_up_consume_filenames
769
770  $dm->_ddl_schema_up_consume_filenames( 'SQLite', [qw( 1.00 )] )
771
772 Just a curried L</__ddl_consume_with_prefix>.  Get's a list of files for an
773 upgrade.
774
775 =head2 _ddl_schema_down_consume_filenames
776
777  $dm->_ddl_schema_down_consume_filenames( 'SQLite', [qw( 1.00 )] )
778
779 Just a curried L</__ddl_consume_with_prefix>.  Get's a list of files for a
780 downgrade.
781
782 =head2 _ddl_schema_up_produce_filenames
783
784  $dm->_ddl_schema_up_produce_filename( 'SQLite', [qw( 1.00 1.01 )] )
785
786 Returns a single file in which the sql to upgrade from one schema to another
787 will be stored.
788
789 =head2 _ddl_schema_down_produce_filename
790
791  $dm->_ddl_schema_down_produce_filename( 'SQLite', [qw( 1.00 1.01 )] )
792
793 Returns a single file in which the sql to downgrade from one schema to another
794 will be stored.
795
796 =head2 _resultsource_install_filename
797
798  my $filename_fn = $dm->_resultsource_install_filename('User');
799  $dm->$filename_fn('SQLite', '1.00')
800
801 Returns a function which in turn returns a single filename used to install a
802 single resultsource.  Weird interface is convenient for me.  Deal with it.
803
804 =head2 _run_sql_and_perl
805
806  $dm->_run_sql_and_perl([qw( list of filenames )])
807
808 Simply put, this runs the list of files passed to it.  If the file ends in
809 C<.sql> it runs it as sql and if it ends in C<.pl> it runs it as a perl file.
810
811 Depending on L</txn_wrap> all of the files run will be wrapped in a single
812 transaction.
813
814 =head2 _prepare_install
815
816  $dm->_prepare_install({ add_drop_table => 0 }, sub { 'file_to_create' })
817
818 Generates the sql file for installing the database.  First arg is simply
819 L<SQL::Translator> args and the second is a coderef that returns the filename
820 to store the sql in.
821
822 =head2 _prepare_changegrade
823
824  $dm->_prepare_changegrade('1.00', '1.01', [qw( 1.00 1.01)], 'up')
825
826 Generates the sql file for migrating from one schema version to another.  First
827 arg is the version to start from, second is the version to go to, third is the
828 L<version set|DBIx::Class::DeploymentHandler/VERSION SET>, and last is the
829 direction of the changegrade, be it 'up' or 'down'.
830
831 =head2 _read_sql_file
832
833  $dm->_read_sql_file('foo.sql')
834
835 Reads a sql file and returns lines in an C<ArrayRef>.  Strips out comments,
836 transactions, and blank lines.
837
838 =end comment