DBIx-Class-Migration

 view release on metacpan or  search on metacpan

lib/DBIx/Class/Migration.pm  view on Meta::CPAN

sub populate_set_to_schema {
  my ($self, $target_set, $schema) = @_;
  $self->build_dbic_fixtures->populate({
    no_deploy => 1,
    schema => $schema,
    directory => $target_set });

  print "Restored set $target_set to database\n";
}

sub populate {
  (my $self = shift)->dbic_dh->version_storage_is_installed
    || _log_die "No Database to populate!";

  my $version = $self->dbic_dh->database_version;
  my $schema = $self->_schema_from_database;

  foreach my $set(@_) {
    my $target_set = _prepare_fixture_data_dir(
      $self->target_dir, $version, $set);
    $self->populate_set_to_schema($target_set, $schema);
  }
}

sub make_schema {
  (my $self = shift)->dbic_dh->version_storage_is_installed
    || _log_die "No Database to make Schema from!";
  my $schema = $self->schema_loader
    ->generate_dump(
      $self->_infer_schema_class,
      catdir($self->target_dir, 'dumped_db'));
}

sub diagram {
  my $self = shift;
  my $number_tables = scalar $self->schema->sources;
  my $dimension = int sqrt($number_tables * 13);
  my $trans = SQL::Translator->new(
    parser => 'SQL::Translator::Parser::DBIx::Class',
    parser_args => { dbic_schema => $self->schema },
    producer => 'GraphViz',
    producer_args => {
      skip_tables => 'dbix_class_deploymenthandler_versions',
      width => $dimension,
      height => $dimension,
      show_constraints => 1,
      show_datatypes => 1,
      show_sizes => 1,
      out_file  => $self->_diagram_default_outfile });

  $trans->translate
    or _log_die $trans->error;
}

  sub _diagram_default_outfile {
    my $self = shift;
    catfile $self->target_dir, 'db-diagram-v' . $self->dbic_dh->schema_version . '.png';
  }

sub install_if_needed {
  my ($self, %callbacks) = @_;
  if(!$self->dbic_dh->version_storage_is_installed) {
    $self->install;
    if(my $on_install = delete($callbacks{on_install})) {
      $on_install->($self->schema, $self);
    } elsif( my $default_fixture_sets = delete($callbacks{default_fixture_sets})) {
      $self->populate(@$default_fixture_sets);
    }
  }
}

sub install_version_storage {
  my $self = shift;
  if(!$self->dbic_dh->version_storage_is_installed) {
    $self->dbic_dh->install_version_storage;
    $self->dbic_dh->add_database_version({ version => $self->dbic_dh->schema_version });
    print "Version storage has been installed in the target database\n";
  } else {
    print "Version storage is already installed in the target database!\n";
  }
}

before [qw/install upgrade downgrade/], sub {
  my ($self, @args) = @_;
  %ENV = (
    %ENV,
    DBIC_MIGRATION_FIXTURES_CLASS => $self->dbic_fixture_class,
    DBIC_MIGRATION_FIXTURES_INIT_ARGS => JSON::MaybeXS->new->encode($self->build_dbic_fixtures_init_args),
    DBIC_MIGRATION_SCHEMA_CLASS => $self->schema_class,
    DBIC_MIGRATION_TARGET_DIR => $self->target_dir,
    DBIC_MIGRATION_FIXTURE_DIR => catdir($self->target_dir, 'fixtures', $self->dbic_dh->schema_version),
    DBIC_MIGRATION_SCHEMA_VERSION => $self->dbic_dh->schema_version,
    DBIC_MIGRATION_TO_VERSION => $self->dbic_dh->to_version,
    DBIC_MIGRATION_DATABASE_VERSION => (
      $self->dbic_dh->version_storage_is_installed ? $self->dbic_dh->database_version : 0),
  );
};

# We need to explicitly disconnect so that we can properly
# shutdown some databases (like Postgresql) without generating
# errors in cleanup.  Basically if we don't disconnect we often
# end up with blocking commands running on the server at the time
# we are trying to shut it down.

sub DEMOLISH {
  my $self = shift;
  return unless $self->has_schema && $self->schema;
  if(my $storage = $self->schema->storage) {
    $storage->disconnect;
  }
}

__PACKAGE__->meta->make_immutable;

=head1 NAME

DBIx::Class::Migration - Use the best tools together for sane database migrations

=head1 SYNOPSIS

    use DBIx::Class::Migration;

    my $migration = DBIx::Class::Migration->new(
      schema_class => 'MyApp::Schema',
      schema_args => \@connect_opts);

lib/DBIx/Class/Migration.pm  view on Meta::CPAN

=head2 downgrade

Run down files to bring the database down to the previous version from what is
installed to the database

=head2 drop_tables

Drops all the tables in the connected database with no backup or recovery.  For
real! (Make sure you are not connected to Prod, for example).

=head2 delete_table_rows

Does a C<delete> on each table in the database, which clears out all your data
but preserves tables.  For Real!  You might want this if you need to load
and unload fixture sets during testing, or perhaps to get rid of data that
accumulated in the database while running an app in development, before dumping
fixtures.

=head2 dump_named_sets

Given an array of fixture set names, dump them for the current database version.

=head2 dump_all_sets

Takes no arguments just dumps all the sets we can find for the current database
version.

=head2 make_schema

Given an existing database, reverse engineer a L<DBIx::Class> Schema in the
L</target_dir> (under C<dumped_db>).  You can use this if you need to bootstrap
your DBIC files.

=head2 populate

Given an array of fixture set names, populate the current database version with
the matching sets for that version.

Skips the table C<dbix_class_deploymenthandler_versions>, so you don't lose
deployment info (this is different from L</drop_tables> which does delete it.)

=head2 diagram

Experimental feature.  Although not specifically a migration task, I find it
useful to output visuals of my databases.  This command will place a file in
your L</target_dir> called C<db-diagram-vXXX.png> where C<XXX> is he current
C<schema> version.

This is using the Graphviz producer (L<SQL::Translator::Producer::GraphViz>)
which in turn requires L<Graphviz>.  Since this is not always trivial to
install, I do not require it.  You will need to add it manually to your
C<Makefile.PL> or C<dist.ini> and manage it yourself.

This feature is experimental and currently does not offer any options, as I
am still determining the best way to meet the need without exceeding the
scope of L<DBIx::Class::Migration>.  Consider this command a 'freebee' and
please don't depend on it in your custom code.

=head2 install_if_needed

If the database is not installed, do so.  Accepts a hash of callbacks or
instructions to perform should installation be needed/

    $migration->install_if_needed(
      on_install => sub {
        my ($schema, $local_migration) = @_;
        DBIx::Class::Migration::Population->new(
          schema=>shift)->populate('all_tables');
      });

The following callbacks / instructions are permitted

=over 4

=item on_install

Accepts: Coderef

Given a coderef, execute it after the database is installed.  The coderef
gets passed two arguments: C<$schema> and C<$self> (the current migration
object).

=item default_fixture_sets

Accepts: Arrayref of fixture sets

    $migration->install_if_needed(
      default_fixture_sets => ['all_tables']);

After database installation, populate the fixtures in order.

=back

=head2 install_version_storage

If the targeted (connected) database does not have the versioning tables
installed, this will install them.  The version is set to whatever your
C<schema> version currently is.

You will only need to use this command in the case where you have an existing
database that you are reverse engineering and you need to setup versioning
storage since you can't rebuild the database from scratch (such as if you have
a huge production database that you now want to start versioning).

=head2 delete_named_sets

Given a (or a list) of fixture sets, delete them if the exist in the current
schema version.

Yes, this really deletes, you've been warned (check in your code to a source
control repository).

=head1 ENVIRONMENT

When running L<DBIx::Class::Migration> we set some C<%ENV> variables during
installation, up / downgrading, so that your Perl run scripts (see
L<DBIx::Class::DeploymentHandler::DeployMethod::SQL::Translator\'PERL SCRIPTS'>)
can receive some useful information.  The Following C<%ENV> variables are set:

    DBIC_MIGRATION_SCHEMA_CLASS => $self->schema_class
    DBIC_MIGRATION_TARGET_DIR => $self->target_dir
    DBIC_MIGRATION_FIXTURE_DIR => catdir($self->target_dir, 'fixtures', $self->dbic_dh->schema_version),
    DBIC_MIGRATION_SCHEMA_VERSION => $self->dbic_dh->schema_version
    DBIC_MIGRATION_TO_VERSION => $self->dbic_dh->to_version
    DBIC_MIGRATION_DATABASE_VERSION => $self->dbic_dh->schema_version || 0

You might find having these available in your migration scripts useful for
doing things like 'populate a database from a fixture set, if it exists, but
if not run a bunch of inserts.

=head1 THANKS



( run in 2.292 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )