spelling fixes in the documaentation, sholud be gud now ;)
[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/;
c9d2e0a2 185
186__PACKAGE__->mk_classdata('_filedata');
187__PACKAGE__->mk_classdata('upgrade_directory');
8795fefb 188__PACKAGE__->mk_classdata('backup_directory');
f925f7cb 189__PACKAGE__->mk_classdata('do_backup');
8424c090 190__PACKAGE__->mk_classdata('do_diff_on_init');
191
e84a43c1 192
193=head1 METHODS
194
195=head2 upgrade_directory
196
197Use this to set the directory your upgrade files are stored in.
198
199=head2 backup_directory
200
201Use this to set the directory you want your backups stored in (note that backups
202are disabled by default).
203
204=cut
205
93e4d41a 206=head2 install
c9d2e0a2 207
93e4d41a 208=over 4
c9d2e0a2 209
93e4d41a 210=item Arguments: $db_version
e6129e56 211
93e4d41a 212=back
8424c090 213
93e4d41a 214Call 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 215
93e4d41a 216Takes one argument which should be the version that the database is currently at. Defaults to the return value of L</schema_version>.
8424c090 217
93e4d41a 218See L</getting_started> for more details.
f81b9157 219
8424c090 220=cut
221
93e4d41a 222sub install
c9d2e0a2 223{
93e4d41a 224 my ($self, $new_version) = @_;
c9d2e0a2 225
93e4d41a 226 # must be called on a fresh database
227 if ($self->get_db_version()) {
341d5ede 228 carp 'Install not possible as versions table already exists in database';
8424c090 229 }
c9d2e0a2 230
93e4d41a 231 # default to current version if none passed
232 $new_version ||= $self->schema_version();
8424c090 233
e84a43c1 234 if ($new_version) {
93e4d41a 235 # create versions table and version row
236 $self->{vschema}->deploy;
a354b842 237 $self->_set_db_version({ version => $new_version });
8424c090 238 }
c9d2e0a2 239}
240
e84a43c1 241=head2 deploy
242
243Same as L<DBIx::Class::Schema/deploy> but also calls C<install>.
244
245=cut
246
247sub deploy {
248 my $self = shift;
249 $self->next::method(@_);
250 $self->install();
251}
252
a354b842 253=head2 create_upgrade_path
254
255=over 4
256
257=item Arguments: { upgrade_file => $file }
258
259=back
260
c1300297 261Virtual method that should be overridden to create an upgrade file.
56988b6c 262This is useful in the case of upgrading across multiple versions
a354b842 263to concatenate several files to create one upgrade file.
264
4a743a00 265You'll probably want the db_version retrieved via $self->get_db_version
56988b6c 266and the schema_version which is retrieved via $self->schema_version
4a743a00 267
a354b842 268=cut
269
270sub create_upgrade_path {
d7a58a29 271 ## override this method
a354b842 272}
273
d2bc7045 274=head2 ordered_schema_versions
275
276=over 4
277
278=item Returns: a list of version numbers, ordered from lowest to highest
279
280=back
281
c1300297 282Virtual method that should be overridden to return an ordered list
d2bc7045 283of schema versions. This is then used to produce a set of steps to
284upgrade through to achieve the required schema version.
285
286You may want the db_version retrieved via $self->get_db_version
56988b6c 287and the schema_version which is retrieved via $self->schema_version
d2bc7045 288
289=cut
290
291sub ordered_schema_versions {
56988b6c 292 ## override this method
d2bc7045 293}
294
8424c090 295=head2 upgrade
e2c0df8e 296
d2bc7045 297Call this to attempt to upgrade your database from the version it
298is at to the version this DBIC schema is at. If they are the same
299it does nothing.
e84a43c1 300
d2bc7045 301It will call L</ordered_schema_versions> to retrieve an ordered
302list of schema versions (if ordered_schema_versions returns nothing
303then it is assumed you can do the upgrade as a single step). It
304then iterates through the list of versions between the current db
305version and the schema version applying one update at a time until
48580715 306all relevant updates are applied.
c9d2e0a2 307
d2bc7045 308The individual update steps are performed by using
309L</upgrade_single_step>, which will apply the update and also
310update the dbix_class_schema_versions table.
c9d2e0a2 311
8424c090 312=cut
c9d2e0a2 313
d2bc7045 314sub upgrade {
315 my ($self) = @_;
316 my $db_version = $self->get_db_version();
c9d2e0a2 317
d2bc7045 318 # db unversioned
319 unless ($db_version) {
320 carp 'Upgrade not possible as database is unversioned. Please call install first.';
321 return;
322 }
323
324 # db and schema at same version. do nothing
325 if ( $db_version eq $self->schema_version ) {
326 carp "Upgrade not necessary\n";
327 return;
328 }
329
330 my @version_list = $self->ordered_schema_versions;
331
332 # if nothing returned then we preload with min/max
333 @version_list = ( $db_version, $self->schema_version )
334 unless ( scalar(@version_list) );
335
336 # catch the case of someone returning an arrayref
337 @version_list = @{ $version_list[0] }
338 if ( ref( $version_list[0] ) eq 'ARRAY' );
339
340 # remove all versions in list above the required version
341 while ( scalar(@version_list)
342 && ( $version_list[-1] ne $self->schema_version ) )
343 {
344 pop @version_list;
345 }
346
347 # remove all versions in list below the current version
348 while ( scalar(@version_list) && ( $version_list[0] ne $db_version ) ) {
349 shift @version_list;
350 }
351
352 # check we have an appropriate list of versions
353 if ( scalar(@version_list) < 2 ) {
354 die;
355 }
356
357 # do sets of upgrade
358 while ( scalar(@version_list) >= 2 ) {
359 $self->upgrade_single_step( $version_list[0], $version_list[1] );
360 shift @version_list;
361 }
362}
363
364=head2 upgrade_single_step
365
366=over 4
367
368=item Arguments: db_version - the version currently within the db
369
370=item Arguments: target_version - the version to upgrade to
371
372=back
373
374Call this to attempt to upgrade your database from the
375I<db_version> to the I<target_version>. If they are the same it
376does nothing.
377
378It requires an SQL diff file to exist in your I<upgrade_directory>,
379normally you will have created this using L<DBIx::Class::Schema/create_ddl_dir>.
380
381If successful the dbix_class_schema_versions table is updated with
382the I<target_version>.
383
384This method may be called repeatedly by the upgrade method to
385upgrade through a series of updates.
386
387=cut
388
389sub upgrade_single_step
390{
391 my ($self,
392 $db_version,
393 $target_version) = @_;
c9d2e0a2 394
8424c090 395 # db and schema at same version. do nothing
d2bc7045 396 if ($db_version eq $target_version) {
341d5ede 397 carp "Upgrade not necessary\n";
8424c090 398 return;
c9d2e0a2 399 }
400
37fcb5b5 401 # strangely the first time this is called can
82625f90 402 # differ to subsequent times. so we call it
37fcb5b5 403 # here to be sure.
404 # XXX - just fix it
405 $self->storage->sqlt_type;
d4daee7b 406
8424c090 407 my $upgrade_file = $self->ddl_filename(
408 $self->storage->sqlt_type,
d2bc7045 409 $target_version,
99a74c4a 410 $self->upgrade_directory,
8424c090 411 $db_version,
412 );
c9d2e0a2 413
a354b842 414 $self->create_upgrade_path({ upgrade_file => $upgrade_file });
415
8424c090 416 unless (-f $upgrade_file) {
341d5ede 417 carp "Upgrade not possible, no upgrade file found ($upgrade_file), please create one\n";
8424c090 418 return;
419 }
c9d2e0a2 420
d7a58a29 421 carp "DB version ($db_version) is lower than the schema version (".$self->schema_version."). Attempting upgrade.\n";
a354b842 422
8424c090 423 # backup if necessary then apply upgrade
424 $self->_filedata($self->_read_sql_file($upgrade_file));
425 $self->backup() if($self->do_backup);
426 $self->txn_do(sub { $self->do_upgrade() });
c9d2e0a2 427
b4b1e91c 428 # set row in dbix_class_schema_versions table
d2bc7045 429 $self->_set_db_version({version => $target_version});
8424c090 430}
c9d2e0a2 431
e6129e56 432=head2 do_upgrade
433
c9d2e0a2 434This is an overwritable method used to run your upgrade. The freeform method
435allows you to run your upgrade any way you please, you can call C<run_upgrade>
436any number of times to run the actual SQL commands, and in between you can
437sandwich your data upgrading. For example, first run all the B<CREATE>
82625f90 438commands, then migrate your data from old to new tables/formats, then
e7b14c5b 439issue the DROP commands when you are finished. Will run the whole file as it is by default.
8424c090 440
441=cut
442
443sub do_upgrade
444{
e7b14c5b 445 my ($self) = @_;
8424c090 446
56988b6c 447 # just run all the commands (including inserts) in order
e7b14c5b 448 $self->run_upgrade(qr/.*?/);
8424c090 449}
450
c9d2e0a2 451=head2 run_upgrade
452
453 $self->run_upgrade(qr/create/i);
454
455Runs a set of SQL statements matching a passed in regular expression. The
456idea is that this method can be called any number of times from your
e84a43c1 457C<do_upgrade> method, running whichever commands you specify via the
8424c090 458regex in the parameter. Probably won't work unless called from the overridable
459do_upgrade method.
c9d2e0a2 460
8424c090 461=cut
8795fefb 462
8424c090 463sub run_upgrade
464{
465 my ($self, $stm) = @_;
8795fefb 466
8424c090 467 return unless ($self->_filedata);
468 my @statements = grep { $_ =~ $stm } @{$self->_filedata};
469 $self->_filedata([ grep { $_ !~ /$stm/i } @{$self->_filedata} ]);
8795fefb 470
8424c090 471 for (@statements)
82625f90 472 {
8424c090 473 $self->storage->debugobj->query_start($_) if $self->storage->debug;
abc8f12a 474 $self->apply_statement($_);
8424c090 475 $self->storage->debugobj->query_end($_) if $self->storage->debug;
476 }
8795fefb 477
8424c090 478 return 1;
479}
42416a0b 480
abc8f12a 481=head2 apply_statement
482
483Takes an SQL statement and runs it. Override this if you want to handle errors
484differently.
485
486=cut
487
488sub apply_statement {
489 my ($self, $statement) = @_;
490
d7a58a29 491 $self->storage->dbh->do($_) or carp "SQL was: $_";
abc8f12a 492}
493
93e4d41a 494=head2 get_db_version
495
496Returns the version that your database is currently at. This is determined by the values in the
e84a43c1 497dbix_class_schema_versions table that C<upgrade> and C<install> write to.
93e4d41a 498
499=cut
500
501sub get_db_version
502{
503 my ($self, $rs) = @_;
504
505 my $vtable = $self->{vschema}->resultset('Table');
56988b6c 506 my $version = eval {
507 $vtable->search({}, { order_by => { -desc => 'installed' }, rows => 1 } )
508 ->get_column ('version')
509 ->next;
93e4d41a 510 };
56988b6c 511 return $version || 0;
93e4d41a 512}
513
514=head2 schema_version
515
516Returns the current schema class' $VERSION
517
518=cut
519
520=head2 backup
521
522This is an overwritable method which is called just before the upgrade, to
523allow you to make a backup of the database. Per default this method attempts
524to call C<< $self->storage->backup >>, to run the standard backup on each
56988b6c 525database type.
93e4d41a 526
527This method should return the name of the backup file, if appropriate..
528
529This method is disabled by default. Set $schema->do_backup(1) to enable it.
530
531=cut
532
533sub backup
534{
535 my ($self) = @_;
536 ## Make each ::DBI::Foo do this
537 $self->storage->backup($self->backup_directory());
538}
539
ecea7937 540=head2 connection
541
542Overloaded method. This checks the DBIC schema version against the DB version and
543warns if they are not the same or if the DB is unversioned. It also provides
544compatibility between the old versions table (SchemaVersions) and the new one
545(dbix_class_schema_versions).
546
48580715 547To 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 548
549 my $schema = MyApp::Schema->connect(
550 $dsn,
551 $user,
552 $password,
553 { ignore_version => 1 },
554 );
ecea7937 555
556=cut
557
8424c090 558sub connection {
559 my $self = shift;
560 $self->next::method(@_);
f81b9157 561 $self->_on_connect($_[3]);
8424c090 562 return $self;
563}
564
565sub _on_connect
566{
f81b9157 567 my ($self, $args) = @_;
568
569 $args = {} unless $args;
06f10f6f 570
8424c090 571 $self->{vschema} = DBIx::Class::Version->connect(@{$self->storage->connect_info()});
b4b1e91c 572 my $vtable = $self->{vschema}->resultset('Table');
573
c99c4801 574 # useful when connecting from scripts etc
575 return if ($args->{ignore_version} || ($ENV{DBIC_NO_VERSION_CHECK} && !exists $args->{ignore_version}));
576
b4b1e91c 577 # check for legacy versions table and move to new if exists
578 my $vschema_compat = DBIx::Class::VersionCompat->connect(@{$self->storage->connect_info()});
579 unless ($self->_source_exists($vtable)) {
580 my $vtable_compat = $vschema_compat->resultset('TableCompat');
581 if ($self->_source_exists($vtable_compat)) {
582 $self->{vschema}->deploy;
732dc718 583 map { $vtable->create({ installed => $_->Installed, version => $_->Version }) } $vtable_compat->all;
b4b1e91c 584 $self->storage->dbh->do("DROP TABLE " . $vtable_compat->result_source->from);
585 }
586 }
f81b9157 587
8424c090 588 my $pversion = $self->get_db_version();
589
590 if($pversion eq $self->schema_version)
591 {
341d5ede 592# carp "This version is already installed\n";
8424c090 593 return 1;
594 }
42416a0b 595
8424c090 596 if(!$pversion)
597 {
341d5ede 598 carp "Your DB is currently unversioned. Please call upgrade on your schema to sync the DB.\n";
8424c090 599 return 1;
600 }
601
d7a58a29 602 carp "Versions out of sync. This is " . $self->schema_version .
8424c090 603 ", your database contains version $pversion, please call upgrade on your Schema.\n";
604}
605
93e4d41a 606# is this just a waste of time? if not then merge with DBI.pm
607sub _create_db_to_schema_diff {
608 my $self = shift;
609
610 my %driver_to_db_map = (
611 'mysql' => 'MySQL'
612 );
613
614 my $db = $driver_to_db_map{$self->storage->dbh->{Driver}->{Name}};
615 unless ($db) {
616 print "Sorry, this is an unsupported DB\n";
617 return;
618 }
619
2527233b 620 unless (DBIx::Class::Optional::Dependencies->req_ok_for ('deploy')) {
621 $self->throw_exception("Unable to proceed without " . DBIx::Class::Optional::Dependencies->req_missing_for ('deploy') );
622 }
93e4d41a 623
b2b2e7fd 624 my $db_tr = SQL::Translator->new({
625 add_drop_table => 1,
93e4d41a 626 parser => 'DBI',
627 parser_args => { dbh => $self->storage->dbh }
628 });
629
630 $db_tr->producer($db);
631 my $dbic_tr = SQL::Translator->new;
632 $dbic_tr->parser('SQL::Translator::Parser::DBIx::Class');
93e4d41a 633 $dbic_tr->data($self);
634 $dbic_tr->producer($db);
635
636 $db_tr->schema->name('db_schema');
637 $dbic_tr->schema->name('dbic_schema');
638
639 # is this really necessary?
640 foreach my $tr ($db_tr, $dbic_tr) {
641 my $data = $tr->data;
642 $tr->parser->($tr, $$data);
643 }
644
82625f90 645 my $diff = SQL::Translator::Diff::schema_diff($db_tr->schema, $db,
93e4d41a 646 $dbic_tr->schema, $db,
647 { ignore_constraint_names => 1, ignore_index_names => 1, caseopt => 1 });
648
649 my $filename = $self->ddl_filename(
650 $db,
651 $self->schema_version,
652 $self->upgrade_directory,
653 'PRE',
654 );
655 my $file;
656 if(!open($file, ">$filename"))
657 {
658 $self->throw_exception("Can't open $filename for writing ($!)");
659 next;
660 }
661 print $file $diff;
662 close($file);
663
341d5ede 664 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 665}
666
667
668sub _set_db_version {
669 my $self = shift;
a354b842 670 my ($params) = @_;
671 $params ||= {};
93e4d41a 672
a354b842 673 my $version = $params->{version} ? $params->{version} : $self->schema_version;
93e4d41a 674 my $vtable = $self->{vschema}->resultset('Table');
93e4d41a 675
d2bc7045 676 ##############################################################################
677 # !!! NOTE !!!
678 ##############################################################################
679 #
680 # The travesty below replaces the old nice timestamp format of %Y-%m-%d %H:%M:%S
681 # This is necessary since there are legitimate cases when upgrades can happen
682 # back to back within the same second. This breaks things since we relay on the
683 # ability to sort by the 'installed' value. The logical choice of an autoinc
684 # is not possible, as it will break multiple legacy installations. Also it is
685 # not possible to format the string sanely, as the column is a varchar(20).
686 # The 'v' character is added to the front of the string, so that any version
687 # formatted by this new function will sort _after_ any existing 200... strings.
688 my @tm = gettimeofday();
689 my @dt = gmtime ($tm[0]);
690 my $o = $vtable->create({
691 version => $version,
692 installed => sprintf("v%04d%02d%02d_%02d%02d%02d.%03.0f",
693 $dt[5] + 1900,
694 $dt[4] + 1,
695 $dt[3],
696 $dt[2],
697 $dt[1],
698 $dt[0],
699 $tm[1] / 1000, # convert to millisecs, format as up/down rounded int above
700 ),
701 });
93e4d41a 702}
703
704sub _read_sql_file {
705 my $self = shift;
706 my $file = shift || return;
707
82625f90 708 open my $fh, '<', $file or carp("Can't open upgrade file, $file ($!)");
709 my @data = split /\n/, join '', <$fh>;
710 close $fh;
711
712 @data = grep {
713 $_ &&
714 !/^--/ &&
715 !/^(BEGIN|BEGIN TRANSACTION|COMMIT)/m
716 } split /;/,
717 join '', @data;
718
93e4d41a 719 return \@data;
720}
721
722sub _source_exists
723{
724 my ($self, $rs) = @_;
725
726 my $c = eval {
727 $rs->search({ 1, 0 })->count;
728 };
729 return 0 if $@ || !defined $c;
730
731 return 1;
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.