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