Apache-LoggedAuthDBI

 view release on metacpan or  search on metacpan

DBI.pm  view on Meta::CPAN

	bind_param_inout=> { U =>[4,5,'$parameter, \\$var, $maxlen, [, \%attr]'] },
	execute		=> { U =>[1,0,'[@args]'], O=>0x1040 },

	bind_param_array  => { U =>[3,4,'$parameter, $var [, \%attr]'] },
	bind_param_inout_array => { U =>[4,5,'$parameter, \\@var, $maxlen, [, \%attr]'] },
	execute_array     => { U =>[2,0,'\\%attribs [, @args]'],         O=>0x1040 },
	execute_for_fetch => { U =>[2,3,'$fetch_sub [, $tuple_status]'], O=>0x1040 },

	fetch    	  => undef, # alias for fetchrow_arrayref
	fetchrow_arrayref => undef,
	fetchrow_hashref  => undef,
	fetchrow_array    => undef,
	fetchrow   	  => undef, # old alias for fetchrow_array

	fetchall_arrayref => { U =>[1,3, '[ $slice [, $max_rows]]'] },
	fetchall_hashref  => { U =>[2,2,'$key_field'] },

	blob_read  =>	{ U =>[4,5,'$field, $offset, $len [, \\$buf [, $bufoffset]]'] },
	blob_copy_to_file => { U =>[3,3,'$field, $filename_or_handleref'] },
	dump_results => { U =>[1,5,'$maxfieldlen, $linesep, $fieldsep, $filehandle'] },
	more_results => { U =>[1,1] },
	finish     => 	{ U =>[1,1] },
	cancel     => 	{ U =>[1,1], O=>0x0800 },
	rows       =>	$keeperr,

	_get_fbav	=> undef,
	_set_fbav	=> { T=>6 },
    },
);

while ( my ($class, $meths) = each %DBI::DBI_methods ) {
    while ( my ($method, $info) = each %$meths ) {
	my $fullmeth = "DBI::${class}::$method";
	DBI->_install_method($fullmeth, 'DBI.pm', $info);
    }
}

{
    package DBI::common;
    @DBI::dr::ISA = ('DBI::common');
    @DBI::db::ISA = ('DBI::common');
    @DBI::st::ISA = ('DBI::common');
}

# End of init code


END {
    return unless defined &DBI::trace_msg; # return unless bootstrap'd ok
    local ($!,$?);
    DBI->trace_msg("    -- DBI::END\n", 2);
    # Let drivers know why we are calling disconnect_all:
    $DBI::PERL_ENDING = $DBI::PERL_ENDING = 1;	# avoid typo warning
    DBI->disconnect_all() if %DBI::installed_drh;
}


sub CLONE {
    my $olddbis = $DBI::_dbistate;
    _clone_dbis() unless $DBI::PurePerl; # clone the DBIS structure
    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
}

sub parse_dsn {
    my ($class, $dsn) = @_;
    $dsn =~ s/^(dbi):(\w*?)(?:\((.*?)\))?://i or return;
    my ($scheme, $driver, $attr, $attr_hash) = (lc($1), $2, $3);
    $driver ||= $ENV{DBI_DRIVER} || '';
    $attr_hash = { split /\s*=>?\s*|\s*,\s*/, $attr, -1 } if $attr;
    return ($scheme, $driver, $attr, $attr_hash, $dsn);
}


# --- The DBI->connect Front Door methods

sub connect_cached {
    # 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) = @_;
    # XXX modifies callers data!
    ($attr ||= {})->{dbi_connect_method} =
	($DBI::connect_via eq "Apache::DBI::connect")
	    ? 'Apache::DBI::connect' : 'connect_cached';
    return $class->connect($dsn, $user, $pass, $attr);
}

sub connect {
    my $class = shift;
    my ($dsn, $user, $pass, $attr, $old_driver) = my @orig_args = @_;
    my $driver;

    if ($attr and !ref($attr)) { # switch $old_driver<->$attr if called in old style
	Carp::carp("DBI->connect using 'old-style' syntax is deprecated and will be an error in future versions");
        ($old_driver, $attr) = ($attr, $old_driver);
    }

    my $connect_meth = $attr->{dbi_connect_method};
    $connect_meth ||= $DBI::connect_via;	# fallback to default

    $dsn ||= $ENV{DBI_DSN} || $ENV{DBI_DBNAME} || '' unless $old_driver;

    if ($DBI::dbi_debug) {
	local $^W = 0;
	pop @_ if $connect_meth ne 'connect';
	my @args = @_; $args[2] = '****'; # hide password
	DBI->trace_msg("    -> $class->$connect_meth(".join(", ",@args).")\n");
    }
    Carp::croak('Usage: $class->connect([$dsn [,$user [,$passwd [,\%attr]]]])')
	if (ref $old_driver or ($attr and not ref $attr) or ref $pass);

    # extract dbi:driver prefix from $dsn into $1
    $dsn =~ s/^dbi:(\w*?)(?:\((.*?)\))?://i
			or '' =~ /()/; # ensure $1 etc are empty if match fails
    my $driver_attrib_spec = $2 || '';

    # Set $driver. Old style driver, if specified, overrides new dsn style.
    $driver = $old_driver || $1 || $ENV{DBI_DRIVER}
	or Carp::croak("Can't connect to data source $dsn, no database driver specified "
		."and DBI_DSN env var not set");

DBI.pm  view on Meta::CPAN

If C<$data_type> is supplied, it is used to try to determine the required
quoting behaviour by using the information returned by L</type_info>.
As a special case, the standard numeric types are optimized to return
C<$value> without calling C<type_info>.

Quote will probably I<not> be able to deal with all possible input
(such as binary data or data containing newlines), and is not related in
any way with escaping or quoting shell meta-characters.

It is valid for the quote() method to return an SQL expression that
evaluates to the desired string. For example:

  $quoted = $dbh->quote("one\ntwo\0three")

may return something like:

  CONCAT('one', CHAR(12), 'two', CHAR(0), 'three')

The quote() method should I<not> be used with L</"Placeholders and
Bind Values">.

=item C<quote_identifier>

  $sql = $dbh->quote_identifier( $name );
  $sql = $dbh->quote_identifier( $catalog, $schema, $table, \%attr );

Quote an identifier (table name etc.) for use in an SQL statement,
by escaping any special characters (such as double quotation marks)
it contains and adding the required type of outer quotation marks.

Undefined names are ignored and the remainder are quoted and then
joined together, typically with a dot (C<.>) character. For example:

  $id = $dbh->quote_identifier( undef, 'Her schema', 'My table' );

would, for most database types, return C<"Her schema"."My table">
(including all the double quotation marks).

If three names are supplied then the first is assumed to be a
catalog name and special rules may be applied based on what L</get_info>
returns for SQL_CATALOG_NAME_SEPARATOR (41) and SQL_CATALOG_LOCATION (114).
For example, for Oracle:

  $id = $dbh->quote_identifier( 'link', 'schema', 'table' );

would return C<"schema"."table"@"link">.

=item C<take_imp_data>

  $imp_data = $dbh->take_imp_data;

Leaves the $dbh in an almost dead, zombie-like, state and returns
a binary string of raw implementation data from the driver which
describes the current database connection. Effectively it detaches
the underlying database API connection data from the DBI handle.
After calling take_imp_data(), all other methods except C<DESTROY>
will generate a warning and return undef.

Why would you want to do this? You don't, forget I even mentioned it.
Unless, that is, you're implementing something advanced like a
multi-threaded connection pool.

The returned $imp_data can be passed as a C<dbi_imp_data> attribute
to a later connect() call, even in a separate thread in the same
process, where the driver can use it to 'adopt' the existing
connection that the implementation data was taken from.

Some things to keep in mind...

B<*> the $imp_data holds the only reference to the underlying
database API connection data. That connection is still 'live' and
won't be cleaned up properly unless the $imp_data is used to create
a new $dbh which can then disconnect() normally.

B<*> using the same $imp_data to create more than one other new
$dbh at a time may well lead to unpleasant problems. Don't do that.

The C<take_imp_data> method was added in DBI 1.36.

=back


=head2 Database Handle Attributes

This section describes attributes specific to database handles.

Changes to these database handle attributes do not affect any other
existing or future database handles.

Attempting to set or get the value of an unknown attribute generates a warning,
except for private driver-specific attributes (which all have names
starting with a lowercase letter).

Example:

  $h->{AutoCommit} = ...;	# set/write
  ... = $h->{AutoCommit};	# get/read

=over 4

=item C<AutoCommit>  (boolean)

If true, then database changes cannot be rolled-back (undone).  If false,
then database changes automatically occur within a "transaction", which
must either be committed or rolled back using the C<commit> or C<rollback>
methods.

Drivers should always default to C<AutoCommit> mode (an unfortunate
choice largely forced on the DBI by ODBC and JDBC conventions.)

Attempting to set C<AutoCommit> to an unsupported value is a fatal error.
This is an important feature of the DBI. Applications that need
full transaction behaviour can set C<$dbh-E<gt>{AutoCommit} = 0> (or
set C<AutoCommit> to 0 via L</connect>)
without having to check that the value was assigned successfully.

For the purposes of this description, we can divide databases into three
categories:

  Databases which don't support transactions at all.
  Databases in which a transaction is always active.
  Databases in which a transaction must be explicitly started (C<'BEGIN WORK'>).

B<* Databases which don't support transactions at all>

DBI.pm  view on Meta::CPAN

  my $data_source = "dbi::DriverName:db_name";
  my $dbh = DBI->connect($data_source, $user, $password)
      or die "Can't connect to $data_source: $DBI::errstr";

  my $sth = $dbh->prepare( q{
          SELECT name, phone
          FROM mytelbook
  }) or die "Can't prepare statement: $DBI::errstr";

  my $rc = $sth->execute
      or die "Can't execute statement: $DBI::errstr";

  print "Query will return $sth->{NUM_OF_FIELDS} fields.\n\n";
  print "Field names: @{ $sth->{NAME} }\n";

  while (($name, $phone) = $sth->fetchrow_array) {
      print "$name: $phone\n";
  }
  # check for problems which may have terminated the fetch early
  die $sth->errstr if $sth->err;

  $dbh->disconnect;

Here's a complete example program to insert some data from a file.
(This example uses C<RaiseError> to avoid needing to check each call).

  my $dbh = DBI->connect("dbi:DriverName:db_name", $user, $password, {
      RaiseError => 1, AutoCommit => 0
  });

  my $sth = $dbh->prepare( q{
      INSERT INTO table (name, phone) VALUES (?, ?)
  });

  open FH, "<phone.csv" or die "Unable to open phone.csv: $!";
  while (<FH>) {
      chomp;
      my ($name, $phone) = split /,/;
      $sth->execute($name, $phone);
  }
  close FH;

  $dbh->commit;
  $dbh->disconnect;

Here's how to convert fetched NULLs (undefined values) into empty strings:

  while($row = $sth->fetchrow_arrayref) {
    # this is a fast and simple way to deal with nulls:
    foreach (@$row) { $_ = '' unless defined }
    print "@$row\n";
  }

The C<q{...}> style quoting used in these examples avoids clashing with
quotes that may be used in the SQL statement. Use the double-quote like
C<qq{...}> operator if you want to interpolate variables into the string.
See L<perlop/"Quote and Quote-like Operators"> for more details.

=head2 Threads and Thread Safety

Perl 5.7 and later support a new threading model called iThreads.
(The old "5.005 style" threads are not supported by the DBI.)

In the iThreads model each thread has it's own copy of the perl
interpreter.  When a new thread is created the original perl
interpreter is 'cloned' to create a new copy for the new thread.

If the DBI and drivers are loaded and handles created before the
thread is created then it will get a cloned copy of the DBI, the
drivers and the handles.

However, the internal pointer data within the handles will refer
to the DBI and drivers in the original interpreter. Using those
handles in the new interpreter thread is not safe, so the DBI detects
this and croaks on any method call using handles that don't belong
to the current thread (except for DESTROY).

Because of this (possibly temporary) restriction, newly created
threads must make their own connctions to the database. Handles
can't be shared across threads.

But BEWARE, some underlying database APIs (the code the DBD driver
uses to talk to the database, often supplied by the database vendor)
are not thread safe. If it's not thread safe, then allowing more
than one thread to enter the code at the same time may cause
subtle/serious problems. In some cases allowing more than
one thread to enter the code, even if I<not> at the same time,
can cause problems. You have been warned.

Using DBI with perl threads is not yet recommended for production
environments. For more information see
L<http://www.perlmonks.org/index.pl?node_id=288022>

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

[The following only applies to systems with unix-like signal handling.
I'd welcome additions for other systems, especially Windows.]

The first thing to say is that signal handling in Perl versions less
than 5.8 is I<not> safe. There is always a small risk of Perl
crashing and/or core dumping when, or after, handling a signal
because the signal could arrive and be handled while internal data
structures are being changed. If the signal handling code
used those same internal data structures it could cause all manner
of subtle and not-so-subtle problems.  The risk was reduced with
5.4.4 but was still present in all perls up through 5.8.0.

Beginning in perl 5.8.0 perl implements 'safe' signal handling if
your system has the POSIX sigaction() routine. Now when a signal
is delivered perl just makes a note of it but does I<not> run the
%SIG handler. The handling is 'defered' until a 'safe' moment.

Although this change made signal handling safe, it also lead to
a problem with signals being defered for longer than you'd like.
If a signal arrived while executing a system call, such as waiting
for data on a network connection, the signal is noted and then the
system call that was executing returns with an EINTR error code
to indicate that it was interrupted. All fine so far.

The problem comes when the code that made the system call sees the
EINTR code and decides it's going to call it again. Perl doesn't
do that, but database code sometimes does. If that happens then the
signal handler doesn't get called untill later. Maybe much later.

Fortunately there are ways around this which we'll discuss below.
Unfortunately they make signals unsafe again.

The two most common uses of signals in relation to the DBI are for
canceling operations when the user types Ctrl-C (interrupt), and for
implementing a timeout using C<alarm()> and C<$SIG{ALRM}>. 

=over 4

=item Cancel

The DBI provides a C<cancel> method for statement handles. The
C<cancel> method should abort the current operation and is designed
to be called from a signal handler.  For example:

  $SIG{INT} = sub { $sth->cancel };

However, few drivers implement this (the DBI provides a default
method that just returns C<undef>) and, even if implemented, there
is still a possibility that the statement handle, and even the
parent database handle, will not be usable afterwards.

If C<cancel> returns true, then it has successfully
invoked the database engine's own cancel function.  If it returns false,
then C<cancel> failed. If it returns C<undef>, then the database
driver does not have cancel implemented.



( run in 1.298 second using v1.01-cache-2.11-cpan-c966e8aa7e8 )