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