1 package DBIx::Class::Storage::DBI;
2 # -*- mode: cperl; cperl-indent-level: 2 -*-
4 use base 'DBIx::Class::Storage';
8 use Carp::Clan qw/^DBIx::Class/;
10 use SQL::Abstract::Limit;
11 use DBIx::Class::Storage::DBI::Cursor;
12 use DBIx::Class::Storage::Statistics;
13 use Scalar::Util qw/blessed weaken/;
15 __PACKAGE__->mk_group_accessors('simple' =>
16 qw/_connect_info _dbi_connect_info _dbh _sql_maker _sql_maker_opts
17 _conn_pid _conn_tid transaction_depth _dbh_autocommit savepoints/
20 # the values for these accessors are picked out (and deleted) from
21 # the attribute hashref passed to connect_info
22 my @storage_options = qw/
23 on_connect_do on_disconnect_do disable_sth_caching unsafe auto_savepoint
25 __PACKAGE__->mk_group_accessors('simple' => @storage_options);
28 # default cursor class, overridable in connect_info attributes
29 __PACKAGE__->cursor_class('DBIx::Class::Storage::DBI::Cursor');
31 __PACKAGE__->mk_group_accessors('inherited' => qw/sql_maker_class/);
32 __PACKAGE__->sql_maker_class('DBIC::SQL::Abstract');
36 package # Hide from PAUSE
37 DBIC::SQL::Abstract; # Would merge upstream, but nate doesn't reply :(
39 use base qw/SQL::Abstract::Limit/;
41 # This prevents the caching of $dbh in S::A::L, I believe
43 my $self = shift->SUPER::new(@_);
45 # If limit_dialect is a ref (like a $dbh), go ahead and replace
46 # it with what it resolves to:
47 $self->{limit_dialect} = $self->_find_syntax($self->{limit_dialect})
48 if ref $self->{limit_dialect};
53 # DB2 is the only remaining DB using this. Even though we are not sure if
54 # RowNumberOver is still needed here (should be part of SQLA) leave the
57 my ($self, $sql, $order, $rows, $offset ) = @_;
60 my $last = $rows + $offset;
61 my ( $order_by ) = $self->_order_by( $order );
66 SELECT Q1.*, ROW_NUMBER() OVER( ) AS ROW_NUM FROM (
71 WHERE ROW_NUM BETWEEN $offset AND $last
79 # While we're at it, this should make LIMIT queries more efficient,
80 # without digging into things too deeply
81 use Scalar::Util 'blessed';
83 my ($self, $syntax) = @_;
85 # DB2 is the only remaining DB using this. Even though we are not sure if
86 # RowNumberOver is still needed here (should be part of SQLA) leave the
88 my $dbhname = blessed($syntax) ? $syntax->{Driver}{Name} : $syntax;
89 if(ref($self) && $dbhname && $dbhname eq 'DB2') {
90 return 'RowNumberOver';
93 $self->{_cached_syntax} ||= $self->SUPER::_find_syntax($syntax);
97 my ($self, $table, $fields, $where, $order, @rest) = @_;
98 local $self->{having_bind} = [];
99 if (ref $table eq 'SCALAR') {
102 elsif (ref $table eq 'HASH') {
103 ## what if they want to alias a sub query?
105 elsif (ref $table eq 'REF') {
106 #my ($sql, @bind) = @{${$t}}; push(@{$self->{having_bind}}, @bind;);
109 while (my $b = shift @$$t) { push @{$self->{having_bind}}, $b; }
111 elsif (not ref $table) {
112 $table = $self->_quote($table);
114 local $self->{rownum_hack_count} = 1
115 if (defined $rest[0] && $self->{limit_dialect} eq 'RowNum');
116 @rest = (-1) unless defined $rest[0];
117 die "LIMIT 0 Does Not Compute" if $rest[0] == 0;
118 # and anyway, SQL::Abstract::Limit will cause a barf if we don't first
119 my ($sql, @ret) = $self->SUPER::select(
120 $table, $self->_recurse_fields($fields), $where, $order, @rest
125 $self->{for} eq 'update' ? ' FOR UPDATE' :
126 $self->{for} eq 'shared' ? ' FOR SHARE' :
131 return wantarray ? ($sql, @ret, @{$self->{having_bind}}) : $sql;
137 $table = $self->_quote($table) unless ref($table);
138 $self->SUPER::insert($table, @_);
144 $table = $self->_quote($table) unless ref($table);
145 $self->SUPER::update($table, @_);
151 $table = $self->_quote($table) unless ref($table);
152 $self->SUPER::delete($table, @_);
158 return $_[1].$self->_order_by($_[2]);
160 return $self->SUPER::_emulate_limit(@_);
164 sub _recurse_fields {
165 my ($self, $fields, $params) = @_;
166 my $ref = ref $fields;
167 return $self->_quote($fields) unless $ref;
168 return $$fields if $ref eq 'SCALAR';
170 if ($ref eq 'ARRAY') {
171 return join(', ', map {
172 $self->_recurse_fields($_)
173 .(exists $self->{rownum_hack_count} && !($params && $params->{no_rownum_hack})
174 ? ' AS col'.$self->{rownum_hack_count}++
177 } elsif ($ref eq 'HASH') {
178 foreach my $func (keys %$fields) {
179 return $self->_sqlcase($func)
180 .'( '.$self->_recurse_fields($fields->{$func}).' )';
183 # Is the second check absolutely necessary?
184 elsif ( $ref eq 'REF' and ref($$fields) eq 'ARRAY' ) {
185 return $self->_bind_to_sql( $fields );
188 Carp::croak($ref . qq{ unexpected in _recurse_fields()})
196 if (ref $_[0] eq 'HASH') {
197 if (defined $_[0]->{group_by}) {
198 $ret = $self->_sqlcase(' group by ')
199 .$self->_recurse_fields($_[0]->{group_by}, { no_rownum_hack => 1 });
201 if (defined $_[0]->{having}) {
203 ($frag, @extra) = $self->_recurse_where($_[0]->{having});
204 push(@{$self->{having_bind}}, @extra);
205 $ret .= $self->_sqlcase(' having ').$frag;
207 if (defined $_[0]->{order_by}) {
208 $ret .= $self->_order_by($_[0]->{order_by});
210 if (grep { $_ =~ /^-(desc|asc)/i } keys %{$_[0]}) {
211 return $self->SUPER::_order_by($_[0]);
213 } elsif (ref $_[0] eq 'SCALAR') {
214 $ret = $self->_sqlcase(' order by ').${ $_[0] };
215 } elsif (ref $_[0] eq 'ARRAY' && @{$_[0]}) {
216 my @order = @{+shift};
217 $ret = $self->_sqlcase(' order by ')
219 my $r = $self->_order_by($_, @_);
220 $r =~ s/^ ?ORDER BY //i;
224 $ret = $self->SUPER::_order_by(@_);
229 sub _order_directions {
230 my ($self, $order) = @_;
231 $order = $order->{order_by} if ref $order eq 'HASH';
232 return $self->SUPER::_order_directions($order);
236 my ($self, $from) = @_;
237 if (ref $from eq 'ARRAY') {
238 return $self->_recurse_from(@$from);
239 } elsif (ref $from eq 'HASH') {
240 return $self->_make_as($from);
242 return $from; # would love to quote here but _table ends up getting called
243 # twice during an ->select without a limit clause due to
244 # the way S::A::Limit->select works. should maybe consider
245 # bypassing this and doing S::A::select($self, ...) in
246 # our select method above. meantime, quoting shims have
247 # been added to select/insert/update/delete here
252 my ($self, $from, @join) = @_;
254 push(@sqlf, $self->_make_as($from));
255 foreach my $j (@join) {
258 # check whether a join type exists
259 my $join_clause = '';
260 my $to_jt = ref($to) eq 'ARRAY' ? $to->[0] : $to;
261 if (ref($to_jt) eq 'HASH' and exists($to_jt->{-join_type})) {
262 $join_clause = ' '.uc($to_jt->{-join_type}).' JOIN ';
264 $join_clause = ' JOIN ';
266 push(@sqlf, $join_clause);
268 if (ref $to eq 'ARRAY') {
269 push(@sqlf, '(', $self->_recurse_from(@$to), ')');
271 push(@sqlf, $self->_make_as($to));
273 push(@sqlf, ' ON ', $self->_join_condition($on));
275 return join('', @sqlf);
281 my $sql = shift @$$arr;
282 $sql =~ s/\?/$self->_quote((shift @$$arr)->[1])/eg;
287 my ($self, $from) = @_;
288 return join(' ', map { (ref $_ eq 'SCALAR' ? $$_
289 : ref $_ eq 'REF' ? $self->_bind_to_sql($_)
291 } reverse each %{$self->_skip_options($from)});
295 my ($self, $hash) = @_;
297 $clean_hash->{$_} = $hash->{$_}
298 for grep {!/^-/} keys %$hash;
302 sub _join_condition {
303 my ($self, $cond) = @_;
304 if (ref $cond eq 'HASH') {
309 # XXX no throw_exception() in this package and croak() fails with strange results
310 Carp::croak(ref($v) . qq{ reference arguments are not supported in JOINS - try using \"..." instead'})
311 if ref($v) ne 'SCALAR';
315 my $x = '= '.$self->_quote($v); $j{$_} = \$x;
318 return scalar($self->_recurse_where(\%j));
319 } elsif (ref $cond eq 'ARRAY') {
320 return join(' OR ', map { $self->_join_condition($_) } @$cond);
322 die "Can't handle this yet!";
327 my ($self, $label) = @_;
328 return '' unless defined $label;
329 return "*" if $label eq '*';
330 return $label unless $self->{quote_char};
331 if(ref $self->{quote_char} eq "ARRAY"){
332 return $self->{quote_char}->[0] . $label . $self->{quote_char}->[1]
333 if !defined $self->{name_sep};
334 my $sep = $self->{name_sep};
335 return join($self->{name_sep},
336 map { $self->{quote_char}->[0] . $_ . $self->{quote_char}->[1] }
337 split(/\Q$sep\E/,$label));
339 return $self->SUPER::_quote($label);
344 $self->{limit_dialect} = shift if @_;
345 return $self->{limit_dialect};
350 $self->{quote_char} = shift if @_;
351 return $self->{quote_char};
356 $self->{name_sep} = shift if @_;
357 return $self->{name_sep};
360 } # End of BEGIN block
364 DBIx::Class::Storage::DBI - DBI storage handler
368 my $schema = MySchema->connect('dbi:SQLite:my.db');
370 $schema->storage->debug(1);
371 $schema->dbh_do("DROP TABLE authors");
373 $schema->resultset('Book')->search({
374 written_on => $schema->storage->datetime_parser(DateTime->now)
379 This class represents the connection to an RDBMS via L<DBI>. See
380 L<DBIx::Class::Storage> for general information. This pod only
381 documents DBI-specific methods and behaviors.
388 my $new = shift->next::method(@_);
390 $new->transaction_depth(0);
391 $new->_sql_maker_opts({});
392 $new->{savepoints} = [];
393 $new->{_in_dbh_do} = 0;
394 $new->{_dbh_gen} = 0;
401 This method is normally called by L<DBIx::Class::Schema/connection>, which
402 encapsulates its argument list in an arrayref before passing them here.
404 The argument list may contain:
410 The same 4-element argument set one would normally pass to
411 L<DBI/connect>, optionally followed by
412 L<extra attributes|/DBIx::Class specific connection attributes>
413 recognized by DBIx::Class:
415 $connect_info_args = [ $dsn, $user, $password, \%dbi_attributes?, \%extra_attributes? ];
419 A single code reference which returns a connected
420 L<DBI database handle|DBI/connect> optionally followed by
421 L<extra attributes|/DBIx::Class specific connection attributes> recognized
424 $connect_info_args = [ sub { DBI->connect (...) }, \%extra_attributes? ];
428 A single hashref with all the attributes and the dsn/user/password
431 $connect_info_args = [{
439 This is particularly useful for L<Catalyst> based applications, allowing the
440 following config (L<Config::General> style):
445 dsn dbi:mysql:database=test
454 Please note that the L<DBI> docs recommend that you always explicitly
455 set C<AutoCommit> to either I<0> or I<1>. L<DBIx::Class> further
456 recommends that it be set to I<1>, and that you perform transactions
457 via our L<DBIx::Class::Schema/txn_do> method. L<DBIx::Class> will set it
458 to I<1> if you do not do explicitly set it to zero. This is the default
459 for most DBDs. See L</DBIx::Class and AutoCommit> for details.
461 =head3 DBIx::Class specific connection attributes
463 In addition to the standard L<DBI|DBI/ATTRIBUTES_COMMON_TO_ALL_HANDLES>
464 L<connection|DBI/Database_Handle_Attributes> attributes, DBIx::Class recognizes
465 the following connection options. These options can be mixed in with your other
466 L<DBI> connection attributes, or placed in a seperate hashref
467 (C<\%extra_attributes>) as shown above.
469 Every time C<connect_info> is invoked, any previous settings for
470 these options will be cleared before setting the new ones, regardless of
471 whether any options are specified in the new C<connect_info>.
478 Specifies things to do immediately after connecting or re-connecting to
479 the database. Its value may contain:
483 =item an array reference
485 This contains SQL statements to execute in order. Each element contains
486 a string or a code reference that returns a string.
488 =item a code reference
490 This contains some code to execute. Unlike code references within an
491 array reference, its return value is ignored.
495 =item on_disconnect_do
497 Takes arguments in the same form as L</on_connect_do> and executes them
498 immediately before disconnecting from the database.
500 Note, this only runs if you explicitly call L</disconnect> on the
503 =item disable_sth_caching
505 If set to a true value, this option will disable the caching of
506 statement handles via L<DBI/prepare_cached>.
510 Sets the limit dialect. This is useful for JDBC-bridge among others
511 where the remote SQL-dialect cannot be determined by the name of the
512 driver alone. See also L<SQL::Abstract::Limit>.
516 Specifies what characters to use to quote table and column names. If
517 you use this you will want to specify L</name_sep> as well.
519 C<quote_char> expects either a single character, in which case is it
520 is placed on either side of the table/column name, or an arrayref of length
521 2 in which case the table/column name is placed between the elements.
523 For example under MySQL you should use C<< quote_char => '`' >>, and for
524 SQL Server you should use C<< quote_char => [qw/[ ]/] >>.
528 This only needs to be used in conjunction with C<quote_char>, and is used to
529 specify the charecter that seperates elements (schemas, tables, columns) from
530 each other. In most cases this is simply a C<.>.
532 The consequences of not supplying this value is that L<SQL::Abstract>
533 will assume DBIx::Class' uses of aliases to be complete column
534 names. The output will look like I<"me.name"> when it should actually
539 This Storage driver normally installs its own C<HandleError>, sets
540 C<RaiseError> and C<ShowErrorStatement> on, and sets C<PrintError> off on
541 all database handles, including those supplied by a coderef. It does this
542 so that it can have consistent and useful error behavior.
544 If you set this option to a true value, Storage will not do its usual
545 modifications to the database handle's attributes, and instead relies on
546 the settings in your connect_info DBI options (or the values you set in
547 your connection coderef, in the case that you are connecting via coderef).
549 Note that your custom settings can cause Storage to malfunction,
550 especially if you set a C<HandleError> handler that suppresses exceptions
551 and/or disable C<RaiseError>.
555 If this option is true, L<DBIx::Class> will use savepoints when nesting
556 transactions, making it possible to recover from failure in the inner
557 transaction without having to abort all outer transactions.
561 Use this argument to supply a cursor class other than the default
562 L<DBIx::Class::Storage::DBI::Cursor>.
566 Some real-life examples of arguments to L</connect_info> and
567 L<DBIx::Class::Schema/connect>
569 # Simple SQLite connection
570 ->connect_info([ 'dbi:SQLite:./foo.db' ]);
573 ->connect_info([ sub { DBI->connect(...) } ]);
575 # A bit more complicated
582 { quote_char => q{"}, name_sep => q{.} },
586 # Equivalent to the previous example
592 { AutoCommit => 1, quote_char => q{"}, name_sep => q{.} },
596 # Same, but with hashref as argument
597 # See parse_connect_info for explanation
600 dsn => 'dbi:Pg:dbname=foo',
602 password => 'my_pg_password',
609 # Subref + DBIx::Class-specific connection options
612 sub { DBI->connect(...) },
616 on_connect_do => ['SET search_path TO myschema,otherschema,public'],
617 disable_sth_caching => 1,
627 my ($self, $info_arg) = @_;
629 return $self->_connect_info if !$info_arg;
631 my @args = @$info_arg; # take a shallow copy for further mutilation
632 $self->_connect_info([@args]); # copy for _connect_info
635 # combine/pre-parse arguments depending on invocation style
638 if (ref $args[0] eq 'CODE') { # coderef with optional \%extra_attributes
639 %attrs = %{ $args[1] || {} };
642 elsif (ref $args[0] eq 'HASH') { # single hashref (i.e. Catalyst config)
643 %attrs = %{$args[0]};
645 for (qw/password user dsn/) {
646 unshift @args, delete $attrs{$_};
649 else { # otherwise assume dsn/user/password + \%attrs + \%extra_attrs
651 % { $args[3] || {} },
652 % { $args[4] || {} },
654 @args = @args[0,1,2];
657 # Kill sql_maker/_sql_maker_opts, so we get a fresh one with only
658 # the new set of options
659 $self->_sql_maker(undef);
660 $self->_sql_maker_opts({});
663 for my $storage_opt (@storage_options, 'cursor_class') { # @storage_options is declared at the top of the module
664 if(my $value = delete $attrs{$storage_opt}) {
665 $self->$storage_opt($value);
668 for my $sql_maker_opt (qw/limit_dialect quote_char name_sep/) {
669 if(my $opt_val = delete $attrs{$sql_maker_opt}) {
670 $self->_sql_maker_opts->{$sql_maker_opt} = $opt_val;
675 %attrs = () if (ref $args[0] eq 'CODE'); # _connect() never looks past $args[0] in this case
677 $self->_dbi_connect_info([@args, keys %attrs ? \%attrs : ()]);
678 $self->_connect_info;
683 This method is deprecated in favour of setting via L</connect_info>.
688 Arguments: ($subref | $method_name), @extra_coderef_args?
690 Execute the given $subref or $method_name using the new exception-based
691 connection management.
693 The first two arguments will be the storage object that C<dbh_do> was called
694 on and a database handle to use. Any additional arguments will be passed
695 verbatim to the called subref as arguments 2 and onwards.
697 Using this (instead of $self->_dbh or $self->dbh) ensures correct
698 exception handling and reconnection (or failover in future subclasses).
700 Your subref should have no side-effects outside of the database, as
701 there is the potential for your subref to be partially double-executed
702 if the database connection was stale/dysfunctional.
706 my @stuff = $schema->storage->dbh_do(
708 my ($storage, $dbh, @cols) = @_;
709 my $cols = join(q{, }, @cols);
710 $dbh->selectrow_array("SELECT $cols FROM foo");
721 my $dbh = $self->_dbh;
723 return $self->$code($dbh, @_) if $self->{_in_dbh_do}
724 || $self->{transaction_depth};
726 local $self->{_in_dbh_do} = 1;
729 my $want_array = wantarray;
732 $self->_verify_pid if $dbh;
734 $self->_populate_dbh;
739 @result = $self->$code($dbh, @_);
741 elsif(defined $want_array) {
742 $result[0] = $self->$code($dbh, @_);
745 $self->$code($dbh, @_);
750 if(!$exception) { return $want_array ? @result : $result[0] }
752 $self->throw_exception($exception) if $self->connected;
754 # We were not connected - reconnect and retry, but let any
755 # exception fall right through this time
756 $self->_populate_dbh;
757 $self->$code($self->_dbh, @_);
760 # This is basically a blend of dbh_do above and DBIx::Class::Storage::txn_do.
761 # It also informs dbh_do to bypass itself while under the direction of txn_do,
762 # via $self->{_in_dbh_do} (this saves some redundant eval and errorcheck, etc)
767 ref $coderef eq 'CODE' or $self->throw_exception
768 ('$coderef must be a CODE reference');
770 return $coderef->(@_) if $self->{transaction_depth} && ! $self->auto_savepoint;
772 local $self->{_in_dbh_do} = 1;
775 my $want_array = wantarray;
780 $self->_verify_pid if $self->_dbh;
781 $self->_populate_dbh if !$self->_dbh;
785 @result = $coderef->(@_);
787 elsif(defined $want_array) {
788 $result[0] = $coderef->(@_);
797 if(!$exception) { return $want_array ? @result : $result[0] }
799 if($tried++ > 0 || $self->connected) {
800 eval { $self->txn_rollback };
801 my $rollback_exception = $@;
802 if($rollback_exception) {
803 my $exception_class = "DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION";
804 $self->throw_exception($exception) # propagate nested rollback
805 if $rollback_exception =~ /$exception_class/;
807 $self->throw_exception(
808 "Transaction aborted: ${exception}. "
809 . "Rollback failed: ${rollback_exception}"
812 $self->throw_exception($exception)
815 # We were not connected, and was first try - reconnect and retry
817 $self->_populate_dbh;
823 Our C<disconnect> method also performs a rollback first if the
824 database is not in C<AutoCommit> mode.
831 if( $self->connected ) {
832 my $connection_do = $self->on_disconnect_do;
833 $self->_do_connection_actions($connection_do) if ref($connection_do);
835 $self->_dbh->rollback unless $self->_dbh_autocommit;
836 $self->_dbh->disconnect;
842 =head2 with_deferred_fk_checks
846 =item Arguments: C<$coderef>
848 =item Return Value: The return value of $coderef
852 Storage specific method to run the code ref with FK checks deferred or
853 in MySQL's case disabled entirely.
857 # Storage subclasses should override this
858 sub with_deferred_fk_checks {
859 my ($self, $sub) = @_;
867 if(my $dbh = $self->_dbh) {
868 if(defined $self->_conn_tid && $self->_conn_tid != threads->tid) {
875 return 0 if !$self->_dbh;
877 return ($dbh->FETCH('Active') && $dbh->ping);
883 # handle pid changes correctly
884 # NOTE: assumes $self->_dbh is a valid $dbh
888 return if defined $self->_conn_pid && $self->_conn_pid == $$;
890 $self->_dbh->{InactiveDestroy} = 1;
897 sub ensure_connected {
900 unless ($self->connected) {
901 $self->_populate_dbh;
907 Returns the dbh - a data base handle of class L<DBI>.
914 $self->ensure_connected;
918 sub _sql_maker_args {
921 return ( bindtype=>'columns', array_datatypes => 1, limit_dialect => $self->dbh, %{$self->_sql_maker_opts} );
926 unless ($self->_sql_maker) {
927 my $sql_maker_class = $self->sql_maker_class;
928 $self->_sql_maker($sql_maker_class->new( $self->_sql_maker_args ));
930 return $self->_sql_maker;
937 my @info = @{$self->_dbi_connect_info || []};
938 $self->_dbh($self->_connect(@info));
940 # Always set the transaction depth on connect, since
941 # there is no transaction in progress by definition
942 $self->{transaction_depth} = $self->_dbh_autocommit ? 0 : 1;
944 if(ref $self eq 'DBIx::Class::Storage::DBI') {
945 my $driver = $self->_dbh->{Driver}->{Name};
946 if ($self->load_optional_class("DBIx::Class::Storage::DBI::${driver}")) {
947 bless $self, "DBIx::Class::Storage::DBI::${driver}";
952 $self->_conn_pid($$);
953 $self->_conn_tid(threads->tid) if $INC{'threads.pm'};
955 my $connection_do = $self->on_connect_do;
956 $self->_do_connection_actions($connection_do) if ref($connection_do);
959 sub _do_connection_actions {
961 my $connection_do = shift;
963 if (ref $connection_do eq 'ARRAY') {
964 $self->_do_query($_) foreach @$connection_do;
966 elsif (ref $connection_do eq 'CODE') {
967 $connection_do->($self);
974 my ($self, $action) = @_;
976 if (ref $action eq 'CODE') {
977 $action = $action->($self);
978 $self->_do_query($_) foreach @$action;
981 # Most debuggers expect ($sql, @bind), so we need to exclude
982 # the attribute hash which is the second argument to $dbh->do
983 # furthermore the bind values are usually to be presented
984 # as named arrayref pairs, so wrap those here too
985 my @do_args = (ref $action eq 'ARRAY') ? (@$action) : ($action);
986 my $sql = shift @do_args;
987 my $attrs = shift @do_args;
988 my @bind = map { [ undef, $_ ] } @do_args;
990 $self->_query_start($sql, @bind);
991 $self->_dbh->do($sql, $attrs, @do_args);
992 $self->_query_end($sql, @bind);
999 my ($self, @info) = @_;
1001 $self->throw_exception("You failed to provide any connection info")
1004 my ($old_connect_via, $dbh);
1006 if ($INC{'Apache/DBI.pm'} && $ENV{MOD_PERL}) {
1007 $old_connect_via = $DBI::connect_via;
1008 $DBI::connect_via = 'connect';
1012 if(ref $info[0] eq 'CODE') {
1016 $dbh = DBI->connect(@info);
1019 if($dbh && !$self->unsafe) {
1020 my $weak_self = $self;
1022 $dbh->{HandleError} = sub {
1024 $weak_self->throw_exception("DBI Exception: $_[0]");
1027 croak ("DBI Exception: $_[0]");
1030 $dbh->{ShowErrorStatement} = 1;
1031 $dbh->{RaiseError} = 1;
1032 $dbh->{PrintError} = 0;
1036 $DBI::connect_via = $old_connect_via if $old_connect_via;
1038 $self->throw_exception("DBI Connection failed: " . ($@||$DBI::errstr))
1041 $self->_dbh_autocommit($dbh->{AutoCommit});
1047 my ($self, $name) = @_;
1049 $name = $self->_svp_generate_name
1050 unless defined $name;
1052 $self->throw_exception ("You can't use savepoints outside a transaction")
1053 if $self->{transaction_depth} == 0;
1055 $self->throw_exception ("Your Storage implementation doesn't support savepoints")
1056 unless $self->can('_svp_begin');
1058 push @{ $self->{savepoints} }, $name;
1060 $self->debugobj->svp_begin($name) if $self->debug;
1062 return $self->_svp_begin($name);
1066 my ($self, $name) = @_;
1068 $self->throw_exception ("You can't use savepoints outside a transaction")
1069 if $self->{transaction_depth} == 0;
1071 $self->throw_exception ("Your Storage implementation doesn't support savepoints")
1072 unless $self->can('_svp_release');
1074 if (defined $name) {
1075 $self->throw_exception ("Savepoint '$name' does not exist")
1076 unless grep { $_ eq $name } @{ $self->{savepoints} };
1078 # Dig through the stack until we find the one we are releasing. This keeps
1079 # the stack up to date.
1082 do { $svp = pop @{ $self->{savepoints} } } while $svp ne $name;
1084 $name = pop @{ $self->{savepoints} };
1087 $self->debugobj->svp_release($name) if $self->debug;
1089 return $self->_svp_release($name);
1093 my ($self, $name) = @_;
1095 $self->throw_exception ("You can't use savepoints outside a transaction")
1096 if $self->{transaction_depth} == 0;
1098 $self->throw_exception ("Your Storage implementation doesn't support savepoints")
1099 unless $self->can('_svp_rollback');
1101 if (defined $name) {
1102 # If they passed us a name, verify that it exists in the stack
1103 unless(grep({ $_ eq $name } @{ $self->{savepoints} })) {
1104 $self->throw_exception("Savepoint '$name' does not exist!");
1107 # Dig through the stack until we find the one we are releasing. This keeps
1108 # the stack up to date.
1109 while(my $s = pop(@{ $self->{savepoints} })) {
1110 last if($s eq $name);
1112 # Add the savepoint back to the stack, as a rollback doesn't remove the
1113 # named savepoint, only everything after it.
1114 push(@{ $self->{savepoints} }, $name);
1116 # We'll assume they want to rollback to the last savepoint
1117 $name = $self->{savepoints}->[-1];
1120 $self->debugobj->svp_rollback($name) if $self->debug;
1122 return $self->_svp_rollback($name);
1125 sub _svp_generate_name {
1128 return 'savepoint_'.scalar(@{ $self->{'savepoints'} });
1133 $self->ensure_connected();
1134 if($self->{transaction_depth} == 0) {
1135 $self->debugobj->txn_begin()
1137 # this isn't ->_dbh-> because
1138 # we should reconnect on begin_work
1139 # for AutoCommit users
1140 $self->dbh->begin_work;
1141 } elsif ($self->auto_savepoint) {
1144 $self->{transaction_depth}++;
1149 if ($self->{transaction_depth} == 1) {
1150 my $dbh = $self->_dbh;
1151 $self->debugobj->txn_commit()
1154 $self->{transaction_depth} = 0
1155 if $self->_dbh_autocommit;
1157 elsif($self->{transaction_depth} > 1) {
1158 $self->{transaction_depth}--;
1160 if $self->auto_savepoint;
1166 my $dbh = $self->_dbh;
1168 if ($self->{transaction_depth} == 1) {
1169 $self->debugobj->txn_rollback()
1171 $self->{transaction_depth} = 0
1172 if $self->_dbh_autocommit;
1175 elsif($self->{transaction_depth} > 1) {
1176 $self->{transaction_depth}--;
1177 if ($self->auto_savepoint) {
1178 $self->svp_rollback;
1183 die DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION->new;
1188 my $exception_class = "DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION";
1189 $error =~ /$exception_class/ and $self->throw_exception($error);
1190 # ensure that a failed rollback resets the transaction depth
1191 $self->{transaction_depth} = $self->_dbh_autocommit ? 0 : 1;
1192 $self->throw_exception($error);
1196 # This used to be the top-half of _execute. It was split out to make it
1197 # easier to override in NoBindVars without duping the rest. It takes up
1198 # all of _execute's args, and emits $sql, @bind.
1199 sub _prep_for_execute {
1200 my ($self, $op, $extra_bind, $ident, $args) = @_;
1202 if( blessed($ident) && $ident->isa("DBIx::Class::ResultSource") ) {
1203 $ident = $ident->from();
1206 my ($sql, @bind) = $self->sql_maker->$op($ident, @$args);
1209 map { ref $_ eq 'ARRAY' ? $_ : [ '!!dummy', $_ ] } @$extra_bind)
1211 return ($sql, \@bind);
1214 sub _fix_bind_params {
1215 my ($self, @bind) = @_;
1217 ### Turn @bind from something like this:
1218 ### ( [ "artist", 1 ], [ "cdid", 1, 3 ] )
1220 ### ( "'1'", "'1'", "'3'" )
1223 if ( defined( $_ && $_->[1] ) ) {
1224 map { qq{'$_'}; } @{$_}[ 1 .. $#$_ ];
1231 my ( $self, $sql, @bind ) = @_;
1233 if ( $self->debug ) {
1234 @bind = $self->_fix_bind_params(@bind);
1236 $self->debugobj->query_start( $sql, @bind );
1241 my ( $self, $sql, @bind ) = @_;
1243 if ( $self->debug ) {
1244 @bind = $self->_fix_bind_params(@bind);
1245 $self->debugobj->query_end( $sql, @bind );
1250 my ($self, $dbh, $op, $extra_bind, $ident, $bind_attributes, @args) = @_;
1252 my ($sql, $bind) = $self->_prep_for_execute($op, $extra_bind, $ident, \@args);
1254 $self->_query_start( $sql, @$bind );
1256 my $sth = $self->sth($sql,$op);
1258 my $placeholder_index = 1;
1260 foreach my $bound (@$bind) {
1261 my $attributes = {};
1262 my($column_name, @data) = @$bound;
1264 if ($bind_attributes) {
1265 $attributes = $bind_attributes->{$column_name}
1266 if defined $bind_attributes->{$column_name};
1269 foreach my $data (@data) {
1270 my $ref = ref $data;
1271 $data = $ref && $ref ne 'ARRAY' ? ''.$data : $data; # stringify args (except arrayrefs)
1273 $sth->bind_param($placeholder_index, $data, $attributes);
1274 $placeholder_index++;
1278 # Can this fail without throwing an exception anyways???
1279 my $rv = $sth->execute();
1280 $self->throw_exception($sth->errstr) if !$rv;
1282 $self->_query_end( $sql, @$bind );
1284 return (wantarray ? ($rv, $sth, @$bind) : $rv);
1289 $self->dbh_do('_dbh_execute', @_)
1293 my ($self, $source, $to_insert) = @_;
1295 my $ident = $source->from;
1296 my $bind_attributes = $self->source_bind_attributes($source);
1298 $self->ensure_connected;
1299 foreach my $col ( $source->columns ) {
1300 if ( !defined $to_insert->{$col} ) {
1301 my $col_info = $source->column_info($col);
1303 if ( $col_info->{auto_nextval} ) {
1304 $to_insert->{$col} = $self->_sequence_fetch( 'nextval', $col_info->{sequence} || $self->_dbh_get_autoinc_seq($self->dbh, $source) );
1309 $self->_execute('insert' => [], $source, $bind_attributes, $to_insert);
1314 ## Still not quite perfect, and EXPERIMENTAL
1315 ## Currently it is assumed that all values passed will be "normal", i.e. not
1316 ## scalar refs, or at least, all the same type as the first set, the statement is
1317 ## only prepped once.
1319 my ($self, $source, $cols, $data) = @_;
1321 my $table = $source->from;
1322 @colvalues{@$cols} = (0..$#$cols);
1323 my ($sql, @bind) = $self->sql_maker->insert($table, \%colvalues);
1325 $self->_query_start( $sql, @bind );
1326 my $sth = $self->sth($sql);
1328 # @bind = map { ref $_ ? ''.$_ : $_ } @bind; # stringify args
1330 ## This must be an arrayref, else nothing works!
1332 my $tuple_status = [];
1335 ##print STDERR Dumper( $data, $sql, [@bind] );
1339 ## Get the bind_attributes, if any exist
1340 my $bind_attributes = $self->source_bind_attributes($source);
1342 ## Bind the values and execute
1343 my $placeholder_index = 1;
1345 foreach my $bound (@bind) {
1347 my $attributes = {};
1348 my ($column_name, $data_index) = @$bound;
1350 if( $bind_attributes ) {
1351 $attributes = $bind_attributes->{$column_name}
1352 if defined $bind_attributes->{$column_name};
1355 my @data = map { $_->[$data_index] } @$data;
1357 $sth->bind_param_array( $placeholder_index, [@data], $attributes );
1358 $placeholder_index++;
1360 my $rv = $sth->execute_array({ArrayTupleStatus => $tuple_status});
1361 $self->throw_exception($sth->errstr) if !$rv;
1363 $self->_query_end( $sql, @bind );
1364 return (wantarray ? ($rv, $sth, @bind) : $rv);
1368 my $self = shift @_;
1369 my $source = shift @_;
1370 my $bind_attributes = $self->source_bind_attributes($source);
1372 return $self->_execute('update' => [], $source, $bind_attributes, @_);
1377 my $self = shift @_;
1378 my $source = shift @_;
1380 my $bind_attrs = {}; ## If ever it's needed...
1382 return $self->_execute('delete' => [], $source, $bind_attrs, @_);
1387 my $sql_maker = $self->sql_maker;
1388 local $sql_maker->{for};
1389 return $self->_execute($self->_select_args(@_));
1393 my ($self, $ident, $select, $condition, $attrs) = @_;
1394 my $order = $attrs->{order_by};
1396 if (ref $condition eq 'SCALAR') {
1397 my $unwrap = ${$condition};
1398 if ($unwrap =~ s/ORDER BY (.*)$//i) {
1400 $condition = \$unwrap;
1404 my $for = delete $attrs->{for};
1405 my $sql_maker = $self->sql_maker;
1406 $sql_maker->{for} = $for;
1408 if (exists $attrs->{group_by} || $attrs->{having}) {
1410 group_by => $attrs->{group_by},
1411 having => $attrs->{having},
1412 ($order ? (order_by => $order) : ())
1415 my $bind_attrs = {}; ## Future support
1416 my @args = ('select', $attrs->{bind}, $ident, $bind_attrs, $select, $condition, $order);
1417 if ($attrs->{software_limit} ||
1418 $self->sql_maker->_default_limit_syntax eq "GenericSubQ") {
1419 $attrs->{software_limit} = 1;
1421 $self->throw_exception("rows attribute must be positive if present")
1422 if (defined($attrs->{rows}) && !($attrs->{rows} > 0));
1424 # MySQL actually recommends this approach. I cringe.
1425 $attrs->{rows} = 2**48 if not defined $attrs->{rows} and defined $attrs->{offset};
1426 push @args, $attrs->{rows}, $attrs->{offset};
1431 sub source_bind_attributes {
1432 my ($self, $source) = @_;
1434 my $bind_attributes;
1435 foreach my $column ($source->columns) {
1437 my $data_type = $source->column_info($column)->{data_type} || '';
1438 $bind_attributes->{$column} = $self->bind_attribute_by_data_type($data_type)
1442 return $bind_attributes;
1449 =item Arguments: $ident, $select, $condition, $attrs
1453 Handle a SQL select statement.
1459 my ($ident, $select, $condition, $attrs) = @_;
1460 return $self->cursor_class->new($self, \@_, $attrs);
1465 my ($rv, $sth, @bind) = $self->_select(@_);
1466 my @row = $sth->fetchrow_array;
1467 my @nextrow = $sth->fetchrow_array if @row;
1468 if(@row && @nextrow) {
1469 carp "Query returned more than one row. SQL that returns multiple rows is DEPRECATED for ->find and ->single";
1471 # Need to call finish() to work round broken DBDs
1480 =item Arguments: $sql
1484 Returns a L<DBI> sth (statement handle) for the supplied SQL.
1489 my ($self, $dbh, $sql) = @_;
1491 # 3 is the if_active parameter which avoids active sth re-use
1492 my $sth = $self->disable_sth_caching
1493 ? $dbh->prepare($sql)
1494 : $dbh->prepare_cached($sql, {}, 3);
1496 # XXX You would think RaiseError would make this impossible,
1497 # but apparently that's not true :(
1498 $self->throw_exception($dbh->errstr) if !$sth;
1504 my ($self, $sql) = @_;
1505 $self->dbh_do('_dbh_sth', $sql);
1508 sub _dbh_columns_info_for {
1509 my ($self, $dbh, $table) = @_;
1511 if ($dbh->can('column_info')) {
1514 my ($schema,$tab) = $table =~ /^(.+?)\.(.+)$/ ? ($1,$2) : (undef,$table);
1515 my $sth = $dbh->column_info( undef,$schema, $tab, '%' );
1517 while ( my $info = $sth->fetchrow_hashref() ){
1519 $column_info{data_type} = $info->{TYPE_NAME};
1520 $column_info{size} = $info->{COLUMN_SIZE};
1521 $column_info{is_nullable} = $info->{NULLABLE} ? 1 : 0;
1522 $column_info{default_value} = $info->{COLUMN_DEF};
1523 my $col_name = $info->{COLUMN_NAME};
1524 $col_name =~ s/^\"(.*)\"$/$1/;
1526 $result{$col_name} = \%column_info;
1529 return \%result if !$@ && scalar keys %result;
1533 my $sth = $dbh->prepare($self->sql_maker->select($table, undef, \'1 = 0'));
1535 my @columns = @{$sth->{NAME_lc}};
1536 for my $i ( 0 .. $#columns ){
1538 $column_info{data_type} = $sth->{TYPE}->[$i];
1539 $column_info{size} = $sth->{PRECISION}->[$i];
1540 $column_info{is_nullable} = $sth->{NULLABLE}->[$i] ? 1 : 0;
1542 if ($column_info{data_type} =~ m/^(.*?)\((.*?)\)$/) {
1543 $column_info{data_type} = $1;
1544 $column_info{size} = $2;
1547 $result{$columns[$i]} = \%column_info;
1551 foreach my $col (keys %result) {
1552 my $colinfo = $result{$col};
1553 my $type_num = $colinfo->{data_type};
1555 if(defined $type_num && $dbh->can('type_info')) {
1556 my $type_info = $dbh->type_info($type_num);
1557 $type_name = $type_info->{TYPE_NAME} if $type_info;
1558 $colinfo->{data_type} = $type_name if $type_name;
1565 sub columns_info_for {
1566 my ($self, $table) = @_;
1567 $self->dbh_do('_dbh_columns_info_for', $table);
1570 =head2 last_insert_id
1572 Return the row id of the last insert.
1576 sub _dbh_last_insert_id {
1577 # All Storage's need to register their own _dbh_last_insert_id
1578 # the old SQLite-based method was highly inappropriate
1581 my $class = ref $self;
1582 $self->throw_exception (<<EOE);
1584 No _dbh_last_insert_id() method found in $class.
1585 Since the method of obtaining the autoincrement id of the last insert
1586 operation varies greatly between different databases, this method must be
1587 individually implemented for every storage class.
1591 sub last_insert_id {
1593 $self->dbh_do('_dbh_last_insert_id', @_);
1598 Returns the database driver name.
1602 sub sqlt_type { shift->dbh->{Driver}->{Name} }
1604 =head2 bind_attribute_by_data_type
1606 Given a datatype from column info, returns a database specific bind
1607 attribute for C<< $dbh->bind_param($val,$attribute) >> or nothing if we will
1608 let the database planner just handle it.
1610 Generally only needed for special case column types, like bytea in postgres.
1614 sub bind_attribute_by_data_type {
1618 =head2 create_ddl_dir
1622 =item Arguments: $schema \@databases, $version, $directory, $preversion, \%sqlt_args
1626 Creates a SQL file based on the Schema, for each of the specified
1627 database types, in the given directory.
1629 By default, C<\%sqlt_args> will have
1631 { add_drop_table => 1, ignore_constraint_names => 1, ignore_index_names => 1 }
1633 merged with the hash passed in. To disable any of those features, pass in a
1634 hashref like the following
1636 { ignore_constraint_names => 0, # ... other options }
1640 sub create_ddl_dir {
1641 my ($self, $schema, $databases, $version, $dir, $preversion, $sqltargs) = @_;
1643 if(!$dir || !-d $dir) {
1644 warn "No directory given, using ./\n";
1647 $databases ||= ['MySQL', 'SQLite', 'PostgreSQL'];
1648 $databases = [ $databases ] if(ref($databases) ne 'ARRAY');
1650 my $schema_version = $schema->schema_version || '1.x';
1651 $version ||= $schema_version;
1654 add_drop_table => 1,
1655 ignore_constraint_names => 1,
1656 ignore_index_names => 1,
1660 $self->throw_exception(q{Can't create a ddl file without SQL::Translator 0.09003: '}
1661 . $self->_check_sqlt_message . q{'})
1662 if !$self->_check_sqlt_version;
1664 my $sqlt = SQL::Translator->new( $sqltargs );
1666 $sqlt->parser('SQL::Translator::Parser::DBIx::Class');
1667 my $sqlt_schema = $sqlt->translate({ data => $schema }) or die $sqlt->error;
1669 foreach my $db (@$databases) {
1671 $sqlt->{schema} = $sqlt_schema;
1672 $sqlt->producer($db);
1675 my $filename = $schema->ddl_filename($db, $version, $dir);
1676 if (-e $filename && ($version eq $schema_version )) {
1677 # if we are dumping the current version, overwrite the DDL
1678 warn "Overwriting existing DDL file - $filename";
1682 my $output = $sqlt->translate;
1684 warn("Failed to translate to $db, skipping. (" . $sqlt->error . ")");
1687 if(!open($file, ">$filename")) {
1688 $self->throw_exception("Can't open $filename for writing ($!)");
1691 print $file $output;
1694 next unless ($preversion);
1696 require SQL::Translator::Diff;
1698 my $prefilename = $schema->ddl_filename($db, $preversion, $dir);
1699 if(!-e $prefilename) {
1700 warn("No previous schema file found ($prefilename)");
1704 my $difffile = $schema->ddl_filename($db, $version, $dir, $preversion);
1706 warn("Overwriting existing diff file - $difffile");
1712 my $t = SQL::Translator->new($sqltargs);
1715 $t->parser( $db ) or die $t->error;
1716 my $out = $t->translate( $prefilename ) or die $t->error;
1717 $source_schema = $t->schema;
1718 unless ( $source_schema->name ) {
1719 $source_schema->name( $prefilename );
1723 # The "new" style of producers have sane normalization and can support
1724 # diffing a SQL file against a DBIC->SQLT schema. Old style ones don't
1725 # And we have to diff parsed SQL against parsed SQL.
1726 my $dest_schema = $sqlt_schema;
1728 unless ( "SQL::Translator::Producer::$db"->can('preprocess_schema') ) {
1729 my $t = SQL::Translator->new($sqltargs);
1732 $t->parser( $db ) or die $t->error;
1733 my $out = $t->translate( $filename ) or die $t->error;
1734 $dest_schema = $t->schema;
1735 $dest_schema->name( $filename )
1736 unless $dest_schema->name;
1739 my $diff = SQL::Translator::Diff::schema_diff($source_schema, $db,
1743 if(!open $file, ">$difffile") {
1744 $self->throw_exception("Can't write to $difffile ($!)");
1752 =head2 deployment_statements
1756 =item Arguments: $schema, $type, $version, $directory, $sqlt_args
1760 Returns the statements used by L</deploy> and L<DBIx::Class::Schema/deploy>.
1761 The database driver name is given by C<$type>, though the value from
1762 L</sqlt_type> is used if it is not specified.
1764 C<$directory> is used to return statements from files in a previously created
1765 L</create_ddl_dir> directory and is optional. The filenames are constructed
1766 from L<DBIx::Class::Schema/ddl_filename>, the schema name and the C<$version>.
1768 If no C<$directory> is specified then the statements are constructed on the
1769 fly using L<SQL::Translator> and C<$version> is ignored.
1771 See L<SQL::Translator/METHODS> for a list of values for C<$sqlt_args>.
1775 sub deployment_statements {
1776 my ($self, $schema, $type, $version, $dir, $sqltargs) = @_;
1777 # Need to be connected to get the correct sqlt_type
1778 $self->ensure_connected() unless $type;
1779 $type ||= $self->sqlt_type;
1780 $version ||= $schema->schema_version || '1.x';
1782 my $filename = $schema->ddl_filename($type, $version, $dir);
1786 open($file, "<$filename")
1787 or $self->throw_exception("Can't open $filename ($!)");
1790 return join('', @rows);
1793 $self->throw_exception(q{Can't deploy without SQL::Translator 0.09003: '}
1794 . $self->_check_sqlt_message . q{'})
1795 if !$self->_check_sqlt_version;
1797 require SQL::Translator::Parser::DBIx::Class;
1798 eval qq{use SQL::Translator::Producer::${type}};
1799 $self->throw_exception($@) if $@;
1801 # sources needs to be a parser arg, but for simplicty allow at top level
1803 $sqltargs->{parser_args}{sources} = delete $sqltargs->{sources}
1804 if exists $sqltargs->{sources};
1806 my $tr = SQL::Translator->new(%$sqltargs);
1807 SQL::Translator::Parser::DBIx::Class::parse( $tr, $schema );
1808 return "SQL::Translator::Producer::${type}"->can('produce')->($tr);
1812 my ($self, $schema, $type, $sqltargs, $dir) = @_;
1815 return if($line =~ /^--/);
1817 # next if($line =~ /^DROP/m);
1818 return if($line =~ /^BEGIN TRANSACTION/m);
1819 return if($line =~ /^COMMIT/m);
1820 return if $line =~ /^\s+$/; # skip whitespace only
1821 $self->_query_start($line);
1823 $self->dbh->do($line); # shouldn't be using ->dbh ?
1826 warn qq{$@ (running "${line}")};
1828 $self->_query_end($line);
1830 my @statements = $self->deployment_statements($schema, $type, undef, $dir, { no_comments => 1, %{ $sqltargs || {} } } );
1831 if (@statements > 1) {
1832 foreach my $statement (@statements) {
1833 $deploy->( $statement );
1836 elsif (@statements == 1) {
1837 foreach my $line ( split(";\n", $statements[0])) {
1843 =head2 datetime_parser
1845 Returns the datetime parser class
1849 sub datetime_parser {
1851 return $self->{datetime_parser} ||= do {
1852 $self->ensure_connected;
1853 $self->build_datetime_parser(@_);
1857 =head2 datetime_parser_type
1859 Defines (returns) the datetime parser class - currently hardwired to
1860 L<DateTime::Format::MySQL>
1864 sub datetime_parser_type { "DateTime::Format::MySQL"; }
1866 =head2 build_datetime_parser
1868 See L</datetime_parser>
1872 sub build_datetime_parser {
1874 my $type = $self->datetime_parser_type(@_);
1876 $self->throw_exception("Couldn't load ${type}: $@") if $@;
1881 my $_check_sqlt_version; # private
1882 my $_check_sqlt_message; # private
1883 sub _check_sqlt_version {
1884 return $_check_sqlt_version if defined $_check_sqlt_version;
1885 eval 'use SQL::Translator "0.09003"';
1886 $_check_sqlt_message = $@ || '';
1887 $_check_sqlt_version = !$@;
1890 sub _check_sqlt_message {
1891 _check_sqlt_version if !defined $_check_sqlt_message;
1892 $_check_sqlt_message;
1896 =head2 is_replicating
1898 A boolean that reports if a particular L<DBIx::Class::Storage::DBI> is set to
1899 replicate from a master database. Default is undef, which is the result
1900 returned by databases that don't support replication.
1904 sub is_replicating {
1909 =head2 lag_behind_master
1911 Returns a number that represents a certain amount of lag behind a master db
1912 when a given storage is replicating. The number is database dependent, but
1913 starts at zero and increases with the amount of lag. Default in undef
1917 sub lag_behind_master {
1923 return if !$self->_dbh;
1932 =head2 DBIx::Class and AutoCommit
1934 DBIx::Class can do some wonderful magic with handling exceptions,
1935 disconnections, and transactions when you use C<< AutoCommit => 1 >>
1936 combined with C<txn_do> for transaction support.
1938 If you set C<< AutoCommit => 0 >> in your connect info, then you are always
1939 in an assumed transaction between commits, and you're telling us you'd
1940 like to manage that manually. A lot of the magic protections offered by
1941 this module will go away. We can't protect you from exceptions due to database
1942 disconnects because we don't know anything about how to restart your
1943 transactions. You're on your own for handling all sorts of exceptional
1944 cases if you choose the C<< AutoCommit => 0 >> path, just as you would
1950 The module defines a set of methods within the DBIC::SQL::Abstract
1951 namespace. These build on L<SQL::Abstract::Limit> to provide the
1952 SQL query functions.
1954 The following methods are extended:-
1968 See L</connect_info> for details.
1972 See L</connect_info> for details.
1976 See L</connect_info> for details.
1982 Matt S. Trout <mst@shadowcatsystems.co.uk>
1984 Andy Grundman <andy@hybridized.org>
1988 You may distribute this code under the same terms as Perl itself.