[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/se3-unattended/var/se3/unattended/install/linuxaux/opt/perl/lib/site_perl/5.10.0/i586-linux-thread-multi/DBI/ -> PurePerl.pm (source)

   1  ########################################################################
   2  package        # hide from PAUSE
   3      DBI;
   4  # vim: ts=8:sw=4
   5  ########################################################################
   6  #
   7  # Copyright (c) 2002,2003  Tim Bunce  Ireland.
   8  #
   9  # See COPYRIGHT section in DBI.pm for usage and distribution rights.
  10  #
  11  ########################################################################
  12  #
  13  # Please send patches and bug reports to
  14  #
  15  # Jeff Zucker <jeff@vpservices.com>  with cc to <dbi-dev@perl.org>
  16  #
  17  ########################################################################
  18  
  19  use strict;
  20  use Carp;
  21  require Symbol;
  22  
  23  require utf8;
  24  *utf8::is_utf8 = sub { # hack for perl 5.6
  25      require bytes;
  26      return unless defined $_[0];
  27      return !(length($_[0]) == bytes::length($_[0]))
  28  } unless defined &utf8::is_utf8;
  29  
  30  $DBI::PurePerl = $ENV{DBI_PUREPERL} || 1;
  31  $DBI::PurePerl::VERSION = sprintf("2.%06d", q$Revision: 11372 $ =~ /(\d+)/o);
  32  
  33  $DBI::neat_maxlen ||= 400;
  34  
  35  $DBI::tfh = Symbol::gensym();
  36  open $DBI::tfh, ">&STDERR" or warn "Can't dup STDERR: $!";
  37  select( (select($DBI::tfh), $| = 1)[0] );  # autoflush
  38  
  39  # check for weaken support, used by ChildHandles
  40  my $HAS_WEAKEN = eval {
  41      require Scalar::Util;
  42      # this will croak() if this Scalar::Util doesn't have a working weaken().
  43      Scalar::Util::weaken( my $test = [] );
  44      1;
  45  };
  46  
  47  %DBI::last_method_except = map { $_=>1 } qw(DESTROY _set_fbav set_err);
  48  
  49  use constant SQL_ALL_TYPES => 0;
  50  use constant SQL_ARRAY => 50;
  51  use constant SQL_ARRAY_LOCATOR => 51;
  52  use constant SQL_BIGINT => (-5);
  53  use constant SQL_BINARY => (-2);
  54  use constant SQL_BIT => (-7);
  55  use constant SQL_BLOB => 30;
  56  use constant SQL_BLOB_LOCATOR => 31;
  57  use constant SQL_BOOLEAN => 16;
  58  use constant SQL_CHAR => 1;
  59  use constant SQL_CLOB => 40;
  60  use constant SQL_CLOB_LOCATOR => 41;
  61  use constant SQL_DATE => 9;
  62  use constant SQL_DATETIME => 9;
  63  use constant SQL_DECIMAL => 3;
  64  use constant SQL_DOUBLE => 8;
  65  use constant SQL_FLOAT => 6;
  66  use constant SQL_GUID => (-11);
  67  use constant SQL_INTEGER => 4;
  68  use constant SQL_INTERVAL => 10;
  69  use constant SQL_INTERVAL_DAY => 103;
  70  use constant SQL_INTERVAL_DAY_TO_HOUR => 108;
  71  use constant SQL_INTERVAL_DAY_TO_MINUTE => 109;
  72  use constant SQL_INTERVAL_DAY_TO_SECOND => 110;
  73  use constant SQL_INTERVAL_HOUR => 104;
  74  use constant SQL_INTERVAL_HOUR_TO_MINUTE => 111;
  75  use constant SQL_INTERVAL_HOUR_TO_SECOND => 112;
  76  use constant SQL_INTERVAL_MINUTE => 105;
  77  use constant SQL_INTERVAL_MINUTE_TO_SECOND => 113;
  78  use constant SQL_INTERVAL_MONTH => 102;
  79  use constant SQL_INTERVAL_SECOND => 106;
  80  use constant SQL_INTERVAL_YEAR => 101;
  81  use constant SQL_INTERVAL_YEAR_TO_MONTH => 107;
  82  use constant SQL_LONGVARBINARY => (-4);
  83  use constant SQL_LONGVARCHAR => (-1);
  84  use constant SQL_MULTISET => 55;
  85  use constant SQL_MULTISET_LOCATOR => 56;
  86  use constant SQL_NUMERIC => 2;
  87  use constant SQL_REAL => 7;
  88  use constant SQL_REF => 20;
  89  use constant SQL_ROW => 19;
  90  use constant SQL_SMALLINT => 5;
  91  use constant SQL_TIME => 10;
  92  use constant SQL_TIMESTAMP => 11;
  93  use constant SQL_TINYINT => (-6);
  94  use constant SQL_TYPE_DATE => 91;
  95  use constant SQL_TYPE_TIME => 92;
  96  use constant SQL_TYPE_TIMESTAMP => 93;
  97  use constant SQL_TYPE_TIMESTAMP_WITH_TIMEZONE => 95;
  98  use constant SQL_TYPE_TIME_WITH_TIMEZONE => 94;
  99  use constant SQL_UDT => 17;
 100  use constant SQL_UDT_LOCATOR => 18;
 101  use constant SQL_UNKNOWN_TYPE => 0;
 102  use constant SQL_VARBINARY => (-3);
 103  use constant SQL_VARCHAR => 12;
 104  use constant SQL_WCHAR => (-8);
 105  use constant SQL_WLONGVARCHAR => (-10);
 106  use constant SQL_WVARCHAR => (-9);
 107  
 108  # for Cursor types
 109  use constant SQL_CURSOR_FORWARD_ONLY  => 0;
 110  use constant SQL_CURSOR_KEYSET_DRIVEN => 1;
 111  use constant SQL_CURSOR_DYNAMIC       => 2;
 112  use constant SQL_CURSOR_STATIC        => 3;
 113  use constant SQL_CURSOR_TYPE_DEFAULT  => SQL_CURSOR_FORWARD_ONLY;
 114  
 115  use constant IMA_HAS_USAGE    => 0x0001; #/* check parameter usage    */
 116  use constant IMA_FUNC_REDIRECT    => 0x0002; #/* is $h->func(..., "method")*/
 117  use constant IMA_KEEP_ERR    => 0x0004; #/* don't reset err & errstr    */
 118  use constant IMA_KEEP_ERR_SUB    => 0x0008; #/*  '' if in nested call */
 119  use constant IMA_NO_TAINT_IN       => 0x0010; #/* don't check for tainted args*/
 120  use constant IMA_NO_TAINT_OUT   => 0x0020; #/* don't taint results    */
 121  use constant IMA_COPY_UP_STMT   => 0x0040; #/* copy sth Statement to dbh */
 122  use constant IMA_END_WORK    => 0x0080; #/* set on commit & rollback    */
 123  use constant IMA_STUB        => 0x0100; #/* donothing eg $dbh->connected */
 124  use constant IMA_CLEAR_STMT     => 0x0200; #/* clear Statement before call  */
 125  use constant IMA_UNRELATED_TO_STMT=> 0x0400; #/* profile as empty Statement   */
 126  use constant IMA_NOT_FOUND_OKAY    => 0x0800; #/* not error if not found */
 127  use constant IMA_EXECUTE    => 0x1000; #/* do/execute: DBIcf_Executed   */
 128  use constant IMA_SHOW_ERR_STMT  => 0x2000; #/* dbh meth relates to Statement*/
 129  use constant IMA_HIDE_ERR_PARAMVALUES => 0x4000; #/* ParamValues are not relevant */
 130  use constant IMA_IS_FACTORY     => 0x8000; #/* new h ie connect & prepare */
 131  use constant IMA_CLEAR_CACHED_KIDS    => 0x10000; #/* clear CachedKids before call */
 132  
 133  my %is_flag_attribute = map {$_ =>1 } qw(
 134      Active
 135      AutoCommit
 136      ChopBlanks
 137      CompatMode
 138      Executed
 139      Taint
 140      TaintIn
 141      TaintOut
 142      InactiveDestroy
 143      LongTruncOk
 144      MultiThread
 145      PrintError
 146      PrintWarn
 147      RaiseError
 148      ShowErrorStatement
 149      Warn
 150  );
 151  my %is_valid_attribute = map {$_ =>1 } (keys %is_flag_attribute, qw(
 152      ActiveKids
 153      Attribution
 154      BegunWork
 155      CachedKids
 156          Callbacks
 157      ChildHandles
 158      CursorName
 159      Database
 160      DebugDispatch
 161      Driver
 162          Err
 163          Errstr
 164      ErrCount
 165      FetchHashKeyName
 166      HandleError
 167      HandleSetErr
 168      ImplementorClass
 169      Kids
 170      LongReadLen
 171      NAME NAME_uc NAME_lc NAME_uc_hash NAME_lc_hash
 172      NULLABLE
 173      NUM_OF_FIELDS
 174      NUM_OF_PARAMS
 175      Name
 176      PRECISION
 177      ParamValues
 178      Profile
 179      Provider
 180          ReadOnly
 181      RootClass
 182      RowCacheSize
 183      RowsInCache
 184      SCALE
 185          State
 186      Statement
 187      TYPE
 188          Type
 189      TraceLevel
 190      Username
 191      Version
 192  ));
 193  
 194  sub valid_attribute {
 195      my $attr = shift;
 196      return 1 if $is_valid_attribute{$attr};
 197      return 1 if $attr =~ m/^[a-z]/; # starts with lowercase letter
 198      return 0
 199  }
 200  
 201  my $initial_setup;
 202  sub initial_setup {
 203      $initial_setup = 1;
 204      print $DBI::tfh  __FILE__ . " version " . $DBI::PurePerl::VERSION . "\n"
 205      if $DBI::dbi_debug & 0xF;
 206      untie $DBI::err;
 207      untie $DBI::errstr;
 208      untie $DBI::state;
 209      untie $DBI::rows;
 210      #tie $DBI::lasth,  'DBI::var', '!lasth';  # special case: return boolean
 211  }
 212  
 213  sub  _install_method {
 214      my ( $caller, $method, $from, $param_hash ) = @_;
 215      initial_setup() unless $initial_setup;
 216  
 217      my ($class, $method_name) = $method =~ /^[^:]+::(.+)::(.+)$/;
 218      my $bitmask = $param_hash->{'O'} || 0;
 219      my @pre_call_frag;
 220  
 221      return if $method_name eq 'can';
 222  
 223      push @pre_call_frag, q{
 224      return if $h_inner; # ignore DESTROY for outer handle
 225      # copy err/errstr/state up to driver so $DBI::err etc still work
 226      if ($h->{err} and my $drh = $h->{Driver}) {
 227          $drh->{$_} = $h->{$_} for ('err','errstr','state');
 228      }
 229      } if $method_name eq 'DESTROY';
 230  
 231      push @pre_call_frag, q{
 232      return $h->{$_[0]} if exists $h->{$_[0]};
 233      } if $method_name eq 'FETCH' && !exists $ENV{DBI_TRACE}; # XXX ?
 234  
 235      push @pre_call_frag, "return;"
 236      if IMA_STUB & $bitmask;
 237  
 238      push @pre_call_frag, q{
 239      $method_name = pop @_;
 240      } if IMA_FUNC_REDIRECT & $bitmask;
 241  
 242      push @pre_call_frag, q{
 243      my $parent_dbh = $h->{Database};
 244      } if (IMA_COPY_UP_STMT|IMA_EXECUTE) & $bitmask;
 245  
 246      push @pre_call_frag, q{
 247      warn "No Database set for $h on $method_name!" unless $parent_dbh; # eg proxy problems
 248      $parent_dbh->{Statement} = $h->{Statement} if $parent_dbh;
 249      } if IMA_COPY_UP_STMT & $bitmask;
 250  
 251      push @pre_call_frag, q{
 252      $h->{Executed} = 1;
 253      $parent_dbh->{Executed} = 1 if $parent_dbh;
 254      } if IMA_EXECUTE & $bitmask;
 255  
 256      push @pre_call_frag, q{
 257      %{ $h->{CachedKids} } = () if $h->{CachedKids};
 258      } if IMA_CLEAR_CACHED_KIDS & $bitmask;
 259  
 260      if (IMA_KEEP_ERR & $bitmask) {
 261      push @pre_call_frag, q{
 262          my $keep_error = 1;
 263      };
 264      }
 265      else {
 266      my $ke_init = (IMA_KEEP_ERR_SUB & $bitmask)
 267          ? q{= $h->{dbi_pp_parent}->{dbi_pp_call_depth} }
 268          : "";
 269      push @pre_call_frag, qq{
 270          my \$keep_error $ke_init;
 271      };
 272      my $keep_error_code = q{
 273          #warn "$method_name cleared err";
 274          $h->{err}    = $DBI::err    = undef;
 275          $h->{errstr} = $DBI::errstr = undef;
 276          $h->{state}  = $DBI::state  = '';
 277      };
 278      $keep_error_code = q{
 279          printf $DBI::tfh "    !! %s: %s CLEARED by call to }.$method_name.q{ method\n".
 280              $h->{err}, $h->{err}
 281          if defined $h->{err} && $DBI::dbi_debug & 0xF;
 282      }. $keep_error_code
 283          if exists $ENV{DBI_TRACE};
 284      push @pre_call_frag, ($ke_init)
 285          ? qq{ unless (\$keep_error) { $keep_error_code }}
 286          : $keep_error_code
 287          unless $method_name eq 'set_err';
 288      }
 289  
 290      push @pre_call_frag, q{
 291      my $ErrCount = $h->{ErrCount};
 292      };
 293  
 294      push @pre_call_frag, q{
 295          if (($DBI::dbi_debug & 0xF) >= 2) {
 296          local $^W;
 297          my $args = join " ", map { DBI::neat($_) } ($h, @_);
 298          printf $DBI::tfh "    > $method_name in $imp ($args) [$@]\n";
 299      }
 300      } if exists $ENV{DBI_TRACE};    # note use of 'exists'
 301  
 302      push @pre_call_frag, q{
 303          $h->{'dbi_pp_last_method'} = $method_name;
 304      } unless exists $DBI::last_method_except{$method_name};
 305  
 306      # --- post method call code fragments ---
 307      my @post_call_frag;
 308  
 309      push @post_call_frag, q{
 310          if (my $trace_level = ($DBI::dbi_debug & 0xF)) {
 311          if ($h->{err}) {
 312          printf $DBI::tfh "    !! ERROR: %s %s\n", $h->{err}, $h->{errstr};
 313          }
 314          my $ret = join " ", map { DBI::neat($_) } @ret;
 315          my $msg = "    < $method_name= $ret";
 316          $msg = ($trace_level >= 2) ? Carp::shortmess($msg) : "$msg\n";
 317          print $DBI::tfh $msg;
 318      }
 319      } if exists $ENV{DBI_TRACE}; # note use of exists
 320  
 321      push @post_call_frag, q{
 322      $h->{Executed} = 0;
 323      if ($h->{BegunWork}) {
 324          $h->{BegunWork}  = 0;
 325          $h->{AutoCommit} = 1;
 326      }
 327      } if IMA_END_WORK & $bitmask;
 328  
 329      push @post_call_frag, q{
 330          if ( ref $ret[0] and
 331              UNIVERSAL::isa($ret[0], 'DBI::_::common') and
 332              defined( (my $h_new = tied(%{$ret[0]})||$ret[0])->{err} )
 333          ) {
 334              # copy up info/warn to drh so PrintWarn on connect is triggered
 335              $h->set_err($h_new->{err}, $h_new->{errstr}, $h_new->{state})
 336          }
 337      } if IMA_IS_FACTORY & $bitmask;
 338  
 339      push @post_call_frag, q{
 340      $keep_error = 0 if $keep_error && $h->{ErrCount} > $ErrCount;
 341  
 342      $DBI::err    = $h->{err};
 343      $DBI::errstr = $h->{errstr};
 344      $DBI::state  = $h->{state};
 345  
 346          if ( !$keep_error
 347      && defined(my $err = $h->{err})
 348      && ($call_depth <= 1 && !$h->{dbi_pp_parent}{dbi_pp_call_depth})
 349      ) {
 350  
 351          my($pe,$pw,$re,$he) = @{$h}{qw(PrintError PrintWarn RaiseError HandleError)};
 352          my $msg;
 353  
 354          if ($err && ($pe || $re || $he)    # error
 355          or (!$err && length($err) && $pw)    # warning
 356          ) {
 357          my $last = ($DBI::last_method_except{$method_name})
 358              ? ($h->{'dbi_pp_last_method'}||$method_name) : $method_name;
 359          my $errstr = $h->{errstr} || $DBI::errstr || $err || '';
 360          my $msg = sprintf "%s %s %s: %s", $imp, $last,
 361              ($err eq "0") ? "warning" : "failed", $errstr;
 362  
 363          if ($h->{'ShowErrorStatement'} and my $Statement = $h->{Statement}) {
 364              $msg .= ' [for Statement "' . $Statement;
 365              if (my $ParamValues = $h->FETCH('ParamValues')) {
 366              $msg .= '" with ParamValues: ';
 367              $msg .= DBI::_concat_hash_sorted($ParamValues, "=", ", ", 1, undef);
 368                          $msg .= "]";
 369              }
 370                      else {
 371                          $msg .= '"]';
 372                      }
 373          }
 374          if ($err eq "0") { # is 'warning' (not info)
 375              carp $msg if $pw;
 376          }
 377          else {
 378              my $do_croak = 1;
 379              if (my $subsub = $h->{'HandleError'}) {
 380              $do_croak = 0 if &$subsub($msg,$h,$ret[0]);
 381              }
 382              if ($do_croak) {
 383              printf $DBI::tfh "    $method_name has failed ($h->{PrintError},$h->{RaiseError})\n"
 384                  if ($DBI::dbi_debug & 0xF) >= 4;
 385              carp  $msg if $pe;
 386              die $msg if $h->{RaiseError};
 387              }
 388          }
 389          }
 390      }
 391      };
 392  
 393  
 394      my $method_code = q[
 395        sub {
 396          my $h = shift;
 397      my $h_inner = tied(%$h);
 398      $h = $h_inner if $h_inner;
 399  
 400          my $imp;
 401      if ($method_name eq 'DESTROY') {
 402          # during global destruction, $h->{...} can trigger "Can't call FETCH on an undef value"
 403          # implying that tied() above lied to us, so we need to use eval
 404          local $@;     # protect $@
 405          $imp = eval { $h->{"ImplementorClass"} } or return; # probably global destruction
 406      }
 407      else {
 408          $imp = $h->{"ImplementorClass"} or do {
 409                  warn "Can't call $method_name method on handle $h after take_imp_data()\n"
 410                      if not exists $h->{Active};
 411                  return; # or, more likely, global destruction
 412              };
 413      }
 414  
 415      ] . join("\n", '', @pre_call_frag, '') . q[
 416  
 417      my $call_depth = $h->{'dbi_pp_call_depth'} + 1;
 418      local ($h->{'dbi_pp_call_depth'}) = $call_depth;
 419  
 420      my @ret;
 421          my $sub = $imp->can($method_name);
 422          if (!$sub and IMA_FUNC_REDIRECT & $bitmask and $sub = $imp->can('func')) {
 423              push @_, $method_name;
 424          }
 425      if ($sub) {
 426          (wantarray) ? (@ret = &$sub($h,@_)) : (@ret = scalar &$sub($h,@_));
 427      }
 428      else {
 429          # XXX could try explicit fallback to $imp->can('AUTOLOAD') etc
 430          # which would then let Multiplex pass PurePerl tests, but some
 431          # hook into install_method may be better.
 432          croak "Can't locate DBI object method \"$method_name\" via package \"$imp\""
 433          if ] . ((IMA_NOT_FOUND_OKAY & $bitmask) ? 0 : 1) . q[;
 434      }
 435  
 436      ] . join("\n", '', @post_call_frag, '') . q[
 437  
 438      return (wantarray) ? @ret : $ret[0];
 439        }
 440      ];
 441      no strict qw(refs);
 442      my $code_ref = eval qq{#line 1 "DBI::PurePerl $method"\n$method_code};
 443      warn "$@\n$method_code\n" if $@;
 444      die "$@\n$method_code\n" if $@;
 445      *$method = $code_ref;
 446      if (0 && $method =~ /\b(connect|FETCH)\b/) { # debuging tool
 447      my $l=0; # show line-numbered code for method
 448      warn "*$method code:\n".join("\n", map { ++$l.": $_" } split/\n/,$method_code);
 449      }
 450  }
 451  
 452  
 453  sub _new_handle {
 454      my ($class, $parent, $attr, $imp_data, $imp_class) = @_;
 455  
 456      DBI->trace_msg("    New $class (for $imp_class, parent=$parent, id=".($imp_data||'').")\n")
 457          if $DBI::dbi_debug >= 3;
 458  
 459      $attr->{ImplementorClass} = $imp_class
 460          or Carp::croak("_new_handle($class): 'ImplementorClass' attribute not given");
 461  
 462      # This is how we create a DBI style Object:
 463      # %outer gets tied to %$attr (which becomes the 'inner' handle)
 464      my (%outer, $i, $h);
 465      $i = tie    %outer, $class, $attr;  # ref to inner hash (for driver)
 466      $h = bless \%outer, $class;         # ref to outer hash (for application)
 467      # The above tie and bless may migrate down into _setup_handle()...
 468      # Now add magic so DBI method dispatch works
 469      DBI::_setup_handle($h, $imp_class, $parent, $imp_data);
 470      return $h unless wantarray;
 471      return ($h, $i);
 472  }
 473  
 474  sub _setup_handle {
 475      my($h, $imp_class, $parent, $imp_data) = @_;
 476      my $h_inner = tied(%$h) || $h;
 477      if (($DBI::dbi_debug & 0xF) >= 4) {
 478      local $^W;
 479      print $DBI::tfh "      _setup_handle(@_)\n";
 480      }
 481      $h_inner->{"imp_data"} = $imp_data;
 482      $h_inner->{"ImplementorClass"} = $imp_class;
 483      $h_inner->{"Kids"} = $h_inner->{"ActiveKids"} = 0;    # XXX not maintained
 484      if ($parent) {
 485      foreach (qw(
 486          RaiseError PrintError PrintWarn HandleError HandleSetErr
 487          Warn LongTruncOk ChopBlanks AutoCommit ReadOnly
 488          ShowErrorStatement FetchHashKeyName LongReadLen CompatMode
 489      )) {
 490          $h_inner->{$_} = $parent->{$_}
 491          if exists $parent->{$_} && !exists $h_inner->{$_};
 492      }
 493      if (ref($parent) =~ /::db$/) {
 494          $h_inner->{Database} = $parent;
 495          $parent->{Statement} = $h_inner->{Statement};
 496          $h_inner->{NUM_OF_PARAMS} = 0;
 497      }
 498      elsif (ref($parent) =~ /::dr$/){
 499          $h_inner->{Driver} = $parent;
 500      }
 501      $h_inner->{dbi_pp_parent} = $parent;
 502  
 503      # add to the parent's ChildHandles
 504      if ($HAS_WEAKEN) {
 505          my $handles = $parent->{ChildHandles} ||= [];
 506          push @$handles, $h;
 507          Scalar::Util::weaken($handles->[-1]);
 508          # purge destroyed handles occasionally
 509          if (@$handles % 120 == 0) {
 510          @$handles = grep { defined } @$handles;
 511          Scalar::Util::weaken($_) for @$handles; # re-weaken after grep
 512          }
 513      }
 514      }
 515      else {    # setting up a driver handle
 516          $h_inner->{Warn}        = 1;
 517          $h_inner->{PrintWarn}        = $^W;
 518          $h_inner->{AutoCommit}        = 1;
 519          $h_inner->{TraceLevel}        = 0;
 520          $h_inner->{CompatMode}        = (1==0);
 521      $h_inner->{FetchHashKeyName}    ||= 'NAME';
 522      $h_inner->{LongReadLen}        ||= 80;
 523      $h_inner->{ChildHandles}        ||= [] if $HAS_WEAKEN;
 524      $h_inner->{Type}                ||= 'dr';
 525      }
 526      $h_inner->{"dbi_pp_call_depth"} = 0;
 527      $h_inner->{ErrCount} = 0;
 528      $h_inner->{Active} = 1;
 529  }
 530  
 531  sub constant {
 532      warn "constant(@_) called unexpectedly"; return undef;
 533  }
 534  
 535  sub trace {
 536      my ($h, $level, $file) = @_;
 537      $level = $h->parse_trace_flags($level)
 538      if defined $level and !DBI::looks_like_number($level);
 539      my $old_level = $DBI::dbi_debug;
 540      _set_trace_file($file) if $level;
 541      if (defined $level) {
 542      $DBI::dbi_debug = $level;
 543      print $DBI::tfh "    DBI $DBI::VERSION (PurePerl) "
 544                  . "dispatch trace level set to $DBI::dbi_debug\n"
 545          if $DBI::dbi_debug & 0xF;
 546      }
 547      _set_trace_file($file) if !$level;
 548      return $old_level;
 549  }
 550  
 551  sub _set_trace_file {
 552      my ($file) = @_;
 553      #
 554      #   DAA add support for filehandle inputs
 555      #
 556      # DAA required to avoid closing a prior fh trace()
 557      $DBI::tfh = undef unless $DBI::tfh_needs_close;
 558  
 559      if (ref $file eq 'GLOB') {
 560      $DBI::tfh = $file;
 561          select((select($DBI::tfh), $| = 1)[0]);
 562          $DBI::tfh_needs_close = 0;
 563          return 1;
 564      }
 565      $DBI::tfh_needs_close = 1;
 566      if (!$file || $file eq 'STDERR') {
 567      open $DBI::tfh, ">&STDERR" or carp "Can't dup STDERR: $!";
 568      }
 569      elsif ($file eq 'STDOUT') {
 570      open $DBI::tfh, ">&STDOUT" or carp "Can't dup STDOUT: $!";
 571      }
 572      else {
 573          open $DBI::tfh, ">>$file" or carp "Can't open $file: $!";
 574      }
 575      select((select($DBI::tfh), $| = 1)[0]);
 576      return 1;
 577  }
 578  sub _get_imp_data {  shift->{"imp_data"}; }
 579  sub _svdump       { }
 580  sub dump_handle   {
 581      my ($h,$msg,$level) = @_;
 582      $msg||="dump_handle $h";
 583      print $DBI::tfh "$msg:\n";
 584      for my $attrib (sort keys %$h) {
 585      print $DBI::tfh "\t$attrib => ".DBI::neat($h->{$attrib})."\n";
 586      }
 587  }
 588  
 589  sub _handles {
 590      my $h = shift;
 591      my $h_inner = tied %$h;
 592      if ($h_inner) {    # this is okay
 593      return $h unless wantarray;
 594      return ($h, $h_inner);
 595      }
 596      # XXX this isn't okay... we have an inner handle but
 597      # currently have no way to get at its outer handle,
 598      # so we just warn and return the inner one for both...
 599      Carp::carp("Can't return outer handle from inner handle using DBI::PurePerl");
 600      return $h unless wantarray;
 601      return ($h,$h);
 602  }
 603  
 604  sub hash {
 605      my ($key, $type) = @_;
 606      my ($hash);
 607      if (!$type) {
 608          $hash = 0;
 609          # XXX The C version uses the "char" type, which could be either
 610          # signed or unsigned.  I use signed because so do the two
 611          # compilers on my system.
 612          for my $char (unpack ("c*", $key)) {
 613              $hash = $hash * 33 + $char;
 614          }
 615          $hash &= 0x7FFFFFFF;    # limit to 31 bits
 616          $hash |= 0x40000000;    # set bit 31
 617          return -$hash;          # return negative int
 618      }
 619      elsif ($type == 1) {    # Fowler/Noll/Vo hash
 620          # see http://www.isthe.com/chongo/tech/comp/fnv/
 621          require Math::BigInt;   # feel free to reimplement w/o BigInt!
 622      (my $version = $Math::BigInt::VERSION || 0) =~ s/_.*//; # eg "1.70_01"
 623      if ($version >= 1.56) {
 624          $hash = Math::BigInt->new(0x811c9dc5);
 625          for my $uchar (unpack ("C*", $key)) {
 626          # multiply by the 32 bit FNV magic prime mod 2^64
 627          $hash = ($hash * 0x01000193) & 0xffffffff;
 628          # xor the bottom with the current octet
 629          $hash ^= $uchar;
 630          }
 631          # cast to int
 632          return unpack "i", pack "i", $hash;
 633      }
 634      croak("DBI::PurePerl doesn't support hash type 1 without Math::BigInt >= 1.56 (available on CPAN)");
 635      }
 636      else {
 637          croak("bad hash type $type");
 638      }
 639  }
 640  
 641  sub looks_like_number {
 642      my @new = ();
 643      for my $thing(@_) {
 644          if (!defined $thing or $thing eq '') {
 645              push @new, undef;
 646          }
 647          else {
 648              push @new, ($thing =~ /^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/) ? 1 : 0;
 649          }
 650      }
 651      return (@_ >1) ? @new : $new[0];
 652  }
 653  
 654  sub neat {
 655      my $v = shift;
 656      return "undef" unless defined $v;
 657      my $quote = q{"};
 658      if (not utf8::is_utf8($v)) {
 659          return $v if (($v & ~ $v) eq "0"); # is SvNIOK
 660          $quote = q{'};
 661      }
 662      my $maxlen = shift || $DBI::neat_maxlen;
 663      if ($maxlen && $maxlen < length($v) + 2) {
 664      $v = substr($v,0,$maxlen-5);
 665      $v .= '...';
 666      }
 667      $v =~ s/[^[:print:]]/./g;
 668      return "$quote$v$quote";
 669  }
 670  
 671  sub dbi_time {
 672      return time();
 673  }
 674  
 675  sub DBI::st::TIEHASH { bless $_[1] => $_[0] };
 676  
 677  sub _concat_hash_sorted {
 678      my ( $hash_ref, $kv_separator, $pair_separator, $use_neat, $num_sort ) = @_;
 679      # $num_sort: 0=lexical, 1=numeric, undef=try to guess
 680  
 681      return undef unless defined $hash_ref;
 682      die "hash is not a hash reference" unless ref $hash_ref eq 'HASH';
 683      my $keys = _get_sorted_hash_keys($hash_ref, $num_sort);
 684      my $string = '';
 685      for my $key (@$keys) {
 686          $string .= $pair_separator if length $string > 0;
 687          my $value = $hash_ref->{$key};
 688          if ($use_neat) {
 689              $value = DBI::neat($value, 0);
 690          }
 691          else {
 692              $value = (defined $value) ? "'$value'" : 'undef';
 693          }
 694          $string .= $key . $kv_separator . $value;
 695      }
 696      return $string;
 697  }
 698  
 699  sub _get_sorted_hash_keys {
 700      my ($hash_ref, $num_sort) = @_;
 701      if (not defined $num_sort) {
 702          my $sort_guess = 1;
 703          $sort_guess = (not looks_like_number($_)) ? 0 : $sort_guess
 704              for keys %$hash_ref;
 705          $num_sort = $sort_guess;
 706      }
 707      
 708      my @keys = keys %$hash_ref;
 709      no warnings 'numeric';
 710      my @sorted = ($num_sort)
 711          ? sort { $a <=> $b or $a cmp $b } @keys
 712          : sort    @keys;
 713      return \@sorted;
 714  }
 715  
 716  
 717  
 718  package
 719      DBI::var;
 720  
 721  sub FETCH {
 722      my($key)=shift;
 723      return $DBI::err     if $$key eq '*err';
 724      return $DBI::errstr  if $$key eq '&errstr';
 725      Carp::confess("FETCH $key not supported when using DBI::PurePerl");
 726  }
 727  
 728  package
 729      DBD::_::common;
 730  
 731  sub swap_inner_handle {
 732      my ($h1, $h2) = @_;
 733      # can't make this work till we can get the outer handle from the inner one
 734      # probably via a WeakRef
 735      return $h1->set_err($DBI::stderr, "swap_inner_handle not currently supported by DBI::PurePerl");
 736  }
 737  
 738  sub trace {    # XXX should set per-handle level, not global
 739      my ($h, $level, $file) = @_;
 740      $level = $h->parse_trace_flags($level)
 741      if defined $level and !DBI::looks_like_number($level);
 742      my $old_level = $DBI::dbi_debug;
 743      DBI::_set_trace_file($file) if defined $file;
 744      if (defined $level) {
 745      $DBI::dbi_debug = $level;
 746      if ($DBI::dbi_debug) {
 747          printf $DBI::tfh
 748          "    %s trace level set to %d in DBI $DBI::VERSION (PurePerl)\n",
 749          $h, $DBI::dbi_debug;
 750          print $DBI::tfh "    Full trace not available because DBI_TRACE is not in environment\n"
 751          unless exists $ENV{DBI_TRACE};
 752      }
 753      }
 754      return $old_level;
 755  }
 756  *debug = \&trace; *debug = \&trace; # twice to avoid typo warning
 757  
 758  sub FETCH {
 759      my($h,$key)= @_;
 760      my $v = $h->{$key};
 761      #warn ((exists $h->{$key}) ? "$key=$v\n" : "$key NONEXISTANT\n");
 762      return $v if defined $v;
 763      if ($key =~ /^NAME_.c$/) {
 764          my $cols = $h->FETCH('NAME');
 765          return undef unless $cols;
 766          my @lcols = map { lc $_ } @$cols;
 767          $h->{NAME_lc} = \@lcols;
 768          my @ucols = map { uc $_ } @$cols;
 769          $h->{NAME_uc} = \@ucols;
 770          return $h->FETCH($key);
 771      }
 772      if ($key =~ /^NAME.*_hash$/) {
 773          my $i=0;
 774          for my $c(@{$h->FETCH('NAME')||[]}) {
 775              $h->{'NAME_hash'}->{$c}    = $i;
 776              $h->{'NAME_lc_hash'}->{"\L$c"} = $i;
 777              $h->{'NAME_uc_hash'}->{"\U$c"} = $i;
 778              $i++;
 779          }
 780          return $h->{$key};
 781      }
 782      if (!defined $v && !exists $h->{$key}) {
 783      return ($h->FETCH('TaintIn') && $h->FETCH('TaintOut')) if $key eq'Taint';
 784      return (1==0) if $is_flag_attribute{$key}; # return perl-style sv_no, not undef
 785      return $DBI::dbi_debug if $key eq 'TraceLevel';
 786          return [] if $key eq 'ChildHandles' && $HAS_WEAKEN;
 787          if ($key eq 'Type') {
 788              return "dr" if $h->isa('DBI::dr');
 789              return "db" if $h->isa('DBI::db');
 790              return "st" if $h->isa('DBI::st');
 791              Carp::carp( sprintf "Can't determine Type for %s",$h );
 792          }
 793      if (!$is_valid_attribute{$key} and $key =~ m/^[A-Z]/) {
 794          local $^W; # hide undef warnings
 795          Carp::carp( sprintf "Can't get %s->{%s}: unrecognised attribute (@{[ %$h ]})",$h,$key )
 796      }
 797      }
 798      return $v;
 799  }
 800  sub STORE {
 801      my ($h,$key,$value) = @_;
 802      if ($key eq 'AutoCommit') {
 803          Carp::croak("DBD driver has not implemented the AutoCommit attribute")
 804          unless $value == -900 || $value == -901;
 805      $value = ($value == -901);
 806      }
 807      elsif ($key =~ /^Taint/ ) {
 808      Carp::croak(sprintf "Can't set %s->{%s}: Taint mode not supported by DBI::PurePerl",$h,$key)
 809          if $value;
 810      }
 811      elsif ($key eq 'TraceLevel') {
 812      $h->trace($value);
 813      return 1;
 814      }
 815      elsif ($key eq 'NUM_OF_FIELDS') {
 816          $h->{$key} = $value;
 817          if ($value) {
 818              my $fbav = DBD::_::st::dbih_setup_fbav($h);
 819              @$fbav = (undef) x $value if @$fbav != $value;
 820          }
 821      return 1;
 822      }
 823      elsif (!$is_valid_attribute{$key} && $key =~ /^[A-Z]/ && !exists $h->{$key}) {
 824         Carp::carp(sprintf "Can't set %s->{%s}: unrecognised attribute or invalid value %s",
 825          $h,$key,$value);
 826      }
 827      $h->{$key} = $is_flag_attribute{$key} ? !!$value : $value;
 828      return 1;
 829  }
 830  sub err    { return shift->{err}    }
 831  sub errstr { return shift->{errstr} }
 832  sub state  { return shift->{state}  }
 833  sub set_err {
 834      my ($h, $errnum,$msg,$state, $method, $rv) = @_;
 835      $h = tied(%$h) || $h;
 836  
 837      if (my $hss = $h->{HandleSetErr}) {
 838      return if $hss->($h, $errnum, $msg, $state, $method);
 839      }
 840  
 841      if (!defined $errnum) {
 842      $h->{err}    = $DBI::err    = undef;
 843      $h->{errstr} = $DBI::errstr = undef;
 844      $h->{state}  = $DBI::state  = '';
 845          return;
 846      }
 847  
 848      if ($h->{errstr}) {
 849      $h->{errstr} .= sprintf " [err was %s now %s]", $h->{err}, $errnum
 850          if $h->{err} && $errnum && $h->{err} ne $errnum;
 851      $h->{errstr} .= sprintf " [state was %s now %s]", $h->{state}, $state
 852          if $h->{state} and $h->{state} ne "S1000" && $state && $h->{state} ne $state;
 853      $h->{errstr} .= "\n$msg" if $h->{errstr} ne $msg;
 854      $DBI::errstr = $h->{errstr};
 855      }
 856      else {
 857      $h->{errstr} = $DBI::errstr = $msg;
 858      }
 859  
 860      # assign if higher priority: err > "0" > "" > undef
 861      my $err_changed;
 862      if ($errnum            # new error: so assign
 863      or !defined $h->{err}    # no existing warn/info: so assign
 864             # new warn ("0" len 1) > info ("" len 0): so assign
 865      or defined $errnum && length($errnum) > length($h->{err})
 866      ) {
 867          $h->{err} = $DBI::err = $errnum;
 868      ++$h->{ErrCount} if $errnum;
 869      ++$err_changed;
 870      }
 871  
 872      if ($err_changed) {
 873      $state ||= "S1000" if $DBI::err;
 874      $h->{state} = $DBI::state = ($state eq "00000") ? "" : $state
 875          if $state;
 876      }
 877  
 878      if (my $p = $h->{Database}) { # just sth->dbh, not dbh->drh (see ::db::DESTROY)
 879      $p->{err}    = $DBI::err;
 880      $p->{errstr} = $DBI::errstr;
 881      $p->{state}  = $DBI::state;
 882      }
 883  
 884      $h->{'dbi_pp_last_method'} = $method;
 885      return $rv; # usually undef
 886  }
 887  sub trace_msg {
 888      my ($h, $msg, $minlevel)=@_;
 889      $minlevel = 1 unless defined $minlevel;
 890      return unless $minlevel <= ($DBI::dbi_debug & 0xF);
 891      print $DBI::tfh $msg;
 892      return 1;
 893  }
 894  sub private_data {
 895      warn "private_data @_";
 896  }
 897  sub take_imp_data {
 898      my $dbh = shift;
 899      # A reasonable default implementation based on the one in DBI.xs.
 900      # Typically a pure-perl driver would have their own take_imp_data method
 901      # that would delete all but the essential items in the hash before einding with:
 902      #      return $dbh->SUPER::take_imp_data();
 903      # Of course it's useless if the driver doesn't also implement support for
 904      # the dbi_imp_data attribute to the connect() method.
 905      require Storable;
 906      croak("Can't take_imp_data from handle that's not Active")
 907          unless $dbh->{Active};
 908      for my $sth (@{ $dbh->{ChildHandles} || [] }) {
 909          next unless $sth;
 910          $sth->finish if $sth->{Active};
 911          bless $sth, 'DBI::zombie';
 912      }
 913      delete $dbh->{$_} for (keys %is_valid_attribute);
 914      delete $dbh->{$_} for grep { m/^dbi_/ } keys %$dbh;
 915      # warn "@{[ %$dbh ]}";
 916      local $Storable::forgive_me = 1; # in case there are some CODE refs
 917      my $imp_data = Storable::freeze($dbh);
 918      # XXX um, should probably untie here - need to check dispatch behaviour
 919      return $imp_data;
 920  }
 921  sub rows {
 922      return -1; # always returns -1 here, see DBD::_::st::rows below
 923  }
 924  sub DESTROY {
 925  }
 926  
 927  package
 928      DBD::_::dr;
 929  
 930  sub dbixs_revision {
 931      return 0;
 932  }
 933  
 934  package
 935      DBD::_::db;
 936  
 937  sub connected {
 938  }
 939  
 940  
 941  package
 942      DBD::_::st;
 943  
 944  sub fetchrow_arrayref    {
 945      my $h = shift;
 946      # if we're here then driver hasn't implemented fetch/fetchrow_arrayref
 947      # so we assume they've implemented fetchrow_array and call that instead
 948      my @row = $h->fetchrow_array or return;
 949      return $h->_set_fbav(\@row);
 950  }
 951  # twice to avoid typo warning
 952  *fetch = \&fetchrow_arrayref;  *fetch = \&fetchrow_arrayref;
 953  
 954  sub fetchrow_array    {
 955      my $h = shift;
 956      # if we're here then driver hasn't implemented fetchrow_array
 957      # so we assume they've implemented fetch/fetchrow_arrayref
 958      my $row = $h->fetch or return;
 959      return @$row;
 960  }
 961  *fetchrow = \&fetchrow_array; *fetchrow = \&fetchrow_array;
 962  
 963  sub fetchrow_hashref {
 964      my $h         = shift;
 965      my $row       = $h->fetch or return;
 966      my $FetchCase = shift;
 967      my $FetchHashKeyName = $FetchCase || $h->{'FetchHashKeyName'} || 'NAME';
 968      my $FetchHashKeys    = $h->FETCH($FetchHashKeyName);
 969      my %rowhash;
 970      @rowhash{ @$FetchHashKeys } = @$row;
 971      return \%rowhash;
 972  }
 973  sub dbih_setup_fbav {
 974      my $h = shift;
 975      return $h->{'_fbav'} || do {
 976          $DBI::rows = $h->{'_rows'} = 0;
 977          my $fields = $h->{'NUM_OF_FIELDS'}
 978                    or DBI::croak("NUM_OF_FIELDS not set");
 979          my @row = (undef) x $fields;
 980          \@row;
 981      };
 982  }
 983  sub _get_fbav {
 984      my $h = shift;
 985      my $av = $h->{'_fbav'} ||= dbih_setup_fbav($h);
 986      $DBI::rows = ++$h->{'_rows'};
 987      return $av;
 988  }
 989  sub _set_fbav {
 990      my $h = shift;
 991      my $fbav = $h->{'_fbav'};
 992      if ($fbav) {
 993      $DBI::rows = ++$h->{'_rows'};
 994      }
 995      else {
 996      $fbav = $h->_get_fbav;
 997      }
 998      my $row = shift;
 999      if (my $bc = $h->{'_bound_cols'}) {
1000          for my $i (0..@$row-1) {
1001              my $bound = $bc->[$i];
1002              $fbav->[$i] = ($bound) ? ($$bound = $row->[$i]) : $row->[$i];
1003          }
1004      }
1005      else {
1006          @$fbav = @$row;
1007      }
1008      return $fbav;
1009  }
1010  sub bind_col {
1011      my ($h, $col, $value_ref,$from_bind_columns) = @_;
1012      my $fbav = $h->{'_fbav'} ||= dbih_setup_fbav($h); # from _get_fbav()
1013      my $num_of_fields = @$fbav;
1014      DBI::croak("bind_col: column $col is not a valid column (1..$num_of_fields)")
1015          if $col < 1 or $col > $num_of_fields;
1016      return 1 if not defined $value_ref; # ie caller is just trying to set TYPE
1017      DBI::croak("bind_col($col,$value_ref) needs a reference to a scalar")
1018      unless ref $value_ref eq 'SCALAR';
1019      $h->{'_bound_cols'}->[$col-1] = $value_ref;
1020      return 1;
1021  }
1022  sub finish {
1023      my $h = shift;
1024      $h->{'_fbav'} = undef;
1025      $h->{'Active'} = 0;
1026      return 1;
1027  }
1028  sub rows {
1029      my $h = shift;
1030      my $rows = $h->{'_rows'};
1031      return -1 unless defined $rows;
1032      return $rows;
1033  }
1034  
1035  1;
1036  __END__
1037  
1038  =pod
1039  
1040  =head1 NAME
1041  
1042  DBI::PurePerl -- a DBI emulation using pure perl (no C/XS compilation required)
1043  
1044  =head1 SYNOPSIS
1045  
1046   BEGIN { $ENV{DBI_PUREPERL} = 2 }
1047   use DBI;
1048  
1049  =head1 DESCRIPTION
1050  
1051  This is a pure perl emulation of the DBI internals.  In almost all
1052  cases you will be better off using standard DBI since the portions
1053  of the standard version written in C make it *much* faster.
1054  
1055  However, if you are in a situation where it isn't possible to install
1056  a compiled version of standard DBI, and you're using pure-perl DBD
1057  drivers, then this module allows you to use most common features
1058  of DBI without needing any changes in your scripts.
1059  
1060  =head1 EXPERIMENTAL STATUS
1061  
1062  DBI::PurePerl is new so please treat it as experimental pending
1063  more extensive testing.  So far it has passed all tests with DBD::CSV,
1064  DBD::AnyData, DBD::XBase, DBD::Sprite, DBD::mysqlPP.  Please send
1065  bug reports to Jeff Zucker at <jeff@vpservices.com> with a cc to
1066  <dbi-dev@perl.org>.
1067  
1068  =head1 USAGE
1069  
1070  The usage is the same as for standard DBI with the exception
1071  that you need to set the enviornment variable DBI_PUREPERL if
1072  you want to use the PurePerl version.
1073  
1074   DBI_PUREPERL == 0 (the default) Always use compiled DBI, die
1075                     if it isn't properly compiled & installed
1076  
1077   DBI_PUREPERL == 1 Use compiled DBI if it is properly compiled
1078                     & installed, otherwise use PurePerl
1079  
1080   DBI_PUREPERL == 2 Always use PurePerl
1081  
1082  You may set the enviornment variable in your shell (e.g. with
1083  set or setenv or export, etc) or else set it in your script like
1084  this:
1085  
1086   BEGIN { $ENV{DBI_PUREPERL}=2 }
1087  
1088  before you C<use DBI;>.
1089  
1090  =head1 INSTALLATION
1091  
1092  In most situations simply install DBI (see the DBI pod for details).
1093  
1094  In the situation in which you can not install DBI itself, you
1095  may manually copy DBI.pm and PurePerl.pm into the appropriate
1096  directories.
1097  
1098  For example:
1099  
1100   cp DBI.pm      /usr/jdoe/mylibs/.
1101   cp PurePerl.pm /usr/jdoe/mylibs/DBI/.
1102  
1103  Then add this to the top of scripts:
1104  
1105   BEGIN {
1106     $ENV{DBI_PUREPERL} = 1;    # or =2
1107     unshift @INC, '/usr/jdoe/mylibs';
1108   }
1109  
1110  (Or should we perhaps patch Makefile.PL so that if DBI_PUREPERL
1111  is set to 2 prior to make, the normal compile process is skipped
1112  and the files are installed automatically?)
1113  
1114  =head1 DIFFERENCES BETWEEN DBI AND DBI::PurePerl
1115  
1116  =head2 Attributes
1117  
1118  Boolean attributes still return boolean values but the actual values
1119  used may be different, i.e., 0 or undef instead of an empty string.
1120  
1121  Some handle attributes are either not supported or have very limited
1122  functionality:
1123  
1124    ActiveKids
1125    InactiveDestroy
1126    Kids
1127    Taint
1128    TaintIn
1129    TaintOut
1130  
1131  (and probably others)
1132  
1133  =head2 Tracing
1134  
1135  Trace functionality is more limited and the code to handle tracing is
1136  only embeded into DBI:PurePerl if the DBI_TRACE environment variable
1137  is defined.  To enable total tracing you can set the DBI_TRACE
1138  environment variable as usual.  But to enable individual handle
1139  tracing using the trace() method you also need to set the DBI_TRACE
1140  environment variable, but set it to 0.
1141  
1142  =head2 Parameter Usage Checking
1143  
1144  The DBI does some basic parameter count checking on method calls.
1145  DBI::PurePerl doesn't.
1146  
1147  =head2 Speed
1148  
1149  DBI::PurePerl is slower. Although, with some drivers in some
1150  contexts this may not be very significant for you.
1151  
1152  By way of example... the test.pl script in the DBI source
1153  distribution has a simple benchmark that just does:
1154  
1155      my $null_dbh = DBI->connect('dbi:NullP:','','');
1156      my $i = 10_000;
1157      $null_dbh->prepare('') while $i--;
1158  
1159  In other words just prepares a statement, creating and destroying
1160  a statement handle, over and over again.  Using the real DBI this
1161  runs at ~4550 handles per second whereas DBI::PurePerl manages
1162  ~2800 per second on the same machine (not too bad really).
1163  
1164  =head2 May not fully support hash()
1165  
1166  If you want to use type 1 hash, i.e., C<hash($string,1)> with
1167  DBI::PurePerl, you'll need version 1.56 or higher of Math::BigInt
1168  (available on CPAN).
1169  
1170  =head2 Doesn't support preparse()
1171  
1172  The DBI->preparse() method isn't supported in DBI::PurePerl.
1173  
1174  =head2 Doesn't support DBD::Proxy
1175  
1176  There's a subtle problem somewhere I've not been able to identify.
1177  DBI::ProxyServer seem to work fine with DBI::PurePerl but DBD::Proxy
1178  does not work 100% (which is sad because that would be far more useful :)
1179  Try re-enabling t/80proxy.t for DBI::PurePerl to see if the problem
1180  that remains will affect you're usage.
1181  
1182  =head2 Others
1183  
1184    can() - doesn't have any special behaviour
1185  
1186  Please let us know if you find any other differences between DBI
1187  and DBI::PurePerl.
1188  
1189  =head1 AUTHORS
1190  
1191  Tim Bunce and Jeff Zucker.
1192  
1193  Tim provided the direction and basis for the code.  The original
1194  idea for the module and most of the brute force porting from C to
1195  Perl was by Jeff. Tim then reworked some core parts to boost the
1196  performance and accuracy of the emulation. Thanks also to Randal
1197  Schwartz and John Tobey for patches.
1198  
1199  =head1 COPYRIGHT
1200  
1201  Copyright (c) 2002  Tim Bunce  Ireland.
1202  
1203  See COPYRIGHT section in DBI.pm for usage and distribution rights.
1204  
1205  =cut


Generated: Tue Mar 17 22:47:18 2015 Cross-referenced by PHPXref 0.7.1