- Added post_ddl and cascade attributes to populate().
Drew Taylor [Tue, 11 Mar 2008 16:19:16 +0000 (16:19 +0000)]
- Test for post_ddl attribute.
- Refactor sql reading into private function.
- Removed auto_provides() in Makefile.PL at direction of mst.

Makefile.PL
lib/DBIx/Class/Fixtures.pm
t/14-populate-post.t [new file with mode: 0644]
t/lib/post_sqlite.sql [new file with mode: 0644]

index 150f91a..f044414 100644 (file)
@@ -22,8 +22,6 @@ build_requires 'Test::More'       => 0.7;
 
 tests_recursive();
 
-auto_provides;
-
 auto_install;
 
 WriteAll;
index 8730fae..94e3127 100644 (file)
@@ -52,7 +52,8 @@ DBIx::Class::Fixtures
   $fixtures->populate({
     directory => '/home/me/app/fixtures',
     ddl => '/home/me/app/sql/ddl.sql',
-    connection_details => ['dbi:mysql:dbname=app_dev', 'me', 'password']
+    connection_details => ['dbi:mysql:dbname=app_dev', 'me', 'password'],
+    post_ddl => '/home/me/app/sql/post_ddl.sql',
   });
 
 =head1 DESCRIPTION
@@ -681,25 +682,22 @@ sub _generate_schema {
     return DBIx::Class::Exception->throw('connection details not valid');
   }
   my @tables = map { $pre_schema->source($_)->from } $pre_schema->sources;
+  $self->msg("Tables to drop: [". join(', ', sort @tables) . "]");
   my $dbh = $pre_schema->storage->dbh;
 
   # clear existing db
   $self->msg("- clearing DB of existing tables");
   eval { $dbh->do('SET foreign_key_checks=0') };
-  $dbh->do('drop table ' . $_) for (@tables);
+  foreach my $table (@tables) {
+    eval { $dbh->do('drop table ' . $table . ($params->{cascade} ? ' cascade' : '') ) };
+  }
 
   # import new ddl file to db
   my $ddl_file = $params->{ddl};
   $self->msg("- deploying schema using $ddl_file");
-  my $fh;
-  open $fh, "<$ddl_file" or die ("Can't open DDL file, $ddl_file ($!)");
-  my @data = split(/\n/, join('', <$fh>));
-  @data = grep(!/^--/, @data);
-  @data = split(/;/, join('', @data));
-  close($fh);
-  @data = grep { $_ && $_ !~ /^-- / } @data;
-  for (@data) {
-      eval { $dbh->do($_) or warn "SQL was:\n $_"};
+  my $data = _read_sql($ddl_file);
+  foreach (@$data) {
+    eval { $dbh->do($_) or warn "SQL was:\n $_"};
          if ($@) { die "SQL was:\n $_\n$@"; }
   }
   $self->msg("- finished importing DDL into DB");
@@ -712,6 +710,17 @@ sub _generate_schema {
   return $schema;
 }
 
+sub _read_sql {
+  my $ddl_file = shift;
+  my $fh;
+  open $fh, "<$ddl_file" or die ("Can't open DDL file, $ddl_file ($!)");
+  my @data = split(/\n/, join('', <$fh>));
+  @data = grep(!/^--/, @data);
+  @data = split(/;/, join('', @data));
+  close($fh);
+  @data = grep { $_ && $_ !~ /^-- / } @data;
+  return \@data;
+}
 
 =head2 populate
 
@@ -726,7 +735,9 @@ sub _generate_schema {
   $fixtures->populate({
     directory => '/home/me/app/fixtures', # directory to look for fixtures in, as specified to dump
     ddl => '/home/me/app/sql/ddl.sql', # DDL to deploy
-    connection_details => ['dbi:mysql:dbname=app_dev', 'me', 'password'] # database to clear, deploy and then populate
+    connection_details => ['dbi:mysql:dbname=app_dev', 'me', 'password'], # database to clear, deploy and then populate
+    post_ddl => '/home/me/app/sql/post_ddl.sql', # DDL to deploy after populating records, ie. FK constraints
+    cascade => 1, # use CASCADE option when dropping tables
   });
 
 In this case the database app_dev will be cleared of all tables, then the specified DDL deployed to it,
@@ -735,6 +746,13 @@ its own DBIx::Class schema from the DDL rather than being passed one to use. Thi
 custom insert methods are avoided which can to get in the way. In some cases you might not
 have a DDL, and so this method will eventually allow a $schema object to be passed instead.
 
+If needed, you can specify a post_ddl attribute which is a DDL to be applied after all the fixtures
+have been added to the database. A good use of this option would be to add foreign key constraints
+since databases like Postgresql cannot disable foreign key checks.
+
+If your tables have foreign key constraints you may want to use the cascade attribute which will
+make the drop table functionality cascade, ie 'DROP TABLE $table CASCADE'.
+
 directory, dll and connection_details are all required attributes.
 
 =cut
@@ -822,6 +840,15 @@ sub populate {
     }
   }
 
+  if ($params->{post_ddl}) {
+    my $data = _read_sql($params->{post_ddl});
+    foreach (@$data) {
+      eval { $schema->storage->dbh->do($_) or warn "SQL was:\n $_"};
+         if ($@) { die "SQL was:\n $_\n$@"; }
+    }
+    $self->msg("- finished importing post-populate DDL into DB");
+  }
+
   $self->msg("- fixtures imported");
   $self->msg("- cleaning up");
   $tmp_fixture_dir->rmtree;
diff --git a/t/14-populate-post.t b/t/14-populate-post.t
new file mode 100644 (file)
index 0000000..ff5ca21
--- /dev/null
@@ -0,0 +1,27 @@
+#!perl
+
+use DBIx::Class::Fixtures;
+use Test::More tests => 5;
+use lib qw(t/lib);
+use DBICTest;
+use Path::Class;
+use Data::Dumper;
+
+# set up and populate schema
+ok(my $schema = DBICTest->init_schema(), 'got schema');
+my $config_dir = 't/var/configs';
+
+# do dump
+ok(my $fixtures = DBIx::Class::Fixtures->new({ config_dir => $config_dir, debug => 0 }), 'object created with correct config dir');
+
+no warnings 'redefine';
+DBICTest->clear_schema($schema);
+DBICTest->populate_schema($schema);
+ok($fixtures->dump({ config => "simple.json", schema => $schema, directory => 't/var/fixtures' }), "simple dump executed okay");
+$fixtures->populate({ ddl => 't/lib/sqlite.sql', connection_details => ['dbi:SQLite:t/var/DBIxClass.db', '', ''], 
+  directory => 't/var/fixtures', post_ddl => 't/lib/post_sqlite.sql' });
+  
+my ($producer) = $schema->resultset('Producer')->find(999999);
+is($producer->name, "PostDDL", "Got producer name");
+isa_ok($producer, "DBICTest::Producer", "Got post-ddl producer");
+
diff --git a/t/lib/post_sqlite.sql b/t/lib/post_sqlite.sql
new file mode 100644 (file)
index 0000000..75d740d
--- /dev/null
@@ -0,0 +1,9 @@
+-- 
+-- Created by SQL::Translator::Producer::SQLite
+-- Created on Tue Aug  8 01:53:20 2006
+-- 
+BEGIN TRANSACTION;
+
+INSERT INTO producer (producerid, name) VALUES (999999, 'PostDDL');
+
+COMMIT;