also enable that driver explicitly, see the documentation for more details.
With this driver there is unfortunately no way to get the C<last_insert_id>
-without doing a C<select max(col)>.
+without doing a C<SELECT MAX(col)>.
But your queries will be cached.
}
}
+# Make sure we have CHAINED mode turned on, we don't know how DBD::Sybase was
+# compiled.
+sub _populate_dbh {
+ my $self = shift;
+ $self->next::method(@_);
+ $self->_dbh->{syb_chained_txn} = 1;
+}
+
sub _using_freetds {
my $self = shift;
my ($sql, $bind) = $self->next::method (@_);
if ($op eq 'insert') {
- my ($identity_insert_on, $identity_insert_off, $identity_col);
my $table = $ident->from;
my $bind_info = $self->_resolve_column_info($ident, [map $_->[0], @{$bind}]);
- $identity_col =
+ my $identity_col =
List::Util::first { $bind_info->{$_}{is_auto_increment} } (keys %$bind_info);
if ($identity_col) {
- $identity_insert_on = "SET IDENTITY_INSERT $table ON";
- $identity_insert_off = "SET IDENTITY_INSERT $table OFF";
+ $sql =
+"SET IDENTITY_INSERT $table ON\n" .
+"$sql\n" .
+"SET IDENTITY_INSERT $table OFF"
} else {
$identity_col = List::Util::first {
$ident->column_info($_)->{is_auto_increment}
}
if ($identity_col) {
-# Sybase has nested transactions, only the outermost is actually committed
$sql =
- "BEGIN TRANSACTION\n" .
- ($identity_insert_on ? "$identity_insert_on\n" : '') .
"$sql\n" .
- ($identity_insert_off ? "$identity_insert_off\n" : '') .
- $self->_fetch_identity_sql($ident, $identity_col) . "\n" .
- "COMMIT";
+ $self->_fetch_identity_sql($ident, $identity_col) . "\n";
}
}
sub last_insert_id { shift->_identity }
-# override to handle TEXT/IMAGE
+# override to handle TEXT/IMAGE and nested txn
sub insert {
my ($self, $source, $to_insert) = splice @_, 0, 3;
my $dbh = $self->_dbh;
my $blob_cols = $self->_remove_blob_cols($source, $to_insert);
- my $updated_cols = $self->next::method($source, $to_insert, @_);
+# Sybase has nested transactions fortunately, because we have to do the insert
+# in a transaction to avoid race conditions with the SELECT MAX(COL) identity
+# method used when placeholders are enabled.
+ my $updated_cols = do {
+ local $self->{auto_savepoint} = 1;
+ my $args = \@_;
+ my $method = $self->next::can;
+ $self->txn_do(
+ sub { $self->$method($source, $to_insert, @$args) }
+ );
+ };
$self->_insert_blobs($source, $blob_cols, $to_insert) if %$blob_cols;