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