Fix more $schema leaks in the SQLT DBIC Parser (AUGHHHHH!!!!)
[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 use mro 'c3';
8
9 {
10   package # Hide from PAUSE
11     DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION;
12   use base 'DBIx::Class::Exception';
13 }
14
15 use DBIx::Class::Carp;
16 use Scalar::Util qw/blessed weaken/;
17 use DBIx::Class::Storage::TxnScopeGuard;
18 use Try::Tiny;
19 use namespace::clean;
20
21 __PACKAGE__->mk_group_accessors(simple => qw/debug schema transaction_depth auto_savepoint savepoints/);
22 __PACKAGE__->mk_group_accessors(component_class => 'cursor_class');
23
24 __PACKAGE__->cursor_class('DBIx::Class::Cursor');
25
26 sub cursor { shift->cursor_class(@_); }
27
28 =head1 NAME
29
30 DBIx::Class::Storage - Generic Storage Handler
31
32 =head1 DESCRIPTION
33
34 A base implementation of common Storage methods.  For specific
35 information about L<DBI>-based storage, see L<DBIx::Class::Storage::DBI>.
36
37 =head1 METHODS
38
39 =head2 new
40
41 Arguments: $schema
42
43 Instantiates the Storage object.
44
45 =cut
46
47 sub new {
48   my ($self, $schema) = @_;
49
50   $self = ref $self if ref $self;
51
52   my $new = bless( {
53     transaction_depth => 0,
54     savepoints => [],
55   }, $self);
56
57   $new->set_schema($schema);
58   $new->debug(1)
59     if $ENV{DBIX_CLASS_STORAGE_DBI_DEBUG} || $ENV{DBIC_TRACE};
60
61   $new;
62 }
63
64 =head2 set_schema
65
66 Used to reset the schema class or object which owns this
67 storage object, such as during L<DBIx::Class::Schema/clone>.
68
69 =cut
70
71 sub set_schema {
72   my ($self, $schema) = @_;
73   $self->schema($schema);
74   weaken $self->{schema} if ref $self->{schema};
75 }
76
77 =head2 connected
78
79 Returns true if we have an open storage connection, false
80 if it is not (yet) open.
81
82 =cut
83
84 sub connected { die "Virtual method!" }
85
86 =head2 disconnect
87
88 Closes any open storage connection unconditionally.
89
90 =cut
91
92 sub disconnect { die "Virtual method!" }
93
94 =head2 ensure_connected
95
96 Initiate a connection to the storage if one isn't already open.
97
98 =cut
99
100 sub ensure_connected { die "Virtual method!" }
101
102 =head2 throw_exception
103
104 Throws an exception - croaks.
105
106 =cut
107
108 sub throw_exception {
109   my $self = shift;
110
111   if (ref $self and $self->schema) {
112     $self->schema->throw_exception(@_);
113   }
114   else {
115     DBIx::Class::Exception->throw(@_);
116   }
117 }
118
119 =head2 txn_do
120
121 =over 4
122
123 =item Arguments: C<$coderef>, @coderef_args?
124
125 =item Return Value: The return value of $coderef
126
127 =back
128
129 Executes C<$coderef> with (optional) arguments C<@coderef_args> atomically,
130 returning its result (if any). If an exception is caught, a rollback is issued
131 and the exception is rethrown. If the rollback fails, (i.e. throws an
132 exception) an exception is thrown that includes a "Rollback failed" message.
133
134 For example,
135
136   my $author_rs = $schema->resultset('Author')->find(1);
137   my @titles = qw/Night Day It/;
138
139   my $coderef = sub {
140     # If any one of these fails, the entire transaction fails
141     $author_rs->create_related('books', {
142       title => $_
143     }) foreach (@titles);
144
145     return $author->books;
146   };
147
148   my $rs;
149   try {
150     $rs = $schema->txn_do($coderef);
151   } catch {
152     my $error = shift;
153     # Transaction failed
154     die "something terrible has happened!"
155       if ($error =~ /Rollback failed/);          # Rollback failed
156
157     deal_with_failed_transaction();
158   };
159
160 In a nested transaction (calling txn_do() from within a txn_do() coderef) only
161 the outermost transaction will issue a L</txn_commit>, and txn_do() can be
162 called in void, scalar and list context and it will behave as expected.
163
164 Please note that all of the code in your coderef, including non-DBIx::Class
165 code, is part of a transaction.  This transaction may fail out halfway, or
166 it may get partially double-executed (in the case that our DB connection
167 failed halfway through the transaction, in which case we reconnect and
168 restart the txn).  Therefore it is best that any side-effects in your coderef
169 are idempotent (that is, can be re-executed multiple times and get the
170 same result), and that you check up on your side-effects in the case of
171 transaction failure.
172
173 =cut
174
175 sub txn_do {
176   my $self = shift;
177   my $coderef = shift;
178
179   ref $coderef eq 'CODE' or $self->throw_exception
180     ('$coderef must be a CODE reference');
181
182   my $abort_txn = sub {
183     my ($self, $exception) = @_;
184
185     my $rollback_exception = try { $self->txn_rollback; undef } catch { shift };
186
187     if ( $rollback_exception and (
188       ! defined blessed $rollback_exception
189           or
190       ! $rollback_exception->isa('DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION')
191     ) ) {
192       $self->throw_exception(
193         "Transaction aborted: ${exception}. "
194         . "Rollback failed: ${rollback_exception}"
195       );
196     }
197     $self->throw_exception($exception);
198   };
199
200   # take a ref instead of a copy, to preserve coderef @_ aliasing semantics
201   my $args = \@_;
202
203   # do not turn on until a succesful txn_begin
204   my $attempt_commit = 0;
205
206   my $txn_init_depth = $self->transaction_depth;
207
208   try {
209     $self->txn_begin;
210     $attempt_commit = 1;
211     $coderef->(@$args)
212   }
213   catch {
214     $attempt_commit = 0;
215
216     # init depth of > 0 implies nesting or non-autocommit (either way no retry)
217     if($txn_init_depth or $self->connected ) {
218       $abort_txn->($self, $_);
219     }
220     else {
221       carp "Retrying txn_do($coderef) after catching disconnected exception: $_"
222         if $ENV{DBIC_STORAGE_RETRY_DEBUG};
223
224       $self->_populate_dbh;
225
226       # if txn_depth is > 1 this means something was done to the
227       # original $dbh, otherwise we would not get past the if() above
228       $self->throw_exception(sprintf
229         'Unexpected transaction depth of %d on freshly connected handle',
230         $self->transaction_depth,
231       ) if $self->transaction_depth;
232
233       $self->txn_begin;
234       $attempt_commit = 1;
235
236       try {
237         $coderef->(@$args)
238       }
239       catch {
240         $attempt_commit = 0;
241         $abort_txn->($self, $_)
242       };
243     };
244   }
245   finally {
246     if ($attempt_commit) {
247       my $delta_txn = (1 + $txn_init_depth) - $self->transaction_depth;
248
249       if ($delta_txn) {
250         # a rollback in a top-level txn_do is valid-ish (seen in the wild and our own tests)
251         carp "Unexpected reduction of transaction depth by $delta_txn after execution of $coderef, skipping txn_do's commit"
252           unless $delta_txn == 1 and $self->transaction_depth == 0;
253       }
254       else {
255         $self->txn_commit;
256       }
257     }
258   };
259 }
260
261 =head2 txn_begin
262
263 Starts a transaction.
264
265 See the preferred L</txn_do> method, which allows for
266 an entire code block to be executed transactionally.
267
268 =cut
269
270 sub txn_begin {
271   my $self = shift;
272
273   if($self->transaction_depth == 0) {
274     $self->debugobj->txn_begin()
275       if $self->debug;
276     $self->_exec_txn_begin;
277   }
278   elsif ($self->auto_savepoint) {
279     $self->svp_begin;
280   }
281   $self->{transaction_depth}++;
282
283 }
284
285 =head2 txn_commit
286
287 Issues a commit of the current transaction.
288
289 It does I<not> perform an actual storage commit unless there's a DBIx::Class
290 transaction currently in effect (i.e. you called L</txn_begin>).
291
292 =cut
293
294 sub txn_commit {
295   my $self = shift;
296
297   if ($self->transaction_depth == 1) {
298     $self->debugobj->txn_commit() if $self->debug;
299     $self->_exec_txn_commit;
300     $self->{transaction_depth}--;
301   }
302   elsif($self->transaction_depth > 1) {
303     $self->{transaction_depth}--;
304     $self->svp_release if $self->auto_savepoint;
305   }
306   else {
307     $self->throw_exception( 'Refusing to commit without a started transaction' );
308   }
309 }
310
311 =head2 txn_rollback
312
313 Issues a rollback of the current transaction. A nested rollback will
314 throw a L<DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION> exception,
315 which allows the rollback to propagate to the outermost transaction.
316
317 =cut
318
319 sub txn_rollback {
320   my $self = shift;
321
322   if ($self->transaction_depth == 1) {
323     $self->debugobj->txn_rollback() if $self->debug;
324     $self->_exec_txn_rollback;
325     $self->{transaction_depth}--;
326   }
327   elsif ($self->transaction_depth > 1) {
328     $self->{transaction_depth}--;
329
330     if ($self->auto_savepoint) {
331       $self->svp_rollback;
332       $self->svp_release;
333     }
334     else {
335       DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION->throw(
336         "A txn_rollback in nested transaction is ineffective! (depth $self->{transaction_depth})"
337       );
338     }
339   }
340   else {
341     $self->throw_exception( 'Refusing to roll back without a started transaction' );
342   }
343 }
344
345 =head2 svp_begin
346
347 Arguments: $savepoint_name?
348
349 Created a new savepoint using the name provided as argument. If no name
350 is provided, a random name will be used.
351
352 =cut
353
354 sub svp_begin {
355   my ($self, $name) = @_;
356
357   $self->throw_exception ("You can't use savepoints outside a transaction")
358     unless $self->transaction_depth;
359
360   my $exec = $self->can('_exec_svp_begin')
361     or $self->throw_exception ("Your Storage implementation doesn't support savepoints");
362
363   $name = $self->_svp_generate_name
364     unless defined $name;
365
366   push @{ $self->{savepoints} }, $name;
367
368   $self->debugobj->svp_begin($name) if $self->debug;
369
370   $exec->($self, $name);
371 }
372
373 sub _svp_generate_name {
374   my ($self) = @_;
375   return 'savepoint_'.scalar(@{ $self->{'savepoints'} });
376 }
377
378
379 =head2 svp_release
380
381 Arguments: $savepoint_name?
382
383 Release the savepoint provided as argument. If none is provided,
384 release the savepoint created most recently. This will implicitly
385 release all savepoints created after the one explicitly released as well.
386
387 =cut
388
389 sub svp_release {
390   my ($self, $name) = @_;
391
392   $self->throw_exception ("You can't use savepoints outside a transaction")
393     unless $self->transaction_depth;
394
395   my $exec = $self->can('_exec_svp_release')
396     or $self->throw_exception ("Your Storage implementation doesn't support savepoints");
397
398   if (defined $name) {
399     my @stack = @{ $self->savepoints };
400     my $svp;
401
402     do { $svp = pop @stack } until $svp eq $name;
403
404     $self->throw_exception ("Savepoint '$name' does not exist")
405       unless $svp;
406
407     $self->savepoints(\@stack); # put back what's left
408   }
409   else {
410     $name = pop @{ $self->savepoints }
411       or $self->throw_exception('No savepoints to release');;
412   }
413
414   $self->debugobj->svp_release($name) if $self->debug;
415
416   $exec->($self, $name);
417 }
418
419 =head2 svp_rollback
420
421 Arguments: $savepoint_name?
422
423 Rollback to the savepoint provided as argument. If none is provided,
424 rollback to the savepoint created most recently. This will implicitly
425 release all savepoints created after the savepoint we rollback to.
426
427 =cut
428
429 sub svp_rollback {
430   my ($self, $name) = @_;
431
432   $self->throw_exception ("You can't use savepoints outside a transaction")
433     unless $self->transaction_depth;
434
435   my $exec = $self->can('_exec_svp_rollback')
436     or $self->throw_exception ("Your Storage implementation doesn't support savepoints");
437
438   if (defined $name) {
439     my @stack = @{ $self->savepoints };
440     my $svp;
441
442     # a rollback doesn't remove the named savepoint,
443     # only everything after it
444     while (@stack and $stack[-1] ne $name) {
445       pop @stack
446     };
447
448     $self->throw_exception ("Savepoint '$name' does not exist")
449       unless @stack;
450
451     $self->savepoints(\@stack); # put back what's left
452   }
453   else {
454     $name = $self->savepoints->[-1]
455       or $self->throw_exception('No savepoints to rollback');;
456   }
457
458   $self->debugobj->svp_rollback($name) if $self->debug;
459
460   $exec->($self, $name);
461 }
462
463 =head2 txn_scope_guard
464
465 An alternative way of transaction handling based on
466 L<DBIx::Class::Storage::TxnScopeGuard>:
467
468  my $txn_guard = $storage->txn_scope_guard;
469
470  $row->col1("val1");
471  $row->update;
472
473  $txn_guard->commit;
474
475 If an exception occurs, or the guard object otherwise leaves the scope
476 before C<< $txn_guard->commit >> is called, the transaction will be rolled
477 back by an explicit L</txn_rollback> call. In essence this is akin to
478 using a L</txn_begin>/L</txn_commit> pair, without having to worry
479 about calling L</txn_rollback> at the right places. Note that since there
480 is no defined code closure, there will be no retries and other magic upon
481 database disconnection. If you need such functionality see L</txn_do>.
482
483 =cut
484
485 sub txn_scope_guard {
486   return DBIx::Class::Storage::TxnScopeGuard->new($_[0]);
487 }
488
489 =head2 sql_maker
490
491 Returns a C<sql_maker> object - normally an object of class
492 C<DBIx::Class::SQLMaker>.
493
494 =cut
495
496 sub sql_maker { die "Virtual method!" }
497
498 =head2 debug
499
500 Causes trace information to be emitted on the L</debugobj> object.
501 (or C<STDERR> if L</debugobj> has not specifically been set).
502
503 This is the equivalent to setting L</DBIC_TRACE> in your
504 shell environment.
505
506 =head2 debugfh
507
508 Set or retrieve the filehandle used for trace/debug output.  This should be
509 an IO::Handle compatible object (only the C<print> method is used.  Initially
510 set to be STDERR - although see information on the
511 L<DBIC_TRACE> environment variable.
512
513 =cut
514
515 sub debugfh {
516     my $self = shift;
517
518     if ($self->debugobj->can('debugfh')) {
519         return $self->debugobj->debugfh(@_);
520     }
521 }
522
523 =head2 debugobj
524
525 Sets or retrieves the object used for metric collection. Defaults to an instance
526 of L<DBIx::Class::Storage::Statistics> that is compatible with the original
527 method of using a coderef as a callback.  See the aforementioned Statistics
528 class for more information.
529
530 =cut
531
532 sub debugobj {
533   my $self = shift;
534
535   if (@_) {
536     return $self->{debugobj} = $_[0];
537   }
538
539   $self->{debugobj} ||= do {
540     if (my $profile = $ENV{DBIC_TRACE_PROFILE}) {
541       require DBIx::Class::Storage::Debug::PrettyPrint;
542       if ($profile =~ /^\.?\//) {
543         require Config::Any;
544
545         my $cfg = try {
546           Config::Any->load_files({ files => [$profile], use_ext => 1 });
547         } catch {
548           # sanitize the error message a bit
549           $_ =~ s/at \s+ .+ Storage\.pm \s line \s \d+ $//x;
550           $self->throw_exception("Failure processing \$ENV{DBIC_TRACE_PROFILE}: $_");
551         };
552
553         DBIx::Class::Storage::Debug::PrettyPrint->new(values %{$cfg->[0]});
554       }
555       else {
556         DBIx::Class::Storage::Debug::PrettyPrint->new({ profile => $profile });
557       }
558     }
559     else {
560       require DBIx::Class::Storage::Statistics;
561       DBIx::Class::Storage::Statistics->new
562     }
563   };
564 }
565
566 =head2 debugcb
567
568 Sets a callback to be executed each time a statement is run; takes a sub
569 reference.  Callback is executed as $sub->($op, $info) where $op is
570 SELECT/INSERT/UPDATE/DELETE and $info is what would normally be printed.
571
572 See L</debugobj> for a better way.
573
574 =cut
575
576 sub debugcb {
577     my $self = shift;
578
579     if ($self->debugobj->can('callback')) {
580         return $self->debugobj->callback(@_);
581     }
582 }
583
584 =head2 cursor_class
585
586 The cursor class for this Storage object.
587
588 =cut
589
590 =head2 deploy
591
592 Deploy the tables to storage (CREATE TABLE and friends in a SQL-based
593 Storage class). This would normally be called through
594 L<DBIx::Class::Schema/deploy>.
595
596 =cut
597
598 sub deploy { die "Virtual method!" }
599
600 =head2 connect_info
601
602 The arguments of C<connect_info> are always a single array reference,
603 and are Storage-handler specific.
604
605 This is normally accessed via L<DBIx::Class::Schema/connection>, which
606 encapsulates its argument list in an arrayref before calling
607 C<connect_info> here.
608
609 =cut
610
611 sub connect_info { die "Virtual method!" }
612
613 =head2 select
614
615 Handle a select statement.
616
617 =cut
618
619 sub select { die "Virtual method!" }
620
621 =head2 insert
622
623 Handle an insert statement.
624
625 =cut
626
627 sub insert { die "Virtual method!" }
628
629 =head2 update
630
631 Handle an update statement.
632
633 =cut
634
635 sub update { die "Virtual method!" }
636
637 =head2 delete
638
639 Handle a delete statement.
640
641 =cut
642
643 sub delete { die "Virtual method!" }
644
645 =head2 select_single
646
647 Performs a select, fetch and return of data - handles a single row
648 only.
649
650 =cut
651
652 sub select_single { die "Virtual method!" }
653
654 =head2 columns_info_for
655
656 Returns metadata for the given source's columns.  This
657 is *deprecated*, and will be removed before 1.0.  You should
658 be specifying the metadata yourself if you need it.
659
660 =cut
661
662 sub columns_info_for { die "Virtual method!" }
663
664 =head1 ENVIRONMENT VARIABLES
665
666 =head2 DBIC_TRACE
667
668 If C<DBIC_TRACE> is set then trace information
669 is produced (as when the L</debug> method is set).
670
671 If the value is of the form C<1=/path/name> then the trace output is
672 written to the file C</path/name>.
673
674 This environment variable is checked when the storage object is first
675 created (when you call connect on your schema).  So, run-time changes
676 to this environment variable will not take effect unless you also
677 re-connect on your schema.
678
679 =head2 DBIC_TRACE_PROFILE
680
681 If C<DBIC_TRACE_PROFILE> is set, L<DBIx::Class::Storage::Debug::PrettyPrint>
682 will be used to format the output from C<DBIC_TRACE>.  The value it
683 is set to is the C<profile> that it will be used.  If the value is a
684 filename the file is read with L<Config::Any> and the results are
685 used as the configuration for tracing.  See L<SQL::Abstract::Tree/new>
686 for what that structure should look like.
687
688
689 =head2 DBIX_CLASS_STORAGE_DBI_DEBUG
690
691 Old name for DBIC_TRACE
692
693 =head1 SEE ALSO
694
695 L<DBIx::Class::Storage::DBI> - reference storage implementation using
696 SQL::Abstract and DBI.
697
698 =head1 AUTHORS
699
700 Matt S. Trout <mst@shadowcatsystems.co.uk>
701
702 Andy Grundman <andy@hybridized.org>
703
704 =head1 LICENSE
705
706 You may distribute this code under the same terms as Perl itself.
707
708 =cut
709
710 1;