Added doc note that txn_commit does not perform an actual storage commit unless
[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 It does I<not> perform an actual storage commit unless there's a DBIx::Class
246 transaction currently in effect (i.e. you called L</txn_begin>).
247
248 =cut
249
250 sub txn_commit { die "Virtual method!" }
251
252 =head2 txn_rollback
253
254 Issues a rollback of the current transaction. A nested rollback will
255 throw a L<DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION> exception,
256 which allows the rollback to propagate to the outermost transaction.
257
258 =cut
259
260 sub txn_rollback { die "Virtual method!" }
261
262 =head2 svp_begin
263
264 Arguments: $savepoint_name?
265
266 Created a new savepoint using the name provided as argument. If no name
267 is provided, a random name will be used.
268
269 =cut
270
271 sub svp_begin { die "Virtual method!" }
272
273 =head2 svp_release
274
275 Arguments: $savepoint_name?
276
277 Release the savepoint provided as argument. If none is provided,
278 release the savepoint created most recently. This will implicitly
279 release all savepoints created after the one explicitly released as well.
280
281 =cut
282
283 sub svp_release { die "Virtual method!" }
284
285 =head2 svp_rollback
286
287 Arguments: $savepoint_name?
288
289 Rollback to the savepoint provided as argument. If none is provided,
290 rollback to the savepoint created most recently. This will implicitly
291 release all savepoints created after the savepoint we rollback to.
292
293 =cut
294
295 sub svp_rollback { die "Virtual method!" }
296
297 =for comment
298
299 =head2 txn_scope_guard
300
301 An alternative way of transaction handling based on
302 L<DBIx::Class::Storage::TxnScopeGuard>:
303
304  my $txn_guard = $storage->txn_scope_guard;
305
306  $row->col1("val1");
307  $row->update;
308
309  $txn_guard->commit;
310
311 If an exception occurs, or the guard object otherwise leaves the scope
312 before C<< $txn_guard->commit >> is called, the transaction will be rolled
313 back by an explicit L</txn_rollback> call. In essence this is akin to
314 using a L</txn_begin>/L</txn_commit> pair, without having to worry
315 about calling L</txn_rollback> at the right places. Note that since there
316 is no defined code closure, there will be no retries and other magic upon
317 database disconnection. If you need such functionality see L</txn_do>.
318
319 =cut
320
321 sub txn_scope_guard {
322   return DBIx::Class::Storage::TxnScopeGuard->new($_[0]);
323 }
324
325 =head2 sql_maker
326
327 Returns a C<sql_maker> object - normally an object of class
328 C<DBIx::Class::SQLAHacks>.
329
330 =cut
331
332 sub sql_maker { die "Virtual method!" }
333
334 =head2 debug
335
336 Causes trace information to be emitted on the C<debugobj> object.
337 (or C<STDERR> if C<debugobj> has not specifically been set).
338
339 This is the equivalent to setting L</DBIC_TRACE> in your
340 shell environment.
341
342 =head2 debugfh
343
344 Set or retrieve the filehandle used for trace/debug output.  This should be
345 an IO::Handle compatible ojbect (only the C<print> method is used.  Initially
346 set to be STDERR - although see information on the
347 L<DBIC_TRACE> environment variable.
348
349 =cut
350
351 sub debugfh {
352     my $self = shift;
353
354     if ($self->debugobj->can('debugfh')) {
355         return $self->debugobj->debugfh(@_);
356     }
357 }
358
359 =head2 debugobj
360
361 Sets or retrieves the object used for metric collection. Defaults to an instance
362 of L<DBIx::Class::Storage::Statistics> that is compatible with the original
363 method of using a coderef as a callback.  See the aforementioned Statistics
364 class for more information.
365
366 =head2 debugcb
367
368 Sets a callback to be executed each time a statement is run; takes a sub
369 reference.  Callback is executed as $sub->($op, $info) where $op is
370 SELECT/INSERT/UPDATE/DELETE and $info is what would normally be printed.
371
372 See L<debugobj> for a better way.
373
374 =cut
375
376 sub debugcb {
377     my $self = shift;
378
379     if ($self->debugobj->can('callback')) {
380         return $self->debugobj->callback(@_);
381     }
382 }
383
384 =head2 cursor_class
385
386 The cursor class for this Storage object.
387
388 =cut
389
390 =head2 deploy
391
392 Deploy the tables to storage (CREATE TABLE and friends in a SQL-based
393 Storage class). This would normally be called through
394 L<DBIx::Class::Schema/deploy>.
395
396 =cut
397
398 sub deploy { die "Virtual method!" }
399
400 =head2 connect_info
401
402 The arguments of C<connect_info> are always a single array reference,
403 and are Storage-handler specific.
404
405 This is normally accessed via L<DBIx::Class::Schema/connection>, which
406 encapsulates its argument list in an arrayref before calling
407 C<connect_info> here.
408
409 =cut
410
411 sub connect_info { die "Virtual method!" }
412
413 =head2 select
414
415 Handle a select statement.
416
417 =cut
418
419 sub select { die "Virtual method!" }
420
421 =head2 insert
422
423 Handle an insert statement.
424
425 =cut
426
427 sub insert { die "Virtual method!" }
428
429 =head2 update
430
431 Handle an update statement.
432
433 =cut
434
435 sub update { die "Virtual method!" }
436
437 =head2 delete
438
439 Handle a delete statement.
440
441 =cut
442
443 sub delete { die "Virtual method!" }
444
445 =head2 select_single
446
447 Performs a select, fetch and return of data - handles a single row
448 only.
449
450 =cut
451
452 sub select_single { die "Virtual method!" }
453
454 =head2 columns_info_for
455
456 Returns metadata for the given source's columns.  This
457 is *deprecated*, and will be removed before 1.0.  You should
458 be specifying the metadata yourself if you need it.
459
460 =cut
461
462 sub columns_info_for { die "Virtual method!" }
463
464 =head1 ENVIRONMENT VARIABLES
465
466 =head2 DBIC_TRACE
467
468 If C<DBIC_TRACE> is set then trace information
469 is produced (as when the L<debug> method is set).
470
471 If the value is of the form C<1=/path/name> then the trace output is
472 written to the file C</path/name>.
473
474 This environment variable is checked when the storage object is first
475 created (when you call connect on your schema).  So, run-time changes 
476 to this environment variable will not take effect unless you also 
477 re-connect on your schema.
478
479 =head2 DBIX_CLASS_STORAGE_DBI_DEBUG
480
481 Old name for DBIC_TRACE
482
483 =head1 SEE ALSO
484
485 L<DBIx::Class::Storage::DBI> - reference storage implementation using
486 SQL::Abstract and DBI.
487
488 =head1 AUTHORS
489
490 Matt S. Trout <mst@shadowcatsystems.co.uk>
491
492 Andy Grundman <andy@hybridized.org>
493
494 =head1 LICENSE
495
496 You may distribute this code under the same terms as Perl itself.
497
498 =cut
499
500 1;