huge refactoring to clean up SQLTDM and allow running of arbitraty perl in upgrades...
Arthur Axel 'fREW' Schmidt [Sat, 27 Mar 2010 18:30:24 +0000 (13:30 -0500)]
WithReasonableDefaults role to deal with what information is available where

lib/DBIx/Class/DeploymentHandler.pm
lib/DBIx/Class/DeploymentHandler/DeployMethod/SQL/Translator.pm
lib/DBIx/Class/DeploymentHandler/Deprecated.pm
lib/DBIx/Class/DeploymentHandler/WithReasonableDefaults.pm [new file with mode: 0644]
t/deploy_methods/sql_translator.t
t/deploy_methods/sql_translator_deprecated.t

index 3079451..3524615 100644 (file)
@@ -3,9 +3,12 @@ package DBIx::Class::DeploymentHandler;
 use Moose;
 
 extends 'DBIx::Class::DeploymentHandler::Dad';
+# a single with would be better, but we can't do that
+# see: http://rt.cpan.org/Public/Bug/Display.html?id=46347
 with 'DBIx::Class::DeploymentHandler::WithSqltDeployMethod',
      'DBIx::Class::DeploymentHandler::WithDatabaseToSchemaVersions',
      'DBIx::Class::DeploymentHandler::WithStandardVersionStorage';
+with 'DBIx::Class::DeploymentHandler::WithReasonableDefaults';
 
 __PACKAGE__->meta->make_immutable;
 
index f8377bf..637a983 100644 (file)
@@ -86,12 +86,12 @@ method __ddl_consume_with_prefix($type, $versions, $prefix) {
   }
 
   opendir my($dh), $dir;
-  my %files = map { $_ => "$dir/$_" } grep { /\.sql$/ && -f "$dir/$_" } readdir $dh;
+  my %files = map { $_ => "$dir/$_" } grep { /\.(?:sql|pl)$/ && -f "$dir/$_" } readdir $dh;
   closedir $dh;
 
   if (-d $common) {
     opendir my($dh), $common;
-    for my $filename (grep { /\.sql$/ && -f catfile($common,$_) } readdir $dh) {
+    for my $filename (grep { /\.(?:sql|pl)$/ && -f catfile($common,$_) } readdir $dh) {
       unless ($files{$filename}) {
         $files{$filename} = catfile($common,$filename);
       }
@@ -138,32 +138,49 @@ method _ddl_schema_down_produce_filename($type, $versions, $dir) {
   return catfile( $dirname, '001-auto.sql');
 }
 
-sub deploy {
-  my $self = shift;
-  my $storage  = $self->storage;
+method _run_sql_and_perl($filenames) {
+  my @files = @{$filenames};
+  my $storage = $self->storage;
 
   my $guard = $self->schema->txn_scope_guard if $self->txn_wrap;
 
-  my @sql = map @{$self->_read_sql_file($_)}, @{$self->_ddl_schema_consume_filenames(
-      $self->storage->sqlt_type,
-      $self->schema_version
-    )};
-
-  foreach my $line (@sql) {
-    $storage->_query_start($line);
-    try {
-      # do a dbh_do cycle here, as we need some error checking in
-      # place (even though we will ignore errors)
-      $storage->dbh_do (sub { $_[1]->do($line) });
-    }
-    catch {
-      carp "$_ (running '${line}')"
+  my $sql;
+  for my $filename (@files) {
+    if ($filename =~ /\.sql$/) {
+      my @sql = @{$self->_read_sql_file($filename)};
+      $sql .= join "\n", @sql;
+
+      foreach my $line (@sql) {
+        $storage->_query_start($line);
+        try {
+          # do a dbh_do cycle here, as we need some error checking in
+          # place (even though we will ignore errors)
+          $storage->dbh_do (sub { $_[1]->do($line) });
+        }
+        catch {
+          carp "$_ (running '${line}')"
+        }
+        $storage->_query_end($line);
+      }
+    } elsif ( $filename =~ /\.pl$/ ) {
+      qx( $^X $filename );
+    } else {
+      croak "A file got to deploy that wasn't sql or perl!";
     }
-    $storage->_query_end($line);
   }
 
   $guard->commit if $self->txn_wrap;
-  return join "\n", @sql;
+
+  return $sql;
+}
+
+sub deploy {
+  my $self = shift;
+
+  return $self->_run_sql_and_perl($self->_ddl_schema_consume_filenames(
+    $self->storage->sqlt_type,
+    $self->schema_version
+  ));
 }
 
 sub prepare_install {
@@ -209,29 +226,18 @@ sub prepare_install {
 
 sub prepare_upgrade {
   my ($self, $from_version, $to_version, $version_set) = @_;
-
-  $from_version ||= '1.0'; #$self->database_version;
-  $to_version   ||= $self->schema_version;
-
   # for updates prepared automatically (rob's stuff)
   # one would want to explicitly set $version_set to
   # [$to_version]
-  $version_set  ||= [$from_version, $to_version];
-
   $self->_prepare_changegrade($from_version, $to_version, $version_set, 'up');
 }
 
 sub prepare_downgrade {
   my ($self, $from_version, $to_version, $version_set) = @_;
 
-  $from_version ||= $self->db_version;
-  $to_version   ||= $self->schema_version;
-
   # for updates prepared automatically (rob's stuff)
   # one would want to explicitly set $version_set to
   # [$to_version]
-  $version_set  ||= [$from_version, $to_version];
-
   $self->_prepare_changegrade($from_version, $to_version, $version_set, 'down');
 }
 
@@ -350,55 +356,24 @@ method _read_sql_file($file) {
 sub downgrade_single_step {
   my $self = shift;
   my @version_set = @{ shift @_ };
-  my @downgrade_files = @{$self->_ddl_schema_down_consume_filenames(
+
+  my $sql = $self->_run_sql_and_perl($self->_ddl_schema_down_consume_filenames(
     $self->storage->sqlt_type,
     \@version_set,
-  )};
-
-  for my $downgrade_file (@downgrade_files) {
-    $self->_filedata($self->_read_sql_file($downgrade_file)); # I don't like this --fREW 2010-02-22
+  ));
 
-    my $guard = $self->schema->txn_scope_guard if $self->txn_wrap;
-    $self->_do_upgrade;
-    $guard->commit if $self->txn_wrap;
-  }
+  return ['', $sql];
 }
 
 sub upgrade_single_step {
   my $self = shift;
   my @version_set = @{ shift @_ };
-  my @upgrade_files = @{$self->_ddl_schema_up_consume_filenames(
+
+  my $sql = $self->_run_sql_and_perl($self->_ddl_schema_up_consume_filenames(
     $self->storage->sqlt_type,
     \@version_set,
-  )};
-
-  my $upgrade_sql;
-  for my $upgrade_file (@upgrade_files) {
-    my $up = $self->_read_sql_file($upgrade_file);
-    $upgrade_sql .= $up;
-    $self->_filedata($up); # I don't like this --fREW 2010-02-22
-    my $guard = $self->schema->txn_scope_guard if $self->txn_wrap;
-    $self->_do_upgrade;
-    $guard->commit if $self->txn_wrap;
-  }
-  return ['', $upgrade_sql];
-}
-
-method _do_upgrade { $self->_run_upgrade(qr/.*?/) }
-
-method _run_upgrade($stm) {
-  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) {
-  # croak?
-  $self->storage->dbh->do($_) or carp "SQL was: $_"
+  ));
+  return ['', $sql];
 }
 
 __PACKAGE__->meta->make_immutable;
index d13faf4..268546f 100644 (file)
@@ -4,8 +4,11 @@ use Moose;
 use Moose::Util 'apply_all_roles';
 
 extends 'DBIx::Class::DeploymentHandler::Dad';
+# a single with would be better, but we can't do that
+# see: http://rt.cpan.org/Public/Bug/Display.html?id=46347
 with 'DBIx::Class::DeploymentHandler::Deprecated::WithDeprecatedSqltDeployMethod',
      'DBIx::Class::DeploymentHandler::Deprecated::WithDeprecatedVersionStorage';
+with 'DBIx::Class::DeploymentHandler::WithReasonableDefaults';
 
 sub BUILD {
   my $self = shift;
diff --git a/lib/DBIx/Class/DeploymentHandler/WithReasonableDefaults.pm b/lib/DBIx/Class/DeploymentHandler/WithReasonableDefaults.pm
new file mode 100644 (file)
index 0000000..56997df
--- /dev/null
@@ -0,0 +1,22 @@
+package DBIx::Class::DeploymentHandler::WithReasonableDefaults;
+use Moose::Role;
+
+requires qw( prepare_upgrade prepare_downgrade database_version schema_version );
+
+around qw( prepare_upgrade prepare_downgrade ) => sub {
+  my $orig = shift;
+  my $self = shift;
+
+  my $from_version = shift || $self->database_version;
+  my $to_version   = shift || $self->schema_version;
+  my $version_set  = shift || [$from_version, $to_version];
+
+  $self->$orig($from_version, $to_version, $version_set);
+};
+
+
+1;
+
+__END__
+
+vim: ts=2 sw=2 expandtab
index 779867d..17d35e9 100644 (file)
@@ -83,18 +83,18 @@ VERSION2: {
    ok( $dm, 'DBIC::DH::SQL::Translator w/2.0 instantiates correctly');
 
    $version = $s->schema_version();
-   $dm->prepare_install();
+   $dm->prepare_install;
    ok(
       -f catfile(qw( t sql SQLite schema 2.0 001-auto.sql )),
       '2.0 schema gets generated properly'
    );
    mkpath(catfile(qw( t sql SQLite up 1.0-2.0 )));
-   $dm->prepare_upgrade;
+   $dm->prepare_upgrade(qw(1.0 2.0), [qw(1.0 2.0)]);
 
    {
       my $warned = 0;
       local $SIG{__WARN__} = sub{$warned = 1};
-      $dm->prepare_upgrade('0.0', '1.0');
+      $dm->prepare_upgrade(qw(0.0 1.0), [qw(0.0 1.0)]);
       ok( $warned, 'prepare_upgrade with a bogus preversion warns' );
    }
    ok(
@@ -102,7 +102,7 @@ VERSION2: {
       '1.0-2.0 diff gets generated properly and default start and end versions get set'
    );
    mkpath(catfile(qw( t sql SQLite down 2.0-1.0 )));
-   $dm->prepare_downgrade($version, '1.0');
+   $dm->prepare_downgrade($version, '1.0', [$version, '1.0']);
    ok(
       -f catfile(qw( t sql SQLite down 2.0-1.0 001-auto.sql )),
       '2.0-1.0 diff gets generated properly'
@@ -166,7 +166,7 @@ VERSION3: {
       -f catfile(qw( t sql SQLite schema 3.0 001-auto.sql )),
       '2.0 schema gets generated properly'
    );
-   $dm->prepare_downgrade($version, '1.0');
+   $dm->prepare_downgrade($version, '1.0', [$version, '1.0']);
    ok(
       -f catfile(qw( t sql SQLite down 3.0-1.0 001-auto.sql )),
       '3.0-1.0 diff gets generated properly'
@@ -176,11 +176,11 @@ VERSION3: {
       -f catfile(qw( t sql SQLite up 1.0-3.0 001-auto.sql )),
       '1.0-3.0 diff gets generated properly'
    );
-   $dm->prepare_upgrade( '2.0', $version );
+   $dm->prepare_upgrade( '2.0', $version, ['2.0', $version]);
    {
       my $warned = 0;
       local $SIG{__WARN__} = sub{$warned = 1};
-      $dm->prepare_upgrade( '2.0', $version );
+      $dm->prepare_upgrade( '2.0', $version, ['2.0', $version] );
       ok( $warned, 'prepare_upgrade warns if you clobber an existing upgrade file' );
    }
    ok(
index bd9b14d..b69d87a 100644 (file)
@@ -28,7 +28,7 @@ VERSION1: {
 
    ok( $dm, 'DBIC::DH::DM::SQLT::Deprecated gets instantiated correctly' );
 
-   $dm->prepare_install();
+   $dm->prepare_install;
 
    ok(
       -f catfile(qw( t sql DBICVersion-Schema-1.0-SQLite.sql )),
@@ -62,9 +62,9 @@ VERSION2: {
                'DBIC::DH::DM::SQLT::Deprecated gets instantiated correctly w/ version 2.0'
        );
 
-       $version = $s->schema_version();
-       $dm->prepare_install();
-       $dm->prepare_upgrade('1.0', $version);
+       $version = $s->schema_version;
+       $dm->prepare_install;
+       $dm->prepare_upgrade('1.0', $version, ['1.0', $version]);
        dies_ok {
                $s->resultset('Foo')->create({
                        bar => 'frew',