use base 'DBIx::Class::Storage';
-use strict;
+use strict;
use warnings;
use DBI;
use SQL::Abstract::Limit;
use DBIx::Class::Storage::DBI::Cursor;
use DBIx::Class::Storage::Statistics;
use IO::File;
+use Scalar::Util 'blessed';
__PACKAGE__->mk_group_accessors(
'simple' =>
ref $coderef eq 'CODE' or $self->throw_exception
('$coderef must be a CODE reference');
- return $coderef->($self, $self->_dbh, @_) if $self->{_in_dbh_do};
+ return $coderef->($self, $self->_dbh, @_) if $self->{_in_dbh_do}
+ || $self->{transaction_depth};
+
local $self->{_in_dbh_do} = 1;
my @result;
sub _execute {
my ($self, $op, $extra_bind, $ident, $bind_attributes, @args) = @_;
+ if( blessed($ident) && $ident->isa("DBIx::Class::ResultSource") ) {
+ $ident = $ident->from();
+ }
+
my ($sql, @bind) = $self->sql_maker->$op($ident, @args);
unshift(@bind,
map { ref $_ eq 'ARRAY' ? $_ : [ '!!dummy', $_ ] } @$extra_bind)
map { defined ($_ && $_->[1]) ? qq{'$_->[1]'} : q{'NULL'} } @bind;
$self->debugobj->query_start($sql, @debug_bind);
}
- my $sth = eval { $self->sth($sql,$op) };
- if (!$sth || $@) {
- $self->throw_exception(
- 'no sth generated via sql (' . ($@ || $self->_dbh->errstr) . "): $sql"
- );
- }
+ my ($rv, $sth);
+ RETRY: while (1) {
+ $sth = eval { $self->sth($sql,$op) };
- my $rv;
- if ($sth) {
- my $time = time();
-
- $rv = eval {
-
- my $placeholder_index = 1;
+ if (!$sth || $@) {
+ $self->throw_exception(
+ 'no sth generated via sql (' . ($@ || $self->_dbh->errstr) . "): $sql"
+ );
+ }
- foreach my $bound (@bind) {
+ if ($sth) {
+ my $time = time();
+ $rv = eval {
+ my $placeholder_index = 1;
- my $attributes = {};
- my($column_name, @data) = @$bound;
+ foreach my $bound (@bind) {
- if( $bind_attributes ) {
- $attributes = $bind_attributes->{$column_name}
- if defined $bind_attributes->{$column_name};
- }
+ my $attributes = {};
+ my($column_name, @data) = @$bound;
+
+ if( $bind_attributes ) {
+ $attributes = $bind_attributes->{$column_name}
+ if defined $bind_attributes->{$column_name};
+ }
- foreach my $data (@data)
- {
- $data = ref $data ? ''.$data : $data; # stringify args
+ foreach my $data (@data)
+ {
+ $data = ref $data ? ''.$data : $data; # stringify args
- $sth->bind_param($placeholder_index, $data, $attributes);
- $placeholder_index++;
- }
+ $sth->bind_param($placeholder_index, $data, $attributes);
+ $placeholder_index++;
+ }
+ }
+ $sth->execute();
+ };
+
+ if ($@ || !$rv) {
+ $self->throw_exception("Error executing '$sql': ".($@ || $sth->errstr))
+ if $self->connected;
+ $self->_populate_dbh;
+ } else {
+ last RETRY;
}
- $sth->execute();
- };
-
- if ($@ || !$rv) {
- $self->throw_exception("Error executing '$sql': ".($@ || $sth->errstr));
+ } else {
+ $self->throw_exception("'$sql' did not generate a statement.");
}
- } else {
- $self->throw_exception("'$sql' did not generate a statement.");
- }
+ } # While(1) to retry if disconencted
+
if ($self->debug) {
my @debug_bind =
map { defined ($_ && $_->[1]) ? qq{'$_->[1]'} : q{'NULL'} } @bind;
"Couldn't insert ".join(', ',
map "$_ => $to_insert->{$_}", keys %$to_insert
)." into ${ident}"
- ) unless ($self->_execute('insert' => [], $ident, $bind_attributes, $to_insert));
+ ) unless ($self->_execute('insert' => [], $source, $bind_attributes, $to_insert));
return $to_insert;
}
##use Data::Dumper;
##print STDERR Dumper( $data, $sql, [@bind] );
-
+
if ($sth) {
my $time = time();
-
- #$rv = eval {
- #
- # $sth->execute_array({
-
- # ArrayTupleFetch => sub {
-
- # my $values = shift @$data;
- # return if !$values;
- # return [ @{$values}[@bind] ];
- # },
-
- # ArrayTupleStatus => $tuple_status,
- # })
- #};
-
- ## Get the bind_attributes, if any exist
+
+ ## Get the bind_attributes, if any exist
my $bind_attributes = $self->source_bind_attributes($source);
- ## Bind the values and execute
- $rv = eval {
-
+ ## Bind the values and execute
+ $rv = eval {
+
my $placeholder_index = 1;
foreach my $bound (@bind) {
$attributes = $bind_attributes->{$column_name}
if defined $bind_attributes->{$column_name};
}
-
- my @data = map { $_->[$data_index] } @$data;
+
+ my @data = map { $_->[$data_index] } @$data;
$sth->bind_param_array( $placeholder_index, [@data], $attributes );
$placeholder_index++;
}
- $sth->execute_array( {ArrayTupleStatus => $tuple_status} );
+ $sth->execute_array( {ArrayTupleStatus => $tuple_status} );
- };
+ };
if ($@ || !defined $rv) {
my $errors = '';
- foreach my $tuple (@$tuple_status)
- {
+ foreach my $tuple (@$tuple_status) {
$errors .= "\n" . $tuple->[1] if(ref $tuple);
}
$self->throw_exception("Error executing '$sql': ".($@ || $errors));
my $self = shift @_;
my $source = shift @_;
my $bind_attributes = $self->source_bind_attributes($source);
- my $ident = $source->from;
- return $self->_execute('update' => [], $ident, $bind_attributes, @_);
+ return $self->_execute('update' => [], $source, $bind_attributes, @_);
}
my $source = shift @_;
my $bind_attrs = {}; ## If ever it's needed...
- my $ident = $source->from;
- return $self->_execute('delete' => [], $ident, $bind_attrs, @_);
+ return $self->_execute('delete' => [], $source, $bind_attrs, @_);
}
sub _select {
my $data_type = $source->column_info($column)->{data_type} || '';
$bind_attributes->{$column} = $self->bind_attribute_by_data_type($data_type)
- if $data_type;
+ if $data_type;
}
return $bind_attributes;
}
my %result;
- my $sth = $dbh->prepare("SELECT * FROM $table WHERE 1=0");
+ my $sth = $dbh->prepare($self->sql_maker->select($table, undef, \'1 = 0'));
$sth->execute;
my @columns = @{$sth->{NAME_lc}};
for my $i ( 0 .. $#columns ){
my %column_info;
- my $type_num = $sth->{TYPE}->[$i];
- my $type_name;
- if(defined $type_num && $dbh->can('type_info')) {
- my $type_info = $dbh->type_info($type_num);
- $type_name = $type_info->{TYPE_NAME} if $type_info;
- }
- $column_info{data_type} = $type_name ? $type_name : $type_num;
+ $column_info{data_type} = $sth->{TYPE}->[$i];
$column_info{size} = $sth->{PRECISION}->[$i];
$column_info{is_nullable} = $sth->{NULLABLE}->[$i] ? 1 : 0;
$result{$columns[$i]} = \%column_info;
}
+ $sth->finish;
+
+ foreach my $col (keys %result) {
+ my $colinfo = $result{$col};
+ my $type_num = $colinfo->{data_type};
+ my $type_name;
+ if(defined $type_num && $dbh->can('type_info')) {
+ my $type_info = $dbh->type_info($type_num);
+ $type_name = $type_info->{TYPE_NAME} if $type_info;
+ $colinfo->{data_type} = $type_name if $type_name;
+ }
+ }
return \%result;
}