Added doc note that txn_commit does not perform an actual storage commit unless
[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/;
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
be01f1be 245It does I<not> perform an actual storage commit unless there's a DBIx::Class
246transaction currently in effect (i.e. you called L</txn_begin>).
247
046ad905 248=cut
249
250sub txn_commit { die "Virtual method!" }
251
252=head2 txn_rollback
253
254Issues a rollback of the current transaction. A nested rollback will
255throw a L<DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION> exception,
256which allows the rollback to propagate to the outermost transaction.
257
258=cut
259
260sub txn_rollback { die "Virtual method!" }
261
adb3554a 262=head2 svp_begin
263
360dc8a5 264Arguments: $savepoint_name?
adb3554a 265
360dc8a5 266Created a new savepoint using the name provided as argument. If no name
267is provided, a random name will be used.
adb3554a 268
269=cut
270
271sub svp_begin { die "Virtual method!" }
272
273=head2 svp_release
274
360dc8a5 275Arguments: $savepoint_name?
adb3554a 276
360dc8a5 277Release the savepoint provided as argument. If none is provided,
278release the savepoint created most recently. This will implicitly
279release all savepoints created after the one explicitly released as well.
adb3554a 280
281=cut
282
283sub svp_release { die "Virtual method!" }
284
285=head2 svp_rollback
286
360dc8a5 287Arguments: $savepoint_name?
adb3554a 288
360dc8a5 289Rollback to the savepoint provided as argument. If none is provided,
290rollback to the savepoint created most recently. This will implicitly
291release all savepoints created after the savepoint we rollback to.
adb3554a 292
293=cut
294
295sub svp_rollback { die "Virtual method!" }
296
dd018f09 297=for comment
3b7f3eac 298
6936e902 299=head2 txn_scope_guard
1bc193ac 300
6936e902 301An alternative way of transaction handling based on
302L<DBIx::Class::Storage::TxnScopeGuard>:
89028f42 303
6936e902 304 my $txn_guard = $storage->txn_scope_guard;
89028f42 305
306 $row->col1("val1");
307 $row->update;
308
6936e902 309 $txn_guard->commit;
89028f42 310
6936e902 311If an exception occurs, or the guard object otherwise leaves the scope
312before C<< $txn_guard->commit >> is called, the transaction will be rolled
313back by an explicit L</txn_rollback> call. In essence this is akin to
314using a L</txn_begin>/L</txn_commit> pair, without having to worry
315about calling L</txn_rollback> at the right places. Note that since there
316is no defined code closure, there will be no retries and other magic upon
317database disconnection. If you need such functionality see L</txn_do>.
1bc193ac 318
319=cut
320
321sub txn_scope_guard {
322 return DBIx::Class::Storage::TxnScopeGuard->new($_[0]);
323}
324
046ad905 325=head2 sql_maker
326
327Returns a C<sql_maker> object - normally an object of class
6f4ddea1 328C<DBIx::Class::SQLAHacks>.
046ad905 329
330=cut
331
332sub sql_maker { die "Virtual method!" }
333
334=head2 debug
335
336Causes trace information to be emitted on the C<debugobj> object.
337(or C<STDERR> if C<debugobj> has not specifically been set).
338
339This is the equivalent to setting L</DBIC_TRACE> in your
340shell environment.
341
342=head2 debugfh
343
344Set or retrieve the filehandle used for trace/debug output. This should be
345an IO::Handle compatible ojbect (only the C<print> method is used. Initially
346set to be STDERR - although see information on the
347L<DBIC_TRACE> environment variable.
348
349=cut
350
351sub debugfh {
352 my $self = shift;
353
354 if ($self->debugobj->can('debugfh')) {
355 return $self->debugobj->debugfh(@_);
356 }
357}
358
359=head2 debugobj
360
361Sets or retrieves the object used for metric collection. Defaults to an instance
362of L<DBIx::Class::Storage::Statistics> that is compatible with the original
363method of using a coderef as a callback. See the aforementioned Statistics
364class for more information.
365
366=head2 debugcb
367
368Sets a callback to be executed each time a statement is run; takes a sub
369reference. Callback is executed as $sub->($op, $info) where $op is
370SELECT/INSERT/UPDATE/DELETE and $info is what would normally be printed.
371
372See L<debugobj> for a better way.
373
374=cut
375
376sub debugcb {
377 my $self = shift;
378
379 if ($self->debugobj->can('callback')) {
380 return $self->debugobj->callback(@_);
381 }
382}
383
e4eb8ee1 384=head2 cursor_class
046ad905 385
386The cursor class for this Storage object.
387
388=cut
389
046ad905 390=head2 deploy
391
392Deploy the tables to storage (CREATE TABLE and friends in a SQL-based
393Storage class). This would normally be called through
394L<DBIx::Class::Schema/deploy>.
395
396=cut
397
398sub deploy { die "Virtual method!" }
399
a3eaff0e 400=head2 connect_info
401
402The arguments of C<connect_info> are always a single array reference,
403and are Storage-handler specific.
404
405This is normally accessed via L<DBIx::Class::Schema/connection>, which
406encapsulates its argument list in an arrayref before calling
407C<connect_info> here.
408
409=cut
410
046ad905 411sub connect_info { die "Virtual method!" }
a3eaff0e 412
413=head2 select
414
415Handle a select statement.
416
417=cut
418
419sub select { die "Virtual method!" }
420
421=head2 insert
422
423Handle an insert statement.
424
425=cut
426
046ad905 427sub insert { die "Virtual method!" }
a3eaff0e 428
429=head2 update
430
431Handle an update statement.
432
433=cut
434
046ad905 435sub update { die "Virtual method!" }
a3eaff0e 436
437=head2 delete
438
439Handle a delete statement.
440
441=cut
442
046ad905 443sub delete { die "Virtual method!" }
a3eaff0e 444
445=head2 select_single
446
447Performs a select, fetch and return of data - handles a single row
448only.
449
450=cut
451
046ad905 452sub select_single { die "Virtual method!" }
a3eaff0e 453
454=head2 columns_info_for
455
c22c7625 456Returns metadata for the given source's columns. This
457is *deprecated*, and will be removed before 1.0. You should
458be specifying the metadata yourself if you need it.
a3eaff0e 459
460=cut
461
046ad905 462sub columns_info_for { die "Virtual method!" }
463
464=head1 ENVIRONMENT VARIABLES
465
466=head2 DBIC_TRACE
467
468If C<DBIC_TRACE> is set then trace information
469is produced (as when the L<debug> method is set).
470
471If the value is of the form C<1=/path/name> then the trace output is
472written to the file C</path/name>.
473
474This environment variable is checked when the storage object is first
475created (when you call connect on your schema). So, run-time changes
476to this environment variable will not take effect unless you also
477re-connect on your schema.
478
479=head2 DBIX_CLASS_STORAGE_DBI_DEBUG
480
481Old name for DBIC_TRACE
482
ace385bd 483=head1 SEE ALSO
484
2f0790c4 485L<DBIx::Class::Storage::DBI> - reference storage implementation using
486SQL::Abstract and DBI.
ace385bd 487
046ad905 488=head1 AUTHORS
489
490Matt S. Trout <mst@shadowcatsystems.co.uk>
491
492Andy Grundman <andy@hybridized.org>
493
494=head1 LICENSE
495
496You may distribute this code under the same terms as Perl itself.
497
498=cut
499
a62cf8d4 5001;