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