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