Author: timbo
Date: Sun Feb 1 02:31:07 2004
New Revision: 46
Modified:
dbi/trunk/Changes
dbi/trunk/DBI.pm
dbi/trunk/DBI.xs
dbi/trunk/Makefile.PL
dbi/trunk/README
dbi/trunk/ToDo
dbi/trunk/lib/DBD/ExampleP.pm
dbi/trunk/lib/DBD/NullP.pm
dbi/trunk/lib/DBD/Sponge.pm
dbi/trunk/lib/DBI/DBD.pm
dbi/trunk/lib/DBI/DBD/Metadata.pm
dbi/trunk/t/01basics.t
dbi/trunk/t/03handle.t
dbi/trunk/t/05thrclone.t
Log:
Changes for DBI-1.40
Modified: dbi/trunk/Changes
==============================================================================
--- dbi/trunk/Changes (original)
+++ dbi/trunk/Changes Sun Feb 1 02:31:07 2004
@@ -4,18 +4,24 @@
=cut
-Need to add docs for DbTypeSubclass (ala DBIx::AnyDBD)
-Move TIEHASH etc to XS (and pureperl)
+=head1 CHANGES
-$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}.
-Add more macro hooks to Driver.xst: ping, quote etc.
+=head2 Changes in DBI 1.40, 7th January 2004
-=head1 CHANGES
+ Fixed handling of CachedKids when DESTROYing threaded handles.
+ Fixed sql_user_name() in DBI::DBD::Metadata (used by write_getinfo_pm)
+ to use $dbh->{Username}. Driver authors please update your code.
+
+ Changed connect_cached() when running under Apache::DBI
+ to route calls to Apache::DBI::connect().
+
+ Added CLONE() to DBD::Sponge and DBD::ExampleP.
+ Added warning when starting a new thread about any loaded driver
+ which does not have a CLONE() function.
+ Added new prepare_cache($sql, \%attr, 3) option to manage Active handles.
+ Added SCALE and NULLABLE support to DBD::Sponge.
+ Added missing execute() in fetchall_hashref docs thanks to Iain Truskett.
+ Added a CONTRIBUTING section to the docs with notes on creating patches.
=head2 Changes in DBI 1.39, 27th November 2003
Modified: dbi/trunk/DBI.pm
==============================================================================
--- dbi/trunk/DBI.pm (original)
+++ dbi/trunk/DBI.pm Sun Feb 1 02:31:07 2004
@@ -1,7 +1,7 @@
-# $Id: DBI.pm,v 11.40 2003/11/27 23:29:06 timbo Exp $
+# $Id: DBI.pm,v 11.42 2004/01/08 14:03:46 timbo Exp $
# vim: ts=8:sw=4
#
-# Copyright (c) 1994-2003 Tim Bunce Ireland
+# Copyright (c) 1994-2004 Tim Bunce Ireland
#
# See COPYRIGHT section in pod text below for usage and distribution rights.
#
@@ -9,7 +9,7 @@
require 5.006_00;
BEGIN {
-$DBI::VERSION = "1.39"; # ==> ALSO update the version in the pod text below!
+$DBI::VERSION = "1.40"; # ==> ALSO update the version in the pod text below!
}
=head1 NAME
@@ -84,10 +84,9 @@
=head2 GETTING HELP
-If you have questions about DBI, you can get help from
-the I<[EMAIL PROTECTED]> mailing list.
-You can get help on subscribing and using the list by emailing
-I<[EMAIL PROTECTED]>.
+If you have questions about DBI, or DBD driver modules, you can get
+help from the I<[EMAIL PROTECTED]> mailing list. You can get help
+on subscribing and using the list by emailing I<[EMAIL PROTECTED]>.
(To help you make the best use of the dbi-users mailing list,
and any other lists or forums you may use, I I<strongly>
@@ -119,8 +118,8 @@
=head2 NOTES
-This is the DBI specification that corresponds to the DBI version 1.39
-(C<$Date: 2003/11/27 23:29:06 $>).
+This is the DBI specification that corresponds to the DBI version 1.40
+(C<$Date: 2004/01/08 14:03:46 $>).
The DBI is evolving at a steady pace, so it's good to check that
you have the latest copy.
@@ -151,7 +150,7 @@
package DBI;
-my $Revision = substr(q$Revision: 11.40 $, 10);
+my $Revision = substr(q$Revision: 11.42 $, 10);
use Carp();
use DynaLoader ();
@@ -394,7 +393,7 @@
last_insert_id => { U =>[3,4,'$table_name, $field_name [, \%attr ]'],
O=>0x0100 },
preparse => { }, # XXX
prepare => { U =>[2,3,'$statement [, \%attr]'], O=>0x0200 },
- prepare_cached => { U =>[2,4,'$statement [, \%attr [, $allow_active ] ]'] },
+ prepare_cached => { U =>[2,4,'$statement [, \%attr [, $if_active ] ]'] },
selectrow_array => { U =>[2,0,'$statement [, \%attr [, @bind_params ] ]'] },
selectrow_arrayref=>{U =>[2,0,'$statement [, \%attr [, @bind_params ] ]'] },
selectrow_hashref=>{ U =>[2,0,'$statement [, \%attr [, @bind_params ] ]'] },
@@ -479,18 +478,26 @@
sub CLONE {
my $olddbis = $DBI::_dbistate;
_clone_dbis() unless $DBI::PurePerl; # clone the DBIS structure
- %DBI::installed_drh = (); # clear loaded drivers so they have a chance to
reinitialize
DBI->trace_msg(sprintf "CLONE DBI for new thread %s\n",
$DBI::PurePerl ? "" : sprintf("(dbis %x -> %x)",$olddbis, $DBI::_dbistate));
+ while ( my ($driver, $drh) = each %DBI::installed_drh) {
+ no strict 'refs';
+ next if defined &{"DBD::${driver}::CLONE"};
+ warn("$driver has no driver CLONE() function so is unsafe threaded\n");
+ }
+ %DBI::installed_drh = (); # clear loaded drivers so they have a chance to
reinitialize
}
# --- The DBI->connect Front Door methods
sub connect_cached {
- # XXX we expect Apache::DBI users to still call connect()
+ # For library code using connect_cached() with mod_perl
+ # we redirect those calls to Apache::DBI::connect() as well
my ($class, $dsn, $user, $pass, $attr) = @_;
- ($attr ||= {})->{dbi_connect_method} = 'connect_cached';
+ ($attr ||= {})->{dbi_connect_method} =
+ ($DBI::connect_via eq "Apache::DBI::connect")
+ ? 'Apache::DBI::connect' : 'connect_cached';
return $class->connect($dsn, $user, $pass, $attr);
}
@@ -1234,16 +1241,8 @@
sub default_user {
my ($drh, $user, $pass, $attr) = @_;
- unless (defined $user) {
- $user = $ENV{DBI_USER};
- Carp::carp("DBI connect: user not defined and DBI_USER env var not set")
- if 0 && !defined $user && $drh->{Warn}; # XXX enable later
- }
- unless (defined $pass) {
- $pass = $ENV{DBI_PASS};
- Carp::carp("DBI connect: password not defined and DBI_PASS env var not
set")
- if 0 && !defined $pass && $drh->{Warn}; # XXX enable later
- }
+ $user = $ENV{DBI_USER} unless defined $user;
+ $pass = $ENV{DBI_PASS} unless defined $pass;
return ($user, $pass);
}
@@ -1452,7 +1451,7 @@
}
sub prepare_cached {
- my ($dbh, $statement, $attr, $allow_active) = @_;
+ my ($dbh, $statement, $attr, $if_active) = @_;
# Needs support at dbh level to clear cache before complaining about
# active children. The XS template code does this. Drivers not using
# the template must handle clearing the cache themselves.
@@ -1462,12 +1461,11 @@
my $key = ($attr) ? join("~~", $statement, @attr_keys, @[EMAIL PROTECTED]) :
$statement;
my $sth = $cache->{$key};
if ($sth) {
- if ($sth->FETCH('Active') && ($allow_active||0) != 2) {
- Carp::carp("prepare_cached($statement) statement handle $sth was still
active")
- if !$allow_active;
- $sth->finish;
- }
- return $sth;
+ return $sth unless $sth->FETCH('Active');
+ Carp::carp("prepare_cached($statement) statement handle $sth still active")
+ unless ($if_active ||= 0);
+ $sth->finish if $if_active <= 1;
+ return $sth if $if_active <= 2;
}
$sth = $dbh->prepare($statement, $attr);
$cache->{$key} = $sth if $sth;
@@ -2286,8 +2284,7 @@
The C<AutoCommit> and C<PrintError> attributes for each connection default to
"on". (See L</AutoCommit> and L</PrintError> for more information.)
However, it is strongly recommended that you explicitly define C<AutoCommit>
-rather than rely on the default. Future versions of
-the DBI may issue a warning if C<AutoCommit> is not explicitly defined.
+rather than rely on the default.
The C<\%attr> parameter can be used to alter the default settings of
C<PrintError>, C<RaiseError>, C<AutoCommit>, and other attributes. For example:
@@ -3434,7 +3431,7 @@
$sth = $dbh->prepare_cached($statement)
$sth = $dbh->prepare_cached($statement, \%attr)
- $sth = $dbh->prepare_cached($statement, \%attr, $allow_active)
+ $sth = $dbh->prepare_cached($statement, \%attr, $if_active)
Like L</prepare> except that the statement handle returned will be
stored in a hash associated with the C<$dbh>. If another call is made to
@@ -3442,6 +3439,28 @@
corresponding cached C<$sth> will be returned without contacting the
database server.
+The C<$if_active> parameter lets you adjust the behaviour if an
+already cached statement handle is still Active. There are several
+alternatives:
+
+=over 4
+
+B<0>: A warning will be generated, and finish() will be called on
+the statement handle before it is returned. This is the default
+behaviour if $if_active is not passed.
+
+B<1>: finish() will be called on the statement handle, but the
+warning is suppressed.
+
+B<2>: Disables any checking.
+
+B<3>: The existing active statement handle will be removed from the
+cache and a new statement handle prepared and cached in its place.
+This is the safest option because it doesn't affect the state of the
+old handle, it just removes it from the cache. [Added in DBI 1.40]
+
+=back
+
Here are some examples of C<prepare_cached>:
sub insert_hash {
@@ -3469,10 +3488,12 @@
is a contrived case where caching would cause a significant problem:
my $sth = $dbh->prepare_cached('SELECT * FROM foo WHERE bar=?');
- $sth->execute($bar);
+ $sth->execute(...);
while (my $data = $sth->fetchrow_hashref) {
+
+ # later, in some other code called within the loop...
my $sth2 = $dbh->prepare_cached('SELECT * FROM foo WHERE bar=?');
- $sth2->execute($data->{bar});
+ $sth2->execute(...);
while (my $data2 = $sth2->fetchrow_arrayref) {
do_stuff(...);
}
@@ -3485,30 +3506,14 @@
the records and terminating when there are no more, but now $sth
is the same as $sth2 the outer fetch loop will also terminate.
-The C<$allow_active> parameter lets you adjust DBI's behaviour when
-prepare_cached is returning a statement handle that is still active.
-There are three settings:
-
-=over 4
-
-B<0>: A warning will be generated, and C<finish> will be called on
-the statement handle before it is returned. This is the default
-behaviour if C<$allow_active> is not passed.
+You'll know if you run into this problem because prepare_cached()
+will generate a warning by default (when $if_active is false).
-B<1>: C<finish> will be called on the statement handle, but the
-warning is suppressed.
-
-B<2>: DBI will not touch the statement handle before returning it.
-You will need to check C<$sth-E<gt>{Active}> on the returned
-statement handle and deal with it in your own code.
+The cache used by prepare_cached() is keyed by both the statement
+and any attributes so you can also avoid this issue by doing something
+like:
-=back
-
-Because the cache used by prepare_cached() is keyed by all the
-parameters, including any attributes passed, you can also avoid
-this issue by doing something like:
-
- my $sth = $dbh->prepare_cached("...", { dbi_dummy => __FILE__.__LINE__ });
+ $sth = $dbh->prepare_cached("...", { dbi_dummy => __FILE__.__LINE__ });
which will ensure that prepare_cached only returns statements cached
by that line of code in that source file.
@@ -4008,7 +4013,8 @@
If C<$dbh-E<gt>get_info(29)> returns true (29 is SQL_IDENTIFIER_QUOTE_CHAR)
then the table names are constructed and quoted by L</quote_identifier>
to ensure they are usable even if they contain whitespace or reserved
-words etc.
+words etc. This means that the table names returned will include
+quote characters.
=item C<type_info_all>
@@ -4998,6 +5004,7 @@
$dbh->{FetchHashKeyName} = 'NAME_lc';
$sth = $dbh->prepare("SELECT FOO, BAR, ID, NAME, BAZ FROM TABLE");
+ $sth->execute;
$hash_ref = $sth->fetchall_hashref('id');
print "Name for id 42 is $hash_ref->{42}->{name}\n";
@@ -5611,6 +5618,8 @@
Using DBI with perl threads is not yet recommended for production
environments.
+Note: There is a bug in perl 5.8.2 when configured with threads
+and debugging enabled (bug #24463) which causes a DBI test to fail.
=head2 Signal Handling and Canceling Operations
@@ -5962,18 +5971,19 @@
http://www.altavista.com/query?q=sql+tutorial
-=head2 Books and Journals
+=head2 Books and Articles
- Programming the Perl DBI, by Alligator Descartes and Tim Bunce.
+Programming the Perl DBI, by Alligator Descartes and Tim Bunce.
+L<http://books.perl.org/book/154>
- Programming Perl 3rd Ed. by Larry Wall, Tom Christiansen & Jon Orwant.
+Programming Perl 3rd Ed. by Larry Wall, Tom Christiansen & Jon Orwant.
+L<http://books.perl.org/book/134>
- Learning Perl by Randal Schwartz.
-
- Dr Dobb's Journal, November 1996.
-
- The Perl Journal, April 1997.
+Learning Perl by Randal Schwartz.
+L<http://books.perl.org/book/101>
+Details of many other books related to perl can be found at L<http://books.perl.org>
+
=head2 Perl Modules
Index of DBI related modules available from CPAN:
@@ -6096,14 +6106,60 @@
Davide Migliavacca, Jan Pazdziora, Peter Haworth, Edmund Mergl, Steve
Williams, Thomas Lowery, and Phlip Plumlee. Without them, the DBI would
not be the practical reality it is today. I'm also especially grateful
-to Alligator Descartes for starting work on the "Programming the Perl
-DBI" book and letting me jump on board.
+to Alligator Descartes for starting work on the first edition of the
+"Programming the Perl DBI" book and letting me jump on board.
-Much of the DBI and DBD::Oracle was developed while I was Technical
+The DBI and DBD::Oracle were originally developed while I was Technical
Director (CTO) of the Paul Ingram Group (www.ig.co.uk). So I'd
especially like to thank Paul for his generosity and vision in
supporting this work for many years.
+=head1 CONTRIBUTING
+
+As you can see above, many people have contributed to the DBI and
+drivers in many ways over many years.
+
+If you'd like the DBI to do something new or different the best way
+to make that happen is to do it yourself and send me a patch to the
+source code that shows the changes.
+
+=head2 How to create a patch
+
+Unpack a fresh copy of the distribution:
+
+ tar xfz DBI-1.40.tar.gz
+
+Rename the newly created top level directory:
+
+ mv DBI-1.40 DBI-1.40.your_foo
+
+Edit the contents of DBI-1.40.your_foo/* till it does what you want.
+
+Test your changes and then remove all temporary files:
+
+ make test && make distclean
+
+Go back to the directory you originally unpacked the distribution:
+
+ cd ..
+
+Unpack I<another> copy of the original distribution you started with:
+
+ tar xfz DBI-1.40.tar.gz
+
+Then create a patch file by performing a recursive C<diff> on the two
+top level directories:
+
+ diff -r -u DBI-1.40 DBI-1.40.your_foo > DBI-1.40.your_foo.patch
+
+=head2 Speak before you patch
+
+For anything non-trivial or possibly controversial it's a good idea
+to discuss (on [EMAIL PROTECTED]) the changes you propose before
+actually spending time working on them. Otherwise you run the risk
+of them being rejected because they don't fit into some larger plans
+you may not be aware of.
+
=head1 TRANSLATIONS
A German translation of this manual (possibly slightly out of date) is
Modified: dbi/trunk/DBI.xs
==============================================================================
--- dbi/trunk/DBI.xs (original)
+++ dbi/trunk/DBI.xs Sun Feb 1 02:31:07 2004
@@ -1,6 +1,6 @@
/* vim: ts=8:sw=4
*
- * $Id: DBI.xs,v 11.36 2003/11/27 23:29:06 timbo Exp $
+ * $Id: DBI.xs,v 11.37 2004/01/07 17:38:51 timbo Exp $
*
* Copyright (c) 1994-2003 Tim Bunce Ireland.
*
@@ -2135,6 +2135,11 @@
/* refs if the application ceases to use the handle. */
if (is_DESTROY) {
imp_xxh = DBIh_COM(mg->mg_obj);
+#ifdef DBI_USE_THREADS
+ if (imp_xxh && DBIc_THR_USER(imp_xxh) != my_perl) {
+ goto is_DESTROY_wrong_thread;
+ }
+#endif
if (imp_xxh && DBIc_TYPE(imp_xxh) <= DBIt_DB &&
DBIc_CACHED_KIDS((imp_drh_t*)imp_xxh))
clear_cached_kids(mg->mg_obj, imp_xxh, meth_name, debug);
if (debug >= 3)
@@ -2169,6 +2174,7 @@
if (h_perl != my_perl) {
/* XXX could call a 'handle clone' method here, for dbh's at least */
if (is_DESTROY) {
+ is_DESTROY_wrong_thread:
if (debug >= 2) {
PerlIO_printf(DBILOGFP," DESTROY ignored because DBI %sh handle
(%s) is owned by thread %p not current thread %p\n",
dbih_htype_name(DBIc_TYPE(imp_xxh)),
HvNAME(DBIc_IMP_STASH(imp_xxh)), h_perl, my_perl) ;
Modified: dbi/trunk/Makefile.PL
==============================================================================
--- dbi/trunk/Makefile.PL (original)
+++ dbi/trunk/Makefile.PL Sun Feb 1 02:31:07 2004
@@ -1,6 +1,6 @@
# -*- perl -*-
#
-# $Id: Makefile.PL,v 11.19 2003/11/12 10:02:10 timbo Exp $
+# $Id: Makefile.PL,v 11.20 2004/01/08 14:03:46 timbo Exp $
#
# Copyright (c) 1994-2002 Tim Bunce England
#
@@ -196,6 +196,7 @@
sub postamble {
warn <<EOT;
+ I see you're using perl $] on $Config::Config{archname}, okay.
Remember to actually *read* the README file!
Use 'make' to build the software (dmake or nmake on Windows).
Then 'make test' to execute self tests.
Modified: dbi/trunk/README
==============================================================================
--- dbi/trunk/README (original)
+++ dbi/trunk/README Sun Feb 1 02:31:07 2004
@@ -1,16 +1,15 @@
DBI - The Perl Database Interface by Tim Bunce.
-Copyright (c) 1994-2003 Tim Bunce Ireland.
+Copyright (c) 1994-2004 Tim Bunce Ireland.
See COPYRIGHT section in DBI.pm for usage and distribution rights.
-RECENT NEWS:
+See GETTING HELP section in DBI.pm for how to get help.
- The DBI comes bundled with DBI::Shell, DBD::Proxy and
- DBI::ProxyServer modules. Those are still alpha releases.
+RECENT NEWS:
- Note that recent additions to the DBI spec (marked *NEW*) may
- take a little while to be fully supported by individual drivers.
+ Note: There is a bug in perl 5.8.2 when configured with threads
+ and debugging enabled (bug #24463) which causes a DBI test to fail.
QUICK START GUIDE:
@@ -27,6 +26,7 @@
Then delete the source directory tree since it's no longer needed.
Use the 'perldoc DBI' command to read the DBI documentation.
+ See GETTING HELP section in DBI.pm for how to get help.
Fetch the DBD::* driver module you wish to use and unpack it.
http://search.cpan.org/ (or www.activestate.com if on Windows)
@@ -67,7 +67,6 @@
make
make test
make test TEST_VERBOSE=1 (if any of the t/* tests fail)
-
make install (if the tests look okay)
IF YOU HAVE PROBLEMS:
Modified: dbi/trunk/ToDo
==============================================================================
--- dbi/trunk/ToDo (original)
+++ dbi/trunk/ToDo Sun Feb 1 02:31:07 2004
@@ -1,123 +1,131 @@
+*** Changes for DBI v2 ***
-*** Assorted to-do items and random thoughts *** IN NO PARTICULAR ORDER ***
-
-Ability to remove an sth from the prepare_cached cache.
- $sth->uncache;
-and $dbh->uncache; for connect_cached
-implies duplication of key key code or iterate through cache.
-$h->uncache and/or option to prepare_cache to discard (and replace)
-cached $sth if it's still active. Or weak refs?
+New connect() code using parse_dsn()
Add PERL_NO_GET_CONTEXT for multiplicity/threads?
+force it for drivers
And enable xsbypass if possible.
-Perhaps $h->{PrintWarn} $h->{RaiseWarn} $h->{HandleWarn}
-or better still, a more general event mechanism
-but one that makes the above very easy: $h->{HandleEvent}
-but need to classify 'events'. At least SUCCESS_WITH_INFO
-(which covers eg mysql warnings), and something for 'messages'
-from the server while exevuting stored procedures.
-
-$dbh->ping($skip_seconds) - skip the ping if ping'd less than $skip_seconds ago
-Change connect_cached to use ping($skip_seconds || 10);
-
-Polish up and document _dbtype_names with an external interface and using get_info.
-
-$sth->{ParamTypes} eg { "1" => SQL_VARCHAR, "2" => { TYPE=>SQL_VARCHAR, ora_type=>99
}};
-
-Give handles names: $h->{Id} ?
-Useful for reporting, Multiplex, DBD::AnyData etc etc
-May become useful for weakrefs etc
+Need to add docs for DbTypeSubclass (ala DBIx::AnyDBD)
+Move TIEHASH etc to XS (and pureperl)
-Add architecture info to DBI and DBI::DBD build messages so
-users error reports are more useful.
+$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}.
+
+Add more macro hooks to Driver.xst: ping, quote etc.
+
+Make common data a separate SV? Or sv_grow existing imp data sv and
+place com struct at end? But both still mean com pointer is invalid after clone.
+Maybe just increase size of it and check/improve size sanity checks.
+
+Sort out DBIcDBISTATE() and DBIS mess. dDBIS?
+Make it cheap to get h from imp_xxh so only imp_xxh needs
+to be passed around?
+
+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.
+Update DBI::DBD with overview (at least) recommend Driver.xst strongly.
+Find XS drivers that don't use it and talk to authors.
+Ship separate DBD::TemplateP and DBD::TemplateXS drivers as examples.
-$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.
+UTF8
-DBI->setup_driver alias for _setup_driver, and make idempotent.
+Rename finish to discard_pending_rows :-) [or just add an alias and docs :-]
+Or maybe to 'close' (the ODBC equiv - study close() options)
-Devel::Leak
+Rework handle creation to use methods. Maybe $h->new_child(\%override_attr)
-DBIx::DWIW
+ dr::connect =>
+ $dbh = $drh->new_child(\%attr);
+ $dbh->connect(...)
+and
+ db::prepare =>
+ $sth = $dbh->new_child(\%attr);
+ $sth->prepare($statement) # once only?
+ $sth->close(???) # to 'reset' before a different prepare()?
+need to think through prepare_cached and connect_cached
+and relationship to preparse.
+
+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?
+
+Phalanx?
+
+Study alternate DBI's:
+ ruby
+ python
+ php
+ others?
+ ADO object model
+identify any features we need to support and any incompatibilities etc
+Perhaps $h->{PrintWarn} $h->{RaiseWarn} $h->{HandleWarn}
+or better still, a more general event mechanism
+but one that makes the above very easy: $h->{HandleEvent}
+but need to classify 'events'. At least SUCCESS_WITH_INFO
+(which covers eg mysql warnings), and something for 'messages'
+from the server while executing stored procedures.
The DBI needs some standard way to handle the 'success with info' concept:
$h->{HandleEvent}
+ (event_type (== SUCCESS_WITH_INFO)
+ event_msg
+ event_info driver-specific
+ )
+
+Add per-handle debug file pointer:
+ NULL => default => DBIS->tracefp
+ if not NULL then dup() for child handles
+ close(h->tracefp) at end of DESTROY
+ macro to do (h->tracefp || DBIS->tracefp)
+Maybe also need to add locking to prevent file contents being mangled
+by multiple threads/interpreters (esp mod_perl v2 and ActivePerl)?
-Maybe have fetchrow_arrayref return not a new reference to the same
-array each time, but the same reference to the same array each time.
-That would save a new/mortal/free for each row. Need to consider
-safety in case application assigns to the ref etc. Could sanity
-check in get_fbav that SvRV still points to the row array.
-But maybe it's not worth it if perl's "tmp stealing" works for refs.
-
-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.
-
-DBI::Profile: Add calc of approx XS method call and timing overhead
-by calling perl_call("DBI::dbi_time") at boot time for profile, and
-add to each sample.
-
-Sort out DBIcDBISTATE() and DBIS mess
-
-fetchall_hashref: may be better to call (the optimized) fetchall_arrayref
-then convert to hashes
-
-Sponge behave_like - generalize?
+Look for existing CPAN module that reblesses an object into a unique subclass
+and supports SUPER:: from that subclass up into the original class.
+In order to emulate a common perl6 implementation approach.
-Update DBI::DBD with overview (at least) recommend Driver.xst strongly.
-Find XS drivers that don't use it and talk to authors.
-Ship separate DBD::TemplateP and DBD::TemplateXS drivers as examples.
+#define a large negative number to mean 'error' from st_execute and
+change *.xst to treat eaither that or -2 as an error. (The -2 is
+a transition for old drivers.)
-Check: local($h->{PrintError})=0; resets $DBI::errstr at end of scope?
+Remove old informix fudge in tables() (DBD::Informix now has it's own)
-Add UnimpMethodHook (in XS)
-Test and integrate with DProf?
-FetchHashReuse attrib (=1 or ={}) copy from dbh to sth.
-Record attrib STOREs so can be replayed (or use subclass?)
+*** Small/quick/simple changes/checks ***
-Merge/document DBIx::AnyDBD functionality into the DBI
-make lasth return outer handle
+*** Assorted to-do items and random thoughts *** IN NO PARTICULAR ORDER ***
-Add $h->swap_internal_handle($other_h)
+Document DBIx::AnyDBD functionality into the DBI
+Polish up and document _dbtype_names with an external interface and using get_info.
+DBI->setup_driver alias for _setup_driver, and make idempotent?
-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.
+Limit trace array/hash dump eg return from fetchall_arrayref()
-Rename finish to discard_pending_rows :-) [or just add an alias and docs :-]
-Or maybe to 'close' (the ODBC equiv)
+DBIx::DWIW
-add details of the DBI book to the docs
-test shell /connect user etc
+make lasth return outer handle?
document dbi_fetchall_arrayref_attr attr of selectall_arrayref().
-Count execute()s (and do's?) (in ima struct? not thread safe).
-Reset count in commit/rollback.
-In $dbh->DESTROY don't issue warning if count == 0.
-
-#define a large negative number to mean 'error' from st_execute and
-change *.xst to treat eaither that or -2 as an error. (The -2 is
-a transition or old drivers.)
-
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 speficy SQL to allow/deny via regexen
+Proxy: allow config to specify SQL to allow/deny via regexen
Docs for connect_cached and test with proxy.
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.
> 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
@@ -129,98 +137,54 @@
Okay. I'll take that as a vote for bind_param_by_ref as an alias for
bind_param_inout. >>todo.
-LOGGING:
-
-Seperate log for sql statements?
-
-Add per-handle debug file pointer (or at least a macro that _looks_ like that).
-Or, better yet, a function pointer so we can do more clever things.
-Maybe also need to add locking to prevent file contents being mangled
-by multiple threads/interpreters (esp mod_perl v2 and ActivePerl).
+------
OTHERS:
-Enable warnings in default_user().
-Add prompt for user/pass in default_user()?
-
Change bind_column to save the info for get_fbav to use when
first called. Thus making bind before execute work for all drivers.
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. $dbh->{SQLSTATE_map} = code or hash ref
+
+Add minimum subset of ODBC3 SQLSTATE values that should be supported
+(and corresponding ODBC2 values?)
ODBC attribute defining if transactions are supported
http://www.vpservices.com/jeff/programs/SQL/docs/odbc-getinfo-msdn.html
-$dbh-level __WARN__ and __DIE__. Initially just provide DBIXS hooks
-for DBD's to use (and pass h and imp_xxh to). Thus $dbh can redirect
-errors etc from all children in one go.
-
-Informix inspired changes.
+Informix inspired changes?
Add hook to DBI::DBD to write a myconfig.txt file into the
source directory containing key driver and config info.
-attribute for 'last inserted id'?
-
test suite
http://www.mipt.sw.ru/en/products/ots/
-$sth->more_results, now and $sth->become($sth2) later
+Review drivers for handling of multiple result sets
+to define common api for all.
+$sth->more_results, maybe via $sth->become($sth2) later (or transplant/swap)
+
+Add $h->swap_internal_handle($other_h)
dbish - state AutoCommit status clearly at connect time.
(And try to set AutoCommit off in eval?)
-
-Add thread CV locks (not method locks)
-to &DBI::connect and &DBI::connect_cached
-in xs dbi_init code.
-
-fetch_scroll handling via get_fbav.
-Also add:
- getrow_array (or getdata_?)
- getrow_arrayref?
- getrow_hashref?
-
-test that $dbh->do will RaiseError
-RaiseError in %attr - doc it not working - hints.
-
-Consider making all SQL_ known to the DBI. Want to check for
-valid spelling. Also would like C<exists $h->{Attrib}> to
-work. Maybe auto load a module that defines a private hash
-that just serves to list known attributes.
-Or DBI->SQL_FOO and/or DBI::SQL_FOO.
+test shell "/connect user pass" etc
check out http://tegan.deltanet.com/~phlip/DBUIframe.html
-Auto proxying for individual drivers: DBI_PROXY_foo=...
-Else more generic dsn-rewrite via env vars
-
Check DBD::Proxy connect&fetch latency (e.g. CGI use).
-Add SCALE to DBD::Sponge
-
-Rework handle creation for
-$h->clone ?, and maybe
-$dbh->connect([$user, $passwd]) # to reconnect, possibly as a different user
-
-Add (ODBC) attribute to indicate if placeholders are supported.
+Indentify get_info(?) to indicate if placeholders are supported.
http://www.vpservices.com/jeff/programs/SQL/docs/odbc-getinfo-msdn.html
-Fix shared error codes between (dbh) handles, maybe.
-
-Add problem reporting info to DBI.pm
-
-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)
-
---
> > Is there any way to know whether a particular DBD needs a separate
> > connection for nested operations or not?
-Umm, it looks like $dbh->{SQL_ACTIVE_STATEMENTS} would be the one.
+Umm, it looks like $dbh->get_info(SQL_ACTIVE_STATEMENTS) would be the one.
It defines the max number of statements that can be active on a
the $dbh. 0 means unknown or no specific limit.
I'll add that to the DBI and DBI spec.
@@ -258,10 +222,101 @@
Umm. I see what you mean. It's reasonable to assume that a driver
will 'freeze' the value of applicable attributes at prepare or execute
time. The driver should probably document that kind of thing.
+Clarify docs about $sth->{LongReadLen} being readonly for some drivers.
+
+
+****** 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.
+
+
+fetchall_hashref: may be better to call (the optimized) fetchall_arrayref
+then convert to hashes:
+ $_ = do { my %h; @[EMAIL PROTECTED] = @$_; \%h } for @$rows;
+
+
+Give handles names: $h->{Id} ?
+Useful for reporting, Multiplex, DBD::AnyData etc etc
+May become useful for weakrefs etc
+
+
+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]
+
+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.
+
+
+Maybe have fetchrow_arrayref return not a new reference to the same
+array each time, but the same reference to the same array each time.
+That would save a new/mortal/free for each row. Need to consider
+safety in case application assigns to the ref etc. Could sanity
+check in get_fbav that SvRV still points to the row array.
+But maybe it's not worth it if perl's "tmp stealing" works for refs.
+
+
+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)
+
+
+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()?
+
+
+Devel::Leak
-I think the DBI's template .xst file will probably grow some code
-to handle attributes to prepare semi-automatically, sometime.
+$sth->{ParamTypes} eg { "1" => SQL_VARCHAR, "2" => { TYPE=>SQL_VARCHAR, ora_type=>99
}};
+
+DBI::Profile: some way to get count of 'executions' only, not all method calls.
+So avg time is totaltime/executions not totaltime/methodcalls.
+
+FetchHashReuse attrib (=1 or ={}) copy from dbh to sth.
+Record attrib STOREs so can be replayed (or use subclass?)
-Tim.
------------
+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 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?]
+
+Count execute()s (and do's?) in imp_dbh. Reset count in commit/rollback.
+In $dbh->DESTROY don't issue warning if count == 0.
+
+Change CachedKids to be a simple attribute cached in the handle hash
+to remove FETCH method call overhead in prepare_cached().
+
+Ability to remove an sth from the prepare_cached cache.
+ $sth->uncache;
+and $dbh->uncache; for connect_cached
+implies duplication of key key code or iterate through cache.
Modified: dbi/trunk/lib/DBD/ExampleP.pm
==============================================================================
--- dbi/trunk/lib/DBD/ExampleP.pm (original)
+++ dbi/trunk/lib/DBD/ExampleP.pm Sun Feb 1 02:31:07 2004
@@ -6,9 +6,9 @@
use DBI qw(:sql_types);
@EXPORT = qw(); # Do NOT @EXPORT anything.
- $VERSION = sprintf("%d.%02d", q$Revision: 11.11 $ =~ /(\d+)\.(\d+)/o);
+ $VERSION = sprintf("%d.%02d", q$Revision: 11.12 $ =~ /(\d+)\.(\d+)/o);
-# $Id: ExampleP.pm,v 11.11 2003/10/21 15:13:43 timbo Exp $
+# $Id: ExampleP.pm,v 11.12 2004/01/07 17:38:51 timbo Exp $
#
# Copyright (c) 1994,1997,1998 Tim Bunce
#
@@ -47,8 +47,8 @@
$drh;
}
- sub default_user {
- return ('','');
+ sub CLONE {
+ undef $drh;
}
}
Modified: dbi/trunk/lib/DBD/NullP.pm
==============================================================================
--- dbi/trunk/lib/DBD/NullP.pm (original)
+++ dbi/trunk/lib/DBD/NullP.pm Sun Feb 1 02:31:07 2004
@@ -4,9 +4,9 @@
require DBI;
@EXPORT = qw(); # Do NOT @EXPORT anything.
- $VERSION = sprintf("%d.%02d", q$Revision: 11.3 $ =~ /(\d+)\.(\d+)/o);
+ $VERSION = sprintf("%d.%02d", q$Revision: 11.4 $ =~ /(\d+)\.(\d+)/o);
-# $Id: NullP.pm,v 11.3 2003/02/28 17:50:06 timbo Exp $
+# $Id: NullP.pm,v 11.4 2004/01/07 17:38:51 timbo Exp $
#
# Copyright (c) 1994, Tim Bunce
#
@@ -28,8 +28,8 @@
$drh;
}
- sub default_user {
- return ('','');
+ sub CLONE {
+ undef $drh;
}
}
Modified: dbi/trunk/lib/DBD/Sponge.pm
==============================================================================
--- dbi/trunk/lib/DBD/Sponge.pm (original)
+++ dbi/trunk/lib/DBD/Sponge.pm Sun Feb 1 02:31:07 2004
@@ -5,9 +5,9 @@
require Carp;
@EXPORT = qw(); # Do NOT @EXPORT anything.
- $VERSION = sprintf("%d.%02d", q$Revision: 11.9 $ =~ /(\d+)\.(\d+)/o);
+ $VERSION = sprintf("%d.%02d", q$Revision: 11.10 $ =~ /(\d+)\.(\d+)/o);
-# $Id: Sponge.pm,v 11.9 2003/08/20 00:15:24 timbo Exp $
+# $Id: Sponge.pm,v 11.10 2004/01/07 17:38:51 timbo Exp $
#
# Copyright (c) 1994-2003 Tim Bunce Ireland
#
@@ -32,8 +32,8 @@
$drh;
}
- sub default_user {
- return ('','');
+ sub CLONE {
+ undef $drh;
}
}
@@ -93,6 +93,10 @@
|| [ (DBI::SQL_VARCHAR()) x $numFields ];
$sth->{PRECISION} = $attribs->{PRECISION}
|| [ map { length($sth->{NAME}->[$_]) } 0..$numFields -1 ];
+ $sth->{SCALE} = $attribs->{SCALE}
+ || [ (0) x $numFields ];
+ $sth->{NULLABLE} = $attribs->{NULLABLE}
+ || [ (2) x $numFields ];
}
$outer;
Modified: dbi/trunk/lib/DBI/DBD.pm
==============================================================================
--- dbi/trunk/lib/DBI/DBD.pm (original)
+++ dbi/trunk/lib/DBI/DBD.pm Sun Feb 1 02:31:07 2004
@@ -2,10 +2,10 @@
use vars qw($VERSION); # set $VERSION early so we don't confuse PAUSE/CPAN etc
-$VERSION = sprintf("%d.%02d", q$Revision: 11.19 $ =~ /(\d+)\.(\d+)/o);
+$VERSION = sprintf("%d.%02d", q$Revision: 11.20 $ =~ /(\d+)\.(\d+)/o);
-# $Id: DBD.pm,v 11.19 2003/11/12 10:02:10 timbo Exp $
+# $Id: DBD.pm,v 11.20 2004/01/07 17:38:51 timbo Exp $
#
# Copyright (c) 1997-2003 Jonathan Leffler, Jochen Wiedmann, Steffen
# Goeldner and Tim Bunce
@@ -58,8 +58,8 @@
=head2 Version and volatility
- $Revision: 11.19 $
- $Date: 2003/11/12 10:02:10 $
+ $Revision: 11.20 $
+ $Date: 2004/01/07 17:38:51 $
This document is I<still> a minimal draft which is in need of further work.
@@ -708,7 +708,7 @@
SCCS version number is probably not appropriate (despite being very
common). For RCS or CVS you can use this code:
- $VERSION = sprintf "%d.%02d", '$Revision: 11.19 $ ' =~ /(\d+)\.(\d+)/;
+ $VERSION = sprintf "%d.%02d", '$Revision: 11.20 $ ' =~ /(\d+)\.(\d+)/;
which pads out the fractional part with leading zeros so all is well
(so long as you don't go past x.99)
@@ -3627,7 +3627,7 @@
my @xst = grep { -f "$_/Driver.xst" } @try;
Carp::croak("Unable to locate Driver.xst in @try") unless @xst;
Carp::carp( "Multiple copies of Driver.xst found in: @xst") if @xst > 1;
- print "Using DBI $DBI::VERSION installed in $xst[0]\n";
+ print "Using DBI $DBI::VERSION (for perl $] on $Config{archname}) installed in
$xst[0]\n";
return $xst[0];
}
Modified: dbi/trunk/lib/DBI/DBD/Metadata.pm
==============================================================================
--- dbi/trunk/lib/DBI/DBD/Metadata.pm (original)
+++ dbi/trunk/lib/DBI/DBD/Metadata.pm Sun Feb 1 02:31:07 2004
@@ -1,6 +1,6 @@
package DBI::DBD::Metadata;
-# $Id: Metadata.pm,v 1.3 2003/05/10 23:30:28 timbo Exp $
+# $Id: Metadata.pm,v 1.4 2004/01/07 17:38:51 timbo Exp $
#
# Copyright (c) 1997-2003 Jonathan Leffler, Jochen Wiedmann,
# Steffen Goeldner and Tim Bunce
@@ -21,7 +21,7 @@
use strict;
my
-$VERSION = sprintf("%d.%02d", q$Revision: 1.3 $ =~ /(\d+)\.(\d+)/);
+$VERSION = sprintf("%d.%02d", q$Revision: 1.4 $ =~ /(\d+)\.(\d+)/);
=head1 NAME
@@ -168,8 +168,9 @@
sub sql_user_name {
my $dbh = shift;
- # Non-standard attribute
- return $dbh->{CURRENT_USER};
+ # CURRENT_USER is a non-standard attribute, probably undef
+ # Username is a standard DBI attribute
+ return $dbh->{CURRENT_USER} || $dbh->{Username};
}
PERL
Modified: dbi/trunk/t/01basics.t
==============================================================================
--- dbi/trunk/t/01basics.t (original)
+++ dbi/trunk/t/01basics.t Sun Feb 1 02:31:07 2004
@@ -1,5 +1,7 @@
#!../../perl -w
+use Config qw(%Config);
+
$^W=1;
$|=1;
@@ -20,7 +22,8 @@
use DBI qw(:sql_types :utils);
-warn " \tUsing DBI::PurePerl (DBI_PUREPERL=$DBI::PurePerl)\n" if $DBI::PurePerl;
+warn " Using DBI::PurePerl (DBI_PUREPERL=$DBI::PurePerl) on $Config{archname}\n"
+ if $DBI::PurePerl;
if (-f "/dev/null") {
DBI->trace(42,"/dev/null");
Modified: dbi/trunk/t/03handle.t
==============================================================================
--- dbi/trunk/t/03handle.t (original)
+++ dbi/trunk/t/03handle.t Sun Feb 1 02:31:07 2004
@@ -6,16 +6,54 @@
# handle tests
-BEGIN { plan tests => 18 }
+BEGIN { plan tests => 34 }
use DBI;
my $driver = "ExampleP";
+do {
+ my $dbh = DBI->connect("dbi:$driver:", '', '');
+
+ my $sql = "select name from ?";
+ my $sth1 = $dbh->prepare_cached($sql);
+ ok($sth1->execute("."));
+ my $ck = $dbh->{CachedKids};
+ ok(keys %$ck == 1);
+
+ my $warn = 0;
+ local $SIG{__WARN__} = sub { ++$warn if $_[0] =~ /still active/ };
+ my $sth2 = $dbh->prepare_cached($sql);
+ ok($sth1 == $sth2);
+ ok($warn == 1);
+ ok(!$sth1->{Active});
+
+ $sth2 = $dbh->prepare_cached($sql, { foo => 1 });
+ ok($sth1 != $sth2);
+ ok(keys %$ck == 2);
+
+ ok($sth1->execute("."));
+ ok($sth1->{Active});
+ $sth2 = $dbh->prepare_cached($sql, undef, 3);
+ ok($sth1 != $sth2);
+ ok($sth1->{Active}); # active but no longer cached
+ $sth1->finish;
+
+ ok($sth2->execute("."));
+ ok($sth2->{Active});
+ $sth1 = $dbh->prepare_cached($sql, undef, 1);
+ ok($sth1 == $sth2);
+ ok(!$sth2->{Active});
+
+ ok($warn == 1);
+ $dbh->disconnect;
+};
+
my $drh = DBI->install_driver($driver);
ok($drh);
ok($drh->{Kids}, 0);
+
# --- handle reference leak tests
sub work {
@@ -50,7 +88,7 @@
my $imp_data = $dbh->take_imp_data;
ok($imp_data);
ok(length($imp_data) >= 112); # 112 for 32bit, 116 for 64 bit as of DBI 1.37, but may
change
-print Dumper($imp_data);
+#print Dumper($imp_data);
{
my ($tmp, $warn);
Modified: dbi/trunk/t/05thrclone.t
==============================================================================
--- dbi/trunk/t/05thrclone.t (original)
+++ dbi/trunk/t/05thrclone.t Sun Feb 1 02:31:07 2004
@@ -7,33 +7,49 @@
BEGIN {
if (!$Config{useithreads} || $] < 5.008) {
- print "1..0 # Skipped: this perl $] not configured to support iThreads\n";
+ print "1..0 # Skipped: this $^O perl $] not configured to support iThreads\n";
exit 0;
}
}
use threads;
-use Test::More tests => 20;
+use Test::More tests => 10;
# ---
-{ package threads_sub; use base qw(threads); }
+{
+ package threads_sub;
+ use base qw(threads);
+}
use DBI;
-#threads->create( sub { 1 } )->join; warn 2; exit 0;
-
$DBI::neat_maxlen = 12345;
+my @connect_args = ("dbi:ExampleP:", '', '');
+
+my $dbh_parent = DBI->connect_cached(@connect_args);
+ok($dbh_parent);
+
sub tests1 {
is($DBI::neat_maxlen, 12345);
+
+ my $dbh = DBI->connect_cached(@connect_args);
+ ok($dbh);
+ isnt($dbh, $dbh_parent);
+ is($dbh->{Driver}->{Kids}, 1) unless $DBI::PurePerl && ok(1);
}
my @thr;
-foreach (1..10) {
+foreach (1..2) {
+ print "\n\n*** creating thread $_\n";
push @thr, threads_sub->create( \&tests1 );
- tests1();
}
-$_->join foreach @thr;
+foreach (@thr) {
+ print "\n\n*** joining thread $_\n";
+ $_->join;
+}
+
+ok(1);
exit 0;