sub txn_commit {
my $self = shift;
if ($self->{transaction_depth} == 1) {
- my $dbh = $self->_dbh;
$self->debugobj->txn_commit()
if ($self->debug);
$self->_dbh_commit;
sub _dbh_commit {
my $self = shift;
- $self->_dbh->commit;
+ my $dbh = $self->_dbh
+ or $self->throw_exception('cannot COMMIT on a disconnected handle');
+ $dbh->commit;
}
sub txn_rollback {
sub _dbh_rollback {
my $self = shift;
- $self->_dbh->rollback;
+ my $dbh = $self->_dbh
+ or $self->throw_exception('cannot ROLLBACK on a disconnected handle');
+ $dbh->rollback;
}
# This used to be the top-half of _execute. It was split out to make it
next unless ref $first_val eq 'SCALAR';
$colvalues{ $cols->[$i] } = $first_val;
-## This is probably unnecessary since $rs->populate only looks at the first
-## slice anyway.
-# if (grep {
-# ref $_ eq 'SCALAR' && $$_ eq $$first_val
-# } map $data->[$_][$i], (1..$#$data)) == (@$data - 1);
+ }
+
+ # check for bad data and stringify stringifiable objects
+ my $bad_slice = sub {
+ my ($msg, $col_idx, $slice_idx) = @_;
+ $self->throw_exception(sprintf "%s for column '%s' in populate slice:\n%s",
+ $msg,
+ $cols->[$col_idx],
+ do {
+ local $Data::Dumper::Maxdepth = 1; # don't dump objects, if any
+ Data::Dumper::Concise::Dumper({
+ map { $cols->[$_] => $data->[$slice_idx][$_] } (0 .. $#$cols)
+ }),
+ }
+ );
+ };
+
+ for my $datum_idx (0..$#$data) {
+ my $datum = $data->[$datum_idx];
+
+ for my $col_idx (0..$#$cols) {
+ my $val = $datum->[$col_idx];
+ my $sqla_bind = $colvalues{ $cols->[$col_idx] };
+ my $is_literal_sql = (ref $sqla_bind) eq 'SCALAR';
+
+ if ($is_literal_sql) {
+ if (not ref $val) {
+ $bad_slice->('bind found where literal SQL expected', $col_idx, $datum_idx);
+ }
+ elsif ((my $reftype = ref $val) ne 'SCALAR') {
+ $bad_slice->("$reftype reference found where literal SQL expected",
+ $col_idx, $datum_idx);
+ }
+ elsif ($$val ne $$sqla_bind){
+ $bad_slice->("inconsistent literal SQL value, expecting: '$$sqla_bind'",
+ $col_idx, $datum_idx);
+ }
+ }
+ elsif (my $reftype = ref $val) {
+ require overload;
+ if (overload::Method($val, '""')) {
+ $datum->[$col_idx] = "".$val;
+ }
+ else {
+ $bad_slice->("$reftype reference found where bind expected",
+ $col_idx, $datum_idx);
+ }
+ }
+ }
}
my ($sql, $bind) = $self->_prep_for_execute (
);
}
- $self->_query_start( $sql, @bind );
+ $self->_query_start( $sql, ['__BULK__'] );
my $sth = $self->sth($sql);
my $rv = do {
}
};
- $self->_query_end( $sql, @bind );
+ $self->_query_end( $sql, ['__BULK__'] );
return (wantarray ? ($rv, $sth, @bind) : $rv);
}
parser => 'SQL::Translator::Parser::DBIx::Class',
data => $schema,
);
- return $tr->translate;
+
+ my $ret = $tr->translate
+ or $self->throw_exception( 'Unable to produce deployment statements: ' . $tr->error);
+
+ return $ret;
}
sub deploy {