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