X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBIx%2FClass%2FStorage%2FDBI.pm;h=c218ef1d6cc8362be2401744b2174964699bac88;hb=9292561714255448d9ac3aa96eaacb287537ab24;hp=47f88dfb54401b182614c73d03ae989ad45f5aca;hpb=7be93b0768bf9b0a2c1b3d5f191ba7fd2f9937ac;p=dbsrgits%2FDBIx-Class.git diff --git a/lib/DBIx/Class/Storage/DBI.pm b/lib/DBIx/Class/Storage/DBI.pm index 47f88df..c218ef1 100644 --- a/lib/DBIx/Class/Storage/DBI.pm +++ b/lib/DBIx/Class/Storage/DBI.pm @@ -6,6 +6,7 @@ use DBI; use SQL::Abstract::Limit; use DBIx::Class::Storage::DBI::Cursor; use IO::File; +use Carp::Clan qw/DBIx::Class/; BEGIN { @@ -142,11 +143,19 @@ sub limit_dialect { return $self->{limit_dialect}; } +package DBIx::Class::Storage::DBI::DebugCallback; + +sub print { + my ($self, $string) = @_; + $string =~ m/^(\w+)/; + ${$self}->($1, $string); +} + } # End of BEGIN block use base qw/DBIx::Class/; -__PACKAGE__->load_components(qw/Exception AccessorGroup/); +__PACKAGE__->load_components(qw/AccessorGroup/); __PACKAGE__->mk_group_accessors('simple' => qw/connect_info _dbh _sql_maker debug debugfh cursor on_connect_do transaction_depth/); @@ -157,7 +166,7 @@ sub new { $new->transaction_depth(0); if (defined($ENV{DBIX_CLASS_STORAGE_DBI_DEBUG}) && ($ENV{DBIX_CLASS_STORAGE_DBI_DEBUG} =~ /=(.+)$/)) { - $new->debugfh(IO::File->new($1, 'w')||die "Cannot open trace file $1"); + $new->debugfh(IO::File->new($1, 'w')||croak "Cannot open trace file $1"); } else { $new->debugfh(IO::File->new('>&STDERR')); } @@ -195,14 +204,50 @@ should be an IO::Handle compatible object (only the C method is used). Initially set to be STDERR - although see information on the L environment variable. +=head2 debugcb + +Sets a callback to be executed each time a statement is run; takes a sub +reference. Overrides debugfh. Callback is executed as $sub->($op, $info) +where $op is SELECT/INSERT/UPDATE/DELETE and $info is what would normally +be printed. + =cut -sub dbh { +sub debugcb { + my ($self, $cb) = @_; + my $cb_obj = bless(\$cb, 'DBIx::Class::Storage::DBI::DebugCallback'); + $self->debugfh($cb_obj); +} + +sub disconnect { my ($self) = @_; + + if( $self->connected ) { + $self->_dbh->rollback unless $self->_dbh->{AutoCommit}; + $self->_dbh->disconnect; + $self->_dbh(undef); + } +} + +sub connected { + my ($self) = @_; + my $dbh; - unless (($dbh = $self->_dbh) && $dbh->FETCH('Active') && $dbh->ping) { + (($dbh = $self->_dbh) && $dbh->FETCH('Active') && $dbh->ping) +} + +sub ensure_connected { + my ($self) = @_; + + unless ($self->connected) { $self->_populate_dbh; } +} + +sub dbh { + my ($self) = @_; + + $self->ensure_connected; return $self->_dbh; } @@ -277,16 +322,24 @@ sub _execute { my ($self, $op, $extra_bind, $ident, @args) = @_; my ($sql, @bind) = $self->sql_maker->$op($ident, @args); unshift(@bind, @$extra_bind) if $extra_bind; - $self->debugfh->print("$sql: @bind\n") if $self->debug; + if ($self->debug) { + my @debug_bind = map { defined $_ ? $_ : 'NULL' } @bind; + $self->debugfh->print("$sql: @debug_bind\n"); + } my $sth = $self->sth($sql,$op); @bind = map { ref $_ ? ''.$_ : $_ } @bind; # stringify args - my $rv = $sth->execute(@bind); + my $rv; + if ($sth) { + $rv = $sth->execute(@bind); + } else { + croak "'$sql' did not generate a statement."; + } return (wantarray ? ($rv, $sth, @bind) : $rv); } sub insert { my ($self, $ident, $to_insert) = @_; - $self->throw( "Couldn't insert ".join(', ', map "$_ => $to_insert->{$_}", keys %$to_insert)." into ${ident}" ) + croak( "Couldn't insert ".join(', ', map "$_ => $to_insert->{$_}", keys %$to_insert)." into ${ident}" ) unless ($self->_execute('insert' => [], $ident, $to_insert)); return $to_insert; } @@ -325,10 +378,14 @@ sub select { return $self->cursor->new($self, \@_, $attrs); } +# Need to call finish() to work round broken DBDs + sub select_single { my $self = shift; my ($rv, $sth, @bind) = $self->_select(@_); - return $sth->fetchrow_array; + my @row = $sth->fetchrow_array; + $sth->finish(); + return @row; } sub sth { @@ -367,6 +424,8 @@ sub columns_info_for { return \%result; } +sub DESTROY { shift->disconnect } + 1; =head1 ENVIRONMENT VARIABLES