# pass scalarref to SQLA for literal sql if it's the same in all slices
for my $i (0..$#$cols) {
my $first_val = $data->[0][$i];
- next unless (Scalar::Util::reftype($first_val)||'') eq 'SCALAR';
+ next unless ref $first_val eq 'SCALAR';
$colvalues{ $cols->[$i] } = $first_val
if (grep {
- (Scalar::Util::reftype($_)||'') eq 'SCALAR' &&
- $$_ eq $$first_val
+ ref $_ eq 'SCALAR' && $$_ eq $$first_val
} map $data->[$_][$i], (1..$#$data)) == (@$data - 1);
}
my @bind = @$bind;
my $empty_bind = 1 if (not @bind) &&
- (grep { (Scalar::Util::reftype($_)||'') eq 'SCALAR' } values %colvalues)
- == @$cols;
+ (grep { ref $_ eq 'SCALAR' } values %colvalues) == @$cols;
if ((not @bind) && (not $empty_bind)) {
$self->throw_exception(
}
sub _execute_array {
- my ($self, $source, $sth, $bind, $cols, $data, $guard) = @_;
+ my ($self, $source, $sth, $bind, $cols, $data, $after_exec_cb) = @_;
## This must be an arrayref, else nothing works!
my $tuple_status = [];
$placeholder_index++;
}
- my $rv = eval { $sth->execute_array({ArrayTupleStatus => $tuple_status}) };
-
-# only needed for Sybase, it requires a commit before the $sth->finish
- $guard->commit if $guard;
+ my $rv = eval {
+ $sth->execute_array({ArrayTupleStatus => $tuple_status});
+ $after_exec_cb->() if $after_exec_cb;
+ };
+ my $err = $@ || $sth->errstr;
- $sth->finish;
+# Statement must finish even if there was an exception.
+ eval { $sth->finish };
+ $err = $@ unless $err;
- if (my $err = $@ || $sth->errstr) {
+ if ($err) {
my $i = 0;
++$i while $i <= $#$tuple_status && !ref $tuple_status->[$i];
my $dbh = $self->_get_dbh;
local $dbh->{RaiseError} = 1;
local $dbh->{PrintError} = 0;
+
+# In case of a multi-statement with a select, some DBDs (namely Sybase) require
+# the statement to be exhausted.
+ my $fetch = 0;
+ if ($self->_exhaust_statements && $sth->{Statement} =~ /(?:\n|;)select/i) {
+ $fetch = 1;
+ }
+
foreach (1..$count) {
$sth->execute;
-# In case of a multi-statement with a select, some DBDs (namely Sybase) require
-# the cursor to be exhausted.
- $sth->fetchall_arrayref;
+ $sth->fetchall_arrayref if $fetch;
}
};
my $exception = $@;
- $sth->finish;
+
+# Make sure statement is finished even if there was an exception.
+ eval { $sth->finish };
+ $exception = $@ unless $exception;
+
$self->throw_exception($exception) if $exception;
return $count;
}
+# Whether we prefer to exhaust cursors with results, or they can be
+# reused/finished without fetching anything. To be overridden to '1' in storages
+# that need it.
+sub _exhaust_statements { 0 }
+
sub update {
my ($self, $source, @args) = @_;