1 package DBIx::Class::Storage;
6 use base qw/DBIx::Class/;
10 package # Hide from PAUSE
11 DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION;
12 use base 'DBIx::Class::Exception';
15 use DBIx::Class::Carp;
16 use DBIx::Class::Storage::BlockRunner;
17 use Scalar::Util qw/blessed weaken/;
18 use DBIx::Class::Storage::TxnScopeGuard;
22 __PACKAGE__->mk_group_accessors(simple => qw/debug schema transaction_depth auto_savepoint savepoints/);
23 __PACKAGE__->mk_group_accessors(component_class => 'cursor_class');
25 __PACKAGE__->cursor_class('DBIx::Class::Cursor');
27 sub cursor { shift->cursor_class(@_); }
31 DBIx::Class::Storage - Generic Storage Handler
35 A base implementation of common Storage methods. For specific
36 information about L<DBI>-based storage, see L<DBIx::Class::Storage::DBI>.
44 Instantiates the Storage object.
49 my ($self, $schema) = @_;
51 $self = ref $self if ref $self;
54 transaction_depth => 0,
58 $new->set_schema($schema);
60 if $ENV{DBIX_CLASS_STORAGE_DBI_DEBUG} || $ENV{DBIC_TRACE};
67 Used to reset the schema class or object which owns this
68 storage object, such as during L<DBIx::Class::Schema/clone>.
73 my ($self, $schema) = @_;
74 $self->schema($schema);
75 weaken $self->{schema} if ref $self->{schema};
80 Returns true if we have an open storage connection, false
81 if it is not (yet) open.
85 sub connected { die "Virtual method!" }
89 Closes any open storage connection unconditionally.
93 sub disconnect { die "Virtual method!" }
95 =head2 ensure_connected
97 Initiate a connection to the storage if one isn't already open.
101 sub ensure_connected { die "Virtual method!" }
103 =head2 throw_exception
105 Throws an exception - croaks.
109 sub throw_exception {
112 if (ref $self and $self->schema) {
113 $self->schema->throw_exception(@_);
116 DBIx::Class::Exception->throw(@_);
124 =item Arguments: C<$coderef>, @coderef_args?
126 =item Return Value: The return value of $coderef
130 Executes C<$coderef> with (optional) arguments C<@coderef_args> atomically,
131 returning its result (if any). If an exception is caught, a rollback is issued
132 and the exception is rethrown. If the rollback fails, (i.e. throws an
133 exception) an exception is thrown that includes a "Rollback failed" message.
137 my $author_rs = $schema->resultset('Author')->find(1);
138 my @titles = qw/Night Day It/;
141 # If any one of these fails, the entire transaction fails
142 $author_rs->create_related('books', {
144 }) foreach (@titles);
146 return $author->books;
151 $rs = $schema->txn_do($coderef);
155 die "something terrible has happened!"
156 if ($error =~ /Rollback failed/); # Rollback failed
158 deal_with_failed_transaction();
161 In a nested transaction (calling txn_do() from within a txn_do() coderef) only
162 the outermost transaction will issue a L</txn_commit>, and txn_do() can be
163 called in void, scalar and list context and it will behave as expected.
165 Please note that all of the code in your coderef, including non-DBIx::Class
166 code, is part of a transaction. This transaction may fail out halfway, or
167 it may get partially double-executed (in the case that our DB connection
168 failed halfway through the transaction, in which case we reconnect and
169 restart the txn). Therefore it is best that any side-effects in your coderef
170 are idempotent (that is, can be re-executed multiple times and get the
171 same result), and that you check up on your side-effects in the case of
180 DBIx::Class::Storage::BlockRunner->new(
182 run_code => $coderef,
183 run_args => \@_, # take a ref instead of a copy, to preserve coderef @_ aliasing semantics
185 retry_handler => sub { ! ( $_[0]->retried_count or $_[0]->storage->connected ) },
191 Starts a transaction.
193 See the preferred L</txn_do> method, which allows for
194 an entire code block to be executed transactionally.
201 if($self->transaction_depth == 0) {
202 $self->debugobj->txn_begin()
204 $self->_exec_txn_begin;
206 elsif ($self->auto_savepoint) {
209 $self->{transaction_depth}++;
215 Issues a commit of the current transaction.
217 It does I<not> perform an actual storage commit unless there's a DBIx::Class
218 transaction currently in effect (i.e. you called L</txn_begin>).
225 if ($self->transaction_depth == 1) {
226 $self->debugobj->txn_commit() if $self->debug;
227 $self->_exec_txn_commit;
228 $self->{transaction_depth}--;
230 elsif($self->transaction_depth > 1) {
231 $self->{transaction_depth}--;
232 $self->svp_release if $self->auto_savepoint;
235 $self->throw_exception( 'Refusing to commit without a started transaction' );
241 Issues a rollback of the current transaction. A nested rollback will
242 throw a L<DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION> exception,
243 which allows the rollback to propagate to the outermost transaction.
250 if ($self->transaction_depth == 1) {
251 $self->debugobj->txn_rollback() if $self->debug;
252 $self->_exec_txn_rollback;
253 $self->{transaction_depth}--;
255 elsif ($self->transaction_depth > 1) {
256 $self->{transaction_depth}--;
258 if ($self->auto_savepoint) {
263 DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION->throw(
264 "A txn_rollback in nested transaction is ineffective! (depth $self->{transaction_depth})"
269 $self->throw_exception( 'Refusing to roll back without a started transaction' );
275 Arguments: $savepoint_name?
277 Created a new savepoint using the name provided as argument. If no name
278 is provided, a random name will be used.
283 my ($self, $name) = @_;
285 $self->throw_exception ("You can't use savepoints outside a transaction")
286 unless $self->transaction_depth;
288 my $exec = $self->can('_exec_svp_begin')
289 or $self->throw_exception ("Your Storage implementation doesn't support savepoints");
291 $name = $self->_svp_generate_name
292 unless defined $name;
294 push @{ $self->{savepoints} }, $name;
296 $self->debugobj->svp_begin($name) if $self->debug;
298 $exec->($self, $name);
301 sub _svp_generate_name {
303 return 'savepoint_'.scalar(@{ $self->{'savepoints'} });
309 Arguments: $savepoint_name?
311 Release the savepoint provided as argument. If none is provided,
312 release the savepoint created most recently. This will implicitly
313 release all savepoints created after the one explicitly released as well.
318 my ($self, $name) = @_;
320 $self->throw_exception ("You can't use savepoints outside a transaction")
321 unless $self->transaction_depth;
323 my $exec = $self->can('_exec_svp_release')
324 or $self->throw_exception ("Your Storage implementation doesn't support savepoints");
327 my @stack = @{ $self->savepoints };
330 do { $svp = pop @stack } until $svp eq $name;
332 $self->throw_exception ("Savepoint '$name' does not exist")
335 $self->savepoints(\@stack); # put back what's left
338 $name = pop @{ $self->savepoints }
339 or $self->throw_exception('No savepoints to release');;
342 $self->debugobj->svp_release($name) if $self->debug;
344 $exec->($self, $name);
349 Arguments: $savepoint_name?
351 Rollback to the savepoint provided as argument. If none is provided,
352 rollback to the savepoint created most recently. This will implicitly
353 release all savepoints created after the savepoint we rollback to.
358 my ($self, $name) = @_;
360 $self->throw_exception ("You can't use savepoints outside a transaction")
361 unless $self->transaction_depth;
363 my $exec = $self->can('_exec_svp_rollback')
364 or $self->throw_exception ("Your Storage implementation doesn't support savepoints");
367 my @stack = @{ $self->savepoints };
370 # a rollback doesn't remove the named savepoint,
371 # only everything after it
372 while (@stack and $stack[-1] ne $name) {
376 $self->throw_exception ("Savepoint '$name' does not exist")
379 $self->savepoints(\@stack); # put back what's left
382 $name = $self->savepoints->[-1]
383 or $self->throw_exception('No savepoints to rollback');;
386 $self->debugobj->svp_rollback($name) if $self->debug;
388 $exec->($self, $name);
391 =head2 txn_scope_guard
393 An alternative way of transaction handling based on
394 L<DBIx::Class::Storage::TxnScopeGuard>:
396 my $txn_guard = $storage->txn_scope_guard;
403 If an exception occurs, or the guard object otherwise leaves the scope
404 before C<< $txn_guard->commit >> is called, the transaction will be rolled
405 back by an explicit L</txn_rollback> call. In essence this is akin to
406 using a L</txn_begin>/L</txn_commit> pair, without having to worry
407 about calling L</txn_rollback> at the right places. Note that since there
408 is no defined code closure, there will be no retries and other magic upon
409 database disconnection. If you need such functionality see L</txn_do>.
413 sub txn_scope_guard {
414 return DBIx::Class::Storage::TxnScopeGuard->new($_[0]);
419 Returns a C<sql_maker> object - normally an object of class
420 C<DBIx::Class::SQLMaker>.
424 sub sql_maker { die "Virtual method!" }
428 Causes trace information to be emitted on the L</debugobj> object.
429 (or C<STDERR> if L</debugobj> has not specifically been set).
431 This is the equivalent to setting L</DBIC_TRACE> in your
436 Set or retrieve the filehandle used for trace/debug output. This should be
437 an IO::Handle compatible object (only the C<print> method is used. Initially
438 set to be STDERR - although see information on the
439 L<DBIC_TRACE> environment variable.
446 if ($self->debugobj->can('debugfh')) {
447 return $self->debugobj->debugfh(@_);
453 Sets or retrieves the object used for metric collection. Defaults to an instance
454 of L<DBIx::Class::Storage::Statistics> that is compatible with the original
455 method of using a coderef as a callback. See the aforementioned Statistics
456 class for more information.
464 return $self->{debugobj} = $_[0];
467 $self->{debugobj} ||= do {
468 if (my $profile = $ENV{DBIC_TRACE_PROFILE}) {
469 require DBIx::Class::Storage::Debug::PrettyPrint;
470 if ($profile =~ /^\.?\//) {
474 Config::Any->load_files({ files => [$profile], use_ext => 1 });
476 # sanitize the error message a bit
477 $_ =~ s/at \s+ .+ Storage\.pm \s line \s \d+ $//x;
478 $self->throw_exception("Failure processing \$ENV{DBIC_TRACE_PROFILE}: $_");
481 DBIx::Class::Storage::Debug::PrettyPrint->new(values %{$cfg->[0]});
484 DBIx::Class::Storage::Debug::PrettyPrint->new({ profile => $profile });
488 require DBIx::Class::Storage::Statistics;
489 DBIx::Class::Storage::Statistics->new
496 Sets a callback to be executed each time a statement is run; takes a sub
497 reference. Callback is executed as $sub->($op, $info) where $op is
498 SELECT/INSERT/UPDATE/DELETE and $info is what would normally be printed.
500 See L</debugobj> for a better way.
507 if ($self->debugobj->can('callback')) {
508 return $self->debugobj->callback(@_);
514 The cursor class for this Storage object.
520 Deploy the tables to storage (CREATE TABLE and friends in a SQL-based
521 Storage class). This would normally be called through
522 L<DBIx::Class::Schema/deploy>.
526 sub deploy { die "Virtual method!" }
530 The arguments of C<connect_info> are always a single array reference,
531 and are Storage-handler specific.
533 This is normally accessed via L<DBIx::Class::Schema/connection>, which
534 encapsulates its argument list in an arrayref before calling
535 C<connect_info> here.
539 sub connect_info { die "Virtual method!" }
543 Handle a select statement.
547 sub select { die "Virtual method!" }
551 Handle an insert statement.
555 sub insert { die "Virtual method!" }
559 Handle an update statement.
563 sub update { die "Virtual method!" }
567 Handle a delete statement.
571 sub delete { die "Virtual method!" }
575 Performs a select, fetch and return of data - handles a single row
580 sub select_single { die "Virtual method!" }
582 =head2 columns_info_for
584 Returns metadata for the given source's columns. This
585 is *deprecated*, and will be removed before 1.0. You should
586 be specifying the metadata yourself if you need it.
590 sub columns_info_for { die "Virtual method!" }
592 =head1 ENVIRONMENT VARIABLES
596 If C<DBIC_TRACE> is set then trace information
597 is produced (as when the L</debug> method is set).
599 If the value is of the form C<1=/path/name> then the trace output is
600 written to the file C</path/name>.
602 This environment variable is checked when the storage object is first
603 created (when you call connect on your schema). So, run-time changes
604 to this environment variable will not take effect unless you also
605 re-connect on your schema.
607 =head2 DBIC_TRACE_PROFILE
609 If C<DBIC_TRACE_PROFILE> is set, L<DBIx::Class::Storage::Debug::PrettyPrint>
610 will be used to format the output from C<DBIC_TRACE>. The value it
611 is set to is the C<profile> that it will be used. If the value is a
612 filename the file is read with L<Config::Any> and the results are
613 used as the configuration for tracing. See L<SQL::Abstract::Tree/new>
614 for what that structure should look like.
617 =head2 DBIX_CLASS_STORAGE_DBI_DEBUG
619 Old name for DBIC_TRACE
623 L<DBIx::Class::Storage::DBI> - reference storage implementation using
624 SQL::Abstract and DBI.
626 =head1 AUTHOR AND CONTRIBUTORS
628 See L<AUTHOR|DBIx::Class/AUTHOR> and L<CONTRIBUTORS|DBIx::Class/CONTRIBUTORS> in DBIx::Class
632 You may distribute this code under the same terms as Perl itself.