Removed wording from txn_do that implies the coderef could be executed more than...
[dbsrgits/DBIx-Class-Historic.git] / lib / DBIx / Class / Storage.pm
CommitLineData
4012acd8 1package DBIx::Class::Storage;
a62cf8d4 2
3use strict;
4use warnings;
5
046ad905 6use base qw/DBIx::Class/;
7
8use Scalar::Util qw/weaken/;
aaba9524 9use Carp::Clan qw/^DBIx::Class/;
942cd0c1 10use IO::File;
1bc193ac 11use DBIx::Class::Storage::TxnScopeGuard;
046ad905 12
046ad905 13__PACKAGE__->mk_group_accessors('simple' => qw/debug debugobj schema/);
e4eb8ee1 14__PACKAGE__->mk_group_accessors('inherited' => 'cursor_class');
15
16__PACKAGE__->cursor_class('DBIx::Class::Cursor');
17
18sub cursor { shift->cursor_class(@_); }
046ad905 19
4012acd8 20package # Hide from PAUSE
21 DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION;
22
23use overload '"' => sub {
24 'DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION'
25};
26
27sub new {
28 my $class = shift;
29 my $self = {};
30 return bless $self, $class;
31}
32
33package DBIx::Class::Storage;
34
046ad905 35=head1 NAME
36
37DBIx::Class::Storage - Generic Storage Handler
38
39=head1 DESCRIPTION
40
41A base implementation of common Storage methods. For specific
42information about L<DBI>-based storage, see L<DBIx::Class::Storage::DBI>.
43
44=head1 METHODS
45
46=head2 new
47
48Arguments: $schema
49
50Instantiates the Storage object.
51
52=cut
53
54sub 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
70f39278 65 #my $fh;
046ad905 66
67 my $debug_env = $ENV{DBIX_CLASS_STORAGE_DBI_DEBUG}
68 || $ENV{DBIC_TRACE};
69
046ad905 70 $new->debug(1) if $debug_env;
71
72 $new;
73}
74
75=head2 set_schema
76
77Used to reset the schema class or object which owns this
78storage object, such as during L<DBIx::Class::Schema/clone>.
79
80=cut
81
82sub set_schema {
83 my ($self, $schema) = @_;
84 $self->schema($schema);
85 weaken($self->{schema}) if ref $self->{schema};
86}
87
88=head2 connected
89
90Returns true if we have an open storage connection, false
91if it is not (yet) open.
92
93=cut
94
a62cf8d4 95sub connected { die "Virtual method!" }
046ad905 96
97=head2 disconnect
98
99Closes any open storage connection unconditionally.
100
101=cut
102
103sub disconnect { die "Virtual method!" }
104
105=head2 ensure_connected
106
107Initiate a connection to the storage if one isn't already open.
108
109=cut
110
a62cf8d4 111sub ensure_connected { die "Virtual method!" }
046ad905 112
113=head2 throw_exception
114
115Throws an exception - croaks.
116
117=cut
118
119sub throw_exception {
120 my $self = shift;
121
122 $self->schema->throw_exception(@_) if $self->schema;
123 croak @_;
124}
a62cf8d4 125
4012acd8 126=head2 txn_do
a62cf8d4 127
4012acd8 128=over 4
a62cf8d4 129
4012acd8 130=item Arguments: C<$coderef>, @coderef_args?
a62cf8d4 131
4012acd8 132=item Return Value: The return value of $coderef
133
134=back
135
136Executes C<$coderef> with (optional) arguments C<@coderef_args> atomically,
137returning its result (if any). If an exception is caught, a rollback is issued
138and the exception is rethrown. If the rollback fails, (i.e. throws an
139exception) an exception is thrown that includes a "Rollback failed" message.
140
141For 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
167In a nested transaction (calling txn_do() from within a txn_do() coderef) only
168the outermost transaction will issue a L</txn_commit>, and txn_do() can be
169called in void, scalar and list context and it will behave as expected.
170
acf7eb85 171Unlike L</DBIx::Class::Storage/dbh_do>, the coderef will I<not> be
172automatically retried on error.
6500d50f 173
4012acd8 174=cut
175
176sub 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;
a62cf8d4 228}
229
046ad905 230=head2 txn_begin
231
232Starts a transaction.
233
234See the preferred L</txn_do> method, which allows for
235an entire code block to be executed transactionally.
236
237=cut
238
239sub txn_begin { die "Virtual method!" }
240
241=head2 txn_commit
242
243Issues a commit of the current transaction.
244
245=cut
246
247sub txn_commit { die "Virtual method!" }
248
249=head2 txn_rollback
250
251Issues a rollback of the current transaction. A nested rollback will
252throw a L<DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION> exception,
253which allows the rollback to propagate to the outermost transaction.
254
255=cut
256
257sub txn_rollback { die "Virtual method!" }
258
adb3554a 259=head2 svp_begin
260
360dc8a5 261Arguments: $savepoint_name?
adb3554a 262
360dc8a5 263Created a new savepoint using the name provided as argument. If no name
264is provided, a random name will be used.
adb3554a 265
266=cut
267
268sub svp_begin { die "Virtual method!" }
269
270=head2 svp_release
271
360dc8a5 272Arguments: $savepoint_name?
adb3554a 273
360dc8a5 274Release the savepoint provided as argument. If none is provided,
275release the savepoint created most recently. This will implicitly
276release all savepoints created after the one explicitly released as well.
adb3554a 277
278=cut
279
280sub svp_release { die "Virtual method!" }
281
282=head2 svp_rollback
283
360dc8a5 284Arguments: $savepoint_name?
adb3554a 285
360dc8a5 286Rollback to the savepoint provided as argument. If none is provided,
287rollback to the savepoint created most recently. This will implicitly
288release all savepoints created after the savepoint we rollback to.
adb3554a 289
290=cut
291
292sub svp_rollback { die "Virtual method!" }
293
dd018f09 294=for comment
3b7f3eac 295
6936e902 296=head2 txn_scope_guard
1bc193ac 297
6936e902 298An alternative way of transaction handling based on
299L<DBIx::Class::Storage::TxnScopeGuard>:
89028f42 300
6936e902 301 my $txn_guard = $storage->txn_scope_guard;
89028f42 302
303 $row->col1("val1");
304 $row->update;
305
6936e902 306 $txn_guard->commit;
89028f42 307
6936e902 308If an exception occurs, or the guard object otherwise leaves the scope
309before C<< $txn_guard->commit >> is called, the transaction will be rolled
310back by an explicit L</txn_rollback> call. In essence this is akin to
311using a L</txn_begin>/L</txn_commit> pair, without having to worry
312about calling L</txn_rollback> at the right places. Note that since there
313is no defined code closure, there will be no retries and other magic upon
314database disconnection. If you need such functionality see L</txn_do>.
1bc193ac 315
316=cut
317
318sub txn_scope_guard {
319 return DBIx::Class::Storage::TxnScopeGuard->new($_[0]);
320}
321
046ad905 322=head2 sql_maker
323
324Returns a C<sql_maker> object - normally an object of class
6f4ddea1 325C<DBIx::Class::SQLAHacks>.
046ad905 326
327=cut
328
329sub sql_maker { die "Virtual method!" }
330
331=head2 debug
332
333Causes trace information to be emitted on the C<debugobj> object.
334(or C<STDERR> if C<debugobj> has not specifically been set).
335
336This is the equivalent to setting L</DBIC_TRACE> in your
337shell environment.
338
339=head2 debugfh
340
341Set or retrieve the filehandle used for trace/debug output. This should be
342an IO::Handle compatible ojbect (only the C<print> method is used. Initially
343set to be STDERR - although see information on the
344L<DBIC_TRACE> environment variable.
345
346=cut
347
348sub debugfh {
349 my $self = shift;
350
351 if ($self->debugobj->can('debugfh')) {
352 return $self->debugobj->debugfh(@_);
353 }
354}
355
356=head2 debugobj
357
358Sets or retrieves the object used for metric collection. Defaults to an instance
359of L<DBIx::Class::Storage::Statistics> that is compatible with the original
360method of using a coderef as a callback. See the aforementioned Statistics
361class for more information.
362
363=head2 debugcb
364
365Sets a callback to be executed each time a statement is run; takes a sub
366reference. Callback is executed as $sub->($op, $info) where $op is
367SELECT/INSERT/UPDATE/DELETE and $info is what would normally be printed.
368
369See L<debugobj> for a better way.
370
371=cut
372
373sub debugcb {
374 my $self = shift;
375
376 if ($self->debugobj->can('callback')) {
377 return $self->debugobj->callback(@_);
378 }
379}
380
e4eb8ee1 381=head2 cursor_class
046ad905 382
383The cursor class for this Storage object.
384
385=cut
386
046ad905 387=head2 deploy
388
389Deploy the tables to storage (CREATE TABLE and friends in a SQL-based
390Storage class). This would normally be called through
391L<DBIx::Class::Schema/deploy>.
392
393=cut
394
395sub deploy { die "Virtual method!" }
396
a3eaff0e 397=head2 connect_info
398
399The arguments of C<connect_info> are always a single array reference,
400and are Storage-handler specific.
401
402This is normally accessed via L<DBIx::Class::Schema/connection>, which
403encapsulates its argument list in an arrayref before calling
404C<connect_info> here.
405
406=cut
407
046ad905 408sub connect_info { die "Virtual method!" }
a3eaff0e 409
410=head2 select
411
412Handle a select statement.
413
414=cut
415
416sub select { die "Virtual method!" }
417
418=head2 insert
419
420Handle an insert statement.
421
422=cut
423
046ad905 424sub insert { die "Virtual method!" }
a3eaff0e 425
426=head2 update
427
428Handle an update statement.
429
430=cut
431
046ad905 432sub update { die "Virtual method!" }
a3eaff0e 433
434=head2 delete
435
436Handle a delete statement.
437
438=cut
439
046ad905 440sub delete { die "Virtual method!" }
a3eaff0e 441
442=head2 select_single
443
444Performs a select, fetch and return of data - handles a single row
445only.
446
447=cut
448
046ad905 449sub select_single { die "Virtual method!" }
a3eaff0e 450
451=head2 columns_info_for
452
c22c7625 453Returns metadata for the given source's columns. This
454is *deprecated*, and will be removed before 1.0. You should
455be specifying the metadata yourself if you need it.
a3eaff0e 456
457=cut
458
046ad905 459sub columns_info_for { die "Virtual method!" }
460
461=head1 ENVIRONMENT VARIABLES
462
463=head2 DBIC_TRACE
464
465If C<DBIC_TRACE> is set then trace information
466is produced (as when the L<debug> method is set).
467
468If the value is of the form C<1=/path/name> then the trace output is
469written to the file C</path/name>.
470
471This environment variable is checked when the storage object is first
472created (when you call connect on your schema). So, run-time changes
473to this environment variable will not take effect unless you also
474re-connect on your schema.
475
476=head2 DBIX_CLASS_STORAGE_DBI_DEBUG
477
478Old name for DBIC_TRACE
479
ace385bd 480=head1 SEE ALSO
481
2f0790c4 482L<DBIx::Class::Storage::DBI> - reference storage implementation using
483SQL::Abstract and DBI.
ace385bd 484
046ad905 485=head1 AUTHORS
486
487Matt S. Trout <mst@shadowcatsystems.co.uk>
488
489Andy Grundman <andy@hybridized.org>
490
491=head1 LICENSE
492
493You may distribute this code under the same terms as Perl itself.
494
495=cut
496
a62cf8d4 4971;