diff options
Diffstat (limited to 'TODO_2005.txt')
-rw-r--r-- | TODO_2005.txt | 579 |
1 files changed, 579 insertions, 0 deletions
diff --git a/TODO_2005.txt b/TODO_2005.txt new file mode 100644 index 0000000..8020ae7 --- /dev/null +++ b/TODO_2005.txt @@ -0,0 +1,579 @@ +Change ideas for DBI +==================== + +--- Changes that may impact applications: + +Turning AutoCommit on, such as when { local $dbh->{AutoCommit} = 0; ... } +goes out of scope, should trigger rollback not commit. (ODBC does a commit) +RISK: This will break code that assumes a commit. +REMEDY: Explicitly $dbh->commit where required. +MJE: I may misunderstand this but ODBC commits in this case because + AutoCommit is turned back on again when the block completes and that + causes any outstanding txn to be committed. Neither DBD::ODBC or ODBC + turned AutoCommit back on themselves. + +Always taint check the $sql for do() and prepare() +if perl is in taint mode (can't be disabled). +RISK: May impact code running with taint enabled but not DBI TaintIn/Out +Also consider other changes to TaintIn/TaintOut attribute semantics. + +Alter tables() to default $schema to $dbh->current_schema. +So tables() will default to returning tables in the current schema. +(Should include public synonyms) +RISK: This will impact code requiring tables from multiple schema. +REMEDY: specify $schema parameter ("%" for all?) + +Add $dbh->current_schema (default to $dbh->{Username}) + +Remove old informix fudge in tables() (would only impact people +using very old DBD::Informix versions as it now has it's own). + +Remove "old-style" connect syntax (where driver name is 4th parameter). + +Change undocumented DBI->err and DBI->errstr methods to warn. + +Bundle enhanced DBD::Multiplex +RISK: may break apps using old DBD::Multiplex + +disconnect() implies rollback() unless AutoCommit (Driver.xst + drivers) + +--- Internal Changes + +Move DBI::xx classes to DBI::xx_base and sanction use of DBI::xx +classes for extensions via mixins. + +Increase size of DBIS (dbistate) structure and imp_xxh.com structures +and improve size/version sanity checks. + +Make ShowErrorStatement=>1 the default when handle is created + +Mandate use of dbivport.h and related macros. + +Drivers to alter trace level behaviour (no output at low levels +and use named trace topics). + +Mandate that NUM_OF_FIELDS must be set by execute() and +can't be deferred till $sth->{NUM_OF_FIELDS} or fetch*_*() called. + +Add PERL_NO_GET_CONTEXT for multiplicity/threads? + +Remove DBIS global and related macros. +Add dDBIS to be used in functions (eg like dTHR) that can't access it via a imp_xxh + +Remove PERL_POLLUTE (so some names will require PL_ or Perl_ prefixes) + - MJE I believe this is effectively done now as PERL_POLLUTE was removed + in 5.13.3 + +Update dbipport.h from latest Devel::PPPort. + +Add function pointers for setting fetched field values into DBIS. +IV, UV, NV, PV and SV? +Drivers to use this instead of calling sv_setpv (etc) themselves. +Use internally for set_fbav(). + +Add function pointer to indicate 'all fields set'. +Use for both per-field and per-row OnFetch hooks. + +New reset() method: +$dbh->reset - disconnects + discards all state related to the particular connection +$sth->reset - finish + discards all state related to the particular statement +Effectively think of a handle as having two parts: +attributes related to a particular connection/statement (CachedKids/NUM_OF_PARAMS) +and attribute not-related (AutoCommit/RaiseError). +The reset method resets the first set but not the second. +The reset method would call uncache(). + +Rework handle creation to use methods: +Maybe $h->new_child(\%handle_attr) + dr::connect => + $dbh = $drh->new_child(\%attr); + $dbh->connect(...) - calls $dbh->reset() +& db::prepare => + sub ...::db::prepare { + my ($dbh, $sql, $attr) = @_; + $sth = $dbh->new_child($attr) + my @statements = $dbh->preparse($sql); + $sth->{PendingStatements} = \@statements if @statements > 1; + $sth->prepare( shift @statements ) or return; + return $sth; + } + sub prepare_cached - no change, calls $dbh->prepare. + sub ...::st::prepare { + $sth->reset; + ... + } +Also need to consider $sth->more_results and its need for reset()-like behaviour. + +Need to enable drivers to work with old and new approaches, +which means having both ::db::prepare and ::st::prepare +When a driver is loaded the ::db::prepare() method +will be deleted if a ::st::reset method exists. + +Make $DBI::err etc plain (untied) variables. +Set them in set_err() and when returning from dispatch. +Clear them, if appropriate, when entering dispatch dispatch(). + +Enable drivers to provide a hash to map err codes into state values. + +Unified test suite infrastructure to be reused by all drivers. +A big project. + +-- others -- + +Add (auto-maintained) #define macro giving the version number of the DBI +as an integer in a form that can be used by #if statements (eg 1043000) +e.g. Have Makefile.PL write a .h file that contains the value and have +that #included by DBIXS.h + +Fixup @DBD::Foo::ISA and ?->setup_driver issues + +Add "imp_xxh_t* imp_xxh;" element to com struct that points back at +itself so macros can be written to work with imp_??h without needing casts. +ALso make it cheap to get h from imp_xxh so only imp_xxh needs +to be passed around. + +Add utility function that does SvUTF8_on(sv) if the sv contains +valid-looking utf8. To be used (perhaps via OnFetch hook) where +utf8 data is being stored in a non-utf8 aware database. + +Add DBIS->carp(varargs) to simplify access to Carp::carp so warnings +like "execute called with 1 bind variables when 0 are needed" fr do() +get reported against caller's file and line number and not a line in DBI.pm + +pre and post call hooks via ima structure? + +Remove _not_impl. Alias debug to trace in DBI::(dr/db/st) and remove +debug() method from internals. + +DBD::Multiplex enhancements (Thomas Kishel <tom@kishel.net>): +Enable DBIx::HA (http://search.cpan.org/~hasseily/DBIx-HA/HA.pm) features. +SQL translation hooks: +mx_translate_sql_parent - called by prepare() to translate sql from app +mx_translate_sql_child - called for each child handle so each can have different dialect +(note that mx_translate_sql_parent could parse into internal tree +from which mx_translate_sql_child then 'regenerates' custom sql for the child handle) +See also http://c-jdbc.objectweb.org/ + +Use subversion mechanism for $VERSION in source files. + +====== LATER ====== + +Define expected uft8 behaviour. Basically drivers need to set the +uft8 flag on returned strings themselves when appropriate. +The DBI I<may> define a way for an application to indicate that +a particular column should be flagged as uft8 to help drivers +that are not able to determine that themselves. +The DBI won't support automatic character set conversions. + +Define "topic bits" for TraceLevel. +%DBI::TraceTopics & %DBD::Foo::TraceTopics +"Lint" topic for extra checking, eg warn on $sth DESTROY if still Active +"Verbose" topic adds verbosity to any other enabled topics +"Connect" topic to log connect/disconnect/reconnect/failed-ping +Add topic flags to ima struct and log when bits match? +Use one bit for logging just the SQL statement executed +(with no extra text) ideally in a way that lets the text +file be parsed again later. Perhaps append ";\n\n\n" to each. +Add parameter values and row count as comments afterwards? +Use one bit for logging just Errors. + +Ability to remove a handle from the parents cache: + $sth->uncache; +and $dbh->uncache; for connect_cached + +Add discard_pending_rows() as an alias +for finish() - which will be deprecated. + +$sth->{ParamAttr} eg { "1" => SQL_VARCHAR, "2" => { TYPE=>SQL_VARCHAR, ora_type=>99 }}; + +$h->{KidsHandles} = ref to cache (array or hash?) +of weakrefs to child handles (bugs pre 5.8.5 with CLONE and weakrefs, +see Perl changes 21936 and 22106) +DESTROY could automatically disconnect/finish children + +Document DbTypeSubclass (ala DBIx::AnyDBD) +Polish up and document _dbtype_names with an external interface and using get_info. + +FetchHashReuse attrib (=1 or ={}) copy from dbh to sth +and use to optimise fetchrow_hash + +--- Changes that may affect driver authors + +Add PERL_NO_GET_CONTEXT for multiplicity/threads? +force it for drivers? +And enable xsbypass in dispatch if possible. + +Add log_where() to "trace level set to" log message. + +Add bind_col($n, \$foo, { OnFetch => sub { ... } }); + +Add way to specify default bind_col attributes for each TYPE +e.g. $dbh->{DefaultBindTypeArgs} = { + SQL_DATE => { TYPE => SQL_DATE }, + SQL_DATETIME => { TYPE => SQL_DATETIME, OnFetch => \&foo }, + }; + # effectively automatically adds these as defaults: + $sth->bind_col(1, \$foo, { + %{ $dbh->{DefaultBindTypeArgs}{$sth->{TYPE}->[1]}, # <== + OnFetch => sub { ... } + }); # YYYY-MM-DD + +Method call for drivers to get (or indicate they've got) the sth metadata +which can then be used to trigger default bind_cols. + +Add a handle flag to say that the driver has a hash that maps error +codes into SQLSTATE values. The error event mechanism could check for +the flag and lookup the SQLSTATE value for the error from the hash. +Allow code hook as well. Maybe $dbh->{SQLSTATE_map} = code or hash ref + +Add minimum subset of ODBC3 SQLSTATE values that should be supported +(and corresponding ODBC2 values?) + +Add more macro hooks to Driver.xst: ping, quote etc. + +Add dbh active checks to some more sth methods where reasonable. + +Define consise DBI<>DBD interface with view towards parrot. + note that parrot will use more method calls instead of + 'sideways' hooks into DBIS and the driver C code. +DBI::DBD::Base module? +Update DBI::DBD with overview and (at least) recommend Driver.xst strongly. +Find XS drivers that don't use it and talk to authors. + +#define a large negative number to mean 'error' from st_execute and +change *.xst to treat either that or -2 as an error. (The -2 is +a transition for old drivers.) + +--- Other changes + +Simplify layering/subclassing of DBD's + +Reconsider clone() API + +See comment under $drh->$connect_meth in DBI.pm about $drh->errstr + +Ensure child $h has err reset after connect_cached() or prepare_cached() +or else document that $DBI:err may be true after those methods even +though they haven't failed. Umm. Fixed if $DBI::err isn't tied. + +Change t/zz_*_pp.t to be t/zXX_*.t where XX is a combination of: + - 'pp' (for DBI_PUREPERL=2) + - 'mx' (for DBI_AUTOPROXY=dbi:Multiplex:) + - 'pr' (for DBI_AUTOPROXY=dbi:Proxy:) +mx and pr wouldn't both apply to the same test + +Add data structure describing attributes +Use the data structure to replace similar data in Proxy, Multiplex, +PurePerl and other places. + +Add OnConnect attribute to connect() esp. for connect_cached() + +Macro to get new statement handle for XS code + +Trace to tied file handle. + +Add method to try to make the connection (session) read-only. + +preparse() - incl ability to split statements on semicolon + +Hooks for method entry and exit. + +$dbh->{Statement} can be wrong because fetch doesn't update value +maybe imp_dbh holds imp_sth (or inner handle) of last sth method +called (if not DESTROY) and sth outer DESTROY clears it (to reduce ref count) +Then $dbh->{LastSth} would work (returning outer handle if valid). +Then $dbh->{Statement} would be the same as $dbh->{LastSth}->{Statement} +Also $dbh->{ParamValues} would be the same as $dbh->{LastSth}->{ParamValues}. + +Remove dummy 'Switch' driver. + +Sponge behave_like - generalize into new_child() + copy RaiseError, PrintError, HandleError etc from the specified handle + but which attributes? LongReadLen, LongTruncOk etc? Presumably all + as we're acting as a proxy behind the scenes. + Should behave_like handle be dbh or sth or either or same as parent? + +Add per-handle debug file pointer: + NULL default => h->dbis->tracefp + if not NULL then dup() via PerlIO for child handles + close(h->tracefp) at end of DESTROY + macro to do (h->tracefp || h->dbis->tracefp) + $h->{TraceFileHandle} ? (enable "local $h->{TraceFileHandle} = ..."?) + +Move TIEHASH etc to XS (and to PurePerl) + +Change CachedKids to be a simple attribute cached in the handle hash +to remove FETCH method call overhead in prepare_cached(). + +--- Other things to consider + +Add $h->err_errstr_state method that returns all three in one go. + +Support async (non-blocking) mode + +Add $sql = $dbh->show_create($schema_object_name) to return statement +that would create that schema object, where possible. + +Add $id = $dbh->get_session_id() and $dbh->kill_session_id($id). + +Study alternate DBI's: + ruby + python + php + others? + ADO object model +identify any features we could usefully support and any incompatibilities etc + +Add DB version (major.minor ISA major) to DbSubType ISA tree. + +Add API to get table create statement (ala SHOW CREATE TABLE foo in MySQL). + +Consider closer mapping to SQL3 CLI API for driver API. + +Phalanx - test coverage + +=cut + +*** Small/quick/simple changes/checks *** + +fetchall_hashref for multiple keys - pending + my $hash_key_name = $sth->{FetchHashKeyName} || 'NAME'; + my $names_hash = $sth->FETCH("${hash_key_name}_hash"); + + my @key_fields = (ref $key_field) ? @$key_field : ($key_field); + my @key_values; + foreach (@key_fields) { + + my $index = $names_hash->{$_}; # perl index not column + ++$index if defined $index; # convert to column number + $index ||= $key_field if DBI::looks_like_number($key_field) && $key_field>=1; + + push @key_values, undef; + $sth->bind_col($index, \$key_value[-1]) or return; + } + + my $rows = {}; + my $NAME = $sth->{$hash_key_name}; + while (my $row = $sth->fetchrow_arrayref($hash_key_name)) { + my $ref = $rows; + $ref = $ref->{$_} ||= {} for @key_values; + @{$ref}{@$NAME} = @$row; + } + return \%rows; + + + +*** Assorted to-do items and random thoughts *** IN NO PARTICULAR ORDER *** + +DBIx::DWIW + +make lasth return outer handle? + +update lasth on return from method so handles used by the implementation +of the called method don't affect it? + +document dbi_fetchall_arrayref_attr attr of selectall_arrayref(). + +ODBC 3.5 date and intervals types and subtypes (from unixODBC?) +http://www.vpservices.com/jeff/programs/SQL/docs/odbc-getinfo-msdn.html + +Proxy: allow config to specify SQL to allow/deny via regexen +Docs for connect_cached and test with proxy. + +Attribute to prepare() to prefer lazy-prepare, +e.g., don't talk to server till first execute +or a statement handle attribute is accessed. + +How to report error from attribute FETCH as fetch method is marked +keep_error? Perhaps some way to make the current keep_error value +in the dispatch code available to change (via pointer in DBIS?) so +a method can change the value of keep_error that's used when the +method returns. Fixed since 1.43? + +BINDING: + +Add to docs & tutorial re wrong bind type on a param may cause +index to not be used! (Find real examples first) +check using EXPLAIN SELECT * WHERE int_indexed_col='42' vs =42. +also WHERE int_column = '01' relies on db to convert '01' to an int +rather than convert int_colum values to strings (which wouldn't match). + +> And note that if you are using bind_param_inout as 'bind_param_by_ref', +> then the $maxlen parameter is redundant. I suspect all drivers could +> implement bind_param_by_ref; most drivers, and specifically the Informix +> driver, has no need for bind_param_inout as a mechanism for getting data +> back from the database as there are no methods in the database which +> work like that. With Informix, values are passed to the database for +> placeholders, and values are returned through a cursor, and that's all. +Okay. I'll take that as a vote for bind_param_by_ref as an alias for +bind_param_inout. >>todo. + +bind_param_by_ref (or bind_param_byref) could be provided as a fallback +method using a BeforeExecute hook to call bind_param with the 'current value' +from the reference. + +Should ParamValues hold the value or the ref? +Use ParamAttr to indicate byref? + +------ + +OTHERS: + +Add method like + sub perform_transaction { + my ($dbh, $attr, $coderef, @args) = @_; + my $wantarray = wantarray; + my $use_transaction = 1; + my $orig_AutoCommit = $dbh->{AutoCommit}; + if ($orig_AutoCommit) { + unless (eval { $dbh->{AutoCommit} = 0; 1 }) { + die unless $allow_non_transaction; + $use_transaction = 0; + } + } + local $dbh->{RaiseError} = 1; + eval { + @result = ($wantarray) ? $coderef->(@args) : scalar $coderef->(@args); + $dbh->commit if $use_transaction; + $attr->{OnCommit}->() if $attr->{OnCommit}->(); + }; + if ($@) { + local $@; protect original error + my $rv = eval { ($use_transaction) ? $dbh->rollback : 0 }; + $attr->{OnRollback}->($rv) if $attr->{OnRollback}; + } + die if $@; # propagate original error + $dbh->{AutoCommit} = 1 if $orig_AutoCommit; + return $result[0] unless $wantarray; + return @result; + } + +Change bind_column to save the info for get_fbav to use when +first called. Thus making bind before execute work for all drivers. + +ODBC attribute defining if transactions are supported +http://www.vpservices.com/jeff/programs/SQL/docs/odbc-getinfo-msdn.html + +Informix inspired changes? + +Add hook to DBI::DBD to write a myconfig.txt file into the +source directory containing key driver and config info. + +dbish - state AutoCommit status clearly at connect time. +(And try to set AutoCommit off in eval?) +test shell "/connect user pass" etc + +check out http://tegan.deltanet.com/~phlip/DBUIframe.html + +Check DBD::Proxy connect&fetch latency (e.g. CGI use). + +****** Less urgent changes ****** + +$dbh->ping($skip_seconds) - skip the ping if ping'd less than $skip_seconds ago +and $h->err is false +Change connect_cached() to use ping($skip_seconds || 1); + + +$dbh->get_inner_handle / set_inner_handle + use to make $dbh->connect return same handle +Hook to call code ref on each fetch, pass fbav ref +datarow_array(), datarow_arrayref(), datarow_hashref() +remove sth from prepare_cached cache. + + +Give handles names: $h->{Id} ? +Useful for reporting, Multiplex, DBD::AnyData etc etc +May become useful for weakrefs etc + +--- Fetch scroll and row set + +fetch_scroll() handling via get_fbav. +Also add: + row_array(offset) + row_arrayref(offset) + row_hashref(offset) +get_fbav has three modes: + single row - return cached RV to same cached AV + alternate rows - return RV to AV[row % 2] + row set - return RV to AV[++row] + +Enable fetchall_arrayref() to reuse a cached rowset so the overhead +of allocating and freeing the individual row arrays and the rowset +array can be avoided. fetchall_arrayref would then return the same +arrayref each time. Most useful when combined with $maxrows. + +Bless row into DBI::Row ? +Bless row set into DBI::Rowset ? +Give get/set access to entire rowset via method calls? + want to be able to plug in pre-loaded data row cache to new sth + so it'll return the same data. + +Add 'break handling' when field values change? +Use two fbav's so 'previous record' is available. +Define break fields and handlers. +Call them via an alternate fetch_with_break method. +Jan 2002: Also now see DBIx::FetchLoop (Brendan Fagan) +Alternatively, and perferably, add sufficient hooks for this to be +done efficiently externally. + +Devel::Leak integration? + +XA transaction interface. References: +http://xapool.experlog.com/ +http://www.opengroup.org/publications/catalog/s423.htm +http://www-106.ibm.com/developerworks/websphere/library/techarticles/0407_woolf/0407_woolf.html?ca=dnp-327 + +Consider issues affecting OSMM score. Add relevant notes to docs. + +--- DBI::Profile + +Add %time to per-node DBI::Profile dump + +Add 'executer' and 'fetcher' method attributes and increment +corresponding counters in DBIS when method with those attributes +are called. When profiling record in the profile data the amount +they have incremented. +Add DBI_PROFILE option so count is executions and avg time can be +totaltime/executions not totaltime/methodcalls. + +DBI::Profile: add simple way to normalise the sql (convert constants +to placeholders) so profiling is more effective for drivers/applications +which don't use placeholders. Requires preparse()? + +DBI::Profile: Add calc of approx XS method call and timing overhead +by calling perl_call("DBI::dbi_time") x100 at boot time for profile, +and add 1/100 (x2) to each sample. Beware Win32 where resolution +is too small and overhead will be 0 normally but may be eg 100ms +if overhead probe is on cusp of time unit. + +Add mechanism so "call path" can be included in the Path of the +profile data. Something like "<basename>@<linenum>;..." or +optionally just the basename part. (See log_where()) + +Allow code ref in Path and use result as string for that element of the Path. + +Fix dbi_time for Windows by using or linking-to Time::HiRes code. + +--- + +Add a C call to return boolean for is a number' for a given SV. +Needs to do the right thing for a non-numeric string SV that's been +tested in a numeric context (eg $a='S23'; foo() if $a==-1; $sth->execute($a)) +So if SvNVOK is true but the value is 0 then should also do looks_like_number() +to be sure. [Does perl's looks_like_number() do this already, if not what code do +callers of looks_like_number() use?] + +Record attrib STOREs so can be replayed/copied to new or cloned handle. + +--- Test suite (random thoughts beyond the basic architecture in my head) + +one test file = one scenario setup (fixture) +cleanup (destroy all data, disconnect etc) +repeat tests with different data types (CHAR vs NCHAR) (implies changing fixtures?) +repeat tests with contextual changes (pureperl/proxy/multiplex etc) +test with overloaded and other kinds of 'magical' values +Good to have 'behavior' tests were the outcome is noted but doesn't + trigger failure e.g. limitation tests: data values out of range, + eg truncation, may or may not cause an error depending on the database. +random order of subtests +leak detection after cleanup |