1 package DBIx::Class::Storage;
6 use base qw/DBIx::Class/;
9 use Scalar::Util qw/weaken/;
10 use Carp::Clan qw/^DBIx::Class/;
12 use DBIx::Class::Storage::TxnScopeGuard;
14 __PACKAGE__->mk_group_accessors('simple' => qw/debug debugobj schema/);
15 __PACKAGE__->mk_group_accessors('inherited' => 'cursor_class');
17 __PACKAGE__->cursor_class('DBIx::Class::Cursor');
19 sub cursor { shift->cursor_class(@_); }
21 package # Hide from PAUSE
22 DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION;
24 use overload '"' => sub {
25 'DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION'
31 return bless $self, $class;
34 package DBIx::Class::Storage;
38 DBIx::Class::Storage - Generic Storage Handler
42 A base implementation of common Storage methods. For specific
43 information about L<DBI>-based storage, see L<DBIx::Class::Storage::DBI>.
51 Instantiates the Storage object.
56 my ($self, $schema) = @_;
58 $self = ref $self if ref $self;
63 $new->set_schema($schema);
64 $new->debugobj(new DBIx::Class::Storage::Statistics());
68 my $debug_env = $ENV{DBIX_CLASS_STORAGE_DBI_DEBUG}
71 $new->debug(1) if $debug_env;
78 Used to reset the schema class or object which owns this
79 storage object, such as during L<DBIx::Class::Schema/clone>.
84 my ($self, $schema) = @_;
85 $self->schema($schema);
86 weaken($self->{schema}) if ref $self->{schema};
91 Returns true if we have an open storage connection, false
92 if it is not (yet) open.
96 sub connected { die "Virtual method!" }
100 Closes any open storage connection unconditionally.
104 sub disconnect { die "Virtual method!" }
106 =head2 ensure_connected
108 Initiate a connection to the storage if one isn't already open.
112 sub ensure_connected { die "Virtual method!" }
114 =head2 throw_exception
116 Throws an exception - croaks.
120 sub throw_exception {
123 $self->schema->throw_exception(@_) if $self->schema;
131 =item Arguments: C<$coderef>, @coderef_args?
133 =item Return Value: The return value of $coderef
137 Executes C<$coderef> with (optional) arguments C<@coderef_args> atomically,
138 returning its result (if any). If an exception is caught, a rollback is issued
139 and the exception is rethrown. If the rollback fails, (i.e. throws an
140 exception) an exception is thrown that includes a "Rollback failed" message.
144 my $author_rs = $schema->resultset('Author')->find(1);
145 my @titles = qw/Night Day It/;
148 # If any one of these fails, the entire transaction fails
149 $author_rs->create_related('books', {
151 }) foreach (@titles);
153 return $author->books;
158 $rs = $schema->txn_do($coderef);
161 if ($@) { # Transaction failed
162 die "something terrible has happened!" #
163 if ($@ =~ /Rollback failed/); # Rollback failed
165 deal_with_failed_transaction();
168 In a nested transaction (calling txn_do() from within a txn_do() coderef) only
169 the outermost transaction will issue a L</txn_commit>, and txn_do() can be
170 called in void, scalar and list context and it will behave as expected.
172 Please note that all of the code in your coderef, including non-DBIx::Class
173 code, is part of a transaction. This transaction may fail out halfway, or
174 it may get partially double-executed (in the case that our DB connection
175 failed halfway through the transaction, in which case we reconnect and
176 restart the txn). Therefore it is best that any side-effects in your coderef
177 are idempotent (that is, can be re-executed multiple times and get the
178 same result), and that you check up on your side-effects in the case of
184 my ($self, $coderef, @args) = @_;
186 ref $coderef eq 'CODE' or $self->throw_exception
187 ('$coderef must be a CODE reference');
189 my (@return_values, $return_value);
191 $self->txn_begin; # If this throws an exception, no rollback is needed
193 my $wantarray = wantarray; # Need to save this since the context
194 # inside the eval{} block is independent
195 # of the context that called txn_do()
198 # Need to differentiate between scalar/list context to allow for
199 # returning a list in scalar context to get the size of the list
202 @return_values = $coderef->(@args);
203 } elsif (defined $wantarray) {
205 $return_value = $coderef->(@args);
221 my $rollback_error = $@;
222 my $exception_class = "DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION";
223 $self->throw_exception($error) # propagate nested rollback
224 if $rollback_error =~ /$exception_class/;
226 $self->throw_exception(
227 "Transaction aborted: $error. Rollback failed: ${rollback_error}"
230 $self->throw_exception($error); # txn failed but rollback succeeded
234 return $wantarray ? @return_values : $return_value;
239 Starts a transaction.
241 See the preferred L</txn_do> method, which allows for
242 an entire code block to be executed transactionally.
246 sub txn_begin { die "Virtual method!" }
250 Issues a commit of the current transaction.
252 It does I<not> perform an actual storage commit unless there's a DBIx::Class
253 transaction currently in effect (i.e. you called L</txn_begin>).
257 sub txn_commit { die "Virtual method!" }
261 Issues a rollback of the current transaction. A nested rollback will
262 throw a L<DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION> exception,
263 which allows the rollback to propagate to the outermost transaction.
267 sub txn_rollback { die "Virtual method!" }
271 Arguments: $savepoint_name?
273 Created a new savepoint using the name provided as argument. If no name
274 is provided, a random name will be used.
278 sub svp_begin { die "Virtual method!" }
282 Arguments: $savepoint_name?
284 Release the savepoint provided as argument. If none is provided,
285 release the savepoint created most recently. This will implicitly
286 release all savepoints created after the one explicitly released as well.
290 sub svp_release { die "Virtual method!" }
294 Arguments: $savepoint_name?
296 Rollback to the savepoint provided as argument. If none is provided,
297 rollback to the savepoint created most recently. This will implicitly
298 release all savepoints created after the savepoint we rollback to.
302 sub svp_rollback { die "Virtual method!" }
306 =head2 txn_scope_guard
308 An alternative way of transaction handling based on
309 L<DBIx::Class::Storage::TxnScopeGuard>:
311 my $txn_guard = $storage->txn_scope_guard;
318 If an exception occurs, or the guard object otherwise leaves the scope
319 before C<< $txn_guard->commit >> is called, the transaction will be rolled
320 back by an explicit L</txn_rollback> call. In essence this is akin to
321 using a L</txn_begin>/L</txn_commit> pair, without having to worry
322 about calling L</txn_rollback> at the right places. Note that since there
323 is no defined code closure, there will be no retries and other magic upon
324 database disconnection. If you need such functionality see L</txn_do>.
328 sub txn_scope_guard {
329 return DBIx::Class::Storage::TxnScopeGuard->new($_[0]);
334 Returns a C<sql_maker> object - normally an object of class
335 C<DBIx::Class::SQLAHacks>.
339 sub sql_maker { die "Virtual method!" }
343 Causes trace information to be emitted on the C<debugobj> object.
344 (or C<STDERR> if C<debugobj> has not specifically been set).
346 This is the equivalent to setting L</DBIC_TRACE> in your
351 Set or retrieve the filehandle used for trace/debug output. This should be
352 an IO::Handle compatible ojbect (only the C<print> method is used. Initially
353 set to be STDERR - although see information on the
354 L<DBIC_TRACE> environment variable.
361 if ($self->debugobj->can('debugfh')) {
362 return $self->debugobj->debugfh(@_);
368 Sets or retrieves the object used for metric collection. Defaults to an instance
369 of L<DBIx::Class::Storage::Statistics> that is compatible with the original
370 method of using a coderef as a callback. See the aforementioned Statistics
371 class for more information.
375 Sets a callback to be executed each time a statement is run; takes a sub
376 reference. Callback is executed as $sub->($op, $info) where $op is
377 SELECT/INSERT/UPDATE/DELETE and $info is what would normally be printed.
379 See L<debugobj> for a better way.
386 if ($self->debugobj->can('callback')) {
387 return $self->debugobj->callback(@_);
393 The cursor class for this Storage object.
399 Deploy the tables to storage (CREATE TABLE and friends in a SQL-based
400 Storage class). This would normally be called through
401 L<DBIx::Class::Schema/deploy>.
405 sub deploy { die "Virtual method!" }
409 The arguments of C<connect_info> are always a single array reference,
410 and are Storage-handler specific.
412 This is normally accessed via L<DBIx::Class::Schema/connection>, which
413 encapsulates its argument list in an arrayref before calling
414 C<connect_info> here.
418 sub connect_info { die "Virtual method!" }
422 Handle a select statement.
426 sub select { die "Virtual method!" }
430 Handle an insert statement.
434 sub insert { die "Virtual method!" }
438 Handle an update statement.
442 sub update { die "Virtual method!" }
446 Handle a delete statement.
450 sub delete { die "Virtual method!" }
454 Performs a select, fetch and return of data - handles a single row
459 sub select_single { die "Virtual method!" }
461 =head2 columns_info_for
463 Returns metadata for the given source's columns. This
464 is *deprecated*, and will be removed before 1.0. You should
465 be specifying the metadata yourself if you need it.
469 sub columns_info_for { die "Virtual method!" }
471 =head1 ENVIRONMENT VARIABLES
475 If C<DBIC_TRACE> is set then trace information
476 is produced (as when the L<debug> method is set).
478 If the value is of the form C<1=/path/name> then the trace output is
479 written to the file C</path/name>.
481 This environment variable is checked when the storage object is first
482 created (when you call connect on your schema). So, run-time changes
483 to this environment variable will not take effect unless you also
484 re-connect on your schema.
486 =head2 DBIX_CLASS_STORAGE_DBI_DEBUG
488 Old name for DBIC_TRACE
492 L<DBIx::Class::Storage::DBI> - reference storage implementation using
493 SQL::Abstract and DBI.
497 Matt S. Trout <mst@shadowcatsystems.co.uk>
499 Andy Grundman <andy@hybridized.org>
503 You may distribute this code under the same terms as Perl itself.