DBIO-Sybase

 view release on metacpan or  search on metacpan

docs/adr/0002-ase-multi-storage-writer-and-bulk-connections.md  view on Meta::CPAN

standard pattern: one `Storage` object wraps exactly one DBI handle. Sybase
ASE breaks that model. `DBIO::Sybase::Storage::ASE` (`_init`) provisions up to
**three** sibling storage objects from one logical connection:

- the *primary* storage (the user-facing object);
- a `_writer_storage` — a second full storage/connection used to run
  insert/update operations that must be wrapped in their own transaction;
- a `_bulk_storage` — a third connection opened with `;bulkLogin=1` appended to
  the DSN, used for the `DBD::Sybase` bulk-copy (BCP) API.

The auxiliary storages hold a weakened `_parent_storage` backref, and a static
list (`@also_proxy_to_extra_storages`) installs proxy wrappers so that
connection-affecting calls (`disconnect`, `_connect_info`, `debug`, `schema`,
the `connect_call_*` setup hooks, ...) fan out to all three handles.

## Decision

Keep the three-connection architecture in `Storage::ASE`. Do **not** try to
collapse it to a single DBH to match the other drivers.

## Rationale

lib/DBIO/Sybase/Storage/ASE.pm  view on Meta::CPAN

  DBIO::Sybase::Storage::ASE::LOBWriter
  DBIO::Sybase::Storage::ASE::BulkInsert
  DBIO::Sybase::Storage::ASE::IdentityRetrieval
  DBIO::Sybase::Storage::ASE::TxnManager
  DBIO::Sybase::Storage
  DBIO::Storage::DBI::AutoCast
  DBIO::Storage::DBI::IdentityInsert
/;
use mro 'c3';
use DBIO::Carp;
use Scalar::Util qw/blessed weaken/;
use List::Util 'first';
use Sub::Name();
use Try::Tiny;
use Context::Preserve 'preserve_context';
use DBIO::Util 'sigwarn_silencer';
use version ();
use namespace::clean;


__PACKAGE__->sql_maker_class('DBIO::Sybase::SQLMaker');

lib/DBIO/Sybase/Storage/ASE.pm  view on Meta::CPAN

# create storage for insert/(update blob) transactions,
# unless this is that storage
  return if $self->_parent_storage;

  my $writer_storage = (ref $self)->new;

  $writer_storage->_is_writer_storage(1); # just info
  $writer_storage->connect_info($self->connect_info);
  $writer_storage->auto_cast($self->auto_cast);

  weaken ($writer_storage->{_parent_storage} = $self);
  $self->_writer_storage($writer_storage);

# create a bulk storage unless connect_info is a coderef
  return if ref($self->_dbi_connect_info->[0]) eq 'CODE';

# FreeTDS' blk-library cannot do BCP ("Type '7' not implemented", and BULK
# INSERT is rejected inside the multi-statement txn DBD::Sybase keeps open).
# Without a bulk storage the _insert_bulk eligibility check falls back to
# regular array inserts, which is the only thing that works under FreeTDS.
  return if $self->_using_freetds;

  my $bulk_storage = (ref $self)->new;

  $bulk_storage->_is_bulk_storage(1); # for special ->disconnect acrobatics
  $bulk_storage->connect_info($self->connect_info);

# this is why
  $bulk_storage->_dbi_connect_info->[0] .= ';bulkLogin=1';

  weaken ($bulk_storage->{_parent_storage} = $self);
  $self->_bulk_storage($bulk_storage);
}

for my $method (@also_proxy_to_extra_storages) {
  no strict 'refs';
  no warnings 'redefine';

  my $replaced = __PACKAGE__->can($method);

  *{$method} = Sub::Name::subname $method => sub {



( run in 1.327 second using v1.01-cache-2.11-cpan-600a1bdf6e4 )