Fix RT57467, simplify test
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Schema / Versioned.pm
CommitLineData
a89c6fc0 1package # Hide from PAUSE
2 DBIx::Class::Version::Table;
d88ecca6 3use base 'DBIx::Class::Core';
c9d2e0a2 4use strict;
5use warnings;
6
b4b1e91c 7__PACKAGE__->table('dbix_class_schema_versions');
c9d2e0a2 8
ad1446da 9__PACKAGE__->add_columns
732dc718 10 ( 'version' => {
ad1446da 11 'data_type' => 'VARCHAR',
12 'is_auto_increment' => 0,
13 'default_value' => undef,
14 'is_foreign_key' => 0,
732dc718 15 'name' => 'version',
ad1446da 16 'is_nullable' => 0,
17 'size' => '10'
18 },
732dc718 19 'installed' => {
c9d2e0a2 20 'data_type' => 'VARCHAR',
21 'is_auto_increment' => 0,
22 'default_value' => undef,
23 'is_foreign_key' => 0,
732dc718 24 'name' => 'installed',
c9d2e0a2 25 'is_nullable' => 0,
26 'size' => '20'
ad1446da 27 },
28 );
732dc718 29__PACKAGE__->set_primary_key('version');
c9d2e0a2 30
a89c6fc0 31package # Hide from PAUSE
32 DBIx::Class::Version::TableCompat;
d88ecca6 33use base 'DBIx::Class::Core';
b4b1e91c 34__PACKAGE__->table('SchemaVersions');
35
732dc718 36__PACKAGE__->add_columns
37 ( 'Version' => {
38 'data_type' => 'VARCHAR',
39 },
40 'Installed' => {
41 'data_type' => 'VARCHAR',
42 },
43 );
44__PACKAGE__->set_primary_key('Version');
45
a89c6fc0 46package # Hide from PAUSE
47 DBIx::Class::Version;
c9d2e0a2 48use base 'DBIx::Class::Schema';
49use strict;
50use warnings;
51
52__PACKAGE__->register_class('Table', 'DBIx::Class::Version::Table');
53
a89c6fc0 54package # Hide from PAUSE
55 DBIx::Class::VersionCompat;
b4b1e91c 56use base 'DBIx::Class::Schema';
57use strict;
58use warnings;
59
60__PACKAGE__->register_class('TableCompat', 'DBIx::Class::Version::TableCompat');
61
c9d2e0a2 62
63# ---------------------------------------------------------------------------
8424c090 64
65=head1 NAME
66
67DBIx::Class::Schema::Versioned - DBIx::Class::Schema plugin for Schema upgrades
68
69=head1 SYNOPSIS
70
6c2b68ed 71 package MyApp::Schema;
e84a43c1 72 use base qw/DBIx::Class::Schema/;
73
74 our $VERSION = 0.001;
75
6c2b68ed 76 # load MyApp::Schema::CD, MyApp::Schema::Book, MyApp::Schema::DVD
8424c090 77 __PACKAGE__->load_classes(qw/CD Book DVD/);
78
e84a43c1 79 __PACKAGE__->load_components(qw/Schema::Versioned/);
8424c090 80 __PACKAGE__->upgrade_directory('/path/to/upgrades/');
8424c090 81
82
83=head1 DESCRIPTION
84
e84a43c1 85This module provides methods to apply DDL changes to your database using SQL
86diff files. Normally these diff files would be created using
87L<DBIx::Class::Schema/create_ddl_dir>.
8424c090 88
b4b1e91c 89A table called I<dbix_class_schema_versions> is created and maintained by the
e84a43c1 90module. This is used to determine which version your database is currently at.
91Similarly the $VERSION in your DBIC schema class is used to determine the
92current DBIC schema version.
8424c090 93
e84a43c1 94The upgrade is initiated manually by calling C<upgrade> on your schema object,
95this will attempt to upgrade the database from its current version to the current
96schema version using a diff from your I<upgrade_directory>. If a suitable diff is
97not found then no upgrade is possible.
8424c090 98
99NB: At the moment, only SQLite and MySQL are supported. This is due to
100spotty behaviour in the SQL::Translator producers, please help us by
e63a82f7 101enhancing them. Ask on the mailing list or IRC channel for details (community details
e84a43c1 102in L<DBIx::Class>).
93e4d41a 103
104=head1 GETTING STARTED
105
e84a43c1 106Firstly you need to setup your schema class as per the L</SYNOPSIS>, make sure
107you have specified an upgrade_directory and an initial $VERSION.
93e4d41a 108
e84a43c1 109Then you'll need two scripts, one to create DDL files and diffs and another to perform
110upgrades. Your creation script might look like a bit like this:
93e4d41a 111
e84a43c1 112 use strict;
113 use Pod::Usage;
114 use Getopt::Long;
115 use MyApp::Schema;
8424c090 116
56988b6c 117 my ( $preversion, $help );
e84a43c1 118 GetOptions(
119 'p|preversion:s' => \$preversion,
120 ) or die pod2usage;
8424c090 121
e84a43c1 122 my $schema = MyApp::Schema->connect(
123 $dsn,
124 $user,
125 $password,
126 );
127 my $sql_dir = './sql';
128 my $version = $schema->schema_version();
129 $schema->create_ddl_dir( 'MySQL', $version, $sql_dir, $preversion );
8424c090 130
e84a43c1 131Then your upgrade script might look like so:
132
133 use strict;
134 use MyApp::Schema;
135
136 my $schema = MyApp::Schema->connect(
137 $dsn,
138 $user,
139 $password,
140 );
8424c090 141
e84a43c1 142 if (!$schema->get_db_version()) {
143 # schema is unversioned
144 $schema->deploy();
145 } else {
146 $schema->upgrade();
147 }
148
149The script above assumes that if the database is unversioned then it is empty
150and we can safely deploy the DDL to it. However things are not always so simple.
151
152if you want to initialise a pre-existing database where the DDL is not the same
82625f90 153as the DDL for your current schema version then you will need a diff which
e84a43c1 154converts the database's DDL to the current DDL. The best way to do this is
155to get a dump of the database schema (without data) and save that in your
156SQL directory as version 0.000 (the filename must be as with
82625f90 157L<DBIx::Class::Schema/ddl_filename>) then create a diff using your create DDL
e84a43c1 158script given above from version 0.000 to the current version. Then hand check
82625f90 159and if necessary edit the resulting diff to ensure that it will apply. Once you have
e84a43c1 160done all that you can do this:
161
162 if (!$schema->get_db_version()) {
163 # schema is unversioned
164 $schema->install("0.000");
165 }
166
167 # this will now apply the 0.000 to current version diff
168 $schema->upgrade();
169
170In the case of an unversioned database the above code will create the
82625f90 171dbix_class_schema_versions table and write version 0.000 to it, then
e84a43c1 172upgrade will then apply the diff we talked about creating in the previous paragraph
173and then you're good to go.
8424c090 174
175=cut
176
c9d2e0a2 177package DBIx::Class::Schema::Versioned;
178
179use strict;
180use warnings;
d88ecca6 181use base 'DBIx::Class::Schema';
341d5ede 182
183use Carp::Clan qw/^DBIx::Class/;
d2bc7045 184use Time::HiRes qw/gettimeofday/;
9780718f 185use Try::Tiny;
fd323bf1 186use namespace::clean;
c9d2e0a2 187
188__PACKAGE__->mk_classdata('_filedata');
189__PACKAGE__->mk_classdata('upgrade_directory');
8795fefb 190__PACKAGE__->mk_classdata('backup_directory');
f925f7cb 191__PACKAGE__->mk_classdata('do_backup');
8424c090 192__PACKAGE__->mk_classdata('do_diff_on_init');
193
e84a43c1 194
195=head1 METHODS
196
197=head2 upgrade_directory
198
199Use this to set the directory your upgrade files are stored in.
200
201=head2 backup_directory
202
203Use this to set the directory you want your backups stored in (note that backups
204are disabled by default).
205
206=cut
207
93e4d41a 208=head2 install
c9d2e0a2 209
93e4d41a 210=over 4
c9d2e0a2 211
93e4d41a 212=item Arguments: $db_version
e6129e56 213
93e4d41a 214=back
8424c090 215
93e4d41a 216Call this to initialise a previously unversioned database. The table 'dbix_class_schema_versions' will be created which will be used to store the database version.
8424c090 217
93e4d41a 218Takes one argument which should be the version that the database is currently at. Defaults to the return value of L</schema_version>.
8424c090 219
93e4d41a 220See L</getting_started> for more details.
f81b9157 221
8424c090 222=cut
223
93e4d41a 224sub install
c9d2e0a2 225{
93e4d41a 226 my ($self, $new_version) = @_;
c9d2e0a2 227
93e4d41a 228 # must be called on a fresh database
229 if ($self->get_db_version()) {
341d5ede 230 carp 'Install not possible as versions table already exists in database';
8424c090 231 }
c9d2e0a2 232
93e4d41a 233 # default to current version if none passed
234 $new_version ||= $self->schema_version();
8424c090 235
e84a43c1 236 if ($new_version) {
93e4d41a 237 # create versions table and version row
238 $self->{vschema}->deploy;
a354b842 239 $self->_set_db_version({ version => $new_version });
8424c090 240 }
c9d2e0a2 241}
242
e84a43c1 243=head2 deploy
244
245Same as L<DBIx::Class::Schema/deploy> but also calls C<install>.
246
247=cut
248
249sub deploy {
250 my $self = shift;
251 $self->next::method(@_);
252 $self->install();
253}
254
a354b842 255=head2 create_upgrade_path
256
257=over 4
258
259=item Arguments: { upgrade_file => $file }
260
261=back
262
c1300297 263Virtual method that should be overridden to create an upgrade file.
56988b6c 264This is useful in the case of upgrading across multiple versions
a354b842 265to concatenate several files to create one upgrade file.
266
4a743a00 267You'll probably want the db_version retrieved via $self->get_db_version
56988b6c 268and the schema_version which is retrieved via $self->schema_version
4a743a00 269
a354b842 270=cut
271
272sub create_upgrade_path {
d7a58a29 273 ## override this method
a354b842 274}
275
d2bc7045 276=head2 ordered_schema_versions
277
278=over 4
279
280=item Returns: a list of version numbers, ordered from lowest to highest
281
282=back
283
c1300297 284Virtual method that should be overridden to return an ordered list
d2bc7045 285of schema versions. This is then used to produce a set of steps to
286upgrade through to achieve the required schema version.
287
288You may want the db_version retrieved via $self->get_db_version
56988b6c 289and the schema_version which is retrieved via $self->schema_version
d2bc7045 290
291=cut
292
293sub ordered_schema_versions {
56988b6c 294 ## override this method
d2bc7045 295}
296
8424c090 297=head2 upgrade
e2c0df8e 298
d2bc7045 299Call this to attempt to upgrade your database from the version it
300is at to the version this DBIC schema is at. If they are the same
301it does nothing.
e84a43c1 302
d2bc7045 303It will call L</ordered_schema_versions> to retrieve an ordered
304list of schema versions (if ordered_schema_versions returns nothing
305then it is assumed you can do the upgrade as a single step). It
306then iterates through the list of versions between the current db
307version and the schema version applying one update at a time until
48580715 308all relevant updates are applied.
c9d2e0a2 309
d2bc7045 310The individual update steps are performed by using
311L</upgrade_single_step>, which will apply the update and also
312update the dbix_class_schema_versions table.
c9d2e0a2 313
8424c090 314=cut
c9d2e0a2 315
d2bc7045 316sub upgrade {
317 my ($self) = @_;
318 my $db_version = $self->get_db_version();
c9d2e0a2 319
d2bc7045 320 # db unversioned
321 unless ($db_version) {
322 carp 'Upgrade not possible as database is unversioned. Please call install first.';
323 return;
324 }
325
326 # db and schema at same version. do nothing
327 if ( $db_version eq $self->schema_version ) {
328 carp "Upgrade not necessary\n";
329 return;
330 }
331
332 my @version_list = $self->ordered_schema_versions;
333
334 # if nothing returned then we preload with min/max
335 @version_list = ( $db_version, $self->schema_version )
336 unless ( scalar(@version_list) );
337
338 # catch the case of someone returning an arrayref
339 @version_list = @{ $version_list[0] }
340 if ( ref( $version_list[0] ) eq 'ARRAY' );
341
342 # remove all versions in list above the required version
343 while ( scalar(@version_list)
344 && ( $version_list[-1] ne $self->schema_version ) )
345 {
346 pop @version_list;
347 }
348
349 # remove all versions in list below the current version
350 while ( scalar(@version_list) && ( $version_list[0] ne $db_version ) ) {
351 shift @version_list;
352 }
353
354 # check we have an appropriate list of versions
355 if ( scalar(@version_list) < 2 ) {
356 die;
357 }
358
359 # do sets of upgrade
360 while ( scalar(@version_list) >= 2 ) {
361 $self->upgrade_single_step( $version_list[0], $version_list[1] );
362 shift @version_list;
363 }
364}
365
366=head2 upgrade_single_step
367
368=over 4
369
370=item Arguments: db_version - the version currently within the db
371
372=item Arguments: target_version - the version to upgrade to
373
374=back
375
376Call this to attempt to upgrade your database from the
377I<db_version> to the I<target_version>. If they are the same it
378does nothing.
379
380It requires an SQL diff file to exist in your I<upgrade_directory>,
381normally you will have created this using L<DBIx::Class::Schema/create_ddl_dir>.
382
383If successful the dbix_class_schema_versions table is updated with
384the I<target_version>.
385
386This method may be called repeatedly by the upgrade method to
387upgrade through a series of updates.
388
389=cut
390
391sub upgrade_single_step
392{
393 my ($self,
394 $db_version,
395 $target_version) = @_;
c9d2e0a2 396
8424c090 397 # db and schema at same version. do nothing
d2bc7045 398 if ($db_version eq $target_version) {
341d5ede 399 carp "Upgrade not necessary\n";
8424c090 400 return;
c9d2e0a2 401 }
402
37fcb5b5 403 # strangely the first time this is called can
82625f90 404 # differ to subsequent times. so we call it
37fcb5b5 405 # here to be sure.
406 # XXX - just fix it
407 $self->storage->sqlt_type;
d4daee7b 408
8424c090 409 my $upgrade_file = $self->ddl_filename(
410 $self->storage->sqlt_type,
d2bc7045 411 $target_version,
99a74c4a 412 $self->upgrade_directory,
8424c090 413 $db_version,
414 );
c9d2e0a2 415
a354b842 416 $self->create_upgrade_path({ upgrade_file => $upgrade_file });
417
8424c090 418 unless (-f $upgrade_file) {
341d5ede 419 carp "Upgrade not possible, no upgrade file found ($upgrade_file), please create one\n";
8424c090 420 return;
421 }
c9d2e0a2 422
d7a58a29 423 carp "DB version ($db_version) is lower than the schema version (".$self->schema_version."). Attempting upgrade.\n";
a354b842 424
8424c090 425 # backup if necessary then apply upgrade
426 $self->_filedata($self->_read_sql_file($upgrade_file));
427 $self->backup() if($self->do_backup);
428 $self->txn_do(sub { $self->do_upgrade() });
c9d2e0a2 429
b4b1e91c 430 # set row in dbix_class_schema_versions table
d2bc7045 431 $self->_set_db_version({version => $target_version});
8424c090 432}
c9d2e0a2 433
e6129e56 434=head2 do_upgrade
435
c9d2e0a2 436This is an overwritable method used to run your upgrade. The freeform method
437allows you to run your upgrade any way you please, you can call C<run_upgrade>
438any number of times to run the actual SQL commands, and in between you can
439sandwich your data upgrading. For example, first run all the B<CREATE>
82625f90 440commands, then migrate your data from old to new tables/formats, then
e7b14c5b 441issue the DROP commands when you are finished. Will run the whole file as it is by default.
8424c090 442
443=cut
444
445sub do_upgrade
446{
e7b14c5b 447 my ($self) = @_;
8424c090 448
56988b6c 449 # just run all the commands (including inserts) in order
e7b14c5b 450 $self->run_upgrade(qr/.*?/);
8424c090 451}
452
c9d2e0a2 453=head2 run_upgrade
454
455 $self->run_upgrade(qr/create/i);
456
457Runs a set of SQL statements matching a passed in regular expression. The
458idea is that this method can be called any number of times from your
e84a43c1 459C<do_upgrade> method, running whichever commands you specify via the
8424c090 460regex in the parameter. Probably won't work unless called from the overridable
461do_upgrade method.
c9d2e0a2 462
8424c090 463=cut
8795fefb 464
8424c090 465sub run_upgrade
466{
467 my ($self, $stm) = @_;
8795fefb 468
8424c090 469 return unless ($self->_filedata);
470 my @statements = grep { $_ =~ $stm } @{$self->_filedata};
471 $self->_filedata([ grep { $_ !~ /$stm/i } @{$self->_filedata} ]);
8795fefb 472
8424c090 473 for (@statements)
82625f90 474 {
8424c090 475 $self->storage->debugobj->query_start($_) if $self->storage->debug;
abc8f12a 476 $self->apply_statement($_);
8424c090 477 $self->storage->debugobj->query_end($_) if $self->storage->debug;
478 }
8795fefb 479
8424c090 480 return 1;
481}
42416a0b 482
abc8f12a 483=head2 apply_statement
484
485Takes an SQL statement and runs it. Override this if you want to handle errors
486differently.
487
488=cut
489
490sub apply_statement {
491 my ($self, $statement) = @_;
492
d7a58a29 493 $self->storage->dbh->do($_) or carp "SQL was: $_";
abc8f12a 494}
495
93e4d41a 496=head2 get_db_version
497
498Returns the version that your database is currently at. This is determined by the values in the
e84a43c1 499dbix_class_schema_versions table that C<upgrade> and C<install> write to.
93e4d41a 500
501=cut
502
503sub get_db_version
504{
505 my ($self, $rs) = @_;
506
507 my $vtable = $self->{vschema}->resultset('Table');
9780718f 508 my $version = try {
67e7b822 509 $vtable->search({}, { order_by => { -desc => 'installed' }, rows => 1 } )
56988b6c 510 ->get_column ('version')
511 ->next;
93e4d41a 512 };
56988b6c 513 return $version || 0;
93e4d41a 514}
515
516=head2 schema_version
517
518Returns the current schema class' $VERSION
519
520=cut
521
522=head2 backup
523
524This is an overwritable method which is called just before the upgrade, to
525allow you to make a backup of the database. Per default this method attempts
526to call C<< $self->storage->backup >>, to run the standard backup on each
56988b6c 527database type.
93e4d41a 528
529This method should return the name of the backup file, if appropriate..
530
531This method is disabled by default. Set $schema->do_backup(1) to enable it.
532
533=cut
534
535sub backup
536{
537 my ($self) = @_;
538 ## Make each ::DBI::Foo do this
539 $self->storage->backup($self->backup_directory());
540}
541
ecea7937 542=head2 connection
543
544Overloaded method. This checks the DBIC schema version against the DB version and
545warns if they are not the same or if the DB is unversioned. It also provides
546compatibility between the old versions table (SchemaVersions) and the new one
547(dbix_class_schema_versions).
548
48580715 549To avoid the checks on connect, set the environment var DBIC_NO_VERSION_CHECK or alternatively you can set the ignore_version attr in the forth argument like so:
f81b9157 550
551 my $schema = MyApp::Schema->connect(
552 $dsn,
553 $user,
554 $password,
555 { ignore_version => 1 },
556 );
ecea7937 557
558=cut
559
8424c090 560sub connection {
561 my $self = shift;
562 $self->next::method(@_);
8012b15c 563 $self->_on_connect();
8424c090 564 return $self;
565}
566
567sub _on_connect
568{
8012b15c 569 my ($self) = @_;
f81b9157 570
8012b15c 571 my $info = $self->storage->connect_info;
572 my $args = $info->[-1];
06f10f6f 573
8012b15c 574 $self->{vschema} = DBIx::Class::Version->connect(@$info);
b4b1e91c 575 my $vtable = $self->{vschema}->resultset('Table');
576
c99c4801 577 # useful when connecting from scripts etc
578 return if ($args->{ignore_version} || ($ENV{DBIC_NO_VERSION_CHECK} && !exists $args->{ignore_version}));
579
b4b1e91c 580 # check for legacy versions table and move to new if exists
8012b15c 581 my $vschema_compat = DBIx::Class::VersionCompat->connect(@$info);
b4b1e91c 582 unless ($self->_source_exists($vtable)) {
583 my $vtable_compat = $vschema_compat->resultset('TableCompat');
584 if ($self->_source_exists($vtable_compat)) {
585 $self->{vschema}->deploy;
732dc718 586 map { $vtable->create({ installed => $_->Installed, version => $_->Version }) } $vtable_compat->all;
b4b1e91c 587 $self->storage->dbh->do("DROP TABLE " . $vtable_compat->result_source->from);
588 }
589 }
f81b9157 590
8424c090 591 my $pversion = $self->get_db_version();
592
593 if($pversion eq $self->schema_version)
594 {
341d5ede 595# carp "This version is already installed\n";
8424c090 596 return 1;
597 }
42416a0b 598
8424c090 599 if(!$pversion)
600 {
341d5ede 601 carp "Your DB is currently unversioned. Please call upgrade on your schema to sync the DB.\n";
8424c090 602 return 1;
603 }
604
d7a58a29 605 carp "Versions out of sync. This is " . $self->schema_version .
8424c090 606 ", your database contains version $pversion, please call upgrade on your Schema.\n";
607}
608
93e4d41a 609# is this just a waste of time? if not then merge with DBI.pm
610sub _create_db_to_schema_diff {
611 my $self = shift;
612
613 my %driver_to_db_map = (
614 'mysql' => 'MySQL'
615 );
616
617 my $db = $driver_to_db_map{$self->storage->dbh->{Driver}->{Name}};
618 unless ($db) {
619 print "Sorry, this is an unsupported DB\n";
620 return;
621 }
622
2527233b 623 unless (DBIx::Class::Optional::Dependencies->req_ok_for ('deploy')) {
624 $self->throw_exception("Unable to proceed without " . DBIx::Class::Optional::Dependencies->req_missing_for ('deploy') );
625 }
93e4d41a 626
b2b2e7fd 627 my $db_tr = SQL::Translator->new({
628 add_drop_table => 1,
93e4d41a 629 parser => 'DBI',
630 parser_args => { dbh => $self->storage->dbh }
631 });
632
633 $db_tr->producer($db);
634 my $dbic_tr = SQL::Translator->new;
635 $dbic_tr->parser('SQL::Translator::Parser::DBIx::Class');
93e4d41a 636 $dbic_tr->data($self);
637 $dbic_tr->producer($db);
638
639 $db_tr->schema->name('db_schema');
640 $dbic_tr->schema->name('dbic_schema');
641
642 # is this really necessary?
643 foreach my $tr ($db_tr, $dbic_tr) {
644 my $data = $tr->data;
645 $tr->parser->($tr, $$data);
646 }
647
82625f90 648 my $diff = SQL::Translator::Diff::schema_diff($db_tr->schema, $db,
93e4d41a 649 $dbic_tr->schema, $db,
650 { ignore_constraint_names => 1, ignore_index_names => 1, caseopt => 1 });
651
652 my $filename = $self->ddl_filename(
653 $db,
654 $self->schema_version,
655 $self->upgrade_directory,
656 'PRE',
657 );
658 my $file;
659 if(!open($file, ">$filename"))
660 {
661 $self->throw_exception("Can't open $filename for writing ($!)");
662 next;
663 }
664 print $file $diff;
665 close($file);
666
341d5ede 667 carp "WARNING: There may be differences between your DB and your DBIC schema. Please review and if necessary run the SQL in $filename to sync your DB.\n";
93e4d41a 668}
669
670
671sub _set_db_version {
672 my $self = shift;
a354b842 673 my ($params) = @_;
674 $params ||= {};
93e4d41a 675
a354b842 676 my $version = $params->{version} ? $params->{version} : $self->schema_version;
93e4d41a 677 my $vtable = $self->{vschema}->resultset('Table');
93e4d41a 678
d2bc7045 679 ##############################################################################
680 # !!! NOTE !!!
681 ##############################################################################
682 #
683 # The travesty below replaces the old nice timestamp format of %Y-%m-%d %H:%M:%S
684 # This is necessary since there are legitimate cases when upgrades can happen
685 # back to back within the same second. This breaks things since we relay on the
686 # ability to sort by the 'installed' value. The logical choice of an autoinc
fd323bf1 687 # is not possible, as it will break multiple legacy installations. Also it is
d2bc7045 688 # not possible to format the string sanely, as the column is a varchar(20).
689 # The 'v' character is added to the front of the string, so that any version
690 # formatted by this new function will sort _after_ any existing 200... strings.
691 my @tm = gettimeofday();
692 my @dt = gmtime ($tm[0]);
fd323bf1 693 my $o = $vtable->create({
d2bc7045 694 version => $version,
695 installed => sprintf("v%04d%02d%02d_%02d%02d%02d.%03.0f",
696 $dt[5] + 1900,
697 $dt[4] + 1,
698 $dt[3],
699 $dt[2],
700 $dt[1],
701 $dt[0],
702 $tm[1] / 1000, # convert to millisecs, format as up/down rounded int above
703 ),
704 });
93e4d41a 705}
706
707sub _read_sql_file {
708 my $self = shift;
709 my $file = shift || return;
710
82625f90 711 open my $fh, '<', $file or carp("Can't open upgrade file, $file ($!)");
712 my @data = split /\n/, join '', <$fh>;
713 close $fh;
714
b703fec7 715 @data = split /;/,
716 join '',
717 grep { $_ &&
718 !/^--/ &&
719 !/^(BEGIN|BEGIN TRANSACTION|COMMIT)/mi }
720 @data;
82625f90 721
93e4d41a 722 return \@data;
723}
724
725sub _source_exists
726{
727 my ($self, $rs) = @_;
728
52b420dd 729 my $c = try { $rs->search({ 1, 0 })->count };
93e4d41a 730
52b420dd 731 return (defined $c) ? 1 : 0;
93e4d41a 732}
733
8424c090 7341;
735
736
737=head1 AUTHORS
c9d2e0a2 738
1a9251f7 739Jess Robinson <castaway@desert-island.me.uk>
8424c090 740Luke Saunders <luke@shadowcatsystems.co.uk>
741
742=head1 LICENSE
743
744You may distribute this code under the same terms as Perl itself.