NAME
DBIO::Storage::DBI::AccessBroker - DBI-specific AccessBroker integration for DBIO storage
VERSION
version 0.900004
DESCRIPTION
Mixin for DBIO::Storage::DBI that provides the DBI-level DBIO::AccessBroker integration: connect-info detection and mode-based credential routing.
The abstract broker management API (set_access_broker, clear_access_broker, current_access_broker_connect_info, _assert_transaction_safe_access_broker) lives in DBIO::Storage.
_is_access_broker_connect_info
Returns true when the supplied connect_info looks like a broker-style invocation: an arrayref whose first member is a blessed DBIO::AccessBroker instance, either alone or followed by one plain hashref -- the connect call's own settings beside the broker, read by "_access_broker_call_info".
_access_broker_call_info
my $beside = $self->_access_broker_call_info([ $broker, \%options ]);
The connect call's own settings beside the broker, normalised the way the attribute hash of every other connect form is (_normalize_connect_info: async_mode, storage_options, sql_maker_options, attributes), or undef when the broker stands alone or beside an empty hash.
The hash takes every connect option (ADR 0030 addendum) except those naming the connection itself -- dsn, user, password, dbh_maker and the connection parameters dbname, host, port. Which database, and as whom, is the broker's answer (ADR 0013); naming it beside the broker throws.
A key left among the attributes that the storage would not apply to a connection of its own is not refused here but where that connection is opened ("_assert_access_broker_options_apply").
_access_broker_identity_keys
my @keys = $self->_access_broker_identity_keys;
The connect-info keys naming the connection itself -- dsn, user, password, dbh_maker, dbname, host, port -- which only the broker's answer gives. "_access_broker_call_info" refuses them beside a broker; DBIO::Replicated::Storage leaves them behind when it hands a broker-backed replicant the master's connect options, and hands any other replicant none of them but the master's credentials ("connect_replicants" in DBIO::Replicated::Storage).
set_access_broker
$storage->set_access_broker($broker);
$storage->set_access_broker($broker, $mode);
Attaches the broker ("set_access_broker" in DBIO::Storage). An embedded async backend this storage has already built gets it too ("set_access_broker" in DBIO::Storage::Async): its built pool asks the new broker for every connection it opens from then on, where it used to go on asking the broker before, or the static connect info. Connections that are open stay open and a transaction running on one stays with the broker it began with; nothing is torn down. A backend not built yet needs nothing: it is built from what this storage holds.
The connect info this storage keeps names the broker as well: a backend built anew after "disconnect" in DBIO::Storage::DBI, or built for the first time after the attach, is made from it and not from the DSN or the broker the storage was given before. Settings that stood beside a broker there stay; a storage that was never given connect info is left as it is.
A broker attached over static connect info remembers it: "clear_access_broker" puts it back, so the storage falls back to that DSN, sync and async alike. What the static connect info held beside the DSN (pool_size, DBD attributes) is not carried to a backend built from the broker; it is built from the broker alone, as a backend that has the broker attached is.
DBIO::Storage::DBI names set_access_broker itself and calls this one, for the reason given at "clear_access_broker".
clear_access_broker
Detaches the broker ("clear_access_broker" in DBIO::Storage). A storage with a broker attached holds nothing of its answer -- DSN, user, password -- so there is nothing a connection opened without the broker could be opened with. A storage with no broker attached keeps its connect info.
An embedded async backend goes with it: it asks the same broker for every pool and listen connection it opens, and once the broker is detached from this storage nothing more is to be opened from it. The backend this storage has built is detached too ("clear_access_broker" in DBIO::Storage::Async): its next connection fails saying that no broker is attached, and the connections it has open stay open, as this storage keeps its handle. A backend not built yet is not built from the detached broker either -- the first *_async call throws instead (_async_storage in DBIO::Storage::DBI). Connect info that a set_access_broker replaced -- the static DSN the storage was given -- is the exception: it is restored, and a backend built after the detach is made from it. Give the storage connect info again to go on.
DBIO::Storage::DBI names clear_access_broker itself and calls this one. It has to: this mixin stands behind DBIO::Storage in the method resolution order of a driver storage class that does not declare c3 -- the first base of DBIO::Storage::DBI, DBIO::Storage::QueryRewrite, inherits DBIO::Storage -- so such a class found the bare "clear_access_broker" in DBIO::Storage first and never ran this method. clear_access_broker was the one method of the mixins shadowed that way.
_merge_access_broker_call_info
$info = $self->_merge_access_broker_call_info($answer_info, $beside);
The broker's normalised answer with the settings beside the broker ("_access_broker_call_info") joined in. A setting given in both places must have the same value in both, or this throws naming it (DBIO::Storage::_merge_access_broker_settings); the async mode keeps the message naming both modes. pool_size leaves the attributes once the connection has a mode, whichever of the two hashes gave it.
_access_broker_backend_settings
my @names = $self->_access_broker_backend_settings([ $broker, \%options ]);
The names of the settings beside the broker that an async backend applies itself: DBD attributes and pool_size. Every other setting there -- the async mode, the storage options (on_connect_do, on_connect_call, ...), the SQL maker options (quote_names, ...), cursor_class and ignore_version -- is this storage's to apply, and a backend reads none of them from its own connect info whichever form it comes in: the pooled connections replay the connection actions from this storage (ADR 0049). Sorted; empty when there is nothing for the backend.
_access_broker_async_options
my $options = $self->_access_broker_async_options([ $broker, \%options ]);
The async options beside the broker other than pool_size -- acquire_timeout, max_waiters, txn_timeout and those the mode's backend declares -- as a hash reference, empty when there are none. A backend built from the broker alone is given these in [ $broker, \%options ]: it applies them without declaring broker_connect_options.
_current_dbi_connect_info
Returns the connect info to use for the current connection attempt: with a broker attached, its current answer for the requested mode; without one, the stored _dbi_connect_info.
With a broker attached, only its current answer will do. A broker that answers nothing throws (DBIO::Storage::current_access_broker_connect_info) rather than hand the connection the storage's previous, static connection; the storage keeps no earlier answer to fall back to.
An answer that is neither a hash of connection parameters nor the DBI form [ $dsn, $user, $password, \%attrs ] throws as well, naming the broker class and the shape of the answer, never a value of it: a plain string is taken for neither, and may be a DSN carrying a password.
_access_broker_dbi_args
my ($args, $attrs) = $self->_access_broker_dbi_args($mode);
my ($args, $attrs) = $self->_access_broker_dbi_args($mode, connecting => 1);
The broker's current answer joined with the settings beside the broker, as the arguments of DBI->connect ($args) and the full attribute set ($attrs). Formed anew at every call and kept nowhere: a connection (_connect) is opened with it, and _dbi_connect_info reads it.
With connecting => 1 the assertions of a connection of the storage's own apply ("_normalized_access_broker_connect_info", "_assert_access_broker_options_apply"); a plain read makes none.
_normalized_access_broker_connect_info
my $info = $self->_normalized_access_broker_connect_info($mode);
my $info = $self->_normalized_access_broker_connect_info($mode, connecting => 1);
The broker's current answer ("_current_dbi_connect_info"), normalised the way "connect_info" in DBIO::Storage::DBI normalises every connect form. Both connect_info and every new connection build on it.
An answer without a DSN throws, naming the broker class and the shape of the answer, never a value of it: a hash with neither a dsn nor a dbname key -- with or without host and port -- and a hash or the DBI form whose DSN is undefined or empty. An answer giving a code reference (dbh_maker) needs none. The credentials are the broker's, for the database the broker names: a storage with a broker attached never connects to $ENV{DBI_DSN} instead.
With connecting => 1 -- the storage is about to open a connection of its own with the answer -- a hash answer carrying a key this storage would not apply throws too, naming the broker class and the keys ("_assert_access_broker_parameters_apply"). connect_info does not pass it: an answer the storage is merely configured with may be for an async backend, which asks the broker itself.
_assert_access_broker_parameters_apply
$self->_assert_access_broker_parameters_apply($info);
Throws when a broker's hash answer -- $info is its normalised form -- carries a key this storage would not apply. Of a hash, a DBI storage builds dbname, host and port into the DSN and nothing else; what it does not consume itself goes to DBI->connect as an attribute, and a DBD keeps a lowercase attribute it does not know without a word. A parameter of the database client -- sslmode, connect_timeout, sslrootcert, ... -- would be lost there and the connection opened without it, while an async transport hands the same key to its client. So the storage does not connect with the answer.
It is asked where the storage opens a connection of its own, for every connection (_connect, through "_normalized_access_broker_connect_info"), and not by connect_info: the same answer may be all an async backend needs, and the storage that owns the backend then never connects with it itself. Until it does, nothing is refused.
A key of the answer passes when it is one of:
what the storage consumes: the connection itself ("_access_broker_identity_keys"), the storage options, the SQL maker options,
cursor_class,async,pool_sizeandignore_version;the name of a DBI attribute: one starting with an uppercase letter (DBI's own are
MixedCase), one starting withprivate_,dbi_ordbd_, or one starting with a prefix of the DBD the answer's DSN names ("_dbd_attribute_prefixes" in DBIO::Storage::DBI) --pg_fordbi:Pg:;set to
undefor to the empty string, which names no parameter.
Every other key is refused: any other lowercase name, the prefix of another DBD and a lowercase name on a DBD whose prefix is not known among them, since neither can be told from a client parameter. The error names the broker class and the keys, never a value, and the two ways out. One is the DBI form [ $dsn, $user, $password, \%attrs ], which takes a client parameter inside its DSN and, in its attribute hash -- not looked into -- a DBI attribute the storage does not recognise as one. The other is a broker answering by the storage that asks ("connect_info_for_storage" in DBIO::AccessBroker): the DBI storage an answer it applies in full, an async transport the hash with its client's parameters.
An answer giving a code reference (dbh_maker) is not looked into either: the code opens the connection, and the storage applies nothing of the answer to it.
_assert_access_broker_options_apply
$self->_assert_access_broker_options_apply($info, $beside);
Throws when the hash beside the broker -- $beside is its normalised form, as "_access_broker_call_info" returns it -- carries a key this storage would not apply to a connection opened with the broker's answer $info. What stands beside a broker and is not consumed by the storage joins the DBI attributes of every answer ("_merge_access_broker_call_info"), so a parameter of the database client given there -- [ $broker, { sslmode => 'require' } ] -- is lost the way one in a hash answer is, and the storage does not connect with it either.
Which key passes is decided as for a hash answer ("_assert_access_broker_parameters_apply"), the DBD being the one the DSN of the answer names -- the answer in whichever form, a hash or the DBI form. And it is asked at the same place: where the storage opens a connection of its own, for every connection, never by connect_info. The options beside a broker also go to an async backend, which takes or refuses them itself ("_access_broker_call_options" in DBIO::Storage::Async).
The error names the broker class and the keys, never a value, and says that they stand beside the broker. A parameter of the database client is the broker's to answer: inside the DSN of the DBI form, or by the storage that asks ("connect_info_for_storage" in DBIO::AccessBroker).
Beside an answer giving a code reference (dbh_maker) the yardstick is stricter: the code opens the connection, and the storage applies nothing that stands beside the broker to it, a DBI attribute no more than a client parameter. So every key the storage does not consume itself ("_access_broker_unconsumed_options") throws, LongReadLen as much as sslmode; the storage options, the SQL maker options, async, pool_size and ignore_version still pass. The options are judged before they are set against the answer ("_merge_access_broker_call_info"), so this error wins over a conflict between the two.
_access_broker_unapplied_parameters
my @names = $self->_access_broker_unapplied_parameters(\%attributes, $dsn);
The keys of \%attributes -- what a normalised connect info leaves for DBI->connect -- that a connection to $dsn would not apply, sorted; none when \%attributes is undefined. The yardstick of "_assert_access_broker_parameters_apply" and "_assert_access_broker_options_apply", described with the former.
_access_broker_unconsumed_options
my @names = $self->_access_broker_unconsumed_options(\%attributes);
The keys of \%attributes that name something -- defined and not empty -- and that the storage consumes itself neither ("_access_broker_consumed_keys"), sorted. What stands beside a broker answering a code reference (dbh_maker) is judged by it: the code opens the connection and no DBI attribute goes to it, so every other key is lost, a DBI attribute as much as a client parameter.
_access_broker_consumed_keys
my @keys = $self->_access_broker_consumed_keys;
What the storage consumes itself of a normalised attribute hash, whatever the DBD: the connection itself ("_access_broker_identity_keys"), pool_size, ignore_version and -- with an async mode -- the async options (acquire_timeout, max_waiters, txn_timeout and those the backend of the mode declares). Without a mode they are no DBIO options and the DBD decides.
AUTHOR
DBIO & DBIx::Class Authors
COPYRIGHT AND LICENSE
Copyright (C) 2026 DBIO Authors Portions Copyright (C) 2005-2025 DBIx::Class Authors Based on DBIx::Class, heavily modified.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.