X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBIx%2FClass%2FStorage%2FDBI%2FSybase.pm;h=5747cb948ddcfcac8d1dfa9dfeb1051fc744b66a;hb=587daa97726631a2a5edc95ea6bfe62bf340bd8d;hp=0e2682effc1092a93d382ae79ff4cb484ffe2d3f;hpb=0a9a9955657da2985e7f564e16389cfcd7f15ed5;p=dbsrgits%2FDBIx-Class.git diff --git a/lib/DBIx/Class/Storage/DBI/Sybase.pm b/lib/DBIx/Class/Storage/DBI/Sybase.pm index 0e2682e..5747cb9 100644 --- a/lib/DBIx/Class/Storage/DBI/Sybase.pm +++ b/lib/DBIx/Class/Storage/DBI/Sybase.pm @@ -419,19 +419,18 @@ sub update { my $is_identity_update = $identity_col && defined $fields->{$identity_col}; if (not $blob_cols) { - $self->_set_identity_insert($table, 'update') if $is_identity_update; + $self->_set_session_identity(UPDATE => $table, 'ON') + if $is_identity_update; + return $self->next::method(@_); - $self->_unset_identity_insert($table, 'update') if $is_identity_update; - } -# check that we're not updating a blob column that's also in $where - for my $blob (grep $self->_is_lob_column($source, $_), $source->columns) { - if (exists $where->{$blob} && exists $fields->{$blob}) { - croak -'Update of TEXT/IMAGE column that is also in search condition impossible'; - } + $self->_set_session_identity(UPDATE => $table, 'OFF') + if $is_identity_update; } +# If there are any blobs in $where, Sybase will return a descriptive error +# message. + # update+blob update(s) done atomically on separate connection $self = $self->_writer_storage; @@ -449,7 +448,8 @@ sub update { my @res; if (%$fields) { - $self->_set_identity_insert($table, 'update') if $is_identity_update; + $self->_set_session_identity(UPDATE => $table, 'ON') + if $is_identity_update; if ($wantarray) { @res = $self->next::method(@_); @@ -461,7 +461,8 @@ sub update { $self->next::method(@_); } - $self->_unset_identity_insert($table, 'update') if $is_identity_update; + $self->_set_session_identity(UPDATE => $table, 'OFF') + if $is_identity_update; } $guard->commit; @@ -469,21 +470,25 @@ sub update { return $wantarray ? @res : $res[0]; } -### the insert_bulk partially stolen from DBI/MSSQL.pm - -sub _set_identity_insert { - my ($self, $table, $op) = @_; +# for IDENTITY_INSERT / IDENTITY_UPDATE +sub _set_session_identity { + my ($self, $op, $table, $off_on) = @_; my $sql = sprintf ( - 'SET IDENTITY_%s %s ON', - (uc($op) || 'INSERT'), - $self->sql_maker->_quote ($table), + 'SET IDENTITY_%s %s %s', + uc $op, + $self->sql_maker->_quote($table), + uc $off_on, ); $self->_query_start($sql); my $dbh = $self->_get_dbh; - eval { $dbh->do ($sql) }; + eval { + local $dbh->{RaiseError} = 1; + local $dbh->{PrintError} = 0; + $dbh->do ($sql) + }; my $exception = $@; $self->_query_end($sql); @@ -491,31 +496,11 @@ sub _set_identity_insert { if ($exception) { $self->throw_exception (sprintf "Error executing '%s': %s", $sql, - $dbh->errstr, + $exception, ); } } -sub _unset_identity_insert { - my ($self, $table, $op) = @_; - - my $sql = sprintf ( - 'SET IDENTITY_%s %s OFF', - (uc($op) || 'INSERT'), - $self->sql_maker->_quote ($table), - ); - - $self->_query_start($sql); - - my $dbh = $self->_get_dbh; - $dbh->do ($sql); - - $self->_query_end($sql); -} - -# for tests -sub _can_insert_bulk { 1 } - sub insert_bulk { my $self = shift; my ($source, $cols, $data) = @_; @@ -525,7 +510,7 @@ sub insert_bulk { $source->columns; my $is_identity_insert = (List::Util::first - { $source->column_info ($_)->{is_auto_increment} } + { $_ eq $identity_col } @{$cols} ) ? 1 : 0; @@ -540,7 +525,7 @@ sub insert_bulk { (not $self->_bulk_disabled_due_to_coderef_connect_info_warned)) { carp <<'EOF'; Bulk API support disabled due to use of a CODEREF connect_info. Reverting to -array inserts. +regular array inserts. EOF $self->_bulk_disabled_due_to_coderef_connect_info_warned(1); } @@ -548,14 +533,8 @@ EOF if (not $use_bulk_api) { my $blob_cols = $self->_remove_blob_cols_array($source, $cols, $data); - my $dumb_last_insert_id = - $identity_col - && (not $is_identity_insert) - && ($self->_identity_method||'') ne '@@IDENTITY'; - ($self, my ($guard)) = do { - if ($self->{transaction_depth} == 0 && - ($blob_cols || $dumb_last_insert_id)) { + if ($self->{transaction_depth} == 0 && $blob_cols) { ($self->_writer_storage, $self->_writer_storage->txn_scope_guard); } else { @@ -563,9 +542,7 @@ EOF } }; - $self->_set_identity_insert ($source->name) if $is_identity_insert; $self->next::method(@_); - $self->_unset_identity_insert ($source->name) if $is_identity_insert; if ($blob_cols) { if ($is_identity_insert) { @@ -670,42 +647,14 @@ EOF } ); - my $bind_attributes = $self->source_bind_attributes($source); - - foreach my $slice_idx (0..$#source_columns) { - my $col = $source_columns[$slice_idx]; - - my $attributes = $bind_attributes->{$col} - if $bind_attributes && defined $bind_attributes->{$col}; - - my @slice = map $_->[$slice_idx], @new_data; - - $sth->bind_param_array(($slice_idx + 1), \@slice, $attributes); - } - - $bulk->_query_start($sql); - -# this is stolen from DBI::insert_bulk - my $tuple_status = []; - my $rv = eval { $sth->execute_array({ArrayTupleStatus => $tuple_status}) }; - - 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); - - $self->throw_exception(sprintf "%s for populate slice:\n%s", - ($tuple_status->[$i][1] || $err), - $self->_pretty_print ({ - map { $source_columns[$_] => $new_data[$i][$_] } (0 .. $#$cols) - }), - ); - } + my @bind = do { + my $idx = 0; + map [ $_, $idx++ ], @source_columns; + }; - $guard->commit; - $sth->finish; + $self->_execute_array( + $source, $sth, \@bind, \@source_columns, \@new_data, $guard + ); $bulk->_query_end($sql); }; @@ -743,7 +692,7 @@ sub _remove_blob_cols { my %blob_cols; for my $col (keys %$fields) { - if ($self->_is_lob_type($source->column_info($col)->{data_type})) { + if ($self->_is_lob_column($source, $col)) { my $blob_val = delete $fields->{$col}; if (not defined $blob_val) { $fields->{$col} = \'NULL'; @@ -767,7 +716,7 @@ sub _remove_blob_cols_array { for my $i (0..$#$cols) { my $col = $cols->[$i]; - if ($self->_is_lob_type($source->column_info($col)->{data_type})) { + if ($self->_is_lob_column($source, $col)) { for my $j (0..$#$data) { my $blob_val = delete $data->[$j][$i]; if (not defined $blob_val) { @@ -1063,10 +1012,10 @@ session variable. =head1 TRANSACTIONS Due to limitations of the TDS protocol, L, or both; you cannot -begin a transaction while there are active cursors. An active cursor is, for -example, a L that has been executed using -C or C but has not been exhausted or -L. +begin a transaction while there are active cursors; nor can you use multiple +active cursors within a transaction. An active cursor is, for example, a +L that has been executed using C or +C but has not been exhausted or L. For example, this will not work: @@ -1080,6 +1029,11 @@ For example, this will not work: } }); +This won't either: + + my $first_row = $large_rs->first; + $schema->txn_do(sub { ... }); + Transactions done for inserts in C mode when placeholders are in use are not affected, as they are done on an extra database handle.