Apache-LoggedAuthDBI
view release on metacpan or search on metacpan
$rv = $dbh->do($statement);
$rv = $dbh->do($statement, \%attr);
$rv = $dbh->do($statement, \%attr, @bind_values);
$ary_ref = $dbh->selectall_arrayref($statement);
$hash_ref = $dbh->selectall_hashref($statement, $key_field);
$ary_ref = $dbh->selectcol_arrayref($statement);
$ary_ref = $dbh->selectcol_arrayref($statement, \%attr);
@row_ary = $dbh->selectrow_array($statement);
$ary_ref = $dbh->selectrow_arrayref($statement);
$hash_ref = $dbh->selectrow_hashref($statement);
$sth = $dbh->prepare($statement);
$sth = $dbh->prepare_cached($statement);
$rc = $sth->bind_param($p_num, $bind_value);
$rc = $sth->bind_param($p_num, $bind_value, $bind_type);
$rc = $sth->bind_param($p_num, $bind_value, \%attr);
$rv = $sth->execute;
$rv = $sth->execute(@bind_values);
$rv = $sth->execute_array(\%attr, ...);
$rc = $sth->bind_col($col_num, \$col_variable);
$rc = $sth->bind_columns(@list_of_refs_to_vars_to_bind);
@row_ary = $sth->fetchrow_array;
$ary_ref = $sth->fetchrow_arrayref;
$hash_ref = $sth->fetchrow_hashref;
$ary_ref = $sth->fetchall_arrayref;
$ary_ref = $sth->fetchall_arrayref( $slice, $max_rows );
$hash_ref = $sth->fetchall_hashref( $key_field );
$rv = $sth->rows;
$rc = $dbh->begin_work;
$rc = $dbh->commit;
$rc = $dbh->rollback;
$quoted_string = $dbh->quote($string);
$rc = $h->err;
$str = $h->errstr;
$rv = $h->state;
$rc = $dbh->disconnect;
I<The synopsis above only lists the major methods and parameters.>
=head2 GETTING HELP
If you have questions about DBI, or DBD driver modules, you can get
help from the I<dbi-users@perl.org> mailing list. You can get help
on subscribing and using the list by emailing I<dbi-users-help@perl.org>.
(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>
recommend that you read "How To Ask Questions The Smart Way"
by Eric Raymond: L<http://www.catb.org/~esr/faqs/smart-questions.html>)
The DBI home page at L<http://dbi.perl.org/> is always worth a visit
and includes an FAQ and links to other resources.
Before asking any questions, reread this document, consult the
archives and read the DBI FAQ. The archives are listed
at the end of this document and on the DBI home page.
An FAQ is installed as a L<DBI::FAQ> module so
you can read it by executing C<perldoc DBI::FAQ>.
However the DBI::FAQ module is currently (2004) outdated relative
to the online FAQ on the DBI home page.
This document often uses terms like I<references>, I<objects>,
I<methods>. If you're not familar with those terms then it would
be a good idea to read at least the following perl manuals first:
L<perlreftut>, L<perldsc>, L<perllol>, and L<perlboot>.
Please note that Tim Bunce does not maintain the mailing lists or the
web page (generous volunteers do that). So please don't send mail
directly to him; he just doesn't have the time to answer questions
personally. The I<dbi-users> mailing list has lots of experienced
people who should be able to help you if you need it. If you do email
Tim he's very likely to just forward it to the mailing list.
=head2 NOTES
This is the DBI specification that corresponds to the DBI version 1.48.
The DBI is evolving at a steady pace, so it's good to check that
you have the latest copy.
The significant user-visible changes in each release are documented
in the L<DBI::Changes> module so you can read them by executing
C<perldoc DBI::Changes>.
Some DBI changes require changes in the drivers, but the drivers
can take some time to catch up. Newer versions of the DBI have
added features that may not yet be supported by the drivers you
use. Talk to the authors of your drivers if you need a new feature
that's not yet supported.
Features added after DBI 1.21 (February 2002) are marked in the
text with the version number of the DBI release they first appeared in.
Extensions to the DBI API often use the C<DBIx::*> namespace.
See L</Naming Conventions and Name Space>. DBI extension modules
can be found at L<http://search.cpan.org/search?mode=module&query=DBIx>.
And all modules related to the DBI can be found at
L<http://search.cpan.org/search?query=DBI&mode=all>.
=cut
# The POD text continues at the end of the file.
package DBI;
# then you haven't installed the DBI correctly. Read the README
# then install it again.
if ( $ENV{DBI_PUREPERL} ) {
eval { bootstrap DBI } if $ENV{DBI_PUREPERL} == 1;
require DBI::PurePerl if $@ or $ENV{DBI_PUREPERL} >= 2;
$DBI::PurePerl ||= 0; # just to silence "only used once" warnings
}
else {
bootstrap DBI;
}
$EXPORT_TAGS{preparse_flags} = [ grep { /^DBIpp_\w\w_/ } keys %{__PACKAGE__."::"} ];
Exporter::export_ok_tags(keys %EXPORT_TAGS);
}
# Alias some handle methods to also be DBI class methods
for (qw(trace_msg set_err parse_trace_flag parse_trace_flags)) {
no strict;
*$_ = \&{"DBD::_::common::$_"};
}
use strict;
DBI->trace(split /=/, $ENV{DBI_TRACE}, 2) if $ENV{DBI_TRACE};
$DBI::connect_via = "connect";
# check if user wants a persistent database connection ( Apache + mod_perl )
if ($INC{'Apache/DBI.pm'} && $ENV{MOD_PERL}) {
$DBI::connect_via = "Apache::DBI::connect";
DBI->trace_msg("DBI connect via $DBI::connect_via in $INC{'Apache/DBI.pm'}\n");
}
%DBI::installed_drh = (); # maps driver names to installed driver handles
# Setup special DBI dynamic variables. See DBI::var::FETCH for details.
# These are dynamically associated with the last handle used.
tie $DBI::err, 'DBI::var', '*err'; # special case: referenced via IHA list
tie $DBI::state, 'DBI::var', '"state'; # special case: referenced via IHA list
tie $DBI::lasth, 'DBI::var', '!lasth'; # special case: return boolean
tie $DBI::errstr, 'DBI::var', '&errstr'; # call &errstr in last used pkg
tie $DBI::rows, 'DBI::var', '&rows'; # call &rows in last used pkg
sub DBI::var::TIESCALAR{ my $var = $_[1]; bless \$var, 'DBI::var'; }
sub DBI::var::STORE { Carp::croak("Can't modify \$DBI::${$_[0]} special variable") }
{ # used to catch DBI->{Attrib} mistake
sub DBI::DBI_tie::TIEHASH { bless {} }
sub DBI::DBI_tie::STORE { Carp::carp("DBI->{$_[1]} is invalid syntax (you probably want \$h->{$_[1]})");}
*DBI::DBI_tie::FETCH = \&DBI::DBI_tie::STORE;
}
tie %DBI::DBI => 'DBI::DBI_tie';
# --- Driver Specific Prefix Registry ---
my $dbd_prefix_registry = {
ad_ => { class => 'DBD::AnyData', },
ado_ => { class => 'DBD::ADO', },
amzn_ => { class => 'DBD::Amazon', },
best_ => { class => 'DBD::BestWins', },
csv_ => { class => 'DBD::CSV', },
db2_ => { class => 'DBD::DB2', },
dbi_ => { class => 'DBI', },
dbm_ => { class => 'DBD::DBM', },
df_ => { class => 'DBD::DF', },
f_ => { class => 'DBD::File', },
file_ => { class => 'DBD::TextFile', },
ib_ => { class => 'DBD::InterBase', },
ing_ => { class => 'DBD::Ingres', },
ix_ => { class => 'DBD::Informix', },
jdbc_ => { class => 'DBD::JDBC', },
msql_ => { class => 'DBD::mSQL', },
mysql_ => { class => 'DBD::mysql', },
mx_ => { class => 'DBD::Multiplex', },
nullp_ => { class => 'DBD::NullP', },
odbc_ => { class => 'DBD::ODBC', },
ora_ => { class => 'DBD::Oracle', },
pg_ => { class => 'DBD::Pg', },
proxy_ => { class => 'DBD::Proxy', },
rdb_ => { class => 'DBD::RDB', },
sapdb_ => { class => 'DBD::SAP_DB', },
solid_ => { class => 'DBD::Solid', },
sponge_ => { class => 'DBD::Sponge', },
sql_ => { class => 'SQL::Statement', },
syb_ => { class => 'DBD::Sybase', },
tdat_ => { class => 'DBD::Teradata', },
tmpl_ => { class => 'DBD::Template', },
tmplss_ => { class => 'DBD::TemplateSS', },
tuber_ => { class => 'DBD::Tuber', },
uni_ => { class => 'DBD::Unify', },
xbase_ => { class => 'DBD::XBase', },
xl_ => { class => 'DBD::Excel', },
yaswi_ => { class => 'DBD::Yaswi', },
};
sub dump_dbd_registry {
require Data::Dumper;
local $Data::Dumper::Sortkeys=1;
local $Data::Dumper::Indent=1;
print Data::Dumper->Dump([$dbd_prefix_registry], [qw($dbd_prefix_registry)]);
}
# --- Dynamically create the DBI Standard Interface
my $keeperr = { O=>0x0004 };
%DBI::DBI_methods = ( # Define the DBI interface methods per class:
common => { # Interface methods common to all DBI handle classes
'DESTROY' => $keeperr,
'CLEAR' => $keeperr,
'EXISTS' => $keeperr,
'FETCH' => { O=>0x0404 },
'FIRSTKEY' => $keeperr,
'NEXTKEY' => $keeperr,
'STORE' => { O=>0x0418 | 0x4 },
_not_impl => undef,
can => { O=>0x0100 }, # special case, see dispatch
debug => { U =>[1,2,'[$debug_level]'], O=>0x0004 }, # old name for trace
dump_handle => { U =>[1,3,'[$message [, $level]]'], O=>0x0004 },
require bytes;
require utf8;
# hacks to cater for perl 5.6
*utf8::is_utf8 = sub { (DBI::neat(shift)=~/^"/) } unless defined &utf8::is_utf8;
*utf8::valid = sub { 1 } unless defined &utf8::valid;
# Give sufficient info to help diagnose at least these kinds of situations:
# - valid UTF8 byte sequence but UTF8 flag not set
# (might be ascii so also need to check for hibit to make it worthwhile)
# - UTF8 flag set but invalid UTF8 byte sequence
# could do better here, but this'll do for now
my $utf8 = sprintf "UTF8 %s%s",
utf8::is_utf8($a) ? "on" : "off",
utf8::valid($a||'') ? "" : " but INVALID encoding";
return "$utf8, undef" unless defined $a;
my $is_ascii = $a =~ m/^[\000-\177]*$/;
return sprintf "%s, %s, %d characters %d bytes",
$utf8, $is_ascii ? "ASCII" : "non-ASCII",
length($a), bytes::length($a);
}
sub connect_test_perf {
my($class, $dsn,$dbuser,$dbpass, $attr) = @_;
Carp::croak("connect_test_perf needs hash ref as fourth arg") unless ref $attr;
# these are non standard attributes just for this special method
my $loops ||= $attr->{dbi_loops} || 5;
my $par ||= $attr->{dbi_par} || 1; # parallelism
my $verb ||= $attr->{dbi_verb} || 1;
print "$dsn: testing $loops sets of $par connections:\n";
require Benchmark;
require "FileHandle.pm"; # don't let toke.c create empty FileHandle package
$| = 1;
my $t0 = new Benchmark; # not currently used
my $drh = $class->install_driver($dsn) or Carp::croak("Can't install $dsn driver\n");
my $t1 = new Benchmark;
my $loop;
for $loop (1..$loops) {
my @cons;
print "Connecting... " if $verb;
for (1..$par) {
print "$_ ";
push @cons, ($drh->connect($dsn,$dbuser,$dbpass)
or Carp::croak("Can't connect # $_: $DBI::errstr\n"));
}
print "\nDisconnecting...\n" if $verb;
for (@cons) {
$_->disconnect or warn "bad disconnect $DBI::errstr"
}
}
my $t2 = new Benchmark;
my $td = Benchmark::timediff($t2, $t1);
printf "Made %2d connections in %s\n", $loops*$par, Benchmark::timestr($td);
print "\n";
return $td;
}
# Help people doing DBI->errstr, might even document it one day
# XXX probably best moved to cheaper XS code
sub err { $DBI::err }
sub errstr { $DBI::errstr }
# --- Private Internal Function for Creating New DBI Handles
sub _new_handle {
my ($class, $parent, $attr, $imp_data, $imp_class) = @_;
Carp::croak('Usage: DBI::_new_handle'
.'($class_name, parent_handle, \%attr, $imp_data)'."\n"
.'got: ('.join(", ",$class, $parent, $attr, $imp_data).")\n")
unless (@_ == 5 and (!$parent or ref $parent)
and ref $attr eq 'HASH'
and $imp_class);
$attr->{ImplementorClass} = $imp_class
or Carp::croak("_new_handle($class): 'ImplementorClass' attribute not given");
DBI->trace_msg(" New $class (for $imp_class, parent=$parent, id=".($imp_data||'').")\n")
if $DBI::dbi_debug >= 3;
# This is how we create a DBI style Object:
my (%hash, $i, $h);
$i = tie %hash, $class, $attr; # ref to inner hash (for driver)
$h = bless \%hash, $class; # ref to outer hash (for application)
# The above tie and bless may migrate down into _setup_handle()...
# Now add magic so DBI method dispatch works
DBI::_setup_handle($h, $imp_class, $parent, $imp_data);
return $h unless wantarray;
($h, $i);
}
# XXX minimum constructors for the tie's (alias to XS version)
sub DBI::st::TIEHASH { bless $_[1] => $_[0] };
*DBI::dr::TIEHASH = \&DBI::st::TIEHASH;
*DBI::db::TIEHASH = \&DBI::st::TIEHASH;
# These three special constructors are called by the drivers
# The way they are called is likely to change.
my $profile;
sub _new_drh { # called by DBD::<drivername>::driver()
my ($class, $initial_attr, $imp_data) = @_;
# Provide default storage for State,Err and Errstr.
# Note that these are shared by all child handles by default! XXX
# State must be undef to get automatic faking in DBI::var::FETCH
my ($h_state_store, $h_err_store, $h_errstr_store) = (undef, 0, '');
my $attr = {
# these attributes get copied down to child handles by default
'State' => \$h_state_store, # Holder for DBI::state
'Err' => \$h_err_store, # Holder for DBI::err
'Errstr' => \$h_errstr_store, # Holder for DBI::errstr
'TraceLevel' => 0,
FetchHashKeyName=> 'NAME',
%$initial_attr,
};
my ($h, $i) = _new_handle('DBI::dr', '', $attr, $imp_data, $class);
COLUMN_SIZE => 2, # was PRECISION originally
LITERAL_PREFIX => 3,
LITERAL_SUFFIX => 4,
CREATE_PARAMS => 5,
NULLABLE => 6,
CASE_SENSITIVE => 7,
SEARCHABLE => 8,
UNSIGNED_ATTRIBUTE=> 9,
FIXED_PREC_SCALE => 10, # was MONEY originally
AUTO_UNIQUE_VALUE => 11, # was AUTO_INCREMENT originally
LOCAL_TYPE_NAME => 12,
MINIMUM_SCALE => 13,
MAXIMUM_SCALE => 14,
SQL_DATA_TYPE => 15,
SQL_DATETIME_SUB => 16,
NUM_PREC_RADIX => 17,
INTERVAL_PRECISION=> 18,
},
[ 'VARCHAR', SQL_VARCHAR,
undef, "'","'", undef,0, 1,1,0,0,0,undef,1,255, undef
],
[ 'INTEGER', SQL_INTEGER,
undef, "", "", undef,0, 0,1,0,0,0,undef,0, 0, 10
],
];
More than one row may have the same value in the C<DATA_TYPE>
field if there are different ways to spell the type name and/or there
are variants of the type with different attributes (e.g., with and
without C<AUTO_UNIQUE_VALUE> set, with and without C<UNSIGNED_ATTRIBUTE>, etc).
The rows are ordered by C<DATA_TYPE> first and then by how closely each
type maps to the corresponding ODBC SQL data type, closest first.
The meaning of the fields is described in the documentation for
the L</type_info> method.
An 'index' hash is provided so you don't need to rely on index
values defined above. However, using DBD::ODBC with some old ODBC
drivers may return older names, shown as comments in the example above.
Another issue with the index hash is that the lettercase of the
keys is not defined. It is usually uppercase, as show here, but
drivers may return names with any lettercase.
Drivers are also free to return extra driver-specific columns of
information - though it's recommended that they start at column
index 50 to leave room for expansion of the DBI/ODBC specification.
The type_info_all() method is not normally used directly.
The L</type_info> method provides a more usable and useful interface
to the data.
=item C<type_info>
@type_info = $dbh->type_info($data_type);
Returns a list of hash references holding information about one or more
variants of $data_type. The list is ordered by C<DATA_TYPE> first and
then by how closely each type maps to the corresponding ODBC SQL data
type, closest first. If called in a scalar context then only the first
(best) element is returned.
If $data_type is undefined or C<SQL_ALL_TYPES>, then the list will
contain hashes for all data type variants supported by the database and driver.
If $data_type is an array reference then C<type_info> returns the
information for the I<first> type in the array that has any matches.
The keys of the hash follow the same letter case conventions as the
rest of the DBI (see L</Naming Conventions and Name Space>). The
following uppercase items should always exist, though may be undef:
=over 4
=item TYPE_NAME (string)
Data type name for use in CREATE TABLE statements etc.
=item DATA_TYPE (integer)
SQL data type number.
=item COLUMN_SIZE (integer)
For numeric types, this is either the total number of digits (if the
NUM_PREC_RADIX value is 10) or the total number of bits allowed in the
column (if NUM_PREC_RADIX is 2).
For string types, this is the maximum size of the string in characters.
For date and interval types, this is the maximum number of characters
needed to display the value.
=item LITERAL_PREFIX (string)
Characters used to prefix a literal. A typical prefix is "C<'>" for characters,
or possibly "C<0x>" for binary values passed as hexadecimal. NULL (C<undef>) is
returned for data types for which this is not applicable.
=item LITERAL_SUFFIX (string)
Characters used to suffix a literal. Typically "C<'>" for characters.
NULL (C<undef>) is returned for data types where this is not applicable.
=item CREATE_PARAMS (string)
Parameter names for data type definition. For example, C<CREATE_PARAMS> for a
C<DECIMAL> would be "C<precision,scale>" if the DECIMAL type should be
declared as C<DECIMAL(>I<precision,scale>C<)> where I<precision> and I<scale>
are integer values. For a C<VARCHAR> it would be "C<max length>".
NULL (C<undef>) is returned for data types for which this is not applicable.
=item NULLABLE (integer)
Indicates whether the data type accepts a NULL value:
C<0> or an empty string = no, C<1> = yes, C<2> = unknown.
=item CASE_SENSITIVE (boolean)
Indicates whether the data type is case sensitive in collations and
$dbh = DBI->connect(..., { RootClass => 'MySubDBI' });
The only difference between the two is that using an explicit
RootClass attribute will make the DBI automatically attempt to load
a module by that name if the class doesn't exist.
If both forms are used then the attribute takes precedence.
When subclassing is being used then, after a successful new
connect, the DBI->connect method automatically calls:
$dbh->connected($dsn, $user, $pass, \%attr);
The default method does nothing. The call is made just to simplify
any post-connection setup that your subclass may want to perform.
If your subclass supplies a connected method, it should be part of the
MySubDBI::db package.
Here's a brief example of a DBI subclass. A more thorough example
can be found in t/subclass.t in the DBI distribution.
package MySubDBI;
use strict;
use DBI;
use vars qw(@ISA);
@ISA = qw(DBI);
package MySubDBI::db;
use vars qw(@ISA);
@ISA = qw(DBI::db);
sub prepare {
my ($dbh, @args) = @_;
my $sth = $dbh->SUPER::prepare(@args)
or return;
$sth->{private_mysubdbi_info} = { foo => 'bar' };
return $sth;
}
package MySubDBI::st;
use vars qw(@ISA);
@ISA = qw(DBI::st);
sub fetch {
my ($sth, @args) = @_;
my $row = $sth->SUPER::fetch(@args)
or return;
do_something_magical_with_row_data($row)
or return $sth->set_err(1234, "The magic failed", undef, "fetch");
return $row;
}
When calling a SUPER::method that returns a handle, be careful to
check the return value before trying to do other things with it in
your overridden method. This is especially important if you want
to set a hash attribute on the handle, as Perl's autovivification
will bite you by (in)conveniently creating an unblessed hashref,
which your method will then return with usually baffling results
later on. It's best to check right after the call and return undef
immediately on error, just like DBI would and just like the example
above.
If your method needs to record an error it should call the set_err()
method with the error code and error string, as shown in the example
above. The error code and error string will be recorded in the
handle and available via C<$h-E<gt>err> and C<$DBI::errstr> etc.
The set_err() method always returns an undef or empty list as
approriate. Since your method should nearly always return an undef
or empty list as soon as an error is detected it's handy to simply
return what set_err() returns, as shown in the example above.
If the handle has C<RaiseError>, C<PrintError>, or C<HandleError>
etc. set then the set_err() method will honour them. This means
that if C<RaiseError> is set then set_err() won't return in the
normal way but will 'throw an exception' that can be caught with
an C<eval> block.
You can stash private data into DBI handles
via C<$h-E<gt>{private_..._*}>. See the entry under L</ATTRIBUTES
COMMON TO ALL HANDLES> for info and important caveats.
=head1 TRACING
The DBI has a powerful tracing mechanism built in. It enables you
to see what's going on 'behind the scenes', both within the DBI and
the drivers you're using.
=head2 Trace Settings
Which details are written to the trace output is controlled by a
combination of a I<trace level>, an integer from 0 to 15, and a set
of I<trace flags> that are either on or off. Together these are known
as the I<trace settings> and are stored together in a single integer.
For normal use you only need to set the trace level, and generally
only to a value between 1 and 4.
Each handle has it's own trace settings, and so does the DBI.
When you call a method the DBI merges the handles settings into its
own for the duration of the call: the trace flags of the handle are
OR'd into the trace flags of the DBI, and if the handle has a higher
trace level then the DBI trace level is raised to match it.
The previous DBI trace setings are restored when the called method
returns.
=head2 Trace Levels
Trace I<levels> are as follows:
0 - Trace disabled.
1 - Trace DBI method calls returning with results or errors.
2 - Trace method entry with parameters and returning with results.
3 - As above, adding some high-level information from the driver
and some internal information from the DBI.
4 - As above, adding more detailed information from the driver.
5 to 15 - As above but with more and more obscure information.
Trace level 1 is best for a simple overview of what's happening.
Trace level 2 is a good choice for general purpose tracing.
Levels 3 and above are best reserved for investigating a specific
problem, when you need to see "inside" the driver and DBI.
The trace output is detailed and typically very useful. Much of the
trace output is formatted using the L</neat> function, so strings
in the trace output may be edited and truncated by that function.
=head2 Trace Flags
Trace I<flags> are used to enable tracing of specific activities
within the DBI and drivers. The DBI defines some trace flags and
drivers can define others. DBI trace flag names begin with a capital
letter and driver specific names begin with a lowercase letter, as
usual.
Curently the DBI only defines two trace flags:
ALL - turn on all DBI and driver flags (not recommended)
SQL - trace SQL statements executed (not yet implemented)
The L</parse_trace_flags> and L</parse_trace_flag> methods are used
to convert trace flag names into the coresponding integer bit flags.
=head2 Enabling Trace
The C<$h-E<gt>trace> method sets the trace settings for a handle
and C<DBI-E<gt>trace> does the same for the DBI.
In addition to the L</trace> method, you can enable the same trace
information, and direct the output to a file, by setting the
C<DBI_TRACE> environment variable before starting Perl.
See L</DBI_TRACE> for more information.
Finally, you can set, or get, the trace settings for a handle using
the C<TraceLevel> attribute.
All of those methods use parse_trace_flags() and so allow you set
both the trace level and multiple trace flags by using a string
containing the trace level and/or flag names separated by vertical
bar ("C<|>") or comma ("C<,>") characters. For example:
local $h->{TraceLevel} = "3|SQL|foo";
=head2 Trace Output
Initially trace output is written to C<STDERR>. Both the
C<$h-E<gt>trace> and C<DBI-E<gt>trace> methods take an optional
$trace_filename parameter. If specified, and can be opened in
append mode, then I<all> trace output (currently including that
from other handles) is redirected to that file. A warning is
generated if the file can't be opened.
Further calls to trace() without a $trace_filename do not alter where
the trace output is sent. If $trace_filename is undefined, then
trace output is sent to C<STDERR> and the previous trace file is closed.
Currently $trace_filename can't be a filehandle. But meanwhile you
can use the special strings C<"STDERR"> and C<"STDOUT"> to select
those filehandles.
=head2 Tracing Tips
( run in 0.919 second using v1.01-cache-2.11-cpan-ceb78f64989 )