From: Luke Saunders Date: Thu, 31 Jan 2008 16:46:48 +0000 (+0000) Subject: populate code added X-Git-Tag: v1.001002~54 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=384c3f0cf1c812ec7b1b39b6c232ea860be2c951;hp=5eab44a9216545faac9045634f3bf2c65dd649c2;p=dbsrgits%2FDBIx-Class-Fixtures.git populate code added --- diff --git a/lib/DBIx/Class/Fixtures.pm b/lib/DBIx/Class/Fixtures.pm index 6fd5651..dd57bcf 100644 --- a/lib/DBIx/Class/Fixtures.pm +++ b/lib/DBIx/Class/Fixtures.pm @@ -301,6 +301,142 @@ sub dump_object { } } +sub _generate_schema { + my $self = shift; + my $params = shift || {}; + + require DBI; + $self->msg("\ncreating schema"); + # die 'must pass version param to generate_schema_from_ddl' unless $params->{version}; + + my $dbh; + unless ($dbh = DBI->connect(@{$params->{connection_details}})) { + return DBIx::Class::Exception->throw('connection details not valid'); + } + my $connection_details = $params->{connection_details}; + + # clear existing db + $self->msg("- clearing DB of existing tables"); + $dbh->do('SET foreign_key_checks=0'); + my $sth = $dbh->prepare('SHOW TABLES'); + $sth->execute; + my $rows = $sth->fetchall_arrayref; + $dbh->do('drop table ' . $_->[0]) for (@{$rows}); + + # 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 $_"}; + if ($@) { die "SQL was:\n $_\n$@"; } + } + $dbh->do('SET foreign_key_checks=1'); + $self->msg("- finished importing DDL into DB"); + + # load schema object from our new DB + $self->msg("- loading fresh DBIC object from DB"); + my $schema = DBIx::Class::Fixtures::Schema->connect(@{$connection_details}); + + # manually set the version then set DB version to it (upgrade) +# $Takkle::SchemaPopulate::VERSION = $params->{version}; +# $schema->upgrade(); # set version number + return $schema; +} + +sub populate { + my $self = shift; + my ($params) = @_; + unless (ref $params eq 'HASH') { + return DBIx::Class::Exception->throw('first arg to populate must be hash ref'); + } + + foreach my $param (qw/directory/) { + unless ($params->{$param}) { + return DBIx::Class::Exception->throw($param . ' param not specified'); + } + } + my $fixture_dir = dir($params->{directory}); + unless (-e $fixture_dir) { + return DBIx::Class::Exception->throw('fixture directory does not exist at ' . $fixture_dir); + } + + my $ddl_file; + my $dbh; + if ($params->{ddl} && $params->{connection_details}) { + my $ddl_file = file($params->{ddl}); + unless (-e $ddl_file) { + return DBIx::Class::Exception->throw('DDL does not exist at ' . $ddl_file); + } + unless (ref $params->{connection_details} eq 'ARRAY') { + return DBIx::Class::Exception->throw('connection details must be an arrayref'); + } + } elsif ($params->{schema}) { + return DBIx::Class::Exception->throw('passing a schema is not supported at the moment'); + } else { + return DBIx::Class::Exception->throw('you must set the ddl and connection_details params'); + } + + my $schema = $self->_generate_schema({ ddl => $ddl_file, connection_details => $params->{connection_details} }); + $self->msg("importing fixtures"); + + my $tmp_fixture_dir = dir($fixture_dir, "-~populate~-" . $<); + + my $version_file = file($fixture_dir, '_dumper_version'); + unless (-e $version_file) { +# return DBIx::Class::Exception->throw('no version file found'); + } + + if (-e $tmp_fixture_dir) { + $self->msg("- deleting existing temp directory $tmp_fixture_dir"); + system("rm -rf $tmp_fixture_dir"); + } + $self->msg("- creating temp dir"); + system("cp -r $fixture_dir $tmp_fixture_dir"); + + $schema->storage->dbh->do('SET foreign_key_checks=0'); + my $fixup_visitor; + my %callbacks; + if ($params->{datetime_relative_to}) { + $callbacks{'DateTime::Duration'} = sub { + $params->{datetime_relative_to}->clone->add_duration($_); + }; + } else { + $callbacks{'DateTime::Duration'} = sub { + DateTime->today->add_duration($_) + }; + } + $callbacks{object} ||= "visit_ref"; + $fixup_visitor = new Data::Visitor::Callback(%callbacks); + + foreach my $source (sort $schema->sources) { + $self->msg("- adding " . $source); + my $rs = $schema->resultset($source); + my $source_dir = dir($tmp_fixture_dir, lc($rs->result_source->from)); + next unless (-e $source_dir); + while (my $file = $source_dir->next) { + next unless ($file =~ /\.fix$/); + next if $file->is_dir; + my $contents = $file->slurp; + my $HASH1; + eval($contents); + $HASH1 = $fixup_visitor->visit($HASH1) if $fixup_visitor; + $rs->find_or_create($HASH1); + } + } + + $self->msg("- fixtures imported"); + $self->msg("- cleaning up"); + $tmp_fixture_dir->rmtree; + $schema->storage->dbh->do('SET foreign_key_checks=1'); +} + sub msg { my $self = shift; my $subject = shift || return; diff --git a/lib/DBIx/Class/Fixtures/Schema.pm b/lib/DBIx/Class/Fixtures/Schema.pm new file mode 100644 index 0000000..3d7ae67 --- /dev/null +++ b/lib/DBIx/Class/Fixtures/Schema.pm @@ -0,0 +1,10 @@ +package DBIx::Class::Fixtures::Schema; + +use strict; +use warnings; + +use base 'DBIx::Class::Schema::Loader'; + +__PACKAGE__->loader_options( ); + +1; diff --git a/lib/DBIx/Class/Fixtures/SchemaVersioned.pm b/lib/DBIx/Class/Fixtures/SchemaVersioned.pm new file mode 100644 index 0000000..f05d110 --- /dev/null +++ b/lib/DBIx/Class/Fixtures/SchemaVersioned.pm @@ -0,0 +1,15 @@ +package DBIx::Class::Fixtures::SchemaVersioned; + +use strict; +use warnings; + +use base 'DBIx::Class::Schema::Loader'; + +our $VERSION = 'set-when-loading'; + +__PACKAGE__->load_components('Schema::Versioned'); +__PACKAGE__->loader_options( + # debug => 1, + ); + +1; diff --git a/t/var/configs/fetch.json b/t/var/configs/fetch.json new file mode 100644 index 0000000..30d6685 --- /dev/null +++ b/t/var/configs/fetch.json @@ -0,0 +1,23 @@ +{ + might_have: { + fetch: 0 + }, + has_many: { + fetch: 0 + }, + sets: [{ + class: 'Artist', + ids: ['1'], + fetch: [{ + rel: cds, + quantity: all + }] + }, { + class: 'Artist', + ids: ['2'], + fetch: [{ + rel: cds, + cond: { year: {'>': 2002} } + }] + }] +} \ No newline at end of file diff --git a/t/var/configs/quantity.json b/t/var/configs/quantity.json new file mode 100644 index 0000000..d4f9ba4 --- /dev/null +++ b/t/var/configs/quantity.json @@ -0,0 +1,12 @@ +{ + might_have: { + fetch: 0 + }, + has_many: { + fetch: 0 + }, + sets: [{ + class: 'CD', + quantity: 3 + }] +} \ No newline at end of file diff --git a/t/var/configs/rules.json b/t/var/configs/rules.json new file mode 100644 index 0000000..b02a286 --- /dev/null +++ b/t/var/configs/rules.json @@ -0,0 +1,29 @@ +{ + might_have: { + fetch: 0 + }, + has_many: { + fetch: 0 + }, + sets: [{ + class: 'CD', + ids: ['5'] + }, { + class: 'Artist', + ids: ['1'], + fetch: [{ + rel: cds, + quantity: all + }] + }], + rules: { + 'CD': { + cond: [{ 'tags.tag': 'Cheesy' }], + join: ['tags'], + fetch: [{ + rel: tracks, + cond: { position: 2 } + }] + } + } +} \ No newline at end of file