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