Conversion of eval => try (part 1)
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Storage.pm
CommitLineData
4012acd8 1package DBIx::Class::Storage;
a62cf8d4 2
3use strict;
4use warnings;
5
046ad905 6use base qw/DBIx::Class/;
2ad62d97 7use mro 'c3';
046ad905 8
1a58752c 9use DBIx::Class::Exception;
10use Scalar::Util();
942cd0c1 11use IO::File;
1bc193ac 12use DBIx::Class::Storage::TxnScopeGuard;
046ad905 13
046ad905 14__PACKAGE__->mk_group_accessors('simple' => qw/debug debugobj schema/);
e4eb8ee1 15__PACKAGE__->mk_group_accessors('inherited' => 'cursor_class');
16
17__PACKAGE__->cursor_class('DBIx::Class::Cursor');
18
19sub cursor { shift->cursor_class(@_); }
046ad905 20
4012acd8 21package # Hide from PAUSE
22 DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION;
23
24use overload '"' => sub {
25 'DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION'
26};
27
28sub new {
29 my $class = shift;
30 my $self = {};
31 return bless $self, $class;
32}
33
34package DBIx::Class::Storage;
35
046ad905 36=head1 NAME
37
38DBIx::Class::Storage - Generic Storage Handler
39
40=head1 DESCRIPTION
41
42A base implementation of common Storage methods. For specific
43information about L<DBI>-based storage, see L<DBIx::Class::Storage::DBI>.
44
45=head1 METHODS
46
47=head2 new
48
49Arguments: $schema
50
51Instantiates the Storage object.
52
53=cut
54
55sub new {
56 my ($self, $schema) = @_;
57
58 $self = ref $self if ref $self;
59
60 my $new = {};
61 bless $new, $self;
62
63 $new->set_schema($schema);
64 $new->debugobj(new DBIx::Class::Storage::Statistics());
65
70f39278 66 #my $fh;
046ad905 67
68 my $debug_env = $ENV{DBIX_CLASS_STORAGE_DBI_DEBUG}
69 || $ENV{DBIC_TRACE};
70
046ad905 71 $new->debug(1) if $debug_env;
72
73 $new;
74}
75
76=head2 set_schema
77
78Used to reset the schema class or object which owns this
79storage object, such as during L<DBIx::Class::Schema/clone>.
80
81=cut
82
83sub set_schema {
84 my ($self, $schema) = @_;
85 $self->schema($schema);
1a58752c 86 Scalar::Util::weaken($self->{schema}) if ref $self->{schema};
046ad905 87}
88
89=head2 connected
90
91Returns true if we have an open storage connection, false
92if it is not (yet) open.
93
94=cut
95
a62cf8d4 96sub connected { die "Virtual method!" }
046ad905 97
98=head2 disconnect
99
100Closes any open storage connection unconditionally.
101
102=cut
103
104sub disconnect { die "Virtual method!" }
105
106=head2 ensure_connected
107
108Initiate a connection to the storage if one isn't already open.
109
110=cut
111
a62cf8d4 112sub ensure_connected { die "Virtual method!" }
046ad905 113
114=head2 throw_exception
115
116Throws an exception - croaks.
117
118=cut
119
120sub throw_exception {
121 my $self = shift;
122
1a58752c 123 if ($self->schema) {
124 $self->schema->throw_exception(@_);
125 }
126 else {
127 DBIx::Class::Exception->throw(@_);
128 }
046ad905 129}
a62cf8d4 130
4012acd8 131=head2 txn_do
a62cf8d4 132
4012acd8 133=over 4
a62cf8d4 134
4012acd8 135=item Arguments: C<$coderef>, @coderef_args?
a62cf8d4 136
4012acd8 137=item Return Value: The return value of $coderef
138
139=back
140
141Executes C<$coderef> with (optional) arguments C<@coderef_args> atomically,
142returning its result (if any). If an exception is caught, a rollback is issued
143and the exception is rethrown. If the rollback fails, (i.e. throws an
144exception) an exception is thrown that includes a "Rollback failed" message.
145
146For example,
147
148 my $author_rs = $schema->resultset('Author')->find(1);
149 my @titles = qw/Night Day It/;
150
151 my $coderef = sub {
152 # If any one of these fails, the entire transaction fails
153 $author_rs->create_related('books', {
154 title => $_
155 }) foreach (@titles);
156
157 return $author->books;
158 };
159
160 my $rs;
20674fcd 161 try {
4012acd8 162 $rs = $schema->txn_do($coderef);
20674fcd 163 } catch {
164 # Transaction failed
4012acd8 165 die "something terrible has happened!" #
166 if ($@ =~ /Rollback failed/); # Rollback failed
167
168 deal_with_failed_transaction();
20674fcd 169 };
4012acd8 170
171In a nested transaction (calling txn_do() from within a txn_do() coderef) only
172the outermost transaction will issue a L</txn_commit>, and txn_do() can be
173called in void, scalar and list context and it will behave as expected.
174
05075aee 175Please note that all of the code in your coderef, including non-DBIx::Class
176code, is part of a transaction. This transaction may fail out halfway, or
177it may get partially double-executed (in the case that our DB connection
178failed halfway through the transaction, in which case we reconnect and
179restart the txn). Therefore it is best that any side-effects in your coderef
180are idempotent (that is, can be re-executed multiple times and get the
181same result), and that you check up on your side-effects in the case of
182transaction failure.
6500d50f 183
4012acd8 184=cut
185
186sub txn_do {
187 my ($self, $coderef, @args) = @_;
188
189 ref $coderef eq 'CODE' or $self->throw_exception
190 ('$coderef must be a CODE reference');
191
192 my (@return_values, $return_value);
193
194 $self->txn_begin; # If this throws an exception, no rollback is needed
195
196 my $wantarray = wantarray; # Need to save this since the context
197 # inside the eval{} block is independent
198 # of the context that called txn_do()
20674fcd 199 try {
4012acd8 200
201 # Need to differentiate between scalar/list context to allow for
202 # returning a list in scalar context to get the size of the list
203 if ($wantarray) {
204 # list context
205 @return_values = $coderef->(@args);
206 } elsif (defined $wantarray) {
207 # scalar context
208 $return_value = $coderef->(@args);
209 } else {
210 # void context
211 $coderef->(@args);
212 }
213 $self->txn_commit;
20674fcd 214 } catch {
4012acd8 215 my $error = $@;
216
20674fcd 217 try {
4012acd8 218 $self->txn_rollback;
20674fcd 219 } catch {
4012acd8 220 my $rollback_error = $@;
221 my $exception_class = "DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION";
222 $self->throw_exception($error) # propagate nested rollback
223 if $rollback_error =~ /$exception_class/;
224
225 $self->throw_exception(
226 "Transaction aborted: $error. Rollback failed: ${rollback_error}"
227 );
4012acd8 228 }
20674fcd 229 $self->throw_exception($error); # txn failed but rollback succeeded
4012acd8 230 }
231
232 return $wantarray ? @return_values : $return_value;
a62cf8d4 233}
234
046ad905 235=head2 txn_begin
236
237Starts a transaction.
238
239See the preferred L</txn_do> method, which allows for
240an entire code block to be executed transactionally.
241
242=cut
243
244sub txn_begin { die "Virtual method!" }
245
246=head2 txn_commit
247
248Issues a commit of the current transaction.
249
be01f1be 250It does I<not> perform an actual storage commit unless there's a DBIx::Class
251transaction currently in effect (i.e. you called L</txn_begin>).
252
046ad905 253=cut
254
255sub txn_commit { die "Virtual method!" }
256
257=head2 txn_rollback
258
259Issues a rollback of the current transaction. A nested rollback will
260throw a L<DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION> exception,
261which allows the rollback to propagate to the outermost transaction.
262
263=cut
264
265sub txn_rollback { die "Virtual method!" }
266
adb3554a 267=head2 svp_begin
268
360dc8a5 269Arguments: $savepoint_name?
adb3554a 270
360dc8a5 271Created a new savepoint using the name provided as argument. If no name
272is provided, a random name will be used.
adb3554a 273
274=cut
275
276sub svp_begin { die "Virtual method!" }
277
278=head2 svp_release
279
360dc8a5 280Arguments: $savepoint_name?
adb3554a 281
360dc8a5 282Release the savepoint provided as argument. If none is provided,
283release the savepoint created most recently. This will implicitly
284release all savepoints created after the one explicitly released as well.
adb3554a 285
286=cut
287
288sub svp_release { die "Virtual method!" }
289
290=head2 svp_rollback
291
360dc8a5 292Arguments: $savepoint_name?
adb3554a 293
360dc8a5 294Rollback to the savepoint provided as argument. If none is provided,
295rollback to the savepoint created most recently. This will implicitly
296release all savepoints created after the savepoint we rollback to.
adb3554a 297
298=cut
299
300sub svp_rollback { die "Virtual method!" }
301
dd018f09 302=for comment
3b7f3eac 303
6936e902 304=head2 txn_scope_guard
1bc193ac 305
6936e902 306An alternative way of transaction handling based on
307L<DBIx::Class::Storage::TxnScopeGuard>:
89028f42 308
6936e902 309 my $txn_guard = $storage->txn_scope_guard;
89028f42 310
311 $row->col1("val1");
312 $row->update;
313
6936e902 314 $txn_guard->commit;
89028f42 315
6936e902 316If an exception occurs, or the guard object otherwise leaves the scope
317before C<< $txn_guard->commit >> is called, the transaction will be rolled
318back by an explicit L</txn_rollback> call. In essence this is akin to
319using a L</txn_begin>/L</txn_commit> pair, without having to worry
320about calling L</txn_rollback> at the right places. Note that since there
321is no defined code closure, there will be no retries and other magic upon
322database disconnection. If you need such functionality see L</txn_do>.
1bc193ac 323
324=cut
325
326sub txn_scope_guard {
327 return DBIx::Class::Storage::TxnScopeGuard->new($_[0]);
328}
329
046ad905 330=head2 sql_maker
331
332Returns a C<sql_maker> object - normally an object of class
6f4ddea1 333C<DBIx::Class::SQLAHacks>.
046ad905 334
335=cut
336
337sub sql_maker { die "Virtual method!" }
338
339=head2 debug
340
341Causes trace information to be emitted on the C<debugobj> object.
342(or C<STDERR> if C<debugobj> has not specifically been set).
343
344This is the equivalent to setting L</DBIC_TRACE> in your
345shell environment.
346
347=head2 debugfh
348
349Set or retrieve the filehandle used for trace/debug output. This should be
48580715 350an IO::Handle compatible object (only the C<print> method is used. Initially
046ad905 351set to be STDERR - although see information on the
352L<DBIC_TRACE> environment variable.
353
354=cut
355
356sub debugfh {
357 my $self = shift;
358
359 if ($self->debugobj->can('debugfh')) {
360 return $self->debugobj->debugfh(@_);
361 }
362}
363
364=head2 debugobj
365
366Sets or retrieves the object used for metric collection. Defaults to an instance
367of L<DBIx::Class::Storage::Statistics> that is compatible with the original
368method of using a coderef as a callback. See the aforementioned Statistics
369class for more information.
370
371=head2 debugcb
372
373Sets a callback to be executed each time a statement is run; takes a sub
374reference. Callback is executed as $sub->($op, $info) where $op is
375SELECT/INSERT/UPDATE/DELETE and $info is what would normally be printed.
376
377See L<debugobj> for a better way.
378
379=cut
380
381sub debugcb {
382 my $self = shift;
383
384 if ($self->debugobj->can('callback')) {
385 return $self->debugobj->callback(@_);
386 }
387}
388
e4eb8ee1 389=head2 cursor_class
046ad905 390
391The cursor class for this Storage object.
392
393=cut
394
046ad905 395=head2 deploy
396
397Deploy the tables to storage (CREATE TABLE and friends in a SQL-based
398Storage class). This would normally be called through
399L<DBIx::Class::Schema/deploy>.
400
401=cut
402
403sub deploy { die "Virtual method!" }
404
a3eaff0e 405=head2 connect_info
406
407The arguments of C<connect_info> are always a single array reference,
408and are Storage-handler specific.
409
410This is normally accessed via L<DBIx::Class::Schema/connection>, which
411encapsulates its argument list in an arrayref before calling
412C<connect_info> here.
413
414=cut
415
046ad905 416sub connect_info { die "Virtual method!" }
a3eaff0e 417
418=head2 select
419
420Handle a select statement.
421
422=cut
423
424sub select { die "Virtual method!" }
425
426=head2 insert
427
428Handle an insert statement.
429
430=cut
431
046ad905 432sub insert { die "Virtual method!" }
a3eaff0e 433
434=head2 update
435
436Handle an update statement.
437
438=cut
439
046ad905 440sub update { die "Virtual method!" }
a3eaff0e 441
442=head2 delete
443
444Handle a delete statement.
445
446=cut
447
046ad905 448sub delete { die "Virtual method!" }
a3eaff0e 449
450=head2 select_single
451
452Performs a select, fetch and return of data - handles a single row
453only.
454
455=cut
456
046ad905 457sub select_single { die "Virtual method!" }
a3eaff0e 458
459=head2 columns_info_for
460
c22c7625 461Returns metadata for the given source's columns. This
462is *deprecated*, and will be removed before 1.0. You should
463be specifying the metadata yourself if you need it.
a3eaff0e 464
465=cut
466
046ad905 467sub columns_info_for { die "Virtual method!" }
468
469=head1 ENVIRONMENT VARIABLES
470
471=head2 DBIC_TRACE
472
473If C<DBIC_TRACE> is set then trace information
474is produced (as when the L<debug> method is set).
475
476If the value is of the form C<1=/path/name> then the trace output is
477written to the file C</path/name>.
478
479This environment variable is checked when the storage object is first
480created (when you call connect on your schema). So, run-time changes
481to this environment variable will not take effect unless you also
482re-connect on your schema.
483
484=head2 DBIX_CLASS_STORAGE_DBI_DEBUG
485
486Old name for DBIC_TRACE
487
ace385bd 488=head1 SEE ALSO
489
2f0790c4 490L<DBIx::Class::Storage::DBI> - reference storage implementation using
491SQL::Abstract and DBI.
ace385bd 492
046ad905 493=head1 AUTHORS
494
495Matt S. Trout <mst@shadowcatsystems.co.uk>
496
497Andy Grundman <andy@hybridized.org>
498
499=head1 LICENSE
500
501You may distribute this code under the same terms as Perl itself.
502
503=cut
504
a62cf8d4 5051;