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