NAME DBIx::Class::Schema::Versioned::Inline SUMMARY Schema versioning for DBIx::Class with version information embedded inline in the schema definition. VERSION Version 0.001 SYNOPSIS package MyApp::Schema; use base 'DBIx::Class::Schema::Versioned::Inline'; our $VERSION = '0.002'; __PACKAGE__->load_namespaces; ... package MyApp::Schema::Result::Bar; use base 'DBIx::Class::Core'; __PACKAGE__->table('bars'); __PACKAGE__->add_columns( "bars_id" => { data_type => 'integer', is_auto_increment => 1 }, "age" => { data_type => "integer", is_nullable => 1 }, "height" => { data_type => "integer", is_nullable => 1, versioned => { since => '0.003' } }, "weight" => { data_type => "integer", is_nullable => 1, versioned => { until => '0.3' } }, ); __PACKAGE__->set_primary_key('bars_id'); __PACKAGE__->has_many( 'foos', 'TestVersion::Schema::Result::Foo', 'foos_id', { versioned => { until => '0.003' } }, ); __PACKAGE__->resultset_attributes( { versioned => { since => '0.002' } } ); ... package MyApp::Schema::Result::Foo; use base 'DBIx::Class::Core'; __PACKAGE__->table('foos'); __PACKAGE__->add_columns( "foos_id" => { data_type => 'integer', is_auto_increment => 1 }, "age" => { data_type => "integer", is_nullable => 1, versioned => { since => '0.002' } }, "height" => { data_type => "integer", is_nullable => 1, versioned => { until => '0.002' } }, "width" => { data_type => "integer", is_nullable => 1, versioned => { since => '0.002', renamed_from => 'height', changes => { '0.0021' => { is_nullable => 0, default_value => 0 } }, } }, "bars_id" => { data_type => 'integer', is_foreign_key => 1, is_nullable => 0, versioned => { since => '0.002' } }, ); __PACKAGE__->set_primary_key('foos_id'); __PACKAGE__->belongs_to( 'bar', 'TestVersion::Schema::Result::Bar', 'bars_id', { versioned => { since => '0.002' } }, ); __PACKAGE__->resultset_attributes( { versioned => { until => '0.003' } } ); ... package MyApp::Schema::Upgrade; use base 'DBIx::Class::Schema::Versioned::Inline::Upgrade'; use DBIx::Class::Schema::Versioned::Inline::Upgrade qw/before after/; before '0.3.3' => sub { my $schema = shift; $schema->resultset('Foo')->update({ bar => '' }); }; after '0.3.3' => sub { my $schema = shift; # do something else }; DESCRIPTION This module extends DBIx::Class::Schema::Versioned using simple 'since' and 'until' tokens within result classes to specify the schema version at which classes and columns were introduced or removed. Column since/until definitions are included as part of 'versioned' info in add_column(s). since When a class is added to a schema at a specific schema version version then a 'since' attribute must be added to the class which returns the version at which the class was added. For example: __PACKAGE__->resultset_attributes({ versioned => { since => '0.002' }}); It is not necessary to add this to the initial version of a class since any class without this atribute is assumed to have existed for ever. Using 'since' in a column or relationship definition denotes the version at which the column/relation was added. For example: __PACKAGE__->add_column( "age" => { data_type => "integer", is_nullable => 1, versioned => { since => '0.002' } } ); For changes to column_info such as a change of data_type see "changes". Note: if the Result containing the column includes a class-level "since" then there is no need to add "since" markers for columns created at the same version. Relationships are handled in the same way as columns: __PACKAGE__->belongs_to( 'bar', 'MyApp::Schema::Result::Bar', 'bars_id', { versioned => { since => '0.002' } }, ); until When used as a class attribute this should be the schema version at which the class is to be removed. The underlying database table will be removed when the schema is upgraded to this version. Example definitions: __PACKAGE__->resultset_attributes({ versioned => { until => '0.7' }}); __PACKAGE__->add_column( "age" => { data_type => "integer", is_nullable => 1, versioned => { until => '0.5' } } ); Using 'until' in a column or relationship definition will cause removal of the column/relation from the table when the schema is upgraded to this version. renamed_from This is always used alongside 'since' in the renamed class/column and there must also be a corresponding 'until' on the old class/column. For example when renaming a class: package MyApp::Schema::Result::Foo; __PACKAGE__->table('foos'); __PACKAGE__->resultset_attributes({ versioned => { until => '0.5 }}); package MyApp::Schema::Result::Fooey; __PACKAGE__->table('fooeys'); __PACKAGE__->resultset_attributes({ versioned => { since => '0.5, renamed_from => 'Foo' } }); And when renaming a column: __PACKAGE__->add_columns( "height" => { data_type => "integer", versioned => { until => '0.002' } }, "width" => { data_type => "integer", is_nullable => 0, versioned => { since => '0.002', renamed_from => 'height' } }, ); As can been seen in the example it is possible to modify column definitions at the same time as a rename but care should be taken to ensure that any data modification (such as ensuring there are no longer null values when is_nullable => 0 is introduced) must be handled via "Upgrade.pm". changes Column definition changes are handled using the "changes" token. A hashref is created for each version where the column definition changes which details the new column definition in effect from that change revision. For example: __PACKAGE__->add_columns( "item_weight", { data_type => "integer", is_nullable => 1, default_value => 4, versioned => { until => '0.001 }, }, "weight", { data_type => "integer", is_nullable => 1, versioned => { since => '0.002', renamed_from => 'item_weight', changes => { '0.4' => { data_type => "numeric", size => [10,2], is_nullable => 1, } '0.401' => { data_type => "numeric", size => [10,2], is_nullable => 0, default_value => "0.0", } } } } ); Note: the initial column definition should never be changed since that is the definition to be used from when the column is first created until the first change is effected. Upgrade.pm For details on how to apply data modifications that might be required during an upgrade see DBIx::Class::Schema::Versioned::Inline::Upgrade. METHODS Many methods are inherited or overloaded from DBIx::Class::Schema::Versioned. connection Overloaded method. This checks the DBIC schema version against the DB version and ???? TODO ???? (undecided so far) if they are not the same or if the DB is unversioned. deploy Inherited method. Same as "deploy" in DBIx::Class::Schema but also calls "install". install Inherited method. Call this to initialise a previously unversioned database. ordered_schema_versions Overloaded method. Returns 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. upgrade Inherited method. 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. upgrade_single_step Arguments: db_version - the version currently within the db Arguments: target_version - the version to upgrade to Overloaded method. Call this to attempt to upgrade your database from the *db_version* to the *target_version*. If they are the same it does nothing. All upgrade operations within this step are performed inside a single transaction so either all succeed or all fail. 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. versioned_schema Arguments: version - the schema version we want to deploy Parse schema and remove classes, columns and relationships that are not valid for the requested version. CAVEATS Please anticipate API changes in this early state of development. AUTHOR Peter Mottram (SysPete), "peter@sysnix.com" BUGS LOTS of bugs and missing features right now. NOTE: upgrades are NOT yet implemented. Please report any bugs or feature requests via the project's GitHub issue tracker: I will be notified, and then you'll automatically be notified of progress on your bug as I make changes. SUPPORT You can find documentation for this module with the perldoc command. perldoc DBIx::Class::Schema::Versioned::Inline You can also look for information at: * GitHub repository * AnnoCPAN: Annotated CPAN documentation * CPAN Ratings * Search CPAN ACKNOWLEDGEMENTS Thanks to Best Practical Solutions for the Jifty framework and Jifty::DBI which inspired this distribution. Thanks also to Matt S. Trout and all of the DBIx::Class developers for an excellent distribution. LICENSE AND COPYRIGHT Copyright 2014 Peter Mottram (SysPete). This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License. See http://dev.perl.org/licenses/ for more information.