AUTHORS mass update; mst doesn't have to take credit for -everything- :)
[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
90d7422f 9{
10 package # Hide from PAUSE
11 DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION;
12 use base 'DBIx::Class::Exception';
13}
14
15use DBIx::Class::Carp;
9345b14c 16use DBIx::Class::Storage::BlockRunner;
90d7422f 17use Scalar::Util qw/blessed weaken/;
1bc193ac 18use DBIx::Class::Storage::TxnScopeGuard;
f43ea814 19use Try::Tiny;
fd323bf1 20use namespace::clean;
046ad905 21
90d7422f 22__PACKAGE__->mk_group_accessors(simple => qw/debug schema transaction_depth auto_savepoint savepoints/);
23__PACKAGE__->mk_group_accessors(component_class => 'cursor_class');
e4eb8ee1 24
25__PACKAGE__->cursor_class('DBIx::Class::Cursor');
26
27sub cursor { shift->cursor_class(@_); }
046ad905 28
046ad905 29=head1 NAME
30
31DBIx::Class::Storage - Generic Storage Handler
32
33=head1 DESCRIPTION
34
35A base implementation of common Storage methods. For specific
36information about L<DBI>-based storage, see L<DBIx::Class::Storage::DBI>.
37
38=head1 METHODS
39
40=head2 new
41
42Arguments: $schema
43
44Instantiates the Storage object.
45
46=cut
47
48sub new {
49 my ($self, $schema) = @_;
50
51 $self = ref $self if ref $self;
52
90d7422f 53 my $new = bless( {
54 transaction_depth => 0,
55 savepoints => [],
56 }, $self);
046ad905 57
58 $new->set_schema($schema);
4d753fb8 59 $new->debug(1)
60 if $ENV{DBIX_CLASS_STORAGE_DBI_DEBUG} || $ENV{DBIC_TRACE};
046ad905 61
62 $new;
63}
64
65=head2 set_schema
66
67Used to reset the schema class or object which owns this
68storage object, such as during L<DBIx::Class::Schema/clone>.
69
70=cut
71
72sub set_schema {
73 my ($self, $schema) = @_;
74 $self->schema($schema);
6298a324 75 weaken $self->{schema} if ref $self->{schema};
046ad905 76}
77
78=head2 connected
79
80Returns true if we have an open storage connection, false
81if it is not (yet) open.
82
83=cut
84
a62cf8d4 85sub connected { die "Virtual method!" }
046ad905 86
87=head2 disconnect
88
89Closes any open storage connection unconditionally.
90
91=cut
92
93sub disconnect { die "Virtual method!" }
94
95=head2 ensure_connected
96
97Initiate a connection to the storage if one isn't already open.
98
99=cut
100
a62cf8d4 101sub ensure_connected { die "Virtual method!" }
046ad905 102
103=head2 throw_exception
104
105Throws an exception - croaks.
106
107=cut
108
109sub throw_exception {
110 my $self = shift;
111
2a2a7b23 112 if (ref $self and $self->schema) {
1a58752c 113 $self->schema->throw_exception(@_);
114 }
115 else {
116 DBIx::Class::Exception->throw(@_);
117 }
046ad905 118}
a62cf8d4 119
4012acd8 120=head2 txn_do
a62cf8d4 121
4012acd8 122=over 4
a62cf8d4 123
4012acd8 124=item Arguments: C<$coderef>, @coderef_args?
a62cf8d4 125
4012acd8 126=item Return Value: The return value of $coderef
127
128=back
129
130Executes C<$coderef> with (optional) arguments C<@coderef_args> atomically,
131returning its result (if any). If an exception is caught, a rollback is issued
132and the exception is rethrown. If the rollback fails, (i.e. throws an
133exception) an exception is thrown that includes a "Rollback failed" message.
134
135For example,
136
137 my $author_rs = $schema->resultset('Author')->find(1);
138 my @titles = qw/Night Day It/;
139
140 my $coderef = sub {
141 # If any one of these fails, the entire transaction fails
142 $author_rs->create_related('books', {
143 title => $_
144 }) foreach (@titles);
145
146 return $author->books;
147 };
148
149 my $rs;
20674fcd 150 try {
4012acd8 151 $rs = $schema->txn_do($coderef);
20674fcd 152 } catch {
6b89ee0b 153 my $error = shift;
20674fcd 154 # Transaction failed
90d7422f 155 die "something terrible has happened!"
6b89ee0b 156 if ($error =~ /Rollback failed/); # Rollback failed
4012acd8 157
158 deal_with_failed_transaction();
20674fcd 159 };
4012acd8 160
161In a nested transaction (calling txn_do() from within a txn_do() coderef) only
162the outermost transaction will issue a L</txn_commit>, and txn_do() can be
163called in void, scalar and list context and it will behave as expected.
164
05075aee 165Please note that all of the code in your coderef, including non-DBIx::Class
166code, is part of a transaction. This transaction may fail out halfway, or
167it may get partially double-executed (in the case that our DB connection
168failed halfway through the transaction, in which case we reconnect and
169restart the txn). Therefore it is best that any side-effects in your coderef
170are idempotent (that is, can be re-executed multiple times and get the
171same result), and that you check up on your side-effects in the case of
172transaction failure.
6500d50f 173
4012acd8 174=cut
175
176sub txn_do {
38ed54cd 177 my $self = shift;
178 my $coderef = shift;
4012acd8 179
9345b14c 180 DBIx::Class::Storage::BlockRunner->new(
181 storage => $self,
182 run_code => $coderef,
183 run_args => \@_, # take a ref instead of a copy, to preserve coderef @_ aliasing semantics
184 wrap_txn => 1,
185 retry_handler => sub { ! ( $_[0]->retried_count or $_[0]->storage->connected ) },
186 )->run;
a62cf8d4 187}
188
046ad905 189=head2 txn_begin
190
191Starts a transaction.
192
193See the preferred L</txn_do> method, which allows for
194an entire code block to be executed transactionally.
195
196=cut
197
90d7422f 198sub txn_begin {
199 my $self = shift;
200
201 if($self->transaction_depth == 0) {
202 $self->debugobj->txn_begin()
203 if $self->debug;
204 $self->_exec_txn_begin;
205 }
206 elsif ($self->auto_savepoint) {
207 $self->svp_begin;
208 }
209 $self->{transaction_depth}++;
210
211}
046ad905 212
213=head2 txn_commit
214
215Issues a commit of the current transaction.
216
be01f1be 217It does I<not> perform an actual storage commit unless there's a DBIx::Class
218transaction currently in effect (i.e. you called L</txn_begin>).
219
046ad905 220=cut
221
90d7422f 222sub txn_commit {
223 my $self = shift;
224
225 if ($self->transaction_depth == 1) {
226 $self->debugobj->txn_commit() if $self->debug;
227 $self->_exec_txn_commit;
228 $self->{transaction_depth}--;
229 }
230 elsif($self->transaction_depth > 1) {
231 $self->{transaction_depth}--;
232 $self->svp_release if $self->auto_savepoint;
233 }
234 else {
235 $self->throw_exception( 'Refusing to commit without a started transaction' );
236 }
237}
046ad905 238
239=head2 txn_rollback
240
241Issues a rollback of the current transaction. A nested rollback will
242throw a L<DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION> exception,
243which allows the rollback to propagate to the outermost transaction.
244
245=cut
246
90d7422f 247sub txn_rollback {
248 my $self = shift;
249
250 if ($self->transaction_depth == 1) {
251 $self->debugobj->txn_rollback() if $self->debug;
252 $self->_exec_txn_rollback;
253 $self->{transaction_depth}--;
254 }
255 elsif ($self->transaction_depth > 1) {
256 $self->{transaction_depth}--;
257
258 if ($self->auto_savepoint) {
259 $self->svp_rollback;
260 $self->svp_release;
261 }
262 else {
263 DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION->throw(
264 "A txn_rollback in nested transaction is ineffective! (depth $self->{transaction_depth})"
265 );
266 }
267 }
268 else {
269 $self->throw_exception( 'Refusing to roll back without a started transaction' );
270 }
271}
046ad905 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
90d7422f 282sub svp_begin {
283 my ($self, $name) = @_;
284
285 $self->throw_exception ("You can't use savepoints outside a transaction")
286 unless $self->transaction_depth;
287
288 my $exec = $self->can('_exec_svp_begin')
289 or $self->throw_exception ("Your Storage implementation doesn't support savepoints");
290
291 $name = $self->_svp_generate_name
292 unless defined $name;
293
294 push @{ $self->{savepoints} }, $name;
295
296 $self->debugobj->svp_begin($name) if $self->debug;
297
298 $exec->($self, $name);
299}
300
301sub _svp_generate_name {
302 my ($self) = @_;
303 return 'savepoint_'.scalar(@{ $self->{'savepoints'} });
304}
305
adb3554a 306
307=head2 svp_release
308
360dc8a5 309Arguments: $savepoint_name?
adb3554a 310
360dc8a5 311Release the savepoint provided as argument. If none is provided,
312release the savepoint created most recently. This will implicitly
313release all savepoints created after the one explicitly released as well.
adb3554a 314
315=cut
316
90d7422f 317sub svp_release {
318 my ($self, $name) = @_;
319
320 $self->throw_exception ("You can't use savepoints outside a transaction")
321 unless $self->transaction_depth;
322
323 my $exec = $self->can('_exec_svp_release')
324 or $self->throw_exception ("Your Storage implementation doesn't support savepoints");
325
326 if (defined $name) {
327 my @stack = @{ $self->savepoints };
328 my $svp;
329
330 do { $svp = pop @stack } until $svp eq $name;
331
332 $self->throw_exception ("Savepoint '$name' does not exist")
333 unless $svp;
334
335 $self->savepoints(\@stack); # put back what's left
336 }
337 else {
338 $name = pop @{ $self->savepoints }
339 or $self->throw_exception('No savepoints to release');;
340 }
341
342 $self->debugobj->svp_release($name) if $self->debug;
343
344 $exec->($self, $name);
345}
adb3554a 346
347=head2 svp_rollback
348
360dc8a5 349Arguments: $savepoint_name?
adb3554a 350
360dc8a5 351Rollback to the savepoint provided as argument. If none is provided,
352rollback to the savepoint created most recently. This will implicitly
353release all savepoints created after the savepoint we rollback to.
adb3554a 354
355=cut
356
90d7422f 357sub svp_rollback {
358 my ($self, $name) = @_;
359
360 $self->throw_exception ("You can't use savepoints outside a transaction")
361 unless $self->transaction_depth;
362
363 my $exec = $self->can('_exec_svp_rollback')
364 or $self->throw_exception ("Your Storage implementation doesn't support savepoints");
365
366 if (defined $name) {
367 my @stack = @{ $self->savepoints };
368 my $svp;
369
370 # a rollback doesn't remove the named savepoint,
371 # only everything after it
372 while (@stack and $stack[-1] ne $name) {
373 pop @stack
374 };
375
376 $self->throw_exception ("Savepoint '$name' does not exist")
377 unless @stack;
378
379 $self->savepoints(\@stack); # put back what's left
380 }
381 else {
382 $name = $self->savepoints->[-1]
383 or $self->throw_exception('No savepoints to rollback');;
384 }
385
386 $self->debugobj->svp_rollback($name) if $self->debug;
387
388 $exec->($self, $name);
389}
adb3554a 390
11544e1d 391=head2 txn_scope_guard
3b7f3eac 392
11544e1d 393An alternative way of transaction handling based on
394L<DBIx::Class::Storage::TxnScopeGuard>:
1bc193ac 395
11544e1d 396 my $txn_guard = $storage->txn_scope_guard;
89028f42 397
11544e1d 398 $row->col1("val1");
399 $row->update;
89028f42 400
11544e1d 401 $txn_guard->commit;
89028f42 402
11544e1d 403If an exception occurs, or the guard object otherwise leaves the scope
404before C<< $txn_guard->commit >> is called, the transaction will be rolled
405back by an explicit L</txn_rollback> call. In essence this is akin to
406using a L</txn_begin>/L</txn_commit> pair, without having to worry
407about calling L</txn_rollback> at the right places. Note that since there
408is no defined code closure, there will be no retries and other magic upon
409database disconnection. If you need such functionality see L</txn_do>.
1bc193ac 410
411=cut
412
413sub txn_scope_guard {
414 return DBIx::Class::Storage::TxnScopeGuard->new($_[0]);
415}
416
046ad905 417=head2 sql_maker
418
419Returns a C<sql_maker> object - normally an object of class
d5dedbd6 420C<DBIx::Class::SQLMaker>.
046ad905 421
422=cut
423
424sub sql_maker { die "Virtual method!" }
425
426=head2 debug
427
f92a9d79 428Causes trace information to be emitted on the L</debugobj> object.
429(or C<STDERR> if L</debugobj> has not specifically been set).
046ad905 430
431This is the equivalent to setting L</DBIC_TRACE> in your
432shell environment.
433
434=head2 debugfh
435
436Set or retrieve the filehandle used for trace/debug output. This should be
48580715 437an IO::Handle compatible object (only the C<print> method is used. Initially
046ad905 438set to be STDERR - although see information on the
439L<DBIC_TRACE> environment variable.
440
441=cut
442
443sub debugfh {
444 my $self = shift;
445
446 if ($self->debugobj->can('debugfh')) {
447 return $self->debugobj->debugfh(@_);
448 }
449}
450
451=head2 debugobj
452
453Sets or retrieves the object used for metric collection. Defaults to an instance
454of L<DBIx::Class::Storage::Statistics> that is compatible with the original
455method of using a coderef as a callback. See the aforementioned Statistics
456class for more information.
457
4d753fb8 458=cut
459
460sub debugobj {
461 my $self = shift;
462
463 if (@_) {
464 return $self->{debugobj} = $_[0];
465 }
466
467 $self->{debugobj} ||= do {
468 if (my $profile = $ENV{DBIC_TRACE_PROFILE}) {
469 require DBIx::Class::Storage::Debug::PrettyPrint;
470 if ($profile =~ /^\.?\//) {
471 require Config::Any;
472
473 my $cfg = try {
474 Config::Any->load_files({ files => [$profile], use_ext => 1 });
475 } catch {
476 # sanitize the error message a bit
477 $_ =~ s/at \s+ .+ Storage\.pm \s line \s \d+ $//x;
478 $self->throw_exception("Failure processing \$ENV{DBIC_TRACE_PROFILE}: $_");
479 };
480
481 DBIx::Class::Storage::Debug::PrettyPrint->new(values %{$cfg->[0]});
482 }
483 else {
484 DBIx::Class::Storage::Debug::PrettyPrint->new({ profile => $profile });
485 }
486 }
487 else {
488 require DBIx::Class::Storage::Statistics;
489 DBIx::Class::Storage::Statistics->new
490 }
491 };
492}
493
046ad905 494=head2 debugcb
495
496Sets a callback to be executed each time a statement is run; takes a sub
497reference. Callback is executed as $sub->($op, $info) where $op is
498SELECT/INSERT/UPDATE/DELETE and $info is what would normally be printed.
499
f92a9d79 500See L</debugobj> for a better way.
046ad905 501
502=cut
503
504sub debugcb {
505 my $self = shift;
506
507 if ($self->debugobj->can('callback')) {
508 return $self->debugobj->callback(@_);
509 }
510}
511
e4eb8ee1 512=head2 cursor_class
046ad905 513
514The cursor class for this Storage object.
515
516=cut
517
046ad905 518=head2 deploy
519
520Deploy the tables to storage (CREATE TABLE and friends in a SQL-based
521Storage class). This would normally be called through
522L<DBIx::Class::Schema/deploy>.
523
524=cut
525
526sub deploy { die "Virtual method!" }
527
a3eaff0e 528=head2 connect_info
529
530The arguments of C<connect_info> are always a single array reference,
531and are Storage-handler specific.
532
533This is normally accessed via L<DBIx::Class::Schema/connection>, which
534encapsulates its argument list in an arrayref before calling
535C<connect_info> here.
536
537=cut
538
046ad905 539sub connect_info { die "Virtual method!" }
a3eaff0e 540
541=head2 select
542
543Handle a select statement.
544
545=cut
546
547sub select { die "Virtual method!" }
548
549=head2 insert
550
551Handle an insert statement.
552
553=cut
554
046ad905 555sub insert { die "Virtual method!" }
a3eaff0e 556
557=head2 update
558
559Handle an update statement.
560
561=cut
562
046ad905 563sub update { die "Virtual method!" }
a3eaff0e 564
565=head2 delete
566
567Handle a delete statement.
568
569=cut
570
046ad905 571sub delete { die "Virtual method!" }
a3eaff0e 572
573=head2 select_single
574
575Performs a select, fetch and return of data - handles a single row
576only.
577
578=cut
579
046ad905 580sub select_single { die "Virtual method!" }
a3eaff0e 581
582=head2 columns_info_for
583
c22c7625 584Returns metadata for the given source's columns. This
585is *deprecated*, and will be removed before 1.0. You should
586be specifying the metadata yourself if you need it.
a3eaff0e 587
588=cut
589
046ad905 590sub columns_info_for { die "Virtual method!" }
591
592=head1 ENVIRONMENT VARIABLES
593
594=head2 DBIC_TRACE
595
596If C<DBIC_TRACE> is set then trace information
f92a9d79 597is produced (as when the L</debug> method is set).
046ad905 598
599If the value is of the form C<1=/path/name> then the trace output is
600written to the file C</path/name>.
601
602This environment variable is checked when the storage object is first
fd323bf1 603created (when you call connect on your schema). So, run-time changes
604to this environment variable will not take effect unless you also
046ad905 605re-connect on your schema.
606
b6cd6478 607=head2 DBIC_TRACE_PROFILE
608
2514a73f 609If C<DBIC_TRACE_PROFILE> is set, L<DBIx::Class::Storage::Debug::PrettyPrint>
b6cd6478 610will be used to format the output from C<DBIC_TRACE>. The value it
611is set to is the C<profile> that it will be used. If the value is a
612filename the file is read with L<Config::Any> and the results are
613used as the configuration for tracing. See L<SQL::Abstract::Tree/new>
614for what that structure should look like.
615
616
046ad905 617=head2 DBIX_CLASS_STORAGE_DBI_DEBUG
618
619Old name for DBIC_TRACE
620
ace385bd 621=head1 SEE ALSO
622
2f0790c4 623L<DBIx::Class::Storage::DBI> - reference storage implementation using
624SQL::Abstract and DBI.
ace385bd 625
0c11ad0e 626=head1 AUTHOR AND CONTRIBUTORS
046ad905 627
0c11ad0e 628See L<AUTHOR|DBIx::Class/AUTHOR> and L<CONTRIBUTORS|DBIx::Class/CONTRIBUTORS> in DBIx::Class
046ad905 629
630=head1 LICENSE
631
632You may distribute this code under the same terms as Perl itself.
633
634=cut
635
a62cf8d4 6361;