X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBIx%2FClass%2FSchema%2FVersioned.pm;h=877b841220b6f5f82ab1c25090d9cde8e45c61df;hb=99a74c4ad4029a2fde7665d47cd444c041737c58;hp=150c3c9b3a26dcb3fb9863c6bbafbb99342ac81b;hpb=d89d86046f9b0bc02bcedef7000bb7ceec6a33ca;p=dbsrgits%2FDBIx-Class.git diff --git a/lib/DBIx/Class/Schema/Versioned.pm b/lib/DBIx/Class/Schema/Versioned.pm index 150c3c9..877b841 100644 --- a/lib/DBIx/Class/Schema/Versioned.pm +++ b/lib/DBIx/Class/Schema/Versioned.pm @@ -1,40 +1,66 @@ -package DBIx::Class::Version::Table; +package # Hide from PAUSE + DBIx::Class::Version::Table; use base 'DBIx::Class'; use strict; use warnings; __PACKAGE__->load_components(qw/ Core/); -__PACKAGE__->table('SchemaVersions'); +__PACKAGE__->table('dbix_class_schema_versions'); __PACKAGE__->add_columns - ( 'Version' => { + ( 'version' => { 'data_type' => 'VARCHAR', 'is_auto_increment' => 0, 'default_value' => undef, 'is_foreign_key' => 0, - 'name' => 'Version', + 'name' => 'version', 'is_nullable' => 0, 'size' => '10' }, - 'Installed' => { + 'installed' => { 'data_type' => 'VARCHAR', 'is_auto_increment' => 0, 'default_value' => undef, 'is_foreign_key' => 0, - 'name' => 'Installed', + 'name' => 'installed', 'is_nullable' => 0, 'size' => '20' }, ); +__PACKAGE__->set_primary_key('version'); + +package # Hide from PAUSE + DBIx::Class::Version::TableCompat; +use base 'DBIx::Class'; +__PACKAGE__->load_components(qw/ Core/); +__PACKAGE__->table('SchemaVersions'); + +__PACKAGE__->add_columns + ( 'Version' => { + 'data_type' => 'VARCHAR', + }, + 'Installed' => { + 'data_type' => 'VARCHAR', + }, + ); __PACKAGE__->set_primary_key('Version'); -package DBIx::Class::Version; +package # Hide from PAUSE + DBIx::Class::Version; use base 'DBIx::Class::Schema'; use strict; use warnings; __PACKAGE__->register_class('Table', 'DBIx::Class::Version::Table'); +package # Hide from PAUSE + DBIx::Class::VersionCompat; +use base 'DBIx::Class::Schema'; +use strict; +use warnings; + +__PACKAGE__->register_class('TableCompat', 'DBIx::Class::Version::TableCompat'); + # --------------------------------------------------------------------------- @@ -61,7 +87,7 @@ classes, to enable them to upgrade to newer schema layouts. To use this module, you need to have called C on your Schema to create your upgrade files to include with your delivery. -A table called I is created and maintained by the +A table called I is created and maintained by the module. This contains two fields, 'Version' and 'Installed', which contain each VERSION of your Schema, and the date+time it was installed. @@ -126,7 +152,7 @@ sub schema_version { =head2 get_db_version Returns the version that your database is currently at. This is determined by the values in the -SchemaVersions table that $self->upgrade writes to. +dbix_class_schema_versions table that $self->upgrade writes to. =cut @@ -135,18 +161,12 @@ sub get_db_version my ($self, $rs) = @_; my $vtable = $self->{vschema}->resultset('Table'); - return 0 unless ($self->_source_exists($vtable)); - - my $psearch = $vtable->search(undef, - { select => [ - { 'max' => 'Installed' }, - ], - as => ['maxinstall'], - })->first; - my $pversion = $vtable->search({ Installed => $psearch->get_column('maxinstall'), - })->first; - $pversion = $pversion->Version if($pversion); - return $pversion; + my $version = 0; + eval { + my $stamp = $vtable->get_column('installed')->max; + $version = $vtable->search({ installed => $stamp })->first->version; + }; + return $version; } sub _source_exists @@ -170,6 +190,8 @@ database type. This method should return the name of the backup file, if appropriate.. +This method is disabled by default. Set $schema->do_backup(1) to enable it. + =cut sub backup @@ -179,7 +201,7 @@ sub backup $self->storage->backup($self->backup_directory()); } -# is this just a waste of time? +# is this just a waste of time? if not then merge with DBI.pm sub _create_db_to_schema_diff { my $self = shift; @@ -193,8 +215,10 @@ sub _create_db_to_schema_diff { return; } - require SQL::Translator; - require SQL::Translator::Diff; + eval 'require SQL::Translator "0.09"'; + if ($@) { + $self->throw_exception("SQL::Translator 0.09 required"); + } my $db_tr = SQL::Translator->new({ add_drop_table => 1, @@ -224,8 +248,8 @@ sub _create_db_to_schema_diff { my $filename = $self->ddl_filename( $db, - $self->upgrade_directory, $self->schema_version, + $self->upgrade_directory, 'PRE', ); my $file; @@ -257,7 +281,7 @@ sub upgrade # db unversioned unless ($db_version) { - # set version in SchemaVersions table, can't actually upgrade as we don 't know what version the DB is at + # set version in dbix_class_schema_versions table, can't actually upgrade as we don 't know what version the DB is at $self->_create_db_to_schema_diff() if ($self->do_diff_on_init); # create versions table and version row @@ -272,10 +296,16 @@ sub upgrade return; } + # strangely the first time this is called can + # differ to subsequent times. so we call it + # here to be sure. + # XXX - just fix it + $self->storage->sqlt_type; + my $upgrade_file = $self->ddl_filename( $self->storage->sqlt_type, - $self->upgrade_directory, $self->schema_version, + $self->upgrade_directory, $db_version, ); @@ -289,7 +319,7 @@ sub upgrade $self->backup() if($self->do_backup); $self->txn_do(sub { $self->do_upgrade() }); - # set row in SchemaVersions table + # set row in dbix_class_schema_versions table $self->_set_db_version; } @@ -297,8 +327,8 @@ sub _set_db_version { my $self = shift; my $vtable = $self->{vschema}->resultset('Table'); - $vtable->create({ Version => $self->schema_version, - Installed => strftime("%Y-%m-%d %H:%M:%S", gmtime()) + $vtable->create({ version => $self->schema_version, + installed => strftime("%Y-%m-%d %H:%M:%S", gmtime()) }); } @@ -314,7 +344,7 @@ sub _read_sql_file { @data = split(/;/, join('', @data)); close($fh); @data = grep { $_ && $_ !~ /^-- / } @data; - @data = grep { $_ !~ /^(BEGIN TRANACTION|COMMIT)/m } @data; + @data = grep { $_ !~ /^(BEGIN TRANSACTION|COMMIT)/m } @data; return \@data; } @@ -325,22 +355,16 @@ allows you to run your upgrade any way you please, you can call C any number of times to run the actual SQL commands, and in between you can sandwich your data upgrading. For example, first run all the B commands, then migrate your data from old to new tables/formats, then -issue the DROP commands when you are finished. - -Will run the whole file as it is by default. +issue the DROP commands when you are finished. Will run the whole file as it is by default. =cut sub do_upgrade { - my ($self) = @_; + my ($self) = @_; - ## overridable sub, per default just run all the commands. - $self->run_upgrade(qr/create/i); - $self->run_upgrade(qr/alter table .*? add/i); - $self->run_upgrade(qr/alter table .*? (?!drop)/i); - $self->run_upgrade(qr/alter table .*? drop/i); - $self->run_upgrade(qr/drop/i); + # just run all the commands (including inserts) in order + $self->run_upgrade(qr/.*?/); } =head2 run_upgrade @@ -373,23 +397,57 @@ sub run_upgrade return 1; } +=head2 connection + +Overloaded method. This checks the DBIC schema version against the DB version and +warns if they are not the same or if the DB is unversioned. It also provides +compatibility between the old versions table (SchemaVersions) and the new one +(dbix_class_schema_versions). + +To avoid the checks on connect, set the env var DBIC_NO_VERSION_CHECK or alternatively you can set the ignore_version attr in the forth arg like so: + + my $schema = MyApp::Schema->connect( + $dsn, + $user, + $password, + { ignore_version => 1 }, + ); + +=cut + sub connection { my $self = shift; $self->next::method(@_); - $self->_on_connect; + $self->_on_connect($_[3]); return $self; } sub _on_connect { - my ($self) = @_; + my ($self, $args) = @_; + + $args = {} unless $args; $self->{vschema} = DBIx::Class::Version->connect(@{$self->storage->connect_info()}); + my $vtable = $self->{vschema}->resultset('Table'); + + # check for legacy versions table and move to new if exists + my $vschema_compat = DBIx::Class::VersionCompat->connect(@{$self->storage->connect_info()}); + unless ($self->_source_exists($vtable)) { + my $vtable_compat = $vschema_compat->resultset('TableCompat'); + if ($self->_source_exists($vtable_compat)) { + $self->{vschema}->deploy; + map { $vtable->create({ installed => $_->Installed, version => $_->Version }) } $vtable_compat->all; + $self->storage->dbh->do("DROP TABLE " . $vtable_compat->result_source->from); + } + } + # useful when connecting from scripts etc + return if ($args->{ignore_version} || ($ENV{DBIC_NO_VERSION_CHECK} && !exists $args->{ignore_version})); my $pversion = $self->get_db_version(); if($pversion eq $self->schema_version) { - warn "This version is already installed\n"; +# warn "This version is already installed\n"; return 1; }