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