📄 pureperl.pm
字号:
$h->{$key} = $value; if ($value) { my $fbav = DBD::_::st::dbih_setup_fbav($h); @$fbav = (undef) x $value if @$fbav != $value; } return 1; } elsif (!$is_valid_attribute{$key} && $key =~ /^[A-Z]/ && !exists $h->{$key}) { Carp::carp(sprintf "Can't set %s->{%s}: unrecognised attribute or invalid value %s", $h,$key,$value); } $h->{$key} = $is_flag_attribute{$key} ? !!$value : $value; return 1;}sub err { return shift->{err} }sub errstr { return shift->{errstr} }sub state { return shift->{state} }sub set_err { my ($h, $errnum,$msg,$state, $method, $rv) = @_; $h = tied(%$h) || $h; if (my $hss = $h->{HandleSetErr}) { return if $hss->($h, $errnum, $msg, $state, $method); } if (!defined $errnum) { $h->{err} = $DBI::err = undef; $h->{errstr} = $DBI::errstr = undef; $h->{state} = $DBI::state = ''; return; } if ($h->{errstr}) { $h->{errstr} .= sprintf " [err was %s now %s]", $h->{err}, $errnum if $h->{err} && $errnum && $h->{err} ne $errnum; $h->{errstr} .= sprintf " [state was %s now %s]", $h->{state}, $state if $h->{state} and $h->{state} ne "S1000" && $state && $h->{state} ne $state; $h->{errstr} .= "\n$msg" if $h->{errstr} ne $msg; $DBI::errstr = $h->{errstr}; } else { $h->{errstr} = $DBI::errstr = $msg; } # assign if higher priority: err > "0" > "" > undef my $err_changed; if ($errnum # new error: so assign or !defined $h->{err} # no existing warn/info: so assign # new warn ("0" len 1) > info ("" len 0): so assign or defined $errnum && length($errnum) > length($h->{err}) ) { $h->{err} = $DBI::err = $errnum; ++$h->{ErrCount} if $errnum; ++$err_changed; } if ($err_changed) { $state ||= "S1000" if $DBI::err; $h->{state} = $DBI::state = ($state eq "00000") ? "" : $state if $state; } if (my $p = $h->{Database}) { # just sth->dbh, not dbh->drh (see ::db::DESTROY) $p->{err} = $DBI::err; $p->{errstr} = $DBI::errstr; $p->{state} = $DBI::state; } $h->{'dbi_pp_last_method'} = $method; return $rv; # usually undef}sub trace_msg { my ($h, $msg, $minlevel)=@_; $minlevel = 1 unless defined $minlevel; return unless $minlevel <= ($DBI::dbi_debug & 0xF); print $DBI::tfh $msg; return 1;}sub private_data { warn "private_data @_";}sub take_imp_data { my $dbh = shift; # A reasonable default implementation based on the one in DBI.xs. # Typically a pure-perl driver would have their own take_imp_data method # that would delete all but the essential items in the hash before einding with: # return $dbh->SUPER::take_imp_data(); # Of course it's useless if the driver doesn't also implement support for # the dbi_imp_data attribute to the connect() method. require Storable; croak("Can't take_imp_data from handle that's not Active") unless $dbh->{Active}; for my $sth (@{ $dbh->{ChildHandles} || [] }) { next unless $sth; $sth->finish if $sth->{Active}; bless $sth, 'DBI::zombie'; } delete $dbh->{$_} for (keys %is_valid_attribute); delete $dbh->{$_} for grep { m/^dbi_/ } keys %$dbh; # warn "@{[ %$dbh ]}"; local $Storable::forgive_me = 1; # in case there are some CODE refs my $imp_data = Storable::freeze($dbh); # XXX um, should probably untie here - need to check dispatch behaviour return $imp_data;}sub rows { return -1; # always returns -1 here, see DBD::_::st::rows below}sub DESTROY {}package DBD::_::db;sub connected {}package DBD::_::st;sub fetchrow_arrayref { my $h = shift; # if we're here then driver hasn't implemented fetch/fetchrow_arrayref # so we assume they've implemented fetchrow_array and call that instead my @row = $h->fetchrow_array or return; return $h->_set_fbav(\@row);}# twice to avoid typo warning*fetch = \&fetchrow_arrayref; *fetch = \&fetchrow_arrayref;sub fetchrow_array { my $h = shift; # if we're here then driver hasn't implemented fetchrow_array # so we assume they've implemented fetch/fetchrow_arrayref my $row = $h->fetch or return; return @$row;}*fetchrow = \&fetchrow_array; *fetchrow = \&fetchrow_array;sub fetchrow_hashref { my $h = shift; my $row = $h->fetch or return; my $FetchCase = shift; my $FetchHashKeyName = $FetchCase || $h->{'FetchHashKeyName'} || 'NAME'; my $FetchHashKeys = $h->FETCH($FetchHashKeyName); my %rowhash; @rowhash{ @$FetchHashKeys } = @$row; return \%rowhash;}sub dbih_setup_fbav { my $h = shift; return $h->{'_fbav'} || do { $DBI::rows = $h->{'_rows'} = 0; my $fields = $h->{'NUM_OF_FIELDS'} or DBI::croak("NUM_OF_FIELDS not set"); my @row = (undef) x $fields; \@row; };}sub _get_fbav { my $h = shift; my $av = $h->{'_fbav'} ||= dbih_setup_fbav($h); $DBI::rows = ++$h->{'_rows'}; return $av;}sub _set_fbav { my $h = shift; my $fbav = $h->{'_fbav'}; if ($fbav) { $DBI::rows = ++$h->{'_rows'}; } else { $fbav = $h->_get_fbav; } my $row = shift; if (my $bc = $h->{'_bound_cols'}) { for my $i (0..@$row-1) { my $bound = $bc->[$i]; $fbav->[$i] = ($bound) ? ($$bound = $row->[$i]) : $row->[$i]; } } else { @$fbav = @$row; } return $fbav;}sub bind_col { my ($h, $col, $value_ref,$from_bind_columns) = @_; my $fbav = $h->{'_fbav'} ||= dbih_setup_fbav($h); # from _get_fbav() my $num_of_fields = @$fbav; DBI::croak("bind_col: column $col is not a valid column (1..$num_of_fields)") if $col < 1 or $col > $num_of_fields; return 1 if not defined $value_ref; # ie caller is just trying to set TYPE DBI::croak("bind_col($col,$value_ref) needs a reference to a scalar") unless ref $value_ref eq 'SCALAR'; $h->{'_bound_cols'}->[$col-1] = $value_ref; return 1;}sub finish { my $h = shift; $h->{'_fbav'} = undef; $h->{'Active'} = 0; return 1;}sub rows { my $h = shift; my $rows = $h->{'_rows'}; return -1 unless defined $rows; return $rows;}1;__END__=pod=head1 NAMEDBI::PurePerl -- a DBI emulation using pure perl (no C/XS compilation required)=head1 SYNOPSIS BEGIN { $ENV{DBI_PUREPERL} = 2 } use DBI;=head1 DESCRIPTIONThis is a pure perl emulation of the DBI internals. In almost allcases you will be better off using standard DBI since the portionsof the standard version written in C make it *much* faster.However, if you are in a situation where it isn't possible to installa compiled version of standard DBI, and you're using pure-perl DBDdrivers, then this module allows you to use most common featuresof DBI without needing any changes in your scripts.=head1 EXPERIMENTAL STATUSDBI::PurePerl is new so please treat it as experimental pendingmore extensive testing. So far it has passed all tests with DBD::CSV,DBD::AnyData, DBD::XBase, DBD::Sprite, DBD::mysqlPP. Please sendbug reports to Jeff Zucker at <jeff@vpservices.com> with a cc to<dbi-dev@perl.org>.=head1 USAGEThe usage is the same as for standard DBI with the exceptionthat you need to set the enviornment variable DBI_PUREPERL ifyou want to use the PurePerl version. DBI_PUREPERL == 0 (the default) Always use compiled DBI, die if it isn't properly compiled & installed DBI_PUREPERL == 1 Use compiled DBI if it is properly compiled & installed, otherwise use PurePerl DBI_PUREPERL == 2 Always use PurePerlYou may set the enviornment variable in your shell (e.g. withset or setenv or export, etc) or else set it in your script likethis: BEGIN { $ENV{DBI_PUREPERL}=2 }before you C<use DBI;>.=head1 INSTALLATIONIn most situations simply install DBI (see the DBI pod for details).In the situation in which you can not install DBI itself, youmay manually copy DBI.pm and PurePerl.pm into the appropriatedirectories.For example: cp DBI.pm /usr/jdoe/mylibs/. cp PurePerl.pm /usr/jdoe/mylibs/DBI/.Then add this to the top of scripts: BEGIN { $ENV{DBI_PUREPERL} = 1; # or =2 unshift @INC, '/usr/jdoe/mylibs'; }(Or should we perhaps patch Makefile.PL so that if DBI_PUREPERLis set to 2 prior to make, the normal compile process is skippedand the files are installed automatically?)=head1 DIFFERENCES BETWEEN DBI AND DBI::PurePerl=head2 AttributesBoolean attributes still return boolean values but the actual valuesused may be different, i.e., 0 or undef instead of an empty string.Some handle attributes are either not supported or have very limitedfunctionality: ActiveKids InactiveDestroy Kids Taint TaintIn TaintOut(and probably others)=head2 TracingTrace functionality is more limited and the code to handle tracing isonly embeded into DBI:PurePerl if the DBI_TRACE environment variableis defined. To enable total tracing you can set the DBI_TRACEenvironment variable as usual. But to enable individual handletracing using the trace() method you also need to set the DBI_TRACEenvironment variable, but set it to 0.=head2 Parameter Usage CheckingThe DBI does some basic parameter count checking on method calls.DBI::PurePerl doesn't.=head2 SpeedDBI::PurePerl is slower. Although, with some drivers in somecontexts this may not be very significant for you.By way of example... the test.pl script in the DBI sourcedistribution has a simple benchmark that just does: my $null_dbh = DBI->connect('dbi:NullP:','',''); my $i = 10_000; $null_dbh->prepare('') while $i--;In other words just prepares a statement, creating and destroyinga statement handle, over and over again. Using the real DBI thisruns at ~4550 handles per second whereas DBI::PurePerl manages~2800 per second on the same machine (not too bad really).=head2 May not fully support hash()If you want to use type 1 hash, i.e., C<hash($string,1)> withDBI::PurePerl, you'll need version 1.56 or higher of Math::BigInt(available on CPAN).=head2 Doesn't support preparse()The DBI->preparse() method isn't supported in DBI::PurePerl.=head2 Doesn't support DBD::ProxyThere's a subtle problem somewhere I've not been able to identify.DBI::ProxyServer seem to work fine with DBI::PurePerl but DBD::Proxydoes not work 100% (which is sad because that would be far more useful :)Try re-enabling t/80proxy.t for DBI::PurePerl to see if the problemthat remains will affect you're usage.=head2 Others can() - doesn't have any special behaviourPlease let us know if you find any other differences between DBIand DBI::PurePerl.=head1 AUTHORSTim Bunce and Jeff Zucker.Tim provided the direction and basis for the code. The originalidea for the module and most of the brute force porting from C toPerl was by Jeff. Tim then reworked some core parts to boost theperformance and accuracy of the emulation. Thanks also to RandalSchwartz and John Tobey for patches.=head1 COPYRIGHTCopyright (c) 2002 Tim Bunce Ireland.See COPYRIGHT section in DBI.pm for usage and distribution rights.=cut
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -