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