initial shot at "dev version" functionality
[dbsrgits/DBIx-Class-DeploymentHandler.git] / lib / DBIx / Class / DeploymentHandler.pm
CommitLineData
b974984a 1package DBIx::Class::DeploymentHandler;
2
a65184c8 3# ABSTRACT: Extensible DBIx::Class deployment
4
b974984a 5use Moose;
b974984a 6
c4f4d4a2 7extends 'DBIx::Class::DeploymentHandler::Dad';
41219a5d 8# a single with would be better, but we can't do that
9# see: http://rt.cpan.org/Public/Bug/Display.html?id=46347
4f73e4ac 10with 'DBIx::Class::DeploymentHandler::WithApplicatorDumple' => {
36009fc8 11 interface_role => 'DBIx::Class::DeploymentHandler::HandlesDeploy',
12 class_name => 'DBIx::Class::DeploymentHandler::DeployMethod::SQL::Translator',
13 delegate_name => 'deploy_method',
5020d6a2 14 attributes_to_assume => [qw(schema schema_version)],
704577c7 15 attributes_to_copy => [qw(
16 ignore_ddl databases script_directory sql_translator_args force_overwrite
17 )],
36009fc8 18 },
19 'DBIx::Class::DeploymentHandler::WithApplicatorDumple' => {
20 interface_role => 'DBIx::Class::DeploymentHandler::HandlesVersioning',
21 class_name => 'DBIx::Class::DeploymentHandler::VersionHandler::Monotonic',
22 delegate_name => 'version_handler',
23 attributes_to_assume => [qw( database_version schema_version to_version )],
24 },
25 'DBIx::Class::DeploymentHandler::WithApplicatorDumple' => {
26 interface_role => 'DBIx::Class::DeploymentHandler::HandlesVersionStorage',
27 class_name => 'DBIx::Class::DeploymentHandler::VersionStorage::Standard',
28 delegate_name => 'version_storage',
29 attributes_to_assume => ['schema'],
30 };
41219a5d 31with 'DBIx::Class::DeploymentHandler::WithReasonableDefaults';
2e68a8e1 32
c8a2f7bd 33sub prepare_version_storage_install {
34 my $self = shift;
35
d9917093 36 $self->prepare_resultsource_install({
37 result_source => $self->version_storage->version_rs->result_source
38 });
c8a2f7bd 39}
40
41sub install_version_storage {
42 my $self = shift;
43
ba99ba44 44 my $version = (shift||{})->{version} || $self->schema_version;
45
d9917093 46 $self->install_resultsource({
ba99ba44 47 result_source => $self->version_storage->version_rs->result_source,
48 version => $version,
d9917093 49 });
c8a2f7bd 50}
51
d794b8ce 52sub prepare_install {
36821446 53 $_[0]->prepare_deploy;
54 $_[0]->prepare_version_storage_install;
d794b8ce 55}
56
53de57ed 57# the following is just a hack so that ->version_storage
58# won't be lazy
59sub BUILD { $_[0]->version_storage }
2e68a8e1 60__PACKAGE__->meta->make_immutable;
61
88fecddb 62sub dev_version_instaled { shift->database_version eq 'DEV' }
63
64use SQL::Translator;
65sub install_dev_version {
66 my ($self, $extra) = @_;
67
68 die 'roll back existing dev version before installing a new dev version'
69 if $self->dev_version_installed;
70
71 my $from_schema = do {
72 my $t = SQL::Translator->new({
73 debug => 0,
74 trace => 0,
75 parser => 'SQL::Translator::Parser::YAML',
76 });
77 $t->translate($self->deploy_method->_ddl_protoschema_produce_filename(
78 $self->database_version, $self->script_directory
79 ) or die $t->error;
80 $t->schema;
81 };
82
83 my $to_schema = do {
84 my $t = SQL::Translator->new({
85 parser => 'SQL::Translator::Parser::DBIx::Class',
86 parser_args => {
87 package => $self->schema,
88 },
89 });
90 $t->translate or die $t->error;
91 $t->schema;
92 };
93
94 my $db = $self->deploy_method->storage->sqlt_type;
95
96 my @up = [SQL::Translator::Diff::schema_diff(
97 $source_schema, $db,
98 $dest_schema, $db,
99 $sqltargs
100 )];
101
102 my @down = [SQL::Translator::Diff::schema_diff(
103 $dest_schema, $db,
104 $source_schema, $db,
105 $sqltargs
106 )];
107
108 $self->deploy_method->_run_sql_array(\@up);
109
110 $self->version_storage->version_rs->create({
111 version => 'DEV',
112 upgrade_sql => \@up,
113 downgrade_sql => \@down,
114 extra => $extra,
115 });
116}
117
118sub remove_dev_version {
119 my ($self, $extra) = @_;
120
121 die 'no dev version installed to remove'
122 unless $self->dev_version_installed;
123
124 my ($dev_data, $to_version) = $self->version_storage
125 ->version_rs
126 ->search(undef, {
127 order_by => { -desc => 'id' },
128 rows => 2,
129 })->all;
130
131 $self->deploy_method->_run_sql_array(\@sql_to_run);
132
133 $self->version_storage->version_rs->create({
134 version => $to_version->version,
135 upgrade_sql => \@sql_to_run,
136 downgrade_sql => [], # not meant to be "reverted"
137 extra => $extra
138 })
139}
140
b974984a 1411;
61847972 142
d1ae780e 143#vim: ts=2 sw=2 expandtab
144
145__END__
146
a65184c8 147=head1 SYNOPSIS
e9c19a98 148
149 use aliased 'DBIx::Class::DeploymentHandler' => 'DH';
150 my $s = My::Schema->connect(...);
151
152 my $dh = DH->new({
02a7b8ac 153 schema => $s,
154 databases => 'SQLite',
155 sql_translator_args => { add_drop_table => 0 },
e9c19a98 156 });
157
f7e215c9 158 $dh->prepare_install;
e9c19a98 159
160 $dh->install;
161
162or for upgrades:
163
164 use aliased 'DBIx::Class::DeploymentHandler' => 'DH';
165 my $s = My::Schema->connect(...);
166
167 my $dh = DH->new({
02a7b8ac 168 schema => $s,
169 databases => 'SQLite',
170 sql_translator_args => { add_drop_table => 0 },
e9c19a98 171 });
172
c1326825 173 $dh->prepare_upgrade({
174 from_version => 1,
175 to_version => 2,
176 });
e9c19a98 177
178 $dh->upgrade;
179
180=head1 DESCRIPTION
181
8b810386 182C<DBIx::Class::DeploymentHandler> is, as its name suggests, a tool for
e9c19a98 183deploying and upgrading databases with L<DBIx::Class>. It is designed to be
184much more flexible than L<DBIx::Class::Schema::Versioned>, hence the use of
185L<Moose> and lots of roles.
186
187C<DBIx::Class::DeploymentHandler> itself is just a recommended set of roles
327868c9 188that we think will not only work well for everyone, but will also yield the
8b810386 189best overall mileage. Each role it uses has its own nuances and
e9c19a98 190documentation, so I won't describe all of them here, but here are a few of the
191major benefits over how L<DBIx::Class::Schema::Versioned> worked (and
192L<DBIx::Class::DeploymentHandler::Deprecated> tries to maintain compatibility
193with):
194
195=over
196
e9c19a98 197=item *
198
199Downgrades in addition to upgrades.
200
201=item *
202
203Multiple sql files files per upgrade/downgrade/install.
204
205=item *
206
207Perl scripts allowed for upgrade/downgrade/install.
208
209=item *
210
211Just one set of files needed for upgrade, unlike before where one might need
212to generate C<factorial(scalar @versions)>, which is just silly.
213
214=item *
215
216And much, much more!
217
218=back
219
220That's really just a taste of some of the differences. Check out each role for
221all the details.
222
223=head1 WHERE IS ALL THE DOC?!
224
225C<DBIx::Class::DeploymentHandler> extends
226L<DBIx::Class::DeploymentHandler::Dad>, so that's probably the first place to
227look when you are trying to figure out how everything works.
228
961d42b1 229Next would be to look at all the pieces that fill in the blanks that
e9c19a98 230L<DBIx::Class::DeploymentHandler::Dad> expects to be filled. They would be
61627cf0 231L<DBIx::Class::DeploymentHandler::DeployMethod::SQL::Translator>,
232L<DBIx::Class::DeploymentHandler::VersionHandler::Monotonic>,
233L<DBIx::Class::DeploymentHandler::VersionStorage::Standard>, and
e9c19a98 234L<DBIx::Class::DeploymentHandler::WithReasonableDefaults>.
235
236=method prepare_version_storage_install
237
238 $dh->prepare_version_storage_install
239
240Creates the needed C<.sql> file to install the version storage and not the rest
241of the tables
242
f7e215c9 243=method prepare_install
244
245 $dh->prepare_install
246
247First prepare all the tables to be installed and the prepare just the version
248storage
249
e9c19a98 250=method install_version_storage
251
252 $dh->install_version_storage
253
254Install the version storage and not the rest of the tables
255
d1ae780e 256=head1 THIS SUCKS
257
12d6fbad 258You started your project and weren't using C<DBIx::Class::DeploymentHandler>?
259Lucky for you I had you in mind when I wrote this doc.
d1ae780e 260
8b810386 261First,
262L<define the version|DBIx::Class::DeploymentHandler::Intro/Sample_database>
263in your main schema file (maybe using C<$VERSION>).
264
265Then you'll want to just install the version_storage:
d1ae780e 266
267 my $s = My::Schema->connect(...);
8b810386 268 my $dh = DBIx::Class::DeploymentHandler->new({ schema => $s });
d1ae780e 269
270 $dh->prepare_version_storage_install;
271 $dh->install_version_storage;
34ac0a51 272
12d6fbad 273Then set your database version:
274
275 $dh->add_database_version({ version => $s->version });
276
ee37360d 277Now you should be able to use C<DBIx::Class::DeploymentHandler> like normal!
698944cb 278
a66bf899 279=head1 LOGGING
280
281This is a complex tool, and because of that sometimes you'll want to see
8465e767 282what exactly is happening. The best way to do that is to use the built in
283logging functionality. It the standard six log levels; C<fatal>, C<error>,
284C<warn>, C<info>, C<debug>, and C<trace>. Most of those are pretty self
285explanatory. Generally a safe level to see what all is going on is debug,
286which will give you everything except for the exact SQL being run.
287
288To enable the various logging levels all you need to do is set an environment
289variables: C<DBICDH_FATAL>, C<DBICDH_ERROR>, C<DBICDH_WARN>, C<DBICDH_INFO>,
8b810386 290C<DBICDH_DEBUG>, and C<DBICDH_TRACE>. Each level can be set on its own,
8465e767 291but the default is the first three on and the last three off, and the levels
292cascade, so if you turn on trace the rest will turn on automatically.
a66bf899 293
698944cb 294=head1 DONATIONS
295
296If you'd like to thank me for the work I've done on this module, don't give me
297a donation. I spend a lot of free time creating free software, but I do it
298because I love it.
299
300Instead, consider donating to someone who might actually need it. Obviously
301you should do research when donating to a charity, so don't just take my word
26983cf2 302on this. I like Children's Survival Fund:
303L<http://www.childrenssurvivalfund.org>, but there are a host of other
304charities that can do much more good than I will with your money.