use coderef instead of run method
[dbsrgits/DBIx-Class-DeploymentHandler.git] / lib / DBIx / Class / DeploymentHandler / DeployMethod / SQL / Translator.pm
CommitLineData
45d0d9d5 1package DBIx::Class::DeploymentHandler::DeployMethod::SQL::Translator;
334bced5 2use Moose;
9af9d0b2 3
9a3a62f1 4# ABSTRACT: Manage your SQL and Perl migrations in nicely laid out directories
5
9af9d0b2 6use autodie;
7use Carp qw( carp croak );
8
2e68a8e1 9use Method::Signatures::Simple;
7f50d101 10use Try::Tiny;
9af9d0b2 11
d23c7c77 12use SQL::Translator;
13require SQL::Translator::Diff;
9af9d0b2 14
d23c7c77 15require DBIx::Class::Storage; # loaded for type constraint
41863428 16use DBIx::Class::DeploymentHandler::Types;
17
9af9d0b2 18use File::Path 'mkpath';
19use File::Spec::Functions;
2e68a8e1 20
7521a845 21with 'DBIx::Class::DeploymentHandler::HandlesDeploy';
3c1b5ee8 22
d54b8d69 23has schema => (
24 isa => 'DBIx::Class::Schema',
25 is => 'ro',
26 required => 1,
d54b8d69 27);
28
334bced5 29has storage => (
30 isa => 'DBIx::Class::Storage',
31 is => 'ro',
32 lazy_build => 1,
33);
34
2eaf903b 35method _build_storage {
36 my $s = $self->schema->storage;
37 $s->_determine_driver;
38 $s
39}
40
02a7b8ac 41has sql_translator_args => (
334bced5 42 isa => 'HashRef',
43 is => 'ro',
44 default => sub { {} },
45);
46has upgrade_directory => (
47 isa => 'Str',
48 is => 'ro',
49 required => 1,
50 default => 'sql',
51);
52
334bced5 53has databases => (
54 coerce => 1,
55 isa => 'DBIx::Class::DeploymentHandler::Databases',
56 is => 'ro',
57 default => sub { [qw( MySQL SQLite PostgreSQL )] },
58);
59
a7d53deb 60has txn_wrap => (
61 is => 'ro',
62 isa => 'Bool',
63 default => 1,
64);
65
73caa630 66has schema_version => (
67 is => 'ro',
68 lazy_build => 1,
69);
70
71method _build_schema_version { $self->schema->schema_version }
72
76d311e7 73method __ddl_consume_with_prefix($type, $versions, $prefix) {
262166c1 74 my $base_dir = $self->upgrade_directory;
75
76d08d08 76 my $main = catfile( $base_dir, $type );
77 my $generic = catfile( $base_dir, '_generic' );
78 my $common =
79 catfile( $base_dir, '_common', $prefix, join q(-), @{$versions} );
262166c1 80
81 my $dir;
82 if (-d $main) {
76d08d08 83 $dir = catfile($main, $prefix, join q(-), @{$versions})
262166c1 84 } elsif (-d $generic) {
9af9d0b2 85 $dir = catfile($generic, $prefix, join q(-), @{$versions});
262166c1 86 } else {
9af9d0b2 87 croak "neither $main or $generic exist; please write/generate some SQL";
262166c1 88 }
89
90 opendir my($dh), $dir;
41219a5d 91 my %files = map { $_ => "$dir/$_" } grep { /\.(?:sql|pl)$/ && -f "$dir/$_" } readdir $dh;
262166c1 92 closedir $dh;
93
94 if (-d $common) {
95 opendir my($dh), $common;
41219a5d 96 for my $filename (grep { /\.(?:sql|pl)$/ && -f catfile($common,$_) } readdir $dh) {
262166c1 97 unless ($files{$filename}) {
9af9d0b2 98 $files{$filename} = catfile($common,$filename);
262166c1 99 }
100 }
101 closedir $dh;
102 }
103
104 return [@files{sort keys %files}]
105}
3c1b5ee8 106
fc4b7602 107method _ddl_preinstall_consume_filenames($type, $version) {
108 $self->__ddl_consume_with_prefix($type, [ $version ], 'preinstall')
109}
110
76d311e7 111method _ddl_schema_consume_filenames($type, $version) {
112 $self->__ddl_consume_with_prefix($type, [ $version ], 'schema')
3c1b5ee8 113}
114
76d311e7 115method _ddl_schema_produce_filename($type, $version) {
76d08d08 116 my $dirname = catfile( $self->upgrade_directory, $type, 'schema', $version );
117 mkpath($dirname) unless -d $dirname;
d54b8d69 118
76d08d08 119 return catfile( $dirname, '001-auto.sql' );
d54b8d69 120}
121
76d311e7 122method _ddl_schema_up_consume_filenames($type, $versions) {
123 $self->__ddl_consume_with_prefix($type, $versions, 'up')
3c1b5ee8 124}
125
76d311e7 126method _ddl_schema_down_consume_filenames($type, $versions) {
127 $self->__ddl_consume_with_prefix($type, $versions, 'down')
a41a04e5 128}
129
76d311e7 130method _ddl_schema_up_produce_filename($type, $versions) {
131 my $dir = $self->upgrade_directory;
132
76d08d08 133 my $dirname = catfile( $dir, $type, 'up', join q(-), @{$versions});
134 mkpath($dirname) unless -d $dirname;
a41a04e5 135
76d08d08 136 return catfile( $dirname, '001-auto.sql'
a41a04e5 137 );
138}
139
76d311e7 140method _ddl_schema_down_produce_filename($type, $versions, $dir) {
76d08d08 141 my $dirname = catfile( $dir, $type, 'down', join q(-), @{$versions} );
142 mkpath($dirname) unless -d $dirname;
24f4524b 143
76d08d08 144 return catfile( $dirname, '001-auto.sql');
24f4524b 145}
146
41219a5d 147method _run_sql_and_perl($filenames) {
148 my @files = @{$filenames};
149 my $storage = $self->storage;
2e68a8e1 150
c8a2f7bd 151
a7d53deb 152 my $guard = $self->schema->txn_scope_guard if $self->txn_wrap;
153
41219a5d 154 my $sql;
155 for my $filename (@files) {
156 if ($filename =~ /\.sql$/) {
157 my @sql = @{$self->_read_sql_file($filename)};
158 $sql .= join "\n", @sql;
159
160 foreach my $line (@sql) {
161 $storage->_query_start($line);
162 try {
163 # do a dbh_do cycle here, as we need some error checking in
164 # place (even though we will ignore errors)
165 $storage->dbh_do (sub { $_[1]->do($line) });
166 }
167 catch {
168 carp "$_ (running '${line}')"
169 }
170 $storage->_query_end($line);
171 }
0841a743 172 } elsif ( $filename =~ /^(.+)\.pl$/ ) {
0841a743 173 my $filedata = do { local( @ARGV, $/ ) = $filename; <> };
0841a743 174
175 no warnings 'redefine';
5b5defbc 176 my $fn = eval "$filedata";
0841a743 177 use warnings;
178
5b5defbc 179 if ($@) {
180 carp "$filename failed to compile: $@";
181 } elsif (ref $fn eq 'CODE') {
182 $fn->($self->schema)
98c9484a 183 } else {
5b5defbc 184 carp "$filename should define an anonymouse sub that takes a schema but it didn't!";
98c9484a 185 }
41219a5d 186 } else {
fc4b7602 187 croak "A file ($filename) got to deploy that wasn't sql or perl!";
2e68a8e1 188 }
2e68a8e1 189 }
a7d53deb 190
191 $guard->commit if $self->txn_wrap;
41219a5d 192
193 return $sql;
194}
195
196sub deploy {
197 my $self = shift;
92c34cab 198 my $version = shift || $self->schema_version;
41219a5d 199
200 return $self->_run_sql_and_perl($self->_ddl_schema_consume_filenames(
201 $self->storage->sqlt_type,
92c34cab 202 $version,
41219a5d 203 ));
2e68a8e1 204}
205
fc4b7602 206sub preinstall_scripts {
207 my $self = shift;
208 my $version = shift || $self->schema_version;
209
210 my @files = @{$self->_ddl_preinstall_consume_filenames(
211 $self->storage->sqlt_type,
212 $version,
213 )};
214
215 for my $filename (@files) {
216 # We ignore sql for now (till I figure out what to do with it)
217 if ( $filename =~ /^(.+)\.pl$/ ) {
fc4b7602 218 my $filedata = do { local( @ARGV, $/ ) = $filename; <> };
fc4b7602 219
5b5defbc 220 no warnings 'redefine';
221 my $fn = eval "$filedata";
fc4b7602 222 use warnings;
5b5defbc 223
3fa64c79 224 if ($@) {
225 carp "$filename failed to compile: $@";
5b5defbc 226 } elsif (ref $fn eq 'CODE') {
fc4b7602 227 $fn->()
228 } else {
5b5defbc 229 carp "$filename should define an anonymous sub but it didn't!";
fc4b7602 230 }
231 } else {
232 croak "A file ($filename) got to preinstall_scripts that wasn't sql or perl!";
233 }
234 }
235}
236
c8a2f7bd 237sub _prepare_install {
73caa630 238 my $self = shift;
02a7b8ac 239 my $sqltargs = { %{$self->sql_translator_args}, %{shift @_} };
c8a2f7bd 240 my $to_file = shift;
2e68a8e1 241 my $schema = $self->schema;
242 my $databases = $self->databases;
243 my $dir = $self->upgrade_directory;
73caa630 244 my $version = $self->schema_version;
d54b8d69 245
9600776d 246 my $sqlt = SQL::Translator->new({
d54b8d69 247 add_drop_table => 1,
2e68a8e1 248 ignore_constraint_names => 1,
d54b8d69 249 ignore_index_names => 1,
250 parser => 'SQL::Translator::Parser::DBIx::Class',
3aaf766f 251 %{$sqltargs}
9600776d 252 });
2e68a8e1 253
d53e0bfc 254 my $sqlt_schema = $sqlt->translate( data => $schema )
387b11d2 255 or croak($sqlt->error);
2e68a8e1 256
257 foreach my $db (@$databases) {
258 $sqlt->reset;
259 $sqlt->{schema} = $sqlt_schema;
260 $sqlt->producer($db);
261
c8a2f7bd 262 my $filename = $self->$to_file($db, $version, $dir);
9600776d 263 if (-e $filename ) {
2e68a8e1 264 carp "Overwriting existing DDL file - $filename";
265 unlink $filename;
266 }
267
268 my $output = $sqlt->translate;
269 if(!$output) {
270 carp("Failed to translate to $db, skipping. (" . $sqlt->error . ")");
271 next;
272 }
387b11d2 273 open my $file, q(>), $filename;
2e68a8e1 274 print {$file} $output;
275 close $file;
276 }
277}
278
c8a2f7bd 279sub _resultsource_install_filename {
280 my ($self, $source_name) = @_;
281 return sub {
282 my ($self, $type, $version) = @_;
283 my $dirname = catfile( $self->upgrade_directory, $type, 'schema', $version );
284 mkpath($dirname) unless -d $dirname;
285
286 return catfile( $dirname, "001-auto-$source_name.sql" );
287 }
288}
289
290sub install_resultsource {
291 my ($self, $source, $version) = @_;
292
293 my $rs_install_file =
294 $self->_resultsource_install_filename($source->source_name);
295
296 my $files = [
297 $self->$rs_install_file(
298 $self->storage->sqlt_type,
299 $version,
300 )
301 ];
302 $self->_run_sql_and_perl($files);
303}
304
305sub prepare_resultsource_install {
306 my $self = shift;
307 my $source = shift;
308
309 my $filename = $self->_resultsource_install_filename($source->source_name);
310 $self->_prepare_install({
311 parser_args => { sources => [$source->source_name], }
312 }, $filename);
313}
314
91557c90 315sub prepare_deploy {
c8a2f7bd 316 my $self = shift;
317 $self->_prepare_install({}, '_ddl_schema_produce_filename');
318}
319
a41a04e5 320sub prepare_upgrade {
9600776d 321 my ($self, $from_version, $to_version, $version_set) = @_;
76d311e7 322 $self->_prepare_changegrade($from_version, $to_version, $version_set, 'up');
323}
324
325sub prepare_downgrade {
326 my ($self, $from_version, $to_version, $version_set) = @_;
327
76d311e7 328 $self->_prepare_changegrade($from_version, $to_version, $version_set, 'down');
329}
330
331method _prepare_changegrade($from_version, $to_version, $version_set, $direction) {
2e68a8e1 332 my $schema = $self->schema;
333 my $databases = $self->databases;
334 my $dir = $self->upgrade_directory;
02a7b8ac 335 my $sqltargs = $self->sql_translator_args;
2e68a8e1 336
73caa630 337 my $schema_version = $self->schema_version;
2e68a8e1 338
339 $sqltargs = {
340 add_drop_table => 1,
341 ignore_constraint_names => 1,
342 ignore_index_names => 1,
343 %{$sqltargs}
344 };
345
346 my $sqlt = SQL::Translator->new( $sqltargs );
347
348 $sqlt->parser('SQL::Translator::Parser::DBIx::Class');
d53e0bfc 349 my $sqlt_schema = $sqlt->translate( data => $schema )
387b11d2 350 or croak($sqlt->error);
2e68a8e1 351
352 foreach my $db (@$databases) {
353 $sqlt->reset;
354 $sqlt->{schema} = $sqlt_schema;
355 $sqlt->producer($db);
356
76d311e7 357 my $prefilename = $self->_ddl_schema_produce_filename($db, $from_version, $dir);
2e68a8e1 358 unless(-e $prefilename) {
359 carp("No previous schema file found ($prefilename)");
360 next;
361 }
76d311e7 362 my $diff_file_method = "_ddl_schema_${direction}_produce_filename";
363 my $diff_file = $self->$diff_file_method($db, $version_set, $dir );
2e68a8e1 364 if(-e $diff_file) {
76d311e7 365 carp("Overwriting existing $direction-diff file - $diff_file");
2e68a8e1 366 unlink $diff_file;
367 }
368
369 my $source_schema;
370 {
371 my $t = SQL::Translator->new({
372 %{$sqltargs},
373 debug => 0,
374 trace => 0,
375 });
376
377 $t->parser( $db ) # could this really throw an exception?
387b11d2 378 or croak($t->error);
2e68a8e1 379
380 my $out = $t->translate( $prefilename )
387b11d2 381 or croak($t->error);
2e68a8e1 382
383 $source_schema = $t->schema;
384
385 $source_schema->name( $prefilename )
386 unless $source_schema->name;
387 }
388
389 # The "new" style of producers have sane normalization and can support
390 # diffing a SQL file against a DBIC->SQLT schema. Old style ones don't
391 # And we have to diff parsed SQL against parsed SQL.
392 my $dest_schema = $sqlt_schema;
393
394 unless ( "SQL::Translator::Producer::$db"->can('preprocess_schema') ) {
395 my $t = SQL::Translator->new({
396 %{$sqltargs},
397 debug => 0,
398 trace => 0,
399 });
400
401 $t->parser( $db ) # could this really throw an exception?
387b11d2 402 or croak($t->error);
2e68a8e1 403
76d311e7 404 my $filename = $self->_ddl_schema_produce_filename($db, $to_version, $dir);
2e68a8e1 405 my $out = $t->translate( $filename )
387b11d2 406 or croak($t->error);
2e68a8e1 407
408 $dest_schema = $t->schema;
409
410 $dest_schema->name( $filename )
411 unless $dest_schema->name;
412 }
413
414 my $diff = SQL::Translator::Diff::schema_diff(
415 $source_schema, $db,
416 $dest_schema, $db,
417 $sqltargs
418 );
387b11d2 419 open my $file, q(>), $diff_file;
2e68a8e1 420 print {$file} $diff;
421 close $file;
422 }
423}
424
334bced5 425method _read_sql_file($file) {
426 return unless $file;
427
aabd4237 428 open my $fh, '<', $file;
0d19af1d 429 my @data = split /;\n/, join '', <$fh>;
334bced5 430 close $fh;
431
432 @data = grep {
0d19af1d 433 $_ && # remove blank lines
434 !/^(BEGIN|BEGIN TRANSACTION|COMMIT)/ # strip txn's
435 } map {
436 s/^\s+//; s/\s+$//; # trim whitespace
437 join '', grep { !/^--/ } split /\n/ # remove comments
438 } @data;
334bced5 439
440 return \@data;
441}
442
7d2a6974 443sub downgrade_single_step {
76d311e7 444 my $self = shift;
627581cd 445 my $version_set = shift @_;
41219a5d 446
447 my $sql = $self->_run_sql_and_perl($self->_ddl_schema_down_consume_filenames(
76d311e7 448 $self->storage->sqlt_type,
627581cd 449 $version_set,
41219a5d 450 ));
3249629f 451
41219a5d 452 return ['', $sql];
76d311e7 453}
454
7d2a6974 455sub upgrade_single_step {
7521a845 456 my $self = shift;
627581cd 457 my $version_set = shift @_;
41219a5d 458
459 my $sql = $self->_run_sql_and_perl($self->_ddl_schema_up_consume_filenames(
334bced5 460 $self->storage->sqlt_type,
627581cd 461 $version_set,
41219a5d 462 ));
463 return ['', $sql];
334bced5 464}
465
aabd4237 466__PACKAGE__->meta->make_immutable;
467
2e68a8e1 4681;
e051bb00 469
e52174e3 470# vim: ts=2 sw=2 expandtab
471
e051bb00 472__END__
473
bcc72297 474=head1 DESCRIPTION
475
476This class is the meat of L<DBIx::Class::DeploymentHandler>. It takes care of
477generating sql files representing schemata as well as sql files to move from
478one version of a schema to the rest. One of the hallmark features of this
479class is that it allows for multiple sql files for deploy and upgrade, allowing
480developers to fine tune deployment. In addition it also allows for perl files
481to be run at any stage of the process.
482
483For basic usage see L<DBIx::Class::DeploymentHandler::HandlesDeploy>. What's
484documented here is extra fun stuff or private methods.
485
486=head1 DIRECTORY LAYOUT
487
92c34cab 488Arguably this is the best feature of L<DBIx::Class::DeploymentHandler>. It's
489heavily based upon L<DBIx::Migration::Directories>, but has some extensions and
490modifications, so even if you are familiar with it, please read this. I feel
491like the best way to describe the layout is with the following example:
492
493 $sql_migration_dir
494 |- SQLite
495 | |- down
496 | | `- 1-2
497 | | `- 001-auto.sql
498 | |- schema
499 | | `- 1
500 | | `- 001-auto.sql
501 | `- up
502 | |- 1-2
503 | | `- 001-auto.sql
504 | `- 2-3
505 | `- 001-auto.sql
506 |- _common
507 | |- down
508 | | `- 1-2
509 | | `- 002-remove-customers.pl
510 | `- up
511 | `- 1-2
512 | `- 002-generate-customers.pl
513 |- _generic
514 | |- down
515 | | `- 1-2
516 | | `- 001-auto.sql
517 | |- schema
518 | | `- 1
519 | | `- 001-auto.sql
520 | `- up
521 | `- 1-2
522 | |- 001-auto.sql
523 | `- 002-create-stored-procedures.sql
524 `- MySQL
525 |- down
526 | `- 1-2
527 | `- 001-auto.sql
528 |- schema
529 | `- 1
530 | `- 001-auto.sql
531 `- up
532 `- 1-2
533 `- 001-auto.sql
534
535So basically, the code
536
537 $dm->deploy(1)
538
539on an C<SQLite> database that would simply run
540C<$sql_migration_dir/SQLite/schema/1/001-auto.sql>. Next,
541
542 $dm->upgrade_single_step([1,2])
543
544would run C<$sql_migration_dir/SQLite/up/1-2/001-auto.sql> followed by
545C<$sql_migration_dir/_common/up/1-2/002-generate-customers.pl>.
546
547Now, a C<.pl> file doesn't have to be in the C<_common> directory, but most of
548the time it probably should be, since perl scripts will mostly be database
549independent.
550
551C<_generic> exists for when you for some reason are sure that your SQL is
552generic enough to run on all databases. Good luck with that one.
553
554=head1 PERL SCRIPTS
555
556A perl script for this tool is very simple. It merely needs to contain a
557sub called C<run> that takes a L<DBIx::Class::Schema> as it's only argument.
558A very basic perl script might look like:
559
560 #!perl
561
562 use strict;
563 use warnings;
564
565 sub run {
566 my $schema = shift;
567
568 $schema->resultset('Users')->create({
569 name => 'root',
570 password => 'root',
571 })
572 }
bcc72297 573
eb28403b 574=attr schema
a65184c8 575
bcc72297 576The L<DBIx::Class::Schema> (B<required>) that is used to talk to the database
577and generate the DDL.
578
eb28403b 579=attr storage
a65184c8 580
bcc72297 581The L<DBIx::Class::Storage> that is I<actually> used to talk to the database
582and generate the DDL. This is automatically created with L</_build_storage>.
583
02a7b8ac 584=attr sql_translator_args
cfc9edf9 585
02a7b8ac 586The arguments that get passed to L<SQL::Translator> when it's used.
a65184c8 587
eb28403b 588=attr upgrade_directory
cfc9edf9 589
590The directory (default C<'sql'>) that upgrades are stored in
591
eb28403b 592=attr databases
cfc9edf9 593
594The types of databases (default C<< [qw( MySQL SQLite PostgreSQL )] >>) to
595generate files for
596
eb28403b 597=attr txn_wrap
598
bcc72297 599Set to true (which is the default) to wrap all upgrades and deploys in a single
600transaction.
601
73caa630 602=attr schema_version
603
604The version the schema on your harddrive is at. Defaults to
605C<< $self->schema->schema_version >>.
606
eb28403b 607=method __ddl_consume_with_prefix
a65184c8 608
bcc72297 609 $dm->__ddl_consume_with_prefix( 'SQLite', [qw( 1.00 1.01 )], 'up' )
610
611This is the meat of the multi-file upgrade/deploy stuff. It returns a list of
612files in the order that they should be run for a generic "type" of upgrade.
613You should not be calling this in user code.
614
eb28403b 615=method _ddl_schema_consume_filenames
a65184c8 616
bcc72297 617 $dm->__ddl_schema_consume_filenames( 'SQLite', [qw( 1.00 )] )
618
619Just a curried L</__ddl_consume_with_prefix>. Get's a list of files for an
620initial deploy.
621
eb28403b 622=method _ddl_schema_produce_filename
a65184c8 623
bcc72297 624 $dm->__ddl_schema_produce_filename( 'SQLite', [qw( 1.00 )] )
625
626Returns a single file in which an initial schema will be stored.
627
eb28403b 628=method _ddl_schema_up_consume_filenames
a65184c8 629
bcc72297 630 $dm->_ddl_schema_up_consume_filenames( 'SQLite', [qw( 1.00 )] )
631
632Just a curried L</__ddl_consume_with_prefix>. Get's a list of files for an
633upgrade.
634
eb28403b 635=method _ddl_schema_down_consume_filenames
a65184c8 636
bcc72297 637 $dm->_ddl_schema_down_consume_filenames( 'SQLite', [qw( 1.00 )] )
638
639Just a curried L</__ddl_consume_with_prefix>. Get's a list of files for a
640downgrade.
641
eb28403b 642=method _ddl_schema_up_produce_filenames
a65184c8 643
bcc72297 644 $dm->_ddl_schema_up_produce_filename( 'SQLite', [qw( 1.00 1.01 )] )
645
646Returns a single file in which the sql to upgrade from one schema to another
647will be stored.
648
649=method _ddl_schema_down_produce_filename
650
651 $dm->_ddl_schema_down_produce_filename( 'SQLite', [qw( 1.00 1.01 )] )
652
653Returns a single file in which the sql to downgrade from one schema to another
654will be stored.
a65184c8 655
eb28403b 656=method _resultsource_install_filename
a65184c8 657
bcc72297 658 my $filename_fn = $dm->_resultsource_install_filename('User');
659 $dm->$filename_fn('SQLite', '1.00')
660
661Returns a function which in turn returns a single filename used to install a
662single resultsource. Weird interface is convenient for me. Deal with it.
663
eb28403b 664=method _run_sql_and_perl
665
bcc72297 666 $dm->_run_sql_and_perl([qw( list of filenames )])
a65184c8 667
bcc72297 668Simply put, this runs the list of files passed to it. If the file ends in
669C<.sql> it runs it as sql and if it ends in C<.pl> it runs it as a perl file.
a65184c8 670
bcc72297 671Depending on L</txn_wrap> all of the files run will be wrapped in a single
672transaction.
eb28403b 673
bcc72297 674=method _prepare_install
a65184c8 675
bcc72297 676 $dm->_prepare_install({ add_drop_table => 0 }, sub { 'file_to_create' })
a65184c8 677
bcc72297 678Generates the sql file for installing the database. First arg is simply
679L<SQL::Translator> args and the second is a coderef that returns the filename
680to store the sql in.
a65184c8 681
bcc72297 682=method _prepare_changegrade
683
684 $dm->_prepare_changegrade('1.00', '1.01', [qw( 1.00 1.01)], 'up')
a65184c8 685
bcc72297 686Generates the sql file for migrating from one schema version to another. First
687arg is the version to start from, second is the version to go to, third is the
688L<version set|DBIx::Class::DeploymentHandler/VERSION SET>, and last is the
689direction of the changegrade, be it 'up' or 'down'.
a65184c8 690
bcc72297 691=method _read_sql_file
a65184c8 692
bcc72297 693 $dm->_read_sql_file('foo.sql')
a65184c8 694
bcc72297 695Reads a sql file and returns lines in an C<ArrayRef>. Strips out comments,
696transactions, and blank lines.
eb28403b 697