1 package DBIx::Class::Storage;
6 use base qw/DBIx::Class/;
9 use DBIx::Class::Exception;
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 Scalar::Util::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 {
124 $self->schema->throw_exception(@_);
127 DBIx::Class::Exception->throw(@_);
135 =item Arguments: C<$coderef>, @coderef_args?
137 =item Return Value: The return value of $coderef
141 Executes C<$coderef> with (optional) arguments C<@coderef_args> atomically,
142 returning its result (if any). If an exception is caught, a rollback is issued
143 and the exception is rethrown. If the rollback fails, (i.e. throws an
144 exception) an exception is thrown that includes a "Rollback failed" message.
148 my $author_rs = $schema->resultset('Author')->find(1);
149 my @titles = qw/Night Day It/;
152 # If any one of these fails, the entire transaction fails
153 $author_rs->create_related('books', {
155 }) foreach (@titles);
157 return $author->books;
162 $rs = $schema->txn_do($coderef);
166 die "something terrible has happened!" #
167 if ($error =~ /Rollback failed/); # Rollback failed
169 deal_with_failed_transaction();
172 In a nested transaction (calling txn_do() from within a txn_do() coderef) only
173 the outermost transaction will issue a L</txn_commit>, and txn_do() can be
174 called in void, scalar and list context and it will behave as expected.
176 Please note that all of the code in your coderef, including non-DBIx::Class
177 code, is part of a transaction. This transaction may fail out halfway, or
178 it may get partially double-executed (in the case that our DB connection
179 failed halfway through the transaction, in which case we reconnect and
180 restart the txn). Therefore it is best that any side-effects in your coderef
181 are idempotent (that is, can be re-executed multiple times and get the
182 same result), and that you check up on your side-effects in the case of
188 my ($self, $coderef, @args) = @_;
190 ref $coderef eq 'CODE' or $self->throw_exception
191 ('$coderef must be a CODE reference');
193 my (@return_values, $return_value);
195 $self->txn_begin; # If this throws an exception, no rollback is needed
197 my $wantarray = wantarray; # Need to save this since the context
198 # inside the eval{} block is independent
199 # of the context that called txn_do()
202 # Need to differentiate between scalar/list context to allow for
203 # returning a list in scalar context to get the size of the list
206 @return_values = $coderef->(@args);
207 } elsif (defined $wantarray) {
209 $return_value = $coderef->(@args);
221 my $rollback_error = shift;
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
233 return $wantarray ? @return_values : $return_value;
238 Starts a transaction.
240 See the preferred L</txn_do> method, which allows for
241 an entire code block to be executed transactionally.
245 sub txn_begin { die "Virtual method!" }
249 Issues a commit of the current transaction.
251 It does I<not> perform an actual storage commit unless there's a DBIx::Class
252 transaction currently in effect (i.e. you called L</txn_begin>).
256 sub txn_commit { die "Virtual method!" }
260 Issues a rollback of the current transaction. A nested rollback will
261 throw a L<DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION> exception,
262 which allows the rollback to propagate to the outermost transaction.
266 sub txn_rollback { die "Virtual method!" }
270 Arguments: $savepoint_name?
272 Created a new savepoint using the name provided as argument. If no name
273 is provided, a random name will be used.
277 sub svp_begin { die "Virtual method!" }
281 Arguments: $savepoint_name?
283 Release the savepoint provided as argument. If none is provided,
284 release the savepoint created most recently. This will implicitly
285 release all savepoints created after the one explicitly released as well.
289 sub svp_release { die "Virtual method!" }
293 Arguments: $savepoint_name?
295 Rollback to the savepoint provided as argument. If none is provided,
296 rollback to the savepoint created most recently. This will implicitly
297 release all savepoints created after the savepoint we rollback to.
301 sub svp_rollback { die "Virtual method!" }
305 =head2 txn_scope_guard
307 An alternative way of transaction handling based on
308 L<DBIx::Class::Storage::TxnScopeGuard>:
310 my $txn_guard = $storage->txn_scope_guard;
317 If an exception occurs, or the guard object otherwise leaves the scope
318 before C<< $txn_guard->commit >> is called, the transaction will be rolled
319 back by an explicit L</txn_rollback> call. In essence this is akin to
320 using a L</txn_begin>/L</txn_commit> pair, without having to worry
321 about calling L</txn_rollback> at the right places. Note that since there
322 is no defined code closure, there will be no retries and other magic upon
323 database disconnection. If you need such functionality see L</txn_do>.
327 sub txn_scope_guard {
328 return DBIx::Class::Storage::TxnScopeGuard->new($_[0]);
333 Returns a C<sql_maker> object - normally an object of class
334 C<DBIx::Class::SQLAHacks>.
338 sub sql_maker { die "Virtual method!" }
342 Causes trace information to be emitted on the C<debugobj> object.
343 (or C<STDERR> if C<debugobj> has not specifically been set).
345 This is the equivalent to setting L</DBIC_TRACE> in your
350 Set or retrieve the filehandle used for trace/debug output. This should be
351 an IO::Handle compatible object (only the C<print> method is used. Initially
352 set to be STDERR - although see information on the
353 L<DBIC_TRACE> environment variable.
360 if ($self->debugobj->can('debugfh')) {
361 return $self->debugobj->debugfh(@_);
367 Sets or retrieves the object used for metric collection. Defaults to an instance
368 of L<DBIx::Class::Storage::Statistics> that is compatible with the original
369 method of using a coderef as a callback. See the aforementioned Statistics
370 class for more information.
374 Sets a callback to be executed each time a statement is run; takes a sub
375 reference. Callback is executed as $sub->($op, $info) where $op is
376 SELECT/INSERT/UPDATE/DELETE and $info is what would normally be printed.
378 See L<debugobj> for a better way.
385 if ($self->debugobj->can('callback')) {
386 return $self->debugobj->callback(@_);
392 The cursor class for this Storage object.
398 Deploy the tables to storage (CREATE TABLE and friends in a SQL-based
399 Storage class). This would normally be called through
400 L<DBIx::Class::Schema/deploy>.
404 sub deploy { die "Virtual method!" }
408 The arguments of C<connect_info> are always a single array reference,
409 and are Storage-handler specific.
411 This is normally accessed via L<DBIx::Class::Schema/connection>, which
412 encapsulates its argument list in an arrayref before calling
413 C<connect_info> here.
417 sub connect_info { die "Virtual method!" }
421 Handle a select statement.
425 sub select { die "Virtual method!" }
429 Handle an insert statement.
433 sub insert { die "Virtual method!" }
437 Handle an update statement.
441 sub update { die "Virtual method!" }
445 Handle a delete statement.
449 sub delete { die "Virtual method!" }
453 Performs a select, fetch and return of data - handles a single row
458 sub select_single { die "Virtual method!" }
460 =head2 columns_info_for
462 Returns metadata for the given source's columns. This
463 is *deprecated*, and will be removed before 1.0. You should
464 be specifying the metadata yourself if you need it.
468 sub columns_info_for { die "Virtual method!" }
470 =head1 ENVIRONMENT VARIABLES
474 If C<DBIC_TRACE> is set then trace information
475 is produced (as when the L<debug> method is set).
477 If the value is of the form C<1=/path/name> then the trace output is
478 written to the file C</path/name>.
480 This environment variable is checked when the storage object is first
481 created (when you call connect on your schema). So, run-time changes
482 to this environment variable will not take effect unless you also
483 re-connect on your schema.
485 =head2 DBIX_CLASS_STORAGE_DBI_DEBUG
487 Old name for DBIC_TRACE
491 L<DBIx::Class::Storage::DBI> - reference storage implementation using
492 SQL::Abstract and DBI.
496 Matt S. Trout <mst@shadowcatsystems.co.uk>
498 Andy Grundman <andy@hybridized.org>
502 You may distribute this code under the same terms as Perl itself.