NAME¶
DBIx::Class::Schema::Versioned - DBIx::Class::Schema plugin for Schema upgrades
SYNOPSIS¶
package MyApp::Schema;
use base qw/DBIx::Class::Schema/;
our $VERSION = 0.001;
# load MyApp::Schema::CD, MyApp::Schema::Book, MyApp::Schema::DVD
__PACKAGE__->load_classes(qw/CD Book DVD/);
__PACKAGE__->load_components(qw/Schema::Versioned/);
__PACKAGE__->upgrade_directory('/path/to/upgrades/');
DESCRIPTION¶
This module provides methods to apply DDL changes to your database using SQL
diff files. Normally these diff files would be created using
"create_ddl_dir" in DBIx::Class::Schema.
A table called
dbix_class_schema_versions is created and maintained by
the module. This is used to determine which version your database is currently
at. Similarly the $VERSION in your DBIC schema class is used to determine the
current DBIC schema version.
The upgrade is initiated manually by calling "upgrade" on your schema
object, this will attempt to upgrade the database from its current version to
the current schema version using a diff from your
upgrade_directory. If
a suitable diff is not found then no upgrade is possible.
SEE ALSO¶
DBIx::Class::DeploymentHandler is a much more powerful alternative to this
module. Examples of things it can do that this module cannot do include
- •
- Downgrades in addition to upgrades
- •
- Multiple sql files files per upgrade/downgrade/install
- •
- Perl scripts allowed for upgrade/downgrade/install
- •
- Just one set of files needed for upgrade, unlike this
module where one might need to generate "factorial(scalar
@versions)"
GETTING STARTED¶
Firstly you need to setup your schema class as per the "SYNOPSIS",
make sure you have specified an upgrade_directory and an initial $VERSION.
Then you'll need two scripts, one to create DDL files and diffs and another to
perform upgrades. Your creation script might look like a bit like this:
use strict;
use Pod::Usage;
use Getopt::Long;
use MyApp::Schema;
my ( $preversion, $help );
GetOptions(
'p|preversion:s' => \$preversion,
) or die pod2usage;
my $schema = MyApp::Schema->connect(
$dsn,
$user,
$password,
);
my $sql_dir = './sql';
my $version = $schema->schema_version();
$schema->create_ddl_dir( 'MySQL', $version, $sql_dir, $preversion );
Then your upgrade script might look like so:
use strict;
use MyApp::Schema;
my $schema = MyApp::Schema->connect(
$dsn,
$user,
$password,
);
if (!$schema->get_db_version()) {
# schema is unversioned
$schema->deploy();
} else {
$schema->upgrade();
}
The script above assumes that if the database is unversioned then it is empty
and we can safely deploy the DDL to it. However things are not always so
simple.
if you want to initialise a pre-existing database where the DDL is not the same
as the DDL for your current schema version then you will need a diff which
converts the database's DDL to the current DDL. The best way to do this is to
get a dump of the database schema (without data) and save that in your SQL
directory as version 0.000 (the filename must be as with
"ddl_filename" in DBIx::Class::Schema) then create a diff using your
create DDL script given above from version 0.000 to the current version. Then
hand check and if necessary edit the resulting diff to ensure that it will
apply. Once you have done all that you can do this:
if (!$schema->get_db_version()) {
# schema is unversioned
$schema->install("0.000");
}
# this will now apply the 0.000 to current version diff
$schema->upgrade();
In the case of an unversioned database the above code will create the
dbix_class_schema_versions table and write version 0.000 to it, then upgrade
will then apply the diff we talked about creating in the previous paragraph
and then you're good to go.
METHODS¶
upgrade_directory¶
Use this to set the directory your upgrade files are stored in.
backup_directory¶
Use this to set the directory you want your backups stored in (note that backups
are disabled by default).
install¶
- Arguments: $db_version
Call this to initialise a previously unversioned database. The table
'dbix_class_schema_versions' will be created which will be used to store the
database version.
Takes one argument which should be the version that the database is currently
at. Defaults to the return value of "schema_version".
See "getting_started" for more details.
deploy¶
Same as "deploy" in DBIx::Class::Schema but also calls
"install".
create_upgrade_path¶
- Arguments: { upgrade_file => $file }
Virtual method that should be overridden to create an upgrade file. This is
useful in the case of upgrading across multiple versions to concatenate
several files to create one upgrade file.
You'll probably want the db_version retrieved via $self->get_db_version and
the schema_version which is retrieved via $self->schema_version
ordered_schema_versions¶
- Returns: a list of version numbers, ordered from lowest to
highest
Virtual method that should be overridden to return an ordered list of schema
versions. This is then used to produce a set of steps to upgrade through to
achieve the required schema version.
You may want the db_version retrieved via $self->get_db_version and the
schema_version which is retrieved via $self->schema_version
upgrade¶
Call this to attempt to upgrade your database from the version it is at to the
version this DBIC schema is at. If they are the same it does nothing.
It will call "ordered_schema_versions" to retrieve an ordered list of
schema versions (if ordered_schema_versions returns nothing then it is assumed
you can do the upgrade as a single step). It then iterates through the list of
versions between the current db version and the schema version applying one
update at a time until all relevant updates are applied.
The individual update steps are performed by using
"upgrade_single_step", which will apply the update and also update
the dbix_class_schema_versions table.
upgrade_single_step¶
- Arguments: db_version - the version currently within the
db
- Arguments: target_version - the version to upgrade to
Call this to attempt to upgrade your database from the
db_version to the
target_version. If they are the same it does nothing.
It requires an SQL diff file to exist in your
upgrade_directory, normally
you will have created this using "create_ddl_dir" in
DBIx::Class::Schema.
If successful the dbix_class_schema_versions table is updated with the
target_version.
This method may be called repeatedly by the upgrade method to upgrade through a
series of updates.
do_upgrade¶
This is an overwritable method used to run your upgrade. The freeform method
allows you to run your upgrade any way you please, you can call
"run_upgrade" any number of times to run the actual SQL commands,
and in between you can sandwich your data upgrading. For example, first run
all the
CREATE commands, then migrate your data from old to new
tables/formats, then issue the DROP commands when you are finished. Will run
the whole file as it is by default.
run_upgrade¶
$self->run_upgrade(qr/create/i);
Runs a set of SQL statements matching a passed in regular expression. The idea
is that this method can be called any number of times from your
"do_upgrade" method, running whichever commands you specify via the
regex in the parameter. Probably won't work unless called from the overridable
do_upgrade method.
apply_statement¶
Takes an SQL statement and runs it. Override this if you want to handle errors
differently.
get_db_version¶
Returns the version that your database is currently at. This is determined by
the values in the dbix_class_schema_versions table that "upgrade"
and "install" write to.
schema_version¶
Returns the current schema class' $VERSION
backup¶
This is an overwritable method which is called just before the upgrade, to allow
you to make a backup of the database. Per default this method attempts to call
"$self->storage->backup", to run the standard backup on each
database type.
This method should return the name of the backup file, if appropriate..
This method is disabled by default. Set $schema->
do_backup(1) to
enable it.
connection¶
Overloaded method. This checks the DBIC schema version against the DB version
and warns if they are not the same or if the DB is unversioned. It also
provides compatibility between the old versions table (SchemaVersions) and the
new one (dbix_class_schema_versions).
To avoid the checks on connect, set the environment var DBIC_NO_VERSION_CHECK or
alternatively you can set the ignore_version attr in the forth argument like
so:
my $schema = MyApp::Schema->connect(
$dsn,
$user,
$password,
{ ignore_version => 1 },
);
AUTHORS¶
Jess Robinson <castaway@desert-island.me.uk> Luke Saunders
<luke@shadowcatsystems.co.uk>
LICENSE¶
You may distribute this code under the same terms as Perl itself.