}
my %colvalues;
- my $table = $source->from;
@colvalues{@$cols} = (0..$#$cols);
-# XXX some bulk APIs require column list in database order
- my ($sql, @bind) = $self->sql_maker->insert($table, \%colvalues);
+
+ # bind 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';
+
+ $colvalues{ $cols->[$i] } = $first_val
+ if (grep {
+ (Scalar::Util::reftype($_)||'') eq 'SCALAR' &&
+ $$_ eq $$first_val
+ } map $data->[$_][$i], (1..$#$data)) == (@$data - 1);
+ }
+
+ my ($sql, $bind) = $self->_prep_for_execute (
+ 'insert', undef, $source, [\%colvalues]
+ );
+ my @bind = @$bind;
+
+ my $empty_bind = 1 if (not @bind) &&
+ (grep { (Scalar::Util::reftype($_)||'') eq 'SCALAR' } values %colvalues)
+ == @$cols;
+
+ if ((not @bind) && (not $empty_bind)) {
+ croak 'Cannot insert_bulk without support for placeholders';
+ }
$self->_query_start( $sql, @bind );
my $sth = $self->sth($sql, 'insert', $sth_attr);
+ if ($empty_bind) {
+ # bind_param_array doesn't work if there are no binds
+ eval {
+ local $self->_get_dbh->{RaiseError} = 1;
+ local $self->_get_dbh->{PrintError} = 0;
+ foreach (0..$#$data) {
+ $sth->execute;
+ $sth->fetchall_arrayref;
+ }
+ };
+ my $exception = $@;
+ $sth->finish;
+ $self->throw_exception($exception) if $exception;
+ return;
+ }
+
# @bind = map { ref $_ ? ''.$_ : $_ } @bind; # stringify args
## This must be an arrayref, else nothing works!
$sth->bind_param_array( $placeholder_index, [@data], $attributes );
$placeholder_index++;
}
+
my $rv = eval { $sth->execute_array({ArrayTupleStatus => $tuple_status}) };
+ $sth->finish;
if (my $err = $@ || $sth->errstr) {
my $i = 0;
++$i while $i <= $#$tuple_status && !ref $tuple_status->[$i];
- $self->throw_exception($sth->errstr || "Unexpected populate error: $err")
+ $self->throw_exception("Unexpected populate error: $err")
if ($i > $#$tuple_status);
require Data::Dumper;
local $Data::Dumper::Sortkeys = 1;
$self->throw_exception(sprintf "%s for populate slice:\n%s",
- $tuple_status->[$i][1],
+ ($tuple_status->[$i][1] || $err),
Data::Dumper::Dumper(
{ map { $cols->[$_] => $data->[$i][$_] } (0 .. $#$cols) }
),
);
}
- $self->throw_exception($sth->errstr) if !$rv;
-
- $sth->finish;
$self->_query_end( $sql, @bind );
return (wantarray ? ($rv, $sth, @bind) : $rv);