use Scalar::Util();
use List::Util();
+# what version of sqlt do we require if deploy() without a ddl_dir is invoked
+# when changing also adjust the corresponding author_require in Makefile.PL
+my $minimum_sqlt_version = '0.11002';
+
+
__PACKAGE__->mk_group_accessors('simple' =>
qw/_connect_info _dbi_connect_info _dbh _sql_maker _sql_maker_opts _conn_pid
_conn_tid transaction_depth _dbh_autocommit _driver_determined savepoints/
$weak_self->throw_exception("DBI Exception: $_[0]");
}
else {
+ # the handler may be invoked by something totally out of
+ # the scope of DBIC
croak ("DBI Exception: $_[0]");
}
};
}
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("Unexpected populate error: $err")
if ($i > $#$tuple_status);
- require Data::Dumper;
- local $Data::Dumper::Terse = 1;
- local $Data::Dumper::Indent = 1;
- local $Data::Dumper::Useqq = 1;
- local $Data::Dumper::Quotekeys = 0;
- local $Data::Dumper::Sortkeys = 1;
-
$self->throw_exception(sprintf "%s for populate slice:\n%s",
($tuple_status->[$i][1] || $err),
- Data::Dumper::Dumper(
- { map { $cols->[$_] => $data->[$i][$_] } (0 .. $#$cols) }
- ),
+ $self->_pretty_print ({
+ map { $cols->[$_] => $data->[$i][$_] } (0 .. $#$cols)
+ }),
);
}
- $sth->finish;
$self->_query_end( $sql, @bind );
return (wantarray ? ($rv, $sth, @bind) : $rv);
}
return;
}
+# SQLT version handling
+{
+ my $_sqlt_version_ok; # private
+ my $_sqlt_version_error; # private
+
+ sub _sqlt_version_ok {
+ if (!defined $_sqlt_version_ok) {
+ eval "use SQL::Translator $minimum_sqlt_version";
+ if ($@) {
+ $_sqlt_version_ok = 0;
+ $_sqlt_version_error = $@;
+ }
+ else {
+ $_sqlt_version_ok = 1;
+ }
+ }
+ return $_sqlt_version_ok;
+ }
+
+ sub _sqlt_version_error {
+ shift->_sqlt_version_ok unless defined $_sqlt_version_ok;
+ return $_sqlt_version_error;
+ }
+
+ sub _sqlt_minimum_version { $minimum_sqlt_version };
+}
+
sub DESTROY {
my $self = shift;