Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Massive rewrite of bind handling, and overall simplification of ::Sto…
…rage::DBI There's no practical way to split this into smaller pieces so here it goes: Bind attribute handling was badly integrated into dbic almost from the start. Until now the only information about a value was encoded as the column name contained as the first element of the bind arrayref. The column name was then resolved to the proper colinfo (deep in ::Storage::DBI) and then a match was ran on the datatype to try to find an appropriate set of bind attributes. Besides being fragile and inefficient, this method also broke down completely when: * No column name could be associated with a bind (arguments to complex literal functions) * as_query results would encode the column names that can no longer be resolved since the inner result sources are no longer visible To fix this all up and provide more flexibility the standard [ $col => $val ] was replaced with [ \%args => $val ]. The format of \%args is currently: { dbd_attrs => ' If present (in any form) this is what is being passed directly to bind_param. Note that different DBD's expect different bind args, e.g. DBD::SQLite takes a single numerical type, while DBD::Pg takes a hashref if bind options. If this is specified all other bind options described below are ignored ', sqlt_datatype => ' If present it is used to infer the actual bind attribute by passing to $resolved_storage->bind_attribute_by_data_type(). Note that the data type is somewhat freeform (hence the sqlt_ prefix) - currently drivers are expected to dtrt when given a common datatype name (not ideal, but that's what we got at this point). Defaults to the "data_type" from the add_columns colinfo. ', sqlt_size => ' Currently used to correctly allocate buffers for bind_param_inout(). Defaults to "size" from the add_columns colinfo, or to a sensible value based on the "data_type" ', dbic_colname => ' Used to fill in missing sqlt_datatype and sqlt_size attributes (if they are explicitly specified they are never overriden). Also used by some weird DBDs where the column name should be available at bind_param time (hello Oracle). ', } For backcompat/convenience the following shortcuts are supported: [ $name => $val ] === [ { dbic_colname => $name }, $val ] [ \$dt => $val ] === [ { sqlt_datatype => $dt }, $val ] [ undef => $val ] === [ {}, $val ] ( pending in the next patch: [ $val ] === [ {}, $val ] ) On each passage through the storages (either for execute or for as_query formatting) the information is filled in whenever available, so that by the time the final binds_param takes place ::Storage::DBI::_dbi_attrs_for_bind has all the available information about a particular bind value (no matter where it came from). A side efect of this is that as_query now always returns resolved [ \%args => $val ] forms of bind values (hence the huge amount of test changes in this patchset). While it should not be a major concern, it could potentially throw off tests that expect a specific output of as_query. If this becomes a problem a "compat mode as_query" flag will be introduced asap. Additional changes in this patchset are: * The signatures of pretty much the entire execution chain changed. Luckily everything that required changing was private. All drivers were adjusted appropriately (though something could have been missed). Affected methods on ::Storage::DBI are: _prep_for_execute _dbh_execute _execute _select_args_to_query _max_column_bytesize additionally the invocation of _prep_for_execute moved from _dbh_execute to _execute, and the return of _select_args also changed * source_bind_attributes was deprecated. Luckily it was never documented in the main documentation. Sadly it was documented in individual storage drivers. As such it was necessary to provide a compat shim that would invoke the thing if it is detected (with the approproate warning) * _fix_bind_params was renamed to _format_for_trace
- Loading branch information