let you install to a given point in the version history
[dbsrgits/DBIx-Class-DeploymentHandler.git] / lib / DBIx / Class / DeploymentHandler / Dad.pm
1 package DBIx::Class::DeploymentHandler::Dad;
2
3 # ABSTRACT: Parent class for DeploymentHandlers
4
5 use Moose;
6 require DBIx::Class::Schema;    # loaded for type constraint
7 use Carp::Clan '^DBIx::Class::DeploymentHandler';
8 use DBIx::Class::DeploymentHandler::Logger;
9 use DBIx::Class::DeploymentHandler::Types;
10 use Log::Contextual ':log', -package_logger =>
11   DBIx::Class::DeploymentHandler::Logger->new({
12     env_prefix => 'DBICDH'
13   });
14
15 has schema => (
16   isa      => 'DBIx::Class::Schema',
17   is       => 'ro',
18   required => 1,
19 );
20
21 has backup_directory => (
22   isa => 'Str',
23   is  => 'ro',
24   predicate  => 'has_backup_directory',
25 );
26
27 has to_version => (
28   is         => 'ro',
29   isa        => 'Str',
30   lazy_build => 1,
31 );
32
33 sub _build_to_version { $_[0]->schema_version }
34
35 has schema_version => (
36   is         => 'ro',
37   isa        => 'StrSchemaVersion',
38   lazy_build => 1,
39 );
40
41 sub _build_schema_version { $_[0]->schema->schema_version }
42
43 sub install {
44   my $self = shift;
45   log_info { 'installing version ' . $self->to_version };
46   croak 'Install not possible as versions table already exists in database'
47     if $self->version_storage_is_installed;
48
49   my $ddl = $self->deploy({version=>$self->to_version});
50
51   $self->add_database_version({
52     version     => $self->to_version,
53     ddl         => $ddl,
54   });
55 }
56
57 sub upgrade {
58   log_info { 'upgrading' };
59   my $self = shift;
60   my $ran_once = 0;
61   while ( my $version_list = $self->next_version_set ) {
62     $ran_once = 1;
63     my ($ddl, $upgrade_sql) = @{
64       $self->upgrade_single_step({ version_set => $version_list })
65     ||[]};
66
67     $self->add_database_version({
68       version     => $version_list->[-1],
69       ddl         => $ddl,
70       upgrade_sql => $upgrade_sql,
71     });
72   }
73
74   log_warn { 'no need to run upgrade' } unless $ran_once;
75 }
76
77 sub downgrade {
78   log_info { 'downgrading' };
79   my $self = shift;
80   my $ran_once = 0;
81   while ( my $version_list = $self->previous_version_set ) {
82     $ran_once = 1;
83     $self->downgrade_single_step({ version_set => $version_list });
84
85     # do we just delete a row here?  I think so but not sure
86     $self->delete_database_version({ version => $version_list->[0] });
87   }
88   log_warn { 'no version to run downgrade' } unless $ran_once;
89 }
90
91 sub backup {
92   my $self = shift;
93   log_info { 'backing up' };
94   $self->schema->storage->backup($self->backup_directory)
95 }
96
97 __PACKAGE__->meta->make_immutable;
98
99 1;
100
101 # vim: ts=2 sw=2 expandtab
102
103 __END__
104
105 =pod
106
107 =attr schema
108
109 The L<DBIx::Class::Schema> (B<required>) that is used to talk to the database
110 and generate the DDL.
111
112 =attr schema_version
113
114 The version that the schema is currently at.  Defaults to
115 C<< $self->schema->schema_version >>.
116
117 =attr backup_directory
118
119 The directory where backups are stored
120
121 =attr to_version
122
123 The version (defaults to schema's version) to migrate the database to
124
125 =method install
126
127  $dh->install
128
129 Deploys the current schema into the database.  Populates C<version_storage> with
130 C<version> and C<ddl>.
131
132 B<Note>: you typically need to call C<< $dh->prepare_deploy >> before you call
133 this method.
134
135 B<Note>: you cannot install on top of an already installed database
136
137 =method upgrade
138
139  $dh->upgrade
140
141 Upgrades the database one step at a time till L</next_version_set>
142 returns C<undef>.  Each upgrade step will add a C<version>, C<ddl>, and
143 C<upgrade_sql> to the version storage (if C<ddl> and/or C<upgrade_sql> are
144 returned from L</upgrade_single_step>.
145
146 =method downgrade
147
148  $dh->downgrade
149
150 Downgrades the database one step at a time till L</previous_version_set>
151 returns C<undef>.  Each downgrade step will delete a C<version> from the
152 version storage.
153
154 =method backup
155
156  $dh->backup
157
158 Simply calls backup on the C<< $schema->storage >>, passing in
159 C<< $self->backup_directory >> as an argument.  Please test yourself before
160 assuming it will work.
161
162 =head1 METHODS THAT ARE REQUIRED IN SUBCLASSES
163
164 =head2 deploy
165
166 See L<DBIx::Class::DeploymentHandler::HandlesDeploy/deploy>.
167
168 =head2 version_storage_is_installed
169
170 See L<DBIx::Class::DeploymentHandler::HandlesVersionStorage/version_storage_is_installed>.
171
172 =head2 add_database_version
173
174 See L<DBIx::Class::DeploymentHandler::HandlesVersionStorage/add_database_version>.
175
176 =head2 delete_database_version
177
178 See L<DBIx::Class::DeploymentHandler::HandlesVersionStorage/delete_database_version>.
179
180 =head2 next_version_set
181
182 See L<DBIx::Class::DeploymentHandler::HandlesVersioning/next_version_set>.
183
184 =head2 previous_version_set
185
186 See L<DBIx::Class::DeploymentHandler::HandlesVersioning/previous_version_set>.
187
188 =head2 upgrade_single_step
189
190 See L<DBIx::Class::DeploymentHandler::HandlesDeploy/upgrade_single_step>.
191
192 =head2 downgrade_single_step
193
194 See L<DBIx::Class::DeploymentHandler::HandlesDeploy/downgrade_single_step>.
195
196 =head1 ORTHODOX METHODS
197
198 These methods are not actually B<required> as things will probably still work
199 if you don't implement them, but if you want your subclass to get along with
200 other subclasses (or more likely, tools made to use another subclass), you
201 should probably implement these too, even if they are no-ops.
202
203 =head2 database_version
204
205 see L<DBIx::Class::DeploymentHandler::HandlesVersionStorage/database_version>
206
207 =head2 prepare_deploy
208
209 see L<DBIx::Class::DeploymentHandler::HandlesDeploy/prepare_deploy>
210
211 =head2 prepare_resultsource_install
212
213 see L<DBIx::Class::DeploymentHandler::HandlesDeploy/prepare_resultsource_install>
214
215 =head2 install_resultsource
216
217 see L<DBIx::Class::DeploymentHandler::HandlesDeploy/install_resultsource>
218
219 =head2 prepare_upgrade
220
221 see L<DBIx::Class::DeploymentHandler::HandlesDeploy/prepare_upgrade>
222
223 =head2 prepare_downgrade
224
225 see L<DBIx::Class::DeploymentHandler::HandlesDeploy/prepare_downgrade>
226
227 =head2 SUBCLASSING
228
229 All of the methods mentioned in L</METHODS THAT ARE REQUIRED IN SUBCLASSES> and
230 L</ORTHODOX METHODS> can be implemented in any fashion you choose.  In the
231 spirit of code reuse I have used roles to implement them in my two subclasses,
232 L<DBIx::Class::DeploymentHandler> and
233 L<DBIx::Class::DeploymentHandler::Deprecated>, but you are free to implement
234 them entirely in a subclass if you so choose to.
235
236 For in-depth documentation on how methods are supposed to work, see the roles
237 L<DBIx::Class::DeploymentHandler::HandlesDeploy>,
238 L<DBIx::Class::DeploymentHandler::HandlesVersioning>, and
239 L<DBIx::Class::DeploymentHandler::HandlesVersionStorage>.
240