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 )