check for failed compile
[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$/ ) {
173 my $package = $1;
174 my $filedata = do { local( @ARGV, $/ ) = $filename; <> };
175 # make the package name more palateable to perl
176 $package =~ s/\W/_/g;
177
178 no warnings 'redefine';
179 eval "package $package;\n\n$filedata";
180 use warnings;
181
98c9484a 182 if (my $fn = $package->can('run')) {
183 $fn->($self->schema);
184 } else {
185 carp "$filename should define a run method that takes a schema but it didn't!";
186 }
41219a5d 187 } else {
fc4b7602 188 croak "A file ($filename) got to deploy that wasn't sql or perl!";
2e68a8e1 189 }
2e68a8e1 190 }
a7d53deb 191
192 $guard->commit if $self->txn_wrap;
41219a5d 193
194 return $sql;
195}
196
197sub deploy {
198 my $self = shift;
92c34cab 199 my $version = shift || $self->schema_version;
41219a5d 200
201 return $self->_run_sql_and_perl($self->_ddl_schema_consume_filenames(
202 $self->storage->sqlt_type,
92c34cab 203 $version,
41219a5d 204 ));
2e68a8e1 205}
206
fc4b7602 207sub preinstall_scripts {
208 my $self = shift;
209 my $version = shift || $self->schema_version;
210
211 my @files = @{$self->_ddl_preinstall_consume_filenames(
212 $self->storage->sqlt_type,
213 $version,
214 )};
215
216 for my $filename (@files) {
217 # We ignore sql for now (till I figure out what to do with it)
218 if ( $filename =~ /^(.+)\.pl$/ ) {
219 my $package = $1;
220 my $filedata = do { local( @ARGV, $/ ) = $filename; <> };
221 # make the package name more palateable to perl
222 $package =~ s/\W/_/g;
223
224 no warnings 'redefine';
225 eval "package $package;\n\n$filedata";
226 use warnings;
3fa64c79 227 if ($@) {
228 carp "$filename failed to compile: $@";
229 } elsif (my $fn = $package->can('run')) {
fc4b7602 230 $fn->()
231 } else {
232 carp "$filename should define a run sub but it didn't!";
233 }
234 } else {
235 croak "A file ($filename) got to preinstall_scripts that wasn't sql or perl!";
236 }
237 }
238}
239
c8a2f7bd 240sub _prepare_install {
73caa630 241 my $self = shift;
02a7b8ac 242 my $sqltargs = { %{$self->sql_translator_args}, %{shift @_} };
c8a2f7bd 243 my $to_file = shift;
2e68a8e1 244 my $schema = $self->schema;
245 my $databases = $self->databases;
246 my $dir = $self->upgrade_directory;
73caa630 247 my $version = $self->schema_version;
d54b8d69 248
9600776d 249 my $sqlt = SQL::Translator->new({
d54b8d69 250 add_drop_table => 1,
2e68a8e1 251 ignore_constraint_names => 1,
d54b8d69 252 ignore_index_names => 1,
253 parser => 'SQL::Translator::Parser::DBIx::Class',
3aaf766f 254 %{$sqltargs}
9600776d 255 });
2e68a8e1 256
d53e0bfc 257 my $sqlt_schema = $sqlt->translate( data => $schema )
387b11d2 258 or croak($sqlt->error);
2e68a8e1 259
260 foreach my $db (@$databases) {
261 $sqlt->reset;
262 $sqlt->{schema} = $sqlt_schema;
263 $sqlt->producer($db);
264
c8a2f7bd 265 my $filename = $self->$to_file($db, $version, $dir);
9600776d 266 if (-e $filename ) {
2e68a8e1 267 carp "Overwriting existing DDL file - $filename";
268 unlink $filename;
269 }
270
271 my $output = $sqlt->translate;
272 if(!$output) {
273 carp("Failed to translate to $db, skipping. (" . $sqlt->error . ")");
274 next;
275 }
387b11d2 276 open my $file, q(>), $filename;
2e68a8e1 277 print {$file} $output;
278 close $file;
279 }
280}
281
c8a2f7bd 282sub _resultsource_install_filename {
283 my ($self, $source_name) = @_;
284 return sub {
285 my ($self, $type, $version) = @_;
286 my $dirname = catfile( $self->upgrade_directory, $type, 'schema', $version );
287 mkpath($dirname) unless -d $dirname;
288
289 return catfile( $dirname, "001-auto-$source_name.sql" );
290 }
291}
292
293sub install_resultsource {
294 my ($self, $source, $version) = @_;
295
296 my $rs_install_file =
297 $self->_resultsource_install_filename($source->source_name);
298
299 my $files = [
300 $self->$rs_install_file(
301 $self->storage->sqlt_type,
302 $version,
303 )
304 ];
305 $self->_run_sql_and_perl($files);
306}
307
308sub prepare_resultsource_install {
309 my $self = shift;
310 my $source = shift;
311
312 my $filename = $self->_resultsource_install_filename($source->source_name);
313 $self->_prepare_install({
314 parser_args => { sources => [$source->source_name], }
315 }, $filename);
316}
317
91557c90 318sub prepare_deploy {
c8a2f7bd 319 my $self = shift;
320 $self->_prepare_install({}, '_ddl_schema_produce_filename');
321}
322
a41a04e5 323sub prepare_upgrade {
9600776d 324 my ($self, $from_version, $to_version, $version_set) = @_;
76d311e7 325 $self->_prepare_changegrade($from_version, $to_version, $version_set, 'up');
326}
327
328sub prepare_downgrade {
329 my ($self, $from_version, $to_version, $version_set) = @_;
330
76d311e7 331 $self->_prepare_changegrade($from_version, $to_version, $version_set, 'down');
332}
333
334method _prepare_changegrade($from_version, $to_version, $version_set, $direction) {
2e68a8e1 335 my $schema = $self->schema;
336 my $databases = $self->databases;
337 my $dir = $self->upgrade_directory;
02a7b8ac 338 my $sqltargs = $self->sql_translator_args;
2e68a8e1 339
73caa630 340 my $schema_version = $self->schema_version;
2e68a8e1 341
342 $sqltargs = {
343 add_drop_table => 1,
344 ignore_constraint_names => 1,
345 ignore_index_names => 1,
346 %{$sqltargs}
347 };
348
349 my $sqlt = SQL::Translator->new( $sqltargs );
350
351 $sqlt->parser('SQL::Translator::Parser::DBIx::Class');
d53e0bfc 352 my $sqlt_schema = $sqlt->translate( data => $schema )
387b11d2 353 or croak($sqlt->error);
2e68a8e1 354
355 foreach my $db (@$databases) {
356 $sqlt->reset;
357 $sqlt->{schema} = $sqlt_schema;
358 $sqlt->producer($db);
359
76d311e7 360 my $prefilename = $self->_ddl_schema_produce_filename($db, $from_version, $dir);
2e68a8e1 361 unless(-e $prefilename) {
362 carp("No previous schema file found ($prefilename)");
363 next;
364 }
76d311e7 365 my $diff_file_method = "_ddl_schema_${direction}_produce_filename";
366 my $diff_file = $self->$diff_file_method($db, $version_set, $dir );
2e68a8e1 367 if(-e $diff_file) {
76d311e7 368 carp("Overwriting existing $direction-diff file - $diff_file");
2e68a8e1 369 unlink $diff_file;
370 }
371
372 my $source_schema;
373 {
374 my $t = SQL::Translator->new({
375 %{$sqltargs},
376 debug => 0,
377 trace => 0,
378 });
379
380 $t->parser( $db ) # could this really throw an exception?
387b11d2 381 or croak($t->error);
2e68a8e1 382
383 my $out = $t->translate( $prefilename )
387b11d2 384 or croak($t->error);
2e68a8e1 385
386 $source_schema = $t->schema;
387
388 $source_schema->name( $prefilename )
389 unless $source_schema->name;
390 }
391
392 # The "new" style of producers have sane normalization and can support
393 # diffing a SQL file against a DBIC->SQLT schema. Old style ones don't
394 # And we have to diff parsed SQL against parsed SQL.
395 my $dest_schema = $sqlt_schema;
396
397 unless ( "SQL::Translator::Producer::$db"->can('preprocess_schema') ) {
398 my $t = SQL::Translator->new({
399 %{$sqltargs},
400 debug => 0,
401 trace => 0,
402 });
403
404 $t->parser( $db ) # could this really throw an exception?
387b11d2 405 or croak($t->error);
2e68a8e1 406
76d311e7 407 my $filename = $self->_ddl_schema_produce_filename($db, $to_version, $dir);
2e68a8e1 408 my $out = $t->translate( $filename )
387b11d2 409 or croak($t->error);
2e68a8e1 410
411 $dest_schema = $t->schema;
412
413 $dest_schema->name( $filename )
414 unless $dest_schema->name;
415 }
416
417 my $diff = SQL::Translator::Diff::schema_diff(
418 $source_schema, $db,
419 $dest_schema, $db,
420 $sqltargs
421 );
387b11d2 422 open my $file, q(>), $diff_file;
2e68a8e1 423 print {$file} $diff;
424 close $file;
425 }
426}
427
334bced5 428method _read_sql_file($file) {
429 return unless $file;
430
aabd4237 431 open my $fh, '<', $file;
0d19af1d 432 my @data = split /;\n/, join '', <$fh>;
334bced5 433 close $fh;
434
435 @data = grep {
0d19af1d 436 $_ && # remove blank lines
437 !/^(BEGIN|BEGIN TRANSACTION|COMMIT)/ # strip txn's
438 } map {
439 s/^\s+//; s/\s+$//; # trim whitespace
440 join '', grep { !/^--/ } split /\n/ # remove comments
441 } @data;
334bced5 442
443 return \@data;
444}
445
7d2a6974 446sub downgrade_single_step {
76d311e7 447 my $self = shift;
627581cd 448 my $version_set = shift @_;
41219a5d 449
450 my $sql = $self->_run_sql_and_perl($self->_ddl_schema_down_consume_filenames(
76d311e7 451 $self->storage->sqlt_type,
627581cd 452 $version_set,
41219a5d 453 ));
3249629f 454
41219a5d 455 return ['', $sql];
76d311e7 456}
457
7d2a6974 458sub upgrade_single_step {
7521a845 459 my $self = shift;
627581cd 460 my $version_set = shift @_;
41219a5d 461
462 my $sql = $self->_run_sql_and_perl($self->_ddl_schema_up_consume_filenames(
334bced5 463 $self->storage->sqlt_type,
627581cd 464 $version_set,
41219a5d 465 ));
466 return ['', $sql];
334bced5 467}
468
aabd4237 469__PACKAGE__->meta->make_immutable;
470
2e68a8e1 4711;
e051bb00 472
e52174e3 473# vim: ts=2 sw=2 expandtab
474
e051bb00 475__END__
476
bcc72297 477=head1 DESCRIPTION
478
479This class is the meat of L<DBIx::Class::DeploymentHandler>. It takes care of
480generating sql files representing schemata as well as sql files to move from
481one version of a schema to the rest. One of the hallmark features of this
482class is that it allows for multiple sql files for deploy and upgrade, allowing
483developers to fine tune deployment. In addition it also allows for perl files
484to be run at any stage of the process.
485
486For basic usage see L<DBIx::Class::DeploymentHandler::HandlesDeploy>. What's
487documented here is extra fun stuff or private methods.
488
489=head1 DIRECTORY LAYOUT
490
92c34cab 491Arguably this is the best feature of L<DBIx::Class::DeploymentHandler>. It's
492heavily based upon L<DBIx::Migration::Directories>, but has some extensions and
493modifications, so even if you are familiar with it, please read this. I feel
494like the best way to describe the layout is with the following example:
495
496 $sql_migration_dir
497 |- SQLite
498 | |- down
499 | | `- 1-2
500 | | `- 001-auto.sql
501 | |- schema
502 | | `- 1
503 | | `- 001-auto.sql
504 | `- up
505 | |- 1-2
506 | | `- 001-auto.sql
507 | `- 2-3
508 | `- 001-auto.sql
509 |- _common
510 | |- down
511 | | `- 1-2
512 | | `- 002-remove-customers.pl
513 | `- up
514 | `- 1-2
515 | `- 002-generate-customers.pl
516 |- _generic
517 | |- down
518 | | `- 1-2
519 | | `- 001-auto.sql
520 | |- schema
521 | | `- 1
522 | | `- 001-auto.sql
523 | `- up
524 | `- 1-2
525 | |- 001-auto.sql
526 | `- 002-create-stored-procedures.sql
527 `- MySQL
528 |- down
529 | `- 1-2
530 | `- 001-auto.sql
531 |- schema
532 | `- 1
533 | `- 001-auto.sql
534 `- up
535 `- 1-2
536 `- 001-auto.sql
537
538So basically, the code
539
540 $dm->deploy(1)
541
542on an C<SQLite> database that would simply run
543C<$sql_migration_dir/SQLite/schema/1/001-auto.sql>. Next,
544
545 $dm->upgrade_single_step([1,2])
546
547would run C<$sql_migration_dir/SQLite/up/1-2/001-auto.sql> followed by
548C<$sql_migration_dir/_common/up/1-2/002-generate-customers.pl>.
549
550Now, a C<.pl> file doesn't have to be in the C<_common> directory, but most of
551the time it probably should be, since perl scripts will mostly be database
552independent.
553
554C<_generic> exists for when you for some reason are sure that your SQL is
555generic enough to run on all databases. Good luck with that one.
556
557=head1 PERL SCRIPTS
558
559A perl script for this tool is very simple. It merely needs to contain a
560sub called C<run> that takes a L<DBIx::Class::Schema> as it's only argument.
561A very basic perl script might look like:
562
563 #!perl
564
565 use strict;
566 use warnings;
567
568 sub run {
569 my $schema = shift;
570
571 $schema->resultset('Users')->create({
572 name => 'root',
573 password => 'root',
574 })
575 }
bcc72297 576
eb28403b 577=attr schema
a65184c8 578
bcc72297 579The L<DBIx::Class::Schema> (B<required>) that is used to talk to the database
580and generate the DDL.
581
eb28403b 582=attr storage
a65184c8 583
bcc72297 584The L<DBIx::Class::Storage> that is I<actually> used to talk to the database
585and generate the DDL. This is automatically created with L</_build_storage>.
586
02a7b8ac 587=attr sql_translator_args
cfc9edf9 588
02a7b8ac 589The arguments that get passed to L<SQL::Translator> when it's used.
a65184c8 590
eb28403b 591=attr upgrade_directory
cfc9edf9 592
593The directory (default C<'sql'>) that upgrades are stored in
594
eb28403b 595=attr databases
cfc9edf9 596
597The types of databases (default C<< [qw( MySQL SQLite PostgreSQL )] >>) to
598generate files for
599
eb28403b 600=attr txn_wrap
601
bcc72297 602Set to true (which is the default) to wrap all upgrades and deploys in a single
603transaction.
604
73caa630 605=attr schema_version
606
607The version the schema on your harddrive is at. Defaults to
608C<< $self->schema->schema_version >>.
609
eb28403b 610=method __ddl_consume_with_prefix
a65184c8 611
bcc72297 612 $dm->__ddl_consume_with_prefix( 'SQLite', [qw( 1.00 1.01 )], 'up' )
613
614This is the meat of the multi-file upgrade/deploy stuff. It returns a list of
615files in the order that they should be run for a generic "type" of upgrade.
616You should not be calling this in user code.
617
eb28403b 618=method _ddl_schema_consume_filenames
a65184c8 619
bcc72297 620 $dm->__ddl_schema_consume_filenames( 'SQLite', [qw( 1.00 )] )
621
622Just a curried L</__ddl_consume_with_prefix>. Get's a list of files for an
623initial deploy.
624
eb28403b 625=method _ddl_schema_produce_filename
a65184c8 626
bcc72297 627 $dm->__ddl_schema_produce_filename( 'SQLite', [qw( 1.00 )] )
628
629Returns a single file in which an initial schema will be stored.
630
eb28403b 631=method _ddl_schema_up_consume_filenames
a65184c8 632
bcc72297 633 $dm->_ddl_schema_up_consume_filenames( 'SQLite', [qw( 1.00 )] )
634
635Just a curried L</__ddl_consume_with_prefix>. Get's a list of files for an
636upgrade.
637
eb28403b 638=method _ddl_schema_down_consume_filenames
a65184c8 639
bcc72297 640 $dm->_ddl_schema_down_consume_filenames( 'SQLite', [qw( 1.00 )] )
641
642Just a curried L</__ddl_consume_with_prefix>. Get's a list of files for a
643downgrade.
644
eb28403b 645=method _ddl_schema_up_produce_filenames
a65184c8 646
bcc72297 647 $dm->_ddl_schema_up_produce_filename( 'SQLite', [qw( 1.00 1.01 )] )
648
649Returns a single file in which the sql to upgrade from one schema to another
650will be stored.
651
652=method _ddl_schema_down_produce_filename
653
654 $dm->_ddl_schema_down_produce_filename( 'SQLite', [qw( 1.00 1.01 )] )
655
656Returns a single file in which the sql to downgrade from one schema to another
657will be stored.
a65184c8 658
eb28403b 659=method _resultsource_install_filename
a65184c8 660
bcc72297 661 my $filename_fn = $dm->_resultsource_install_filename('User');
662 $dm->$filename_fn('SQLite', '1.00')
663
664Returns a function which in turn returns a single filename used to install a
665single resultsource. Weird interface is convenient for me. Deal with it.
666
eb28403b 667=method _run_sql_and_perl
668
bcc72297 669 $dm->_run_sql_and_perl([qw( list of filenames )])
a65184c8 670
bcc72297 671Simply put, this runs the list of files passed to it. If the file ends in
672C<.sql> it runs it as sql and if it ends in C<.pl> it runs it as a perl file.
a65184c8 673
bcc72297 674Depending on L</txn_wrap> all of the files run will be wrapped in a single
675transaction.
eb28403b 676
bcc72297 677=method _prepare_install
a65184c8 678
bcc72297 679 $dm->_prepare_install({ add_drop_table => 0 }, sub { 'file_to_create' })
a65184c8 680
bcc72297 681Generates the sql file for installing the database. First arg is simply
682L<SQL::Translator> args and the second is a coderef that returns the filename
683to store the sql in.
a65184c8 684
bcc72297 685=method _prepare_changegrade
686
687 $dm->_prepare_changegrade('1.00', '1.01', [qw( 1.00 1.01)], 'up')
a65184c8 688
bcc72297 689Generates the sql file for migrating from one schema version to another. First
690arg is the version to start from, second is the version to go to, third is the
691L<version set|DBIx::Class::DeploymentHandler/VERSION SET>, and last is the
692direction of the changegrade, be it 'up' or 'down'.
a65184c8 693
bcc72297 694=method _read_sql_file
a65184c8 695
bcc72297 696 $dm->_read_sql_file('foo.sql')
a65184c8 697
bcc72297 698Reads a sql file and returns lines in an C<ArrayRef>. Strips out comments,
699transactions, and blank lines.
eb28403b 700