X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBIx%2FClass%2FDeploymentHandler.pm;h=c22b6ab3df6cbcc17b527de6df84659e0d32fdcc;hb=e217d19c58c8beba917e751dd1089281fa1a74ee;hp=0b176bde1ea4050623179c9abbc0ab3883bb0a59;hpb=7eec7eb7f143f2af5f24558da106d5098a58f116;p=dbsrgits%2FDBIx-Class-DeploymentHandler.git diff --git a/lib/DBIx/Class/DeploymentHandler.pm b/lib/DBIx/Class/DeploymentHandler.pm index 0b176bd..c22b6ab 100644 --- a/lib/DBIx/Class/DeploymentHandler.pm +++ b/lib/DBIx/Class/DeploymentHandler.pm @@ -3,263 +3,104 @@ package DBIx::Class::DeploymentHandler; use Moose; use Method::Signatures::Simple; require DBIx::Class::Schema; # loaded for type constraint -require DBIx::Class::Storage; # loaded for type constraint require DBIx::Class::ResultSet; # loaded for type constraint -use Carp 'carp'; +use Carp::Clan '^DBIx::Class::DeploymentHandler'; + +with 'DBIx::Class::DeploymentHandler::WithSqltDeployMethod'; +with 'DBIx::Class::DeploymentHandler::WithDatabaseToSchemaVersions'; + +BEGIN { + use Moose::Util::TypeConstraints; + subtype 'DBIx::Class::DeploymentHandler::Databases' + => as 'ArrayRef[Str]'; + + coerce 'DBIx::Class::DeploymentHandler::Databases' + => from 'Str' + => via { [$_] }; + no Moose::Util::TypeConstraints; +} has schema => ( - isa => 'DBIx::Class::Schema', - is => 'ro', - required => 1, - handles => [qw{schema_version}], + isa => 'DBIx::Class::Schema', + is => 'ro', + required => 1, ); -has upgrade_directory => ( - isa => 'Str', - is => 'ro', - required => 1, - default => 'sql', +has upgrade_directory => ( # configuration + isa => 'Str', + is => 'ro', + required => 1, + default => 'sql', ); -has backup_directory => ( - isa => 'Str', - is => 'ro', +has backup_directory => ( # configuration + isa => 'Str', + is => 'ro', + predicate => 'has_backup_directory', ); -has storage => ( - isa => 'DBIx::Class::Storage', - is => 'ro', - lazy_build => 1, +has do_backup => ( # configuration + isa => 'Bool', + is => 'ro', + default => undef, ); -method _build_storage { - my $s = $self->schema->storage; - $s->_determine_driver; - $s -} - -has _filedata => ( - isa => 'Str', - is => 'rw', +has version_rs => ( + isa => 'DBIx::Class::ResultSet', + is => 'ro', + lazy_build => 1, # builder comes from another role... + # which is... probably not how we want it + handles => [qw( is_installed )], ); -has do_backup => ( - isa => 'Bool', - is => 'ro', - default => undef, +has to_version => ( # configuration + is => 'ro', + lazy_build => 1, # builder comes from another role... + # which is... probably not how we want it ); -has do_diff_on_init => ( - isa => 'Bool', - is => 'ro', - default => undef, +has databases => ( # configuration + coerce => 1, + isa => 'DBIx::Class::DeploymentHandler::Databases', + is => 'ro', + default => sub { [qw( MySQL SQLite PostgreSQL )] }, ); -has version_rs => ( - isa => 'DBIx::Class::ResultSet', - is => 'ro', - lazy_build => 1, - handles => [qw( is_installed db_version )], +has sqltargs => ( # configuration + isa => 'HashRef', + is => 'ro', + default => sub { {} }, ); -method _build_version_rs { $self->schema->resultset('VersionResult') } - -method backup { $self->storage->backup($self->backup_directory) } - -method install($new_version) { +method install { carp 'Install not possible as versions table already exists in database' - unless $self->is_installed; + if $self->is_installed; - $new_version ||= $self->schema_version; + my $new_version = $self->to_version; if ($new_version) { - $self->schema->deploy; + $self->_deploy; $self->version_rs->create({ - version => $new_version, - # ddl => $ddl, - # upgrade_sql => $upgrade_sql, + version => $new_version, + # ddl => $ddl, + # upgrade_sql => $upgrade_sql, }); } } -method create_upgrade_path { } - -method ordered_schema_versions { } - -method upgrade { - my $db_version = $self->db_version; - my $schema_version = $self->schema_version; - - unless ($db_version) { - carp 'Upgrade not possible as database is unversioned. Please call install first.'; - return; - } - - if ( $db_version eq $schema_version ) { - carp "Upgrade not necessary\n"; - return; - } - - my @version_list = $self->ordered_schema_versions || - ( $db_version, $schema_version ); - - # remove all versions in list above the required version - while ( @version_list && ( $version_list[-1] ne $schema_version ) ) { - pop @version_list; - } - - # remove all versions in list below the current version - while ( @version_list && ( $version_list[0] ne $db_version ) ) { - shift @version_list; - } - - # check we have an appropriate list of versions - die if @version_list < 2; - - # do sets of upgrade - while ( @version_list >= 2 ) { - $self->upgrade_single_step( $version_list[0], $version_list[1] ); - shift @version_list; +sub upgrade { + while ( my $version_list = $_[0]->next_version_set ) { + $_[0]->_upgrade_single_step($version_list); } } -method upgrade_single_step($db_version, $target_version) { - if ($db_version eq $target_version) { - carp "Upgrade not necessary\n"; - 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, - $target_version, - $self->upgrade_directory, - $db_version, - ); - - $self->create_upgrade_path({ upgrade_file => $upgrade_file }); - - unless (-f $upgrade_file) { - carp "Upgrade not possible, no upgrade file found ($upgrade_file), please create one\n"; - return; - } - - carp "DB version ($db_version) is lower than the schema version (".$self->schema_version."). Attempting upgrade.\n"; - - # backup if necessary then apply upgrade - $self->_filedata($self->_read_sql_file($upgrade_file)); - $self->backup if $self->do_backup; - $self->schema->txn_do(sub { $self->do_upgrade }); - - # set row in dbix_class_schema_versions table - $self->version_rs->create({ - version => $target_version, - # ddl => $ddl, - # upgrade_sql => $upgrade_sql, - }); -} - -method do_upgrade { $self->run_upgrade(qr/.*?/) } - -method run_upgrade($stm) { - return unless $self->_filedata; - my @statements = grep { $_ =~ $stm } @{$self->_filedata}; - - for (@statements) { - $self->storage->debugobj->query_start($_) if $self->storage->debug; - $self->apply_statement($_); - $self->storage->debugobj->query_end($_) if $self->storage->debug; - } -} - -method apply_statement($statement) { - $self->storage->dbh->do($_) or carp "SQL was: $_" -} - -sub _create_db_to_schema_diff { - my $self = shift; - - my %driver_to_db_map = ( - 'mysql' => 'MySQL' - ); - - my $db = $driver_to_db_map{$self->storage->dbh->{Driver}{Name}}; - unless ($db) { - print "Sorry, this is an unsupported DB\n"; - return; - } - - $self->throw_exception($self->storage->_sqlt_version_error) - unless $self->storage->_sqlt_version_ok; - - my $db_tr = SQL::Translator->new({ - add_drop_table => 1, - parser => 'DBI', - parser_args => { dbh => $self->storage->dbh }, - producer => $db, - }); - - my $dbic_tr = SQL::Translator->new({ - parser => 'SQL::Translator::Parser::DBIx::Class', - data => $self, - producer => $db, - }); - - $db_tr->schema->name('db_schema'); - $dbic_tr->schema->name('dbic_schema'); - - # is this really necessary? - foreach my $tr ($db_tr, $dbic_tr) { - my $data = $tr->data; - $tr->parser->($tr, $$data); - } - - my $diff = SQL::Translator::Diff::schema_diff( - $db_tr->schema, $db, - $dbic_tr->schema, $db, { - ignore_constraint_names => 1, - ignore_index_names => 1, - caseopt => 1, - } - ); - - my $filename = $self->ddl_filename( - $db, - $self->schema_version, - $self->upgrade_directory, - 'PRE', - ); - - open my $file, '>', $filename - or $self->throw_exception("Can't open $filename for writing ($!)"); - print {$file} $diff; - close $file; - - carp "WARNING: There may be differences between your DB and your DBIC schema.\n" . - "Please review and if necessary run the SQL in $filename to sync your DB.\n"; -} - -method _read_sql_file($file) { - return unless $file; +method backup { $self->storage->backup($self->backup_directory) } - open my $fh, '<', $file or carp("Can't open upgrade file, $file ($!)"); - my @data = split /\n/, join '', <$fh>; - close $fh; +__PACKAGE__->meta->make_immutable; - @data = grep { - $_ && - !/^--/ && - !/^(BEGIN|BEGIN TRANSACTION|COMMIT)/m - } split /;/, - join '', @data; +1; - return \@data; -} +__END__ -1; +vim: ts=2 sw=2 expandtab