summaryrefslogtreecommitdiff
path: root/Master/tlpkg/tlperl0/lib/DBI/DBD.pm
diff options
context:
space:
mode:
Diffstat (limited to 'Master/tlpkg/tlperl0/lib/DBI/DBD.pm')
-rwxr-xr-xMaster/tlpkg/tlperl0/lib/DBI/DBD.pm3385
1 files changed, 3385 insertions, 0 deletions
diff --git a/Master/tlpkg/tlperl0/lib/DBI/DBD.pm b/Master/tlpkg/tlperl0/lib/DBI/DBD.pm
new file mode 100755
index 00000000000..fedfc732317
--- /dev/null
+++ b/Master/tlpkg/tlperl0/lib/DBI/DBD.pm
@@ -0,0 +1,3385 @@
+package DBI::DBD;
+# vim:ts=8:sw=4
+
+use vars qw($VERSION); # set $VERSION early so we don't confuse PAUSE/CPAN etc
+
+# don't use Revision here because that's not in svn:keywords so that the
+# examples that use it below won't be messed up
+$VERSION = sprintf("12.%06d", q$Id: DBD.pm 11723 2008-09-02 10:09:51Z mjevans $ =~ /(\d+)/o);
+
+
+# $Id: DBD.pm 11723 2008-09-02 10:09:51Z mjevans $
+#
+# Copyright (c) 1997-2006 Jonathan Leffler, Jochen Wiedmann, Steffen
+# Goeldner and Tim Bunce
+#
+# You may distribute under the terms of either the GNU General Public
+# License or the Artistic License, as specified in the Perl README file.
+
+=head1 NAME
+
+DBI::DBD - Perl DBI Database Driver Writer's Guide
+
+=head1 SYNOPSIS
+
+ perldoc DBI::DBD
+
+=head2 Version and volatility
+
+This document is I<still> a minimal draft which is in need of further work.
+
+The changes will occur both because the B<DBI> specification is changing
+and hence the requirements on B<DBD> drivers change, and because feedback
+from people reading this document will suggest improvements to it.
+
+Please read the B<DBI> documentation first and fully, including the B<DBI> FAQ.
+Then reread the B<DBI> specification again as you're reading this. It'll help.
+
+This document is a patchwork of contributions from various authors.
+More contributions (preferably as patches) are very welcome.
+
+=head1 DESCRIPTION
+
+This document is primarily intended to help people writing new
+database drivers for the Perl Database Interface (Perl DBI).
+It may also help others interested in discovering why the internals of
+a B<DBD> driver are written the way they are.
+
+This is a guide. Few (if any) of the statements in it are completely
+authoritative under all possible circumstances. This means you will
+need to use judgement in applying the guidelines in this document.
+If in I<any> doubt at all, please do contact the I<dbi-dev> mailing list
+(details given below) where Tim Bunce and other driver authors can help.
+
+=head1 CREATING A NEW DRIVER
+
+The first rule for creating a new database driver for the Perl DBI is
+very simple: B<DON'T!>
+
+There is usually a driver already available for the database you want
+to use, almost regardless of which database you choose. Very often, the
+database will provide an ODBC driver interface, so you can often use
+B<DBD::ODBC> to access the database. This is typically less convenient
+on a Unix box than on a Microsoft Windows box, but there are numerous
+options for ODBC driver managers on Unix too, and very often the ODBC
+driver is provided by the database supplier.
+
+Before deciding that you need to write a driver, do your homework to
+ensure that you are not wasting your energies.
+
+[As of December 2002, the consensus is that if you need an ODBC driver
+manager on Unix, then the unixODBC driver (available from
+L<http://www.unixodbc.org/>) is the way to go.]
+
+The second rule for creating a new database driver for the Perl DBI is
+also very simple: B<Don't -- get someone else to do it for you!>
+
+Nevertheless, there are occasions when it is necessary to write a new
+driver, often to use a proprietary language or API to access the
+database more swiftly, or more comprehensively, than an ODBC driver can.
+Then you should read this document very carefully, but with a suitably
+sceptical eye.
+
+If there is something in here that does not make any sense, question it.
+You might be right that the information is bogus, but don't come to that
+conclusion too quickly.
+
+=head2 URLs and mailing lists
+
+The primary web-site for locating B<DBI> software and information is
+
+ http://dbi.perl.org/
+
+There are two main and one auxiliary mailing lists for people working
+with B<DBI>. The primary lists are I<dbi-users@perl.org> for general users
+of B<DBI> and B<DBD> drivers, and I<dbi-dev@perl.org> mainly for B<DBD> driver
+writers (don't join the I<dbi-dev> list unless you have a good reason).
+The auxiliary list is I<dbi-announce@perl.org> for announcing new
+releases of B<DBI> or B<DBD> drivers.
+
+You can join these lists by accessing the web-site L<http://dbi.perl.org/>.
+The lists are closed so you cannot send email to any of the lists
+unless you join the list first.
+
+You should also consider monitoring the I<comp.lang.perl.*> newsgroups,
+especially I<comp.lang.perl.modules>.
+
+=head2 The Cheetah book
+
+The definitive book on Perl DBI is the Cheetah book, so called because
+of the picture on the cover. Its proper title is 'I<Programming the
+Perl DBI: Database programming with Perl>' by Alligator Descartes
+and Tim Bunce, published by O'Reilly Associates, February 2000, ISBN
+1-56592-699-4. Buy it now if you have not already done so, and read it.
+
+=head2 Locating drivers
+
+Before writing a new driver, it is in your interests to find out
+whether there already is a driver for your database. If there is such
+a driver, it would be much easier to make use of it than to write your
+own!
+
+The primary web-site for locating Perl software is
+L<http://search.cpan.org/>. You should look under the various
+modules listings for the software you are after. For example:
+
+ http://search.cpan.org/modlist/Database_Interfaces
+
+Follow the B<DBD::> and B<DBIx::> links at the top to see those subsets.
+
+See the B<DBI> docs for information on B<DBI> web sites and mailing lists.
+
+=head2 Registering a new driver
+
+Before going through any official registration process, you will need
+to establish that there is no driver already in the works. You'll do
+that by asking the B<DBI> mailing lists whether there is such a driver
+available, or whether anybody is working on one.
+
+When you get the go ahead, you will need to establish the name of the
+driver and a prefix for the driver. Typically, the name is based on the
+name of the database software it uses, and the prefix is a contraction
+of that. Hence, B<DBD::Oracle> has the name I<Oracle> and the prefix
+'I<ora_>'. The prefix must be lowercase and contain no underscores other
+than the one at the end.
+
+This information will be recorded in the B<DBI> module. Apart from
+documentation purposes, registration is a prerequisite for
+L<installing private methods|DBI/install_method>.
+
+If you are writing a driver which will not be distributed on CPAN, then
+you should choose a prefix beginning with 'I<x_>', to avoid potential
+prefix collisions with drivers registered in the future. Thus, if you
+wrote a non-CPAN distributed driver called B<DBD::CustomDB>, the prefix
+might be 'I<x_cdb_>'.
+
+This document assumes you are writing a driver called B<DBD::Driver>, and
+that the prefix 'I<drv_>' is assigned to the driver.
+
+=head2 Two styles of database driver
+
+There are two distinct styles of database driver that can be written to
+work with the Perl DBI.
+
+Your driver can be written in pure Perl, requiring no C compiler.
+When feasible, this is the best solution, but most databases are not
+written in such a way that this can be done. Some examples of pure
+Perl drivers are B<DBD::File> and B<DBD::CSV>.
+
+Alternatively, and most commonly, your driver will need to use some C
+code to gain access to the database. This will be classified as a C/XS
+driver.
+
+=head2 What code will you write?
+
+There are a number of files that need to be written for either a pure
+Perl driver or a C/XS driver. There are no extra files needed only by
+a pure Perl driver, but there are several extra files needed only by a
+C/XS driver.
+
+=head3 Files common to pure Perl and C/XS drivers
+
+Assuming that your driver is called B<DBD::Driver>, these files are:
+
+=over 4
+
+=item * F<Makefile.PL>
+
+=item * F<META.yml>
+
+=item * F<README>
+
+=item * F<MANIFEST>
+
+=item * F<Driver.pm>
+
+=item * F<lib/Bundle/DBD/Driver.pm>
+
+=item * F<lib/DBD/Driver/Summary.pm>
+
+=item * F<t/*.t>
+
+=back
+
+The first four files are mandatory. F<Makefile.PL> is used to control
+how the driver is built and installed. The F<README> file tells people
+who download the file about how to build the module and any prerequisite
+software that must be installed. The F<MANIFEST> file is used by the
+standard Perl module distribution mechanism. It lists all the source
+files that need to be distributed with your module. F<Driver.pm> is what
+is loaded by the B<DBI> code; it contains the methods peculiar to your
+driver.
+
+Although the F<META.yml> file is not B<required> you are advised to
+create one. Of particular importance are the I<build_requires> and
+I<configure_requires> attributes which newer CPAN modules understand.
+You use these to tell the CPAN module (and CPANPLUS) that your build
+and configure mechanisms require DBI. The best reference for META.yml
+(at the time of writing) is
+L<http://module-build.sourceforge.net/META-spec-v1.2.html>. You can find
+a reasonable example of a F<META.yml> in DBD::ODBC.
+
+The F<lib/Bundle/DBD/Driver.pm> file allows you to specify other Perl
+modules on which yours depends in a format that allows someone to type a
+simple command and ensure that all the pre-requisites are in place as
+well as building your driver.
+
+The F<lib/DBD/Driver/Summary.pm> file contains (an updated version of) the
+information that was included - or that would have been included - in
+the appendices of the Cheetah book as a summary of the abilities of your
+driver and the associated database.
+
+The files in the F<t> subdirectory are unit tests for your driver.
+You should write your tests as stringently as possible, while taking
+into account the diversity of installations that you can encounter:
+
+=over 4
+
+=item *
+
+Your tests should not casually modify operational databases.
+
+=item *
+
+You should never damage existing tables in a database.
+
+=item *
+
+You should code your tests to use a constrained name space within the
+database. For example, the tables (and all other named objects) that are
+created could all begin with 'I<dbd_drv_>'.
+
+=item *
+
+At the end of a test run, there should be no testing objects left behind
+in the database.
+
+=item *
+
+If you create any databases, you should remove them.
+
+=item *
+
+If your database supports temporary tables that are automatically
+removed at the end of a session, then exploit them as often as possible.
+
+=item *
+
+Try to make your tests independent of each other. If you have a
+test F<t/t11dowhat.t> that depends upon the successful running
+of F<t/t10thingamy.t>, people cannot run the single test case
+F<t/t11dowhat.t>. Further, running F<t/t11dowhat.t> twice in a row is
+likely to fail (at least, if F<t/t11dowhat.t> modifies the database at
+all) because the database at the start of the second run is not what you
+saw at the start of the first run.
+
+=item *
+
+Document in your F<README> file what you do, and what privileges people
+need to do it.
+
+=item *
+
+You can, and probably should, sequence your tests by including a test
+number before an abbreviated version of the test name; the tests are run
+in the order in which the names are expanded by shell-style globbing.
+
+=item *
+
+It is in your interests to ensure that your tests work as widely
+as possible.
+
+=back
+
+Many drivers also install sub-modules B<DBD::Driver::SubModule>
+for any of a variety of different reasons, such as to support
+the metadata methods (see the discussion of L</METADATA METHODS>
+below). Such sub-modules are conventionally stored in the directory
+F<lib/DBD/Driver>. The module itself would usually be in a file
+F<SubModule.pm>. All such sub-modules should themselves be version
+stamped (see the discussions far below).
+
+=head3 Extra files needed by C/XS drivers
+
+The software for a C/XS driver will typically contain at least four
+extra files that are not relevant to a pure Perl driver.
+
+=over 4
+
+=item * F<Driver.xs>
+
+=item * F<Driver.h>
+
+=item * F<dbdimp.h>
+
+=item * F<dbdimp.c>
+
+=back
+
+The F<Driver.xs> file is used to generate C code that Perl can call to gain
+access to the C functions you write that will, in turn, call down onto
+your database software.
+
+The F<Driver.h> header is a stylized header that ensures you can access the
+necessary Perl and B<DBI> macros, types, and function declarations.
+
+The F<dbdimp.h> is used to specify which functions have been implemented by
+your driver.
+
+The F<dbdimp.c> file is where you write the C code that does the real work
+of translating between Perl-ish data types and what the database expects
+to use and return.
+
+There are some (mainly small, but very important) differences between
+the contents of F<Makefile.PL> and F<Driver.pm> for pure Perl and C/XS
+drivers, so those files are described both in the section on creating a
+pure Perl driver and in the section on creating a C/XS driver.
+
+Obviously, you can add extra source code files to the list.
+
+=head2 Requirements on a driver and driver writer
+
+To be remotely useful, your driver must be implemented in a format that
+allows it to be distributed via CPAN, the Comprehensive Perl Archive
+Network (L<http://www.cpan.org/> and L<http://search.cpan.org>).
+Of course, it is easier if you do not have to meet this criterion, but
+you will not be able to ask for much help if you do not do so, and
+no-one is likely to want to install your module if they have to learn a
+new installation mechanism.
+
+=head1 CREATING A PURE PERL DRIVER
+
+Writing a pure Perl driver is surprisingly simple. However, there are
+some problems you should be aware of. The best option is of course
+picking up an existing driver and carefully modifying one method
+after the other.
+
+Also look carefully at B<DBD::AnyData> and B<DBD::Template>.
+
+As an example we take a look at the B<DBD::File> driver, a driver for
+accessing plain files as tables, which is part of the B<DBD::CSV> package.
+
+The minimal set of files we have to implement are F<Makefile.PL>,
+F<README>, F<MANIFEST> and F<Driver.pm>.
+
+=head2 Pure Perl version of Makefile.PL
+
+You typically start with writing F<Makefile.PL>, a Makefile
+generator. The contents of this file are described in detail in
+the L<ExtUtils::MakeMaker> man pages. It is definitely a good idea
+if you start reading them. At least you should know about the
+variables I<CONFIGURE>, I<DEFINED>, I<PM>, I<DIR>, I<EXE_FILES>,
+I<INC>, I<LIBS>, I<LINKTYPE>, I<NAME>, I<OPTIMIZE>, I<PL_FILES>,
+I<VERSION>, I<VERSION_FROM>, I<clean>, I<depend>, I<realclean> from
+the L<ExtUtils::MakeMaker> man page: these are used in almost any
+F<Makefile.PL>.
+
+Additionally read the section on I<Overriding MakeMaker Methods> and the
+descriptions of the I<distcheck>, I<disttest> and I<dist> targets: They
+will definitely be useful for you.
+
+Of special importance for B<DBI> drivers is the I<postamble> method from
+the L<ExtUtils::MM_Unix> man page.
+
+For Emacs users, I recommend the I<libscan> method, which removes
+Emacs backup files (file names which end with a tilde '~') from lists of
+files.
+
+Now an example, I use the word C<Driver> wherever you should insert
+your driver's name:
+
+ # -*- perl -*-
+
+ use ExtUtils::MakeMaker;
+
+ WriteMakefile(
+ dbd_edit_mm_attribs( {
+ 'NAME' => 'DBD::Driver',
+ 'VERSION_FROM' => 'Driver.pm',
+ 'INC' => '',
+ 'dist' => { 'SUFFIX' => '.gz',
+ 'COMPRESS' => 'gzip -9f' },
+ 'realclean' => { FILES => '*.xsi' },
+ 'PREREQ_PM' => '1.03',
+ 'CONFIGURE' => sub {
+ eval {require DBI::DBD;};
+ if ($@) {
+ warn $@;
+ exit 0;
+ }
+ my $dbi_arch_dir = dbd_dbi_arch_dir();
+ if (exists($opts{INC})) {
+ return {INC => "$opts{INC} -I$dbi_arch_dir"};
+ } else {
+ return {INC => "-I$dbi_arch_dir"};
+ }
+ }
+ },
+ { create_pp_tests => 1})
+ );
+
+ package MY;
+ sub postamble { return main::dbd_postamble(@_); }
+ sub libscan {
+ my ($self, $path) = @_;
+ ($path =~ m/\~$/) ? undef : $path;
+ }
+
+Note the calls to C<dbd_edit_mm_attribs()> and C<dbd_postamble()>.
+
+The second hash reference in the call to C<dbd_edit_mm_attribs()>
+(containing C<create_pp_tests()>) is optional; you should not use it
+unless your driver is a pure Perl driver (that is, it does not use C and
+XS code). Therefore, the call to C<dbd_edit_mm_attribs()> is not
+relevant for C/XS drivers and may be omitted; simply use the (single)
+hash reference containing NAME etc as the only argument to C<WriteMakefile()>.
+
+Note that the C<dbd_edit_mm_attribs()> code will fail if you do not have a
+F<t> sub-directory containing at least one test case.
+
+I<PREREQ_PM> tells MakeMaker that DBI (version 1.03 in this case) is
+required for this module. This will issue a warning that DBI 1.03 is
+missing if someone attempts to install your DBD without DBI 1.03. See
+I<CONFIGURE> below for why this does not work reliably in stopping cpan
+testers failing your module if DBI is not installed.
+
+I<CONFIGURE> is a subroutine called by MakeMaker during
+C<WriteMakefile>. By putting the C<require DBI::DBD> in this section
+we can attempt to load DBI::DBD but if it is missing we exit with
+success. As we exit successfully without creating a Makefile when
+DBI::DBD is missing cpan testers will not report a failure. This may
+seem at odds with I<PREREQ_PM> but I<PREREQ_PM> does not cause
+C<WriteMakefile> to fail (unless you also specify PREREQ_FATAL which
+is strongly discouraged by MakeMaker) so C<WriteMakefile> would
+continue to call C<dbd_dbi_arch_dir> and fail.
+
+All drivers must use C<dbd_postamble()> or risk running into problems.
+
+Note the specification of I<VERSION_FROM>; the named file
+(F<Driver.pm>) will be scanned for the first line that looks like an
+assignment to I<$VERSION>, and the subsequent text will be used to
+determine the version number. Note the commentary in
+L<ExtUtils::MakeMaker> on the subject of correctly formatted version
+numbers.
+
+If your driver depends upon external software (it usually will), you
+will need to add code to ensure that your environment is workable
+before the call to C<WriteMakefile()>. If you need to check for the
+existence of an external library and perhaps modify I<INC> to include
+the paths to where the external library header files are located and
+you cannot find the library or header files make sure you output a
+message saying they cannot be found but C<exit 0> (success) B<before>
+calling C<WriteMakefile> or CPAN testers will fail your module if the
+external library is not found.
+
+A full-fledged I<Makefile.PL> can be quite large (for example, the
+files for B<DBD::Oracle> and B<DBD::Informix> are both over 1000 lines
+long, and the Informix one uses - and creates - auxiliary modules
+too).
+
+See also L<ExtUtils::MakeMaker> and L<ExtUtils::MM_Unix>. Consider using
+L<CPAN::MakeMaker> in place of I<ExtUtils::MakeMaker>.
+
+=head2 README
+
+The L<README> file should describe what the driver is for, the
+pre-requisites for the build process, the actual build process, how to
+report errors, and who to report them to.
+
+Users will find ways of breaking the driver build and test process
+which you would never even have dreamed to be possible in your worst
+nightmares. Therefore, you need to write this document defensively,
+precisely and concisely.
+
+As always, use the F<README> from one of the established drivers as a basis
+for your own; the version in B<DBD::Informix> is worth a look as it has
+been quite successful in heading off problems.
+
+=over 4
+
+=item *
+
+Note that users will have versions of Perl and B<DBI> that are both older
+and newer than you expected, but this will seldom cause much trouble.
+When it does, it will be because you are using features of B<DBI> that are
+not supported in the version they are using.
+
+=item *
+
+Note that users will have versions of the database software that are
+both older and newer than you expected. You will save yourself time in
+the long run if you can identify the range of versions which have been
+tested and warn about versions which are not known to be OK.
+
+=item *
+
+Note that many people trying to install your driver will not be experts
+in the database software.
+
+=item *
+
+Note that many people trying to install your driver will not be experts
+in C or Perl.
+
+=back
+
+=head2 MANIFEST
+
+The F<MANIFEST> will be used by the Makefile's dist target to build the
+distribution tar file that is uploaded to CPAN. It should list every
+file that you want to include in your distribution, one per line.
+
+=head2 lib/Bundle/DBD/Driver.pm
+
+The CPAN module provides an extremely powerful bundle mechanism that
+allows you to specify pre-requisites for your driver.
+
+The primary pre-requisite is B<Bundle::DBI>; you may want or need to add
+some more. With the bundle set up correctly, the user can type:
+
+ perl -MCPAN -e 'install Bundle::DBD::Driver'
+
+and Perl will download, compile, test and install all the Perl modules
+needed to build your driver.
+
+The prerequisite modules are listed in the C<CONTENTS> section, with the
+official name of the module followed by a dash and an informal name or
+description.
+
+=over 4
+
+=item *
+
+Listing B<Bundle::DBI> as the main pre-requisite simplifies life.
+
+=item *
+
+Don't forget to list your driver.
+
+=item *
+
+Note that unless the DBMS is itself a Perl module, you cannot list it as
+a pre-requisite in this file.
+
+=item *
+
+You should keep the version of the bundle the same as the version of
+your driver.
+
+=item *
+
+You should add configuration management, copyright, and licencing
+information at the top.
+
+=back
+
+A suitable skeleton for this file is shown below.
+
+ package Bundle::DBD::Driver;
+
+ $VERSION = '0.01';
+
+ 1;
+
+ __END__
+
+ =head1 NAME
+
+ Bundle::DBD::Driver - A bundle to install all DBD::Driver related modules
+
+ =head1 SYNOPSIS
+
+ C<perl -MCPAN -e 'install Bundle::DBD::Driver'>
+
+ =head1 CONTENTS
+
+ Bundle::DBI - Bundle for DBI by TIMB (Tim Bunce)
+
+ DBD::Driver - DBD::Driver by YOU (Your Name)
+
+ =head1 DESCRIPTION
+
+ This bundle includes all the modules used by the Perl Database
+ Interface (DBI) driver for Driver (DBD::Driver), assuming the
+ use of DBI version 1.13 or later, created by Tim Bunce.
+
+ If you've not previously used the CPAN module to install any
+ bundles, you will be interrogated during its setup phase.
+ But when you've done it once, it remembers what you told it.
+ You could start by running:
+
+ C<perl -MCPAN -e 'install Bundle::CPAN'>
+
+ =head1 SEE ALSO
+
+ Bundle::DBI
+
+ =head1 AUTHOR
+
+ Your Name E<lt>F<you@yourdomain.com>E<gt>
+
+ =head1 THANKS
+
+ This bundle was created by ripping off Bundle::libnet created by
+ Graham Barr E<lt>F<gbarr@ti.com>E<gt>, and radically simplified
+ with some information from Jochen Wiedmann E<lt>F<joe@ispsoft.de>E<gt>.
+ The template was then included in the DBI::DBD documentation by
+ Jonathan Leffler E<lt>F<jleffler@informix.com>E<gt>.
+
+ =cut
+
+=head2 lib/DBD/Driver/Summary.pm
+
+There is no substitute for taking the summary file from a driver that
+was documented in the Perl book (such as B<DBD::Oracle> or B<DBD::Informix> or
+B<DBD::ODBC>, to name but three), and adapting it to describe the
+facilities available via B<DBD::Driver> when accessing the Driver database.
+
+=head2 Pure Perl version of Driver.pm
+
+The F<Driver.pm> file defines the Perl module B<DBD::Driver> for your driver.
+It will define a package B<DBD::Driver> along with some version information,
+some variable definitions, and a function C<driver()> which will have a more
+or less standard structure.
+
+It will also define three sub-packages of B<DBD::Driver>:
+
+=over 4
+
+=item DBD::Driver::dr
+
+with methods C<connect()>, C<data_sources()> and C<disconnect_all()>;
+
+=item DBD::Driver::db
+
+with methods such as C<prepare()>;
+
+=item DBD::Driver::st
+
+with methods such as C<execute()> and C<fetch()>.
+
+=back
+
+The F<Driver.pm> file will also contain the documentation specific to
+B<DBD::Driver> in the format used by perldoc.
+
+In a pure Perl driver, the F<Driver.pm> file is the core of the
+implementation. You will need to provide all the key methods needed by B<DBI>.
+
+Now let's take a closer look at an excerpt of F<File.pm> as an example.
+We ignore things that are common to any module (even non-DBI modules)
+or really specific to the B<DBD::File> package.
+
+=head3 The DBD::Driver package
+
+=head4 The header
+
+ package DBD::File;
+
+ use strict;
+ use vars qw($VERSION $drh);
+
+ $VERSION = "1.23.00" # Version number of DBD::File
+
+This is where the version number of your driver is specified, and is
+where F<Makefile.PL> looks for this information. Please ensure that any
+other modules added with your driver are also version stamped so that
+CPAN does not get confused.
+
+It is recommended that you use a two-part (1.23) or three-part (1.23.45)
+version number. Also consider the CPAN system, which gets confused and
+considers version 1.10 to precede version 1.9, so that using a raw CVS,
+RCS or SCCS version number is probably not appropriate (despite being
+very common).
+
+For Subversion you could use:
+
+ $VERSION = sprintf("12.%06d", q$Revision: 12345 $ =~ /(\d+)/o);
+
+(use lots of leading zeros on the second portion so if you move the code to a
+shared repository like svn.perl.org the much larger revision numbers won't
+cause a problem, at least not for a few years). For RCS or CVS you can use:
+
+ $VERSION = sprintf "%d.%02d", '$Revision: 11.21 $ ' =~ /(\d+)\.(\d+)/;
+
+which pads out the fractional part with leading zeros so all is well
+(so long as you don't go past x.99)
+
+ $drh = undef; # holds driver handle once initialized
+
+This is where the driver handle will be stored, once created.
+Note that you may assume there is only one handle for your driver.
+
+=head4 The driver constructor
+
+The C<driver()> method is the driver handle constructor. Note that
+the C<driver()> method is in the B<DBD::Driver> package, not in
+one of the sub-packages B<DBD::Driver::dr>, B<DBD::Driver::db>, or
+B<DBD::Driver::db>.
+
+ sub driver
+ {
+ return $drh if $drh; # already created - return same one
+ my ($class, $attr) = @_;
+
+ $class .= "::dr";
+
+ DBD::Driver::db->install_method('drv_example_dbh_method');
+ DBD::Driver::st->install_method('drv_example_sth_method');
+
+ # not a 'my' since we use it above to prevent multiple drivers
+ $drh = DBI::_new_drh($class, {
+ 'Name' => 'File',
+ 'Version' => $VERSION,
+ 'Attribution' => 'DBD::File by Jochen Wiedmann',
+ })
+ or return undef;
+
+ return $drh;
+ }
+
+This is a reasonable example of how B<DBI> implements its handles. There
+are three kinds: B<driver handles> (typically stored in I<$drh>; from
+now on called I<drh> or I<$drh>), B<database handles> (from now on
+called I<dbh> or I<$dbh>) and B<statement handles> (from now on called
+I<sth> or I<$sth>).
+
+The prototype of C<DBI::_new_drh()> is
+
+ $drh = DBI::_new_drh($class, $public_attrs, $private_attrs);
+
+with the following arguments:
+
+=over 4
+
+=item I<$class>
+
+is typically the class for your driver, (for example, "DBD::File::dr"),
+passed as the first argument to the C<driver()> method.
+
+=item I<$public_attrs>
+
+is a hash ref to attributes like I<Name>, I<Version>, and I<Attribution>.
+These are processed and used by B<DBI>. You had better not make any
+assumptions about them nor should you add private attributes here.
+
+=item I<$private_attrs>
+
+This is another (optional) hash ref with your private attributes.
+B<DBI> will store them and otherwise leave them alone.
+
+=back
+
+The C<DBI::_new_drh()> method and the C<driver()> method both return C<undef>
+for failure (in which case you must look at I<$DBI::err> and I<$DBI::errstr>
+for the failure information, because you have no driver handle to use).
+
+
+=head4 Using install_method() to expose driver-private methods
+
+ DBD::Foo::db->install_method($method_name, \%attr);
+
+Installs the driver-private method named by $method_name into the
+DBI method dispatcher so it can be called directly, avoiding the
+need to use the func() method.
+
+It is called as a static method on the driver class to which the
+method belongs. The method name must begin with the corresponding
+registered driver-private prefix. For example, for DBD::Oracle
+$method_name must being with 'C<ora_>', and for DBD::AnyData it
+must begin with 'C<ad_>'.
+
+The attributes can be used to provide fine control over how the DBI
+dispatcher handles the dispatching of the method. However, at this
+point, it's undocumented and very liable to change. (Volunteers to
+polish up and document the interface are very welcome to get in
+touch via dbi-dev@perl.org)
+
+Methods installed using install_method default to the standard error
+handling behaviour for DBI methods: clearing err and errstr before
+calling the method, and checking for errors to trigger RaiseError
+etc. on return. This differs from the default behaviour of func().
+
+Note for driver authors: The DBD::Foo::xx->install_method call won't
+work until the class-hierarchy has been setup. Normally the DBI
+looks after that just after the driver is loaded. This means
+install_method() can't be called at the time the driver is loaded
+unless the class-hierarchy is set up first. The way to do that is
+to call the setup_driver() method:
+
+ DBI->setup_driver('DBD::Foo');
+
+before using install_method().
+
+
+=head4 The CLONE special subroutine
+
+Also needed here, in the B<DBD::Driver> package, is a C<CLONE()> method
+that will be called by perl when an interpreter is cloned. All your
+C<CLONE()> method needs to do, currently, is clear the cached I<$drh> so
+the new interpreter won't start using the cached I<$drh> from the old
+interpreter:
+
+ sub CLONE {
+ undef $drh;
+ }
+
+See L<http://search.cpan.org/dist/perl/pod/perlmod.pod#Making_your_module_threadsafe>
+for details.
+
+=head3 The DBD::Driver::dr package
+
+The next lines of code look as follows:
+
+ package DBD::Driver::dr; # ====== DRIVER ======
+
+ $DBD::Driver::dr::imp_data_size = 0;
+
+Note that no I<@ISA> is needed here, or for the other B<DBD::Driver::*>
+classes, because the B<DBI> takes care of that for you when the driver is
+loaded.
+
+ *FIX ME* Explain what the imp_data_size is, so that implementors aren't
+ practicing cargo-cult programming.
+
+=head4 The database handle constructor
+
+The database handle constructor is the driver's (hence the changed
+namespace) C<connect()> method:
+
+ sub connect
+ {
+ my ($drh, $dr_dsn, $user, $auth, $attr) = @_;
+
+ # Some database specific verifications, default settings
+ # and the like can go here. This should only include
+ # syntax checks or similar stuff where it's legal to
+ # 'die' in case of errors.
+ # For example, many database packages requires specific
+ # environment variables to be set; this could be where you
+ # validate that they are set, or default them if they are not set.
+
+ my $driver_prefix = "drv_"; # the assigned prefix for this driver
+
+ # Process attributes from the DSN; we assume ODBC syntax
+ # here, that is, the DSN looks like var1=val1;...;varN=valN
+ foreach my $var ( split /;/, $dr_dsn ) {
+ my ($attr_name, $attr_value) = split '=', $var, 2;
+ return $drh->set_err($DBI::stderr, "Can't parse DSN part '$var'")
+ unless defined $attr_value;
+
+ # add driver prefix to attribute name if it doesn't have it already
+ $attr_name = $driver_prefix.$attr_name
+ unless $attr_name =~ /^$driver_prefix/o;
+
+ # Store attribute into %$attr, replacing any existing value.
+ # The DBI will STORE() these into $dbh after we've connected
+ $attr->{$attr_name} = $attr_value;
+ }
+
+ # Get the attributes we'll use to connect.
+ # We use delete here because these no need to STORE them
+ my $db = delete $attr->{drv_database} || delete $attr->{drv_db}
+ or return $drh->set_err($DBI::stderr, "No database name given in DSN '$dr_dsn'");
+ my $host = delete $attr->{drv_host} || 'localhost';
+ my $port = delete $attr->{drv_port} || 123456;
+
+ # Assume you can attach to your database via drv_connect:
+ my $connection = drv_connect($db, $host, $port, $user, $auth)
+ or return $drh->set_err($DBI::stderr, "Can't connect to $dr_dsn: ...");
+
+ # create a 'blank' dbh (call superclass constructor)
+ my ($outer, $dbh) = DBI::_new_dbh($drh, { Name => $dr_dsn });
+
+ $dbh->STORE('Active', 1 );
+ $dbh->{drv_connection} = $connection;
+
+ return $outer;
+ }
+
+This is mostly the same as in the I<driver handle constructor> above.
+The arguments are described in L<DBI>.
+
+The constructor C<DBI::_new_dbh()> is called, returning a database handle.
+The constructor's prototype is:
+
+ ($outer, $inner) = DBI::_new_dbh($drh, $public_attr, $private_attr);
+
+with similar arguments to those in the I<driver handle constructor>,
+except that the I<$class> is replaced by I<$drh>. The I<Name> attribute
+is a standard B<DBI> attribute (see L<DBI/Database Handle Attributes>).
+
+In scalar context, only the outer handle is returned.
+
+Note the use of the C<STORE()> method for setting the I<dbh> attributes.
+That's because within the driver code, the handle object you have is
+the 'inner' handle of a tied hash, not the outer handle that the
+users of your driver have.
+
+Because you have the inner handle, tie magic doesn't get invoked
+when you get or set values in the hash. This is often very handy for
+speed when you want to get or set simple non-special driver-specific
+attributes.
+
+However, some attribute values, such as those handled by the B<DBI> like
+I<PrintError>, don't actually exist in the hash and must be read via
+C<$h-E<gt>FETCH($attrib)> and set via C<$h-E<gt>STORE($attrib, $value)>.
+If in any doubt, use these methods.
+
+=head4 The data_sources() method
+
+The C<data_sources()> method must populate and return a list of valid data
+sources, prefixed with the "I<dbi:Driver>" incantation that allows them to
+be used in the first argument of the C<DBI-E<gt>connect()> method.
+An example of this might be scanning the F<$HOME/.odbcini> file on Unix
+for ODBC data sources (DSNs).
+
+As a trivial example, consider a fixed list of data sources:
+
+ sub data_sources
+ {
+ my($drh, $attr) = @_;
+ my(@list) = ();
+ # You need more sophisticated code than this to set @list...
+ push @list, "dbi:Driver:abc";
+ push @list, "dbi:Driver:def";
+ push @list, "dbi:Driver:ghi";
+ # End of code to set @list
+ return @list;
+ }
+
+=head4 The disconnect_all() method
+
+If you need to release any resources when the driver is unloaded, you
+can provide a disconnect_all method.
+
+=head4 Other driver handle methods
+
+If you need any other driver handle methods, they can follow here.
+
+=head4 Error handling
+
+It is quite likely that something fails in the connect method.
+With B<DBD::File> for example, you might catch an error when setting the
+current directory to something not existent by using the
+(driver-specific) I<f_dir> attribute.
+
+To report an error, you use the C<set_err()> method:
+
+ $h->set_err($err, $errmsg, $state);
+
+This will ensure that the error is recorded correctly and that
+I<RaiseError> and I<PrintError> etc are handled correctly.
+
+Typically you'll always use the method instance, aka your method's first
+argument.
+
+As C<set_err()> always returns C<undef> your error handling code can
+usually be simplified to something like this:
+
+ return $h->set_err($err, $errmsg, $state) if ...;
+
+=head3 The DBD::Driver::db package
+
+ package DBD::Driver::db; # ====== DATABASE ======
+
+ $DBD::Driver::db::imp_data_size = 0;
+
+=head4 The statement handle constructor
+
+There's nothing much new in the statement handle constructor, which
+is the C<prepare()> method:
+
+ sub prepare
+ {
+ my ($dbh, $statement, @attribs) = @_;
+
+ # create a 'blank' sth
+ my ($outer, $sth) = DBI::_new_sth($dbh, { Statement => $statement });
+
+ $sth->STORE('NUM_OF_PARAMS', ($statement =~ tr/?//));
+
+ $sth->{drv_params} = [];
+
+ return $outer;
+ }
+
+This is still the same -- check the arguments and call the super class
+constructor C<DBI::_new_sth()>. Again, in scalar context, only the outer
+handle is returned. The I<Statement> attribute should be cached as
+shown.
+
+Note the prefix I<drv_> in the attribute names: it is required that
+all your private attributes use a lowercase prefix unique to your driver.
+As mentioned earlier in this document, the B<DBI> contains a registry of
+known driver prefixes and may one day warn about unknown attributes
+that don't have a registered prefix.
+
+Note that we parse the statement here in order to set the attribute
+I<NUM_OF_PARAMS>. The technique illustrated is not very reliable; it can
+be confused by question marks appearing in quoted strings, delimited
+identifiers or in SQL comments that are part of the SQL statement. We
+could set I<NUM_OF_PARAMS> in the C<execute()> method instead because
+the B<DBI> specification explicitly allows a driver to defer this, but then
+the user could not call C<bind_param()>.
+
+=head4 Transaction handling
+
+Pure Perl drivers will rarely support transactions. Thus your C<commit()>
+and C<rollback()> methods will typically be quite simple:
+
+ sub commit
+ {
+ my ($dbh) = @_;
+ if ($dbh->FETCH('Warn')) {
+ warn("Commit ineffective while AutoCommit is on");
+ }
+ 0;
+ }
+
+ sub rollback {
+ my ($dbh) = @_;
+ if ($dbh->FETCH('Warn')) {
+ warn("Rollback ineffective while AutoCommit is on");
+ }
+ 0;
+ }
+
+Or even simpler, just use the default methods provided by the B<DBI> that
+do nothing except return C<undef>.
+
+The B<DBI>'s default C<begin_work()> method can be used by inheritance.
+
+=head4 The STORE() and FETCH() methods
+
+These methods (that we have already used, see above) are called for
+you, whenever the user does a:
+
+ $dbh->{$attr} = $val;
+
+or, respectively,
+
+ $val = $dbh->{$attr};
+
+See L<perltie> for details on tied hash refs to understand why these
+methods are required.
+
+The B<DBI> will handle most attributes for you, in particular attributes
+like I<RaiseError> or I<PrintError>. All you have to do is handle your
+driver's private attributes and any attributes, like I<AutoCommit> and
+I<ChopBlanks>, that the B<DBI> can't handle for you.
+
+A good example might look like this:
+
+ sub STORE
+ {
+ my ($dbh, $attr, $val) = @_;
+ if ($attr eq 'AutoCommit') {
+ # AutoCommit is currently the only standard attribute we have
+ # to consider.
+ if (!$val) { die "Can't disable AutoCommit"; }
+ return 1;
+ }
+ if ($attr =~ m/^drv_/) {
+ # Handle only our private attributes here
+ # Note that we could trigger arbitrary actions.
+ # Ideally we should warn about unknown attributes.
+ $dbh->{$attr} = $val; # Yes, we are allowed to do this,
+ return 1; # but only for our private attributes
+ }
+ # Else pass up to DBI to handle for us
+ $dbh->SUPER::STORE($attr, $val);
+ }
+
+ sub FETCH
+ {
+ my ($dbh, $attr) = @_;
+ if ($attr eq 'AutoCommit') { return 1; }
+ if ($attr =~ m/^drv_/) {
+ # Handle only our private attributes here
+ # Note that we could trigger arbitrary actions.
+ return $dbh->{$attr}; # Yes, we are allowed to do this,
+ # but only for our private attributes
+ }
+ # Else pass up to DBI to handle
+ $dbh->SUPER::FETCH($attr);
+ }
+
+The B<DBI> will actually store and fetch driver-specific attributes (with all
+lowercase names) without warning or error, so there's actually no need to
+implement driver-specific any code in your C<FETCH()> and C<STORE()>
+methods unless you need extra logic/checks, beyond getting or setting
+the value.
+
+Unless your driver documentation indicates otherwise, the return value of
+the C<STORE()> method is unspecified and the caller shouldn't use that value.
+
+=head4 Other database handle methods
+
+As with the driver package, other database handle methods may follow here.
+In particular you should consider a (possibly empty) C<disconnect()>
+method and possibly a C<quote()> method if B<DBI>'s default isn't correct for
+you. You may also need the C<type_info_all()> and C<get_info()> methods,
+as described elsewhere in this document.
+
+Where reasonable use C<$h-E<gt>SUPER::foo()> to call the B<DBI>'s method in
+some or all cases and just wrap your custom behavior around that.
+
+If you want to use private trace flags you'll probably want to be
+able to set them by name. To do that you'll need to define a
+C<parse_trace_flag()> method (note that's "parse_trace_flag", singular,
+not "parse_trace_flags", plural).
+
+ sub parse_trace_flag {
+ my ($h, $name) = @_;
+ return 0x01000000 if $name eq 'foo';
+ return 0x02000000 if $name eq 'bar';
+ return 0x04000000 if $name eq 'baz';
+ return 0x08000000 if $name eq 'boo';
+ return 0x10000000 if $name eq 'bop';
+ return $h->SUPER::parse_trace_flag($name);
+ }
+
+All private flag names must be lowercase, and all private flags
+must be in the top 8 of the 32 bits.
+
+=head3 The DBD::Driver::st package
+
+This package follows the same pattern the others do:
+
+ package DBD::Driver::st;
+
+ $DBD::Driver::st::imp_data_size = 0;
+
+=head4 The execute() and bind_param() methods
+
+This is perhaps the most difficult method because we have to consider
+parameter bindings here. In addition to that, there are a number of
+statement attributes which must be set for inherited B<DBI> methods to
+function correctly (see L</Statement attributes> below).
+
+We present a simplified implementation by using the I<drv_params>
+attribute from above:
+
+ sub bind_param
+ {
+ my ($sth, $pNum, $val, $attr) = @_;
+ my $type = (ref $attr) ? $attr->{TYPE} : $attr;
+ if ($type) {
+ my $dbh = $sth->{Database};
+ $val = $dbh->quote($sth, $type);
+ }
+ my $params = $sth->{drv_params};
+ $params->[$pNum-1] = $val;
+ 1;
+ }
+
+ sub execute
+ {
+ my ($sth, @bind_values) = @_;
+
+ # start of by finishing any previous execution if still active
+ $sth->finish if $sth->FETCH('Active');
+
+ my $params = (@bind_values) ?
+ \@bind_values : $sth->{drv_params};
+ my $numParam = $sth->FETCH('NUM_OF_PARAMS');
+ return $sth->set_err($DBI::stderr, "Wrong number of parameters")
+ if @$params != $numParam;
+ my $statement = $sth->{'Statement'};
+ for (my $i = 0; $i < $numParam; $i++) {
+ $statement =~ s/?/$params->[$i]/; # XXX doesn't deal with quoting etc!
+ }
+ # Do anything ... we assume that an array ref of rows is
+ # created and store it:
+ $sth->{'drv_data'} = $data;
+ $sth->{'drv_rows'} = @$data; # number of rows
+ $sth->STORE('NUM_OF_FIELDS') = $numFields;
+ $sth->{Active} = 1;
+ @$data || '0E0';
+ }
+
+There are a number of things you should note here.
+
+We initialize the I<NUM_OF_FIELDS> and I<Active> attributes here,
+because they are essential for C<bind_columns()> to work.
+
+We use attribute C<$sth-E<gt>{Statement}> which we created
+within C<prepare()>. The attribute C<$sth-E<gt>{Database}>, which is
+nothing else than the I<dbh>, was automatically created by B<DBI>.
+
+Finally, note that (as specified in the B<DBI> specification) we return the
+string C<'0E0'> instead of the number 0, so that the result tests true but
+equal to zero.
+
+ $sth->execute() or die $sth->errstr;
+
+=head4 The execute_array(), execute_for_fetch() and bind_param_array() methods
+
+In general, DBD's only need to implement C<execute_for_fetch()> and
+C<bind_param_array>. DBI's default C<execute_array()> will invoke the
+DBD's C<execute_for_fetch()> as needed.
+
+The following sequence describes the interaction between
+DBI C<execute_array> and a DBD's C<execute_for_fetch>:
+
+=over
+
+=item 1
+
+App calls C<$sth-E<gt>execute_array(\%attrs, @array_of_arrays)>
+
+=item 2
+
+If C<@array_of_arrays> was specified, DBI processes C<@array_of_arrays> by calling
+DBD's C<bind_param_array()>. Alternately, App may have directly called
+C<bind_param_array()>
+
+=item 3
+
+DBD validates and binds each array
+
+=item 4
+
+DBI retrieves the validated param arrays from DBD's ParamArray attribute
+
+=item 5
+
+DBI calls DBD's C<execute_for_fetch($fetch_tuple_sub, \@tuple_status)>,
+where C<&$fetch_tuple_sub> is a closure to iterate over the
+returned ParamArray values, and C<\@tuple_status> is an array to receive
+the disposition status of each tuple.
+
+=item 6
+
+DBD iteratively calls C<&$fetch_tuple_sub> to retrieve parameter tuples
+to be added to its bulk database operation/request.
+
+=item 7
+
+when DBD reaches the limit of tuples it can handle in a single database
+operation/request, or the C<&$fetch_tuple_sub> indicates no more
+tuples by returning undef, the DBD executes the bulk operation, and
+reports the disposition of each tuple in \@tuple_status.
+
+=item 8
+
+DBD repeats steps 6 and 7 until all tuples are processed.
+
+=back
+
+E.g., here's the essence of L<DBD::Oracle>'s execute_for_fetch:
+
+ while (1) {
+ my @tuple_batch;
+ for (my $i = 0; $i < $batch_size; $i++) {
+ push @tuple_batch, [ @{$fetch_tuple_sub->() || last} ];
+ }
+ last unless @tuple_batch;
+ my $res = ora_execute_array($sth, \@tuple_batch,
+ scalar(@tuple_batch), $tuple_batch_status);
+ push @$tuple_status, @$tuple_batch_status;
+ }
+
+Note that DBI's default execute_array()/execute_for_fetch() implementation
+requires the use of positional (i.e., '?') placeholders. Drivers
+which B<require> named placeholders must either emulate positional
+placeholders (e.g., see L<DBD::Oracle>), or must implement their own
+execute_array()/execute_for_fetch() methods to properly sequence bound
+parameter arrays.
+
+=head4 Fetching data
+
+Only one method needs to be written for fetching data, C<fetchrow_arrayref()>.
+The other methods, C<fetchrow_array()>, C<fetchall_arrayref()>, etc, as well
+as the database handle's C<select*> methods are part of B<DBI>, and call
+C<fetchrow_arrayref()> as necessary.
+
+ sub fetchrow_arrayref
+ {
+ my ($sth) = @_;
+ my $data = $sth->{drv_data};
+ my $row = shift @$data;
+ if (!$row) {
+ $sth->STORE(Active => 0); # mark as no longer active
+ return undef;
+ }
+ if ($sth->FETCH('ChopBlanks')) {
+ map { $_ =~ s/\s+$//; } @$row;
+ }
+ return $sth->_set_fbav($row);
+ }
+ *fetch = \&fetchrow_arrayref; # required alias for fetchrow_arrayref
+
+Note the use of the method C<_set_fbav()> -- this is required so that
+C<bind_col()> and C<bind_columns()> work.
+
+If an error occurs which leaves the I<$sth> in a state where remaining rows
+can't be fetched then I<Active> should be turned off before the method returns.
+
+The C<rows()> method for this driver can be implemented like this:
+
+ sub rows { shift->{drv_rows} }
+
+because it knows in advance how many rows it has fetched.
+Alternatively you could delete that method and so fallback
+to the B<DBI>'s own method which does the right thing based
+on the number of calls to C<_set_fbav()>.
+
+=head4 The more_results method
+
+If your driver doesn't support multiple result sets, then don't even implement this method.
+
+Otherwise, this method needs to get the statement handle ready to fetch results
+from the next result set, if there is one. Typically you'd start with:
+
+ $sth->finish;
+
+then you should delete all the attributes from the attribute cache that may no
+longer be relevant for the new result set:
+
+ delete $sth->{$_}
+ for qw(NAME TYPE PRECISION SCALE ...);
+
+for drivers written in C use:
+
+ hv_delete((HV*)SvRV(sth), "NAME", 4, G_DISCARD);
+ hv_delete((HV*)SvRV(sth), "NULLABLE", 8, G_DISCARD);
+ hv_delete((HV*)SvRV(sth), "NUM_OF_FIELDS", 13, G_DISCARD);
+ hv_delete((HV*)SvRV(sth), "PRECISION", 9, G_DISCARD);
+ hv_delete((HV*)SvRV(sth), "SCALE", 5, G_DISCARD);
+ hv_delete((HV*)SvRV(sth), "TYPE", 4, G_DISCARD);
+
+Don't forget to also delete, or update, any driver-private attributes that may
+not be correct for the next resultset.
+
+The NUM_OF_FIELDS attribute is a special case. It should be set using STORE:
+
+ $sth->STORE(NUM_OF_FIELDS => 0); /* for DBI <= 1.53 */
+ $sth->STORE(NUM_OF_FIELDS => $new_value);
+
+for drivers written in C use this incantation:
+
+ /* Adjust NUM_OF_FIELDS - which also adjusts the row buffer size */
+ DBIc_NUM_FIELDS(imp_sth) = 0; /* for DBI <= 1.53 */
+ DBIc_STATE(imp_xxh)->set_attr_k(sth, sv_2mortal(newSVpvn("NUM_OF_FIELDS",13)), 0,
+ sv_2mortal(newSViv(mysql_num_fields(imp_sth->result)))
+ );
+
+For DBI versions prior to 1.54 you'll also need to explicitly adjust the
+number of elements in the row buffer array (C<DBIc_FIELDS_AV(imp_sth)>)
+to match the new result set. Fill any new values with newSV(0) not &sv_undef.
+Alternatively you could free DBIc_FIELDS_AV(imp_sth) and set it to null,
+but that would mean bind_columns() wouldn't work across result sets.
+
+
+=head4 Statement attributes
+
+The main difference between I<dbh> and I<sth> attributes is, that you
+should implement a lot of attributes here that are required by
+the B<DBI>, such as I<NAME>, I<NULLABLE>, I<TYPE>, etc. See
+L<DBI/Statement Handle Attributes> for a complete list.
+
+Pay attention to attributes which are marked as read only, such as
+I<NUM_OF_PARAMS>. These attributes can only be set the first time
+a statement is executed. If a statement is prepared, then executed
+multiple times, warnings may be generated.
+
+You can protect against these warnings, and prevent the recalculation
+of attributes which might be expensive to calculate (such as the
+I<NAME> and I<NAME_*> attributes):
+
+ my $storedNumParams = $sth->FETCH('NUM_OF_PARAMS');
+ if (!defined $storedNumParams or $storedNumFields < 0) {
+ $sth->STORE('NUM_OF_PARAMS') = $numParams;
+
+ # Set other useful attributes that only need to be set once
+ # for a statement, like $sth->{NAME} and $sth->{TYPE}
+ }
+
+One particularly important attribute to set correctly (mentioned in
+L<DBI/ATTRIBUTES COMMON TO ALL HANDLES> is I<Active>. Many B<DBI> methods,
+including C<bind_columns()>, depend on this attribute.
+
+Besides that the C<STORE()> and C<FETCH()> methods are mainly the same
+as above for I<dbh>'s.
+
+=head4 Other statement methods
+
+A trivial C<finish()> method to discard stored data, reset any attributes
+(such as I<Active>) and do C<$sth-E<gt>SUPER::finish()>.
+
+If you've defined a C<parse_trace_flag()> method in B<::db> you'll also want
+it in B<::st>, so just alias it in:
+
+ *parse_trace_flag = \&DBD::foo:db::parse_trace_flag;
+
+And perhaps some other methods that are not part of the B<DBI>
+specification, in particular to make metadata available.
+Remember that they must have names that begin with your drivers
+registered prefix so they can be installed using C<install_method()>.
+
+If C<DESTROY()> is called on a statement handle that's still active
+(C<$sth-E<gt>{Active}> is true) then it should effectively call C<finish()>.
+
+ sub DESTROY {
+ my $sth = shift;
+ $sth->finish if $sth->FETCH('Active');
+ }
+
+=head2 Tests
+
+The test process should conform as closely as possibly to the Perl
+standard test harness.
+
+In particular, most (all) of the tests should be run in the F<t> sub-directory,
+and should simply produce an C<ok> when run under C<make test>.
+For details on how this is done, see the Camel book and the section in
+Chapter 7, "The Standard Perl Library" on L<Test::Harness>.
+
+The tests may need to adapt to the type of database which is being used
+for testing, and to the privileges of the user testing the driver. For
+example, the B<DBD::Informix> test code has to adapt in a number of
+places to the type of database to which it is connected as different
+Informix databases have different capabilities: some of the tests are
+for databases without transaction logs; others are for databases with a
+transaction log; some versions of the server have support for blobs, or
+stored procedures, or user-defined data types, and others do not.
+
+When a complete file of tests must be skipped, you can provide a reason
+in a pseudo-comment:
+
+ if ($no_transactions_available)
+ {
+ print "1..0 # Skip: No transactions available\n";
+ exit 0;
+ }
+
+Consider downloading the B<DBD::Informix> code and look at the code in
+F<DBD/Informix/TestHarness.pm> which is used throughout the
+B<DBD::Informix> tests in the F<t> sub-directory.
+
+=head1 CREATING A C/XS DRIVER
+
+Please also see the section under L<CREATING A PURE PERL DRIVER>
+regarding the creation of the F<Makefile.PL>.
+
+Creating a new C/XS driver from scratch will always be a daunting task.
+You can and should greatly simplify your task by taking a good
+reference driver implementation and modifying that to match the
+database product for which you are writing a driver.
+
+The de facto reference driver has been the one for B<DBD::Oracle> written
+by Tim Bunce, who is also the author of the B<DBI> package. The B<DBD::Oracle>
+module is a good example of a driver implemented around a C-level API.
+
+Nowadays it it seems better to base on B<DBD::ODBC>, another driver
+maintained by Tim and Jeff Urlwin, because it offers a lot of metadata
+and seems to become the guideline for the future development. (Also as
+B<DBD::Oracle> digs deeper into the Oracle 8 OCI interface it'll get even
+more hairy than it is now.)
+
+The B<DBD::Informix> driver is one driver implemented using embedded SQL
+instead of a function-based API.
+B<DBD::Ingres> may also be worth a look.
+
+=head2 C/XS version of Driver.pm
+
+A lot of the code in the F<Driver.pm> file is very similar to the code for pure Perl modules
+- see above. However,
+there are also some subtle (and not so subtle) differences, including:
+
+=over 8
+
+=item *
+
+The variables I<$DBD::Driver::{dr|db|st}::imp_data_size> are not defined
+here, but in the XS code, because they declare the size of certain
+C structures.
+
+=item *
+
+Some methods are typically moved to the XS code, in particular
+C<prepare()>, C<execute()>, C<disconnect()>, C<disconnect_all()> and the
+C<STORE()> and C<FETCH()> methods.
+
+=item *
+
+Other methods are still part of F<Driver.pm>, but have callbacks to
+the XS code.
+
+=item *
+
+If the driver-specific parts of the I<imp_drh_t> structure need to be
+formally initialized (which does not seem to be a common requirement),
+then you need to add a call to an appropriate XS function in the driver
+method of C<DBD::Driver::driver()>, and you define the corresponding function
+in F<Driver.xs>, and you define the C code in F<dbdimp.c> and the prototype in
+F<dbdimp.h>.
+
+For example, B<DBD::Informix> has such a requirement, and adds the
+following call after the call to C<_new_drh()> in F<Informix.pm>:
+
+ DBD::Informix::dr::driver_init($drh);
+
+and the following code in F<Informix.xs>:
+
+ # Initialize the DBD::Informix driver data structure
+ void
+ driver_init(drh)
+ SV *drh
+ CODE:
+ ST(0) = dbd_ix_dr_driver_init(drh) ? &sv_yes : &sv_no;
+
+and the code in F<dbdimp.h> declares:
+
+ extern int dbd_ix_dr_driver_init(SV *drh);
+
+and the code in F<dbdimp.ec> (equivalent to F<dbdimp.c>) defines:
+
+ /* Formally initialize the DBD::Informix driver structure */
+ int
+ dbd_ix_dr_driver(SV *drh)
+ {
+ D_imp_drh(drh);
+ imp_drh->n_connections = 0; /* No active connections */
+ imp_drh->current_connection = 0; /* No current connection */
+ imp_drh->multipleconnections = (ESQLC_VERSION >= 600) ? True : False;
+ dbd_ix_link_newhead(&imp_drh->head); /* Empty linked list of connections */
+ return 1;
+ }
+
+B<DBD::Oracle> has a similar requirement but gets around it by checking
+whether the private data part of the driver handle is all zeroed out,
+rather than add extra functions.
+
+=back
+
+Now let's take a closer look at an excerpt from F<Oracle.pm> (revised
+heavily to remove idiosyncrasies) as an example, ignoring things that
+were already discussed for pure Perl drivers.
+
+=head3 The connect method
+
+The connect method is the database handle constructor.
+You could write either of two versions of this method: either one which
+takes connection attributes (new code) and one which ignores them (old
+code only).
+
+If you ignore the connection attributes, then you omit all mention of
+the I<$auth> variable (which is a reference to a hash of attributes), and
+the XS system manages the differences for you.
+
+ sub connect
+ {
+ my ($drh, $dbname, $user, $auth, $attr) = @_;
+
+ # Some database specific verifications, default settings
+ # and the like following here. This should only include
+ # syntax checks or similar stuff where it's legal to
+ # 'die' in case of errors.
+
+ my $dbh = DBI::_new_dbh($drh, {
+ 'Name' => $dbname,
+ })
+ or return undef;
+
+ # Call the driver-specific function _login in Driver.xs file which
+ # calls the DBMS-specific function(s) to connect to the database,
+ # and populate internal handle data.
+ DBD::Driver::db::_login($dbh, $dbname, $user, $auth, $attr)
+ or return undef;
+
+ $dbh;
+ }
+
+This is mostly the same as in the pure Perl case, the exception being
+the use of the private C<_login()> callback, which is the function
+that will really connect to the database. It is implemented in
+F<Driver.xst> (you should not implement it) and calls
+C<dbd_db_login6()> or C<dbd_db_login6_sv> from F<dbdimp.c>. See below
+for details.
+
+If your driver has driver-specific attributes which may be passed in the
+connect method and hence end up in C<$attr> in C<dbd_db_login6> then it
+is best to delete any you process so DBI does not send them again
+via STORE after connect. You can do this in C like this:
+
+ DBD_ATTRIB_DELETE(attr, "my_attribute_name",
+ strlen("my_attribute_name"));
+
+However, prior to DBI subversion version 11605 (and fixed post 1.607)
+DBD_ATTRIB_DELETE segfaulted so if you cannot guarantee the DBI version
+will be post 1.607 you need to use:
+
+ hv_delete((HV*)SvRV(attr), "my_attribute_name",
+ strlen("my_attribute_name"), G_DISCARD);
+
+ *FIX ME* Discuss removing attributes in Perl code.
+
+=head3 The disconnect_all method
+
+ *FIX ME* T.B.S
+
+=head3 The data_sources method
+
+If your C<data_sources()> method can be implemented in pure Perl, then do
+so because it is easier than doing it in XS code (see the section above
+for pure Perl drivers).
+
+If your C<data_sources()> method must call onto compiled functions, then
+you will need to define I<dbd_dr_data_sources> in your F<dbdimp.h> file, which
+will trigger F<Driver.xst> (in B<DBI> v1.33 or greater) to generate the XS
+code that calls your actual C function (see the discussion below for
+details) and you do not code anything in F<Driver.pm> to handle it.
+
+=head3 The prepare method
+
+The prepare method is the statement handle constructor, and most of it
+is not new. Like the C<connect()> method, it now has a C callback:
+
+ package DBD::Driver::db; # ====== DATABASE ======
+ use strict;
+
+ sub prepare
+ {
+ my ($dbh, $statement, $attribs) = @_;
+
+ # create a 'blank' sth
+ my $sth = DBI::_new_sth($dbh, {
+ 'Statement' => $statement,
+ })
+ or return undef;
+
+ # Call the driver-specific function _prepare in Driver.xs file
+ # which calls the DBMS-specific function(s) to prepare a statement
+ # and populate internal handle data.
+ DBD::Driver::st::_prepare($sth, $statement, $attribs)
+ or return undef;
+ $sth;
+ }
+
+=head3 The execute method
+
+ *FIX ME* T.B.S
+
+=head3 The fetchrow_arrayref method
+
+ *FIX ME* T.B.S
+
+=head3 Other methods?
+
+ *FIX ME* T.B.S
+
+=head2 Driver.xs
+
+F<Driver.xs> should look something like this:
+
+ #include "Driver.h"
+
+ DBISTATE_DECLARE;
+
+ INCLUDE: Driver.xsi
+
+ MODULE = DBD::Driver PACKAGE = DBD::Driver::dr
+
+ /* Non-standard drh XS methods following here, if any. */
+ /* If none (the usual case), omit the MODULE line above too. */
+
+ MODULE = DBD::Driver PACKAGE = DBD::Driver::db
+
+ /* Non-standard dbh XS methods following here, if any. */
+ /* Currently this includes things like _list_tables from */
+ /* DBD::mSQL and DBD::mysql. */
+
+ MODULE = DBD::Driver PACKAGE = DBD::Driver::st
+
+ /* Non-standard sth XS methods following here, if any. */
+ /* In particular this includes things like _list_fields from */
+ /* DBD::mSQL and DBD::mysql for accessing metadata. */
+
+Note especially the include of F<Driver.xsi> here: B<DBI> inserts stub
+functions for almost all private methods here which will typically do
+much work for you.
+
+Wherever you really have to implement something, it will call a private
+function in F<dbdimp.c>, and this is what you have to implement.
+
+You need to set up an extra routine if your driver needs to export
+constants of its own, analogous to the SQL types available when you say:
+
+ use DBI qw(:sql_types);
+
+ *FIX ME* T.B.S
+
+=head2 Driver.h
+
+F<Driver.h> is very simple and the operational contents should look like this:
+
+ #ifndef DRIVER_H_INCLUDED
+ #define DRIVER_H_INCLUDED
+
+ #define NEED_DBIXS_VERSION 93 /* 93 for DBI versions 1.00 to 1.51+ */
+ #define PERL_NO_GET_CONTEXT /* if used require DBI 1.51+ */
+
+ #include <DBIXS.h> /* installed by the DBI module */
+
+ #include "dbdimp.h"
+
+ #include "dbivport.h" /* see below */
+
+ #include <dbd_xsh.h> /* installed by the DBI module */
+
+ #endif /* DRIVER_H_INCLUDED */
+
+The F<DBIXS.h> header defines most of the interesting information that
+the writer of a driver needs.
+
+The file F<dbd_xsh.h> header provides prototype declarations for the C
+functions that you might decide to implement. Note that you should
+normally only define one of C<dbd_db_login()>, C<dbd_db_login6()> or
+C<dbd_db_login6_sv> unless you are intent on supporting really old
+versions of B<DBI> (prior to B<DBI> 1.06) as well as modern
+versions. The only standard, B<DBI>-mandated functions that you need
+write are those specified in the F<dbd_xsh.h> header. You might also
+add extra driver-specific functions in F<Driver.xs>.
+
+The F<dbivport.h> file should be I<copied> from the latest B<DBI> release
+into your distribution each time you modify your driver. Its job is to
+allow you to enhance your code to work with the latest B<DBI> API while
+still allowing your driver to be compiled and used with older versions
+of the B<DBI> (for example, when the C<DBIh_SET_ERR_CHAR()> macro was added
+to B<DBI> 1.41, an emulation of it was added to F<dbivport.h>). This makes
+users happy and your life easier. Always read the notes in F<dbivport.h>
+to check for any limitations in the emulation that you should be aware
+of.
+
+With B<DBI> v1.51 or better I recommend that the driver defines
+I<PERL_NO_GET_CONTEXT> before F<DBIXS.h> is included. This can significantly
+improve efficiency when running under a thread enabled perl. (Remember that
+the standard perl in most Linux distributions is built with threads enabled.
+So is ActiveState perl for Windows, and perl built for Apache mod_perl2.)
+If you do this there are some things to keep in mind:
+
+=over 4
+
+=item *
+
+If I<PERL_NO_GET_CONTEXT> is defined, then every function that calls the Perl
+API will need to start out with a C<dTHX;> declaration.
+
+=item *
+
+You'll know which functions need this, because the C compiler will
+complain that the undeclared identifier C<my_perl> is used if I<and only if>
+the perl you are using to develop and test your driver has threads enabled.
+
+=item *
+
+If you don't remember to test with a thread-enabled perl before making
+a release it's likely that you'll get failure reports from users who are.
+
+=item *
+
+For driver private functions it is possible to gain even more
+efficiency by replacing C<dTHX;> with C<pTHX_> prepended to the
+parameter list and then C<aTHX_> prepended to the argument list where
+the function is called.
+
+=back
+
+See L<perlguts/How multiple interpreters and concurrency are supported> for
+additional information about I<PERL_NO_GET_CONTEXT>.
+
+=head2 Implementation header dbdimp.h
+
+This header file has two jobs:
+
+First it defines data structures for your private part of the handles.
+
+Second it defines macros that rename the generic names like
+C<dbd_db_login()> to database specific names like C<ora_db_login()>. This
+avoids name clashes and enables use of different drivers when you work
+with a statically linked perl.
+
+It also will have the important task of disabling XS methods that you
+don't want to implement.
+
+Finally, the macros will also be used to select alternate
+implementations of some functions. For example, the C<dbd_db_login()>
+function is not passed the attribute hash.
+
+Since B<DBI> v1.06, if a C<dbd_db_login6()> macro is defined (for a function
+with 6 arguments), it will be used instead with the attribute hash
+passed as the sixth argument.
+
+Since B<DBI> post v1.607, if a C<dbd_db_login6_sv()> macro is defined (for
+a function like dbd_db_login6 but with scalar pointers for the dbname,
+username and password), it will be used instead. This will allow your
+login6 function to see if there are any unicode characters in the
+dbname.
+
+People used to just pick Oracle's F<dbdimp.c> and use the same names,
+structures and types. I strongly recommend against that. At first glance
+this saves time, but your implementation will be less readable. It was
+just hell when I had to separate B<DBI> specific parts, Oracle specific
+parts, mSQL specific parts and mysql specific parts in B<DBD::mysql>'s
+I<dbdimp.h> and I<dbdimp.c>. (B<DBD::mysql> was a port of B<DBD::mSQL>
+which was based on B<DBD::Oracle>.) [Seconded, based on the experience
+taking B<DBD::Informix> apart, even though the version inherited in 1996
+was only based on B<DBD::Oracle>.]
+
+This part of the driver is I<your exclusive part>. Rewrite it from
+scratch, so it will be clean and short: in other words, a better piece
+of code. (Of course keep an eye on other people's work.)
+
+ struct imp_drh_st {
+ dbih_drc_t com; /* MUST be first element in structure */
+ /* Insert your driver handle attributes here */
+ };
+
+ struct imp_dbh_st {
+ dbih_dbc_t com; /* MUST be first element in structure */
+ /* Insert your database handle attributes here */
+ };
+
+ struct imp_sth_st {
+ dbih_stc_t com; /* MUST be first element in structure */
+ /* Insert your statement handle attributes here */
+ };
+
+ /* Rename functions for avoiding name clashes; prototypes are */
+ /* in dbd_xst.h */
+ #define dbd_init drv_dr_init
+ #define dbd_db_login6_sv drv_db_login_sv
+ #define dbd_db_do drv_db_do
+ ... many more here ...
+
+These structures implement your private part of the handles.
+
+You I<have> to use the name C<imp_dbh_{dr|db|st}> and the first field
+I<must> be of type I<dbih_drc_t|_dbc_t|_stc_t> and I<must> be called
+C<com>.
+
+You should never access these fields directly, except by using the
+I<DBIc_xxx()> macros below.
+
+=head2 Implementation source dbdimp.c
+
+Conventionally, F<dbdimp.c> is the main implementation file (but
+B<DBD::Informix> calls the file F<dbdimp.ec>). This section includes a
+short note on each function that is used in the F<Driver.xsi> template
+and thus I<has> to be implemented.
+
+Of course, you will probably also need to implement other support
+functions, which should usually be file static if they are placed in
+F<dbdimp.c>. If they are placed in other files, you need to list those
+files in F<Makefile.PL> (and F<MANIFEST>) to handle them correctly.
+
+It is wise to adhere to a namespace convention for your functions to
+avoid conflicts. For example, for a driver with prefix I<drv_>, you
+might call externally visible functions I<dbd_drv_xxxx>. You should also
+avoid non-constant global variables as much as possible to improve the
+support for threading.
+
+Since Perl requires support for function prototypes (ANSI or ISO or
+Standard C), you should write your code using function prototypes too.
+
+It is possible to use either the unmapped names such as C<dbd_init()> or
+the mapped names such as C<dbd_ix_dr_init()> in the F<dbdimp.c> file.
+B<DBD::Informix> uses the mapped names which makes it easier to identify
+where to look for linkage problems at runtime (which will report errors
+using the mapped names).
+
+Most other drivers, and in particular B<DBD::Oracle>, use the unmapped
+names in the source code which makes it a little easier to compare code
+between drivers and eases discussions on the I<dbi-dev> mailing list.
+The majority of the code fragments here will use the unmapped names.
+
+Ultimately, you should provide implementations for most of the
+functions listed in the F<dbd_xsh.h> header. The exceptions are
+optional functions (such as C<dbd_st_rows()>) and those functions with
+alternative signatures, such as C<dbd_db_login6_sv>,
+C<dbd_db_login6()> and I<dbd_db_login()>. Then you should only
+implement one of the alternatives, and generally the newer one of the
+alternatives.
+
+=head3 The dbd_init method
+
+ #include "Driver.h"
+
+ DBISTATE_DECLARE;
+
+ void dbd_init(dbistate_t* dbistate)
+ {
+ DBISTATE_INIT; /* Initialize the DBI macros */
+ }
+
+The C<dbd_init()> function will be called when your driver is first
+loaded; the bootstrap command in C<DBD::Driver::dr::driver()> triggers this,
+and the call is generated in the I<BOOT> section of F<Driver.xst>.
+These statements are needed to allow your driver to use the B<DBI> macros.
+They will include your private header file F<dbdimp.h> in turn.
+Note that I<DBISTATE_INIT> requires the name of the argument to C<dbd_init()>
+to be called C<dbistate()>.
+
+=head3 The dbd_drv_error method
+
+You need a function to record errors so B<DBI> can access them properly.
+You can call it whatever you like, but we'll call it C<dbd_drv_error()>
+here.
+
+The argument list depends on your database software; different systems
+provide different ways to get at error information.
+
+ static void dbd_drv_error(SV *h, int rc, const char *what)
+ {
+
+Note that I<h> is a generic handle, may it be a driver handle, a
+database or a statement handle.
+
+ D_imp_xxh(h);
+
+This macro will declare and initialize a variable I<imp_xxh> with
+a pointer to your private handle pointer. You may cast this to
+to I<imp_drh_t>, I<imp_dbh_t> or I<imp_sth_t>.
+
+To record the error correctly, equivalent to the C<set_err()> method,
+use one of the C<DBIh_SET_ERR_CHAR(...)> or C<DBIh_SET_ERR_SV(...)> macros,
+which were added in B<DBI> 1.41:
+
+ DBIh_SET_ERR_SV(h, imp_xxh, err, errstr, state, method);
+ DBIh_SET_ERR_CHAR(h, imp_xxh, err_c, err_i, errstr, state, method);
+
+For C<DBIh_SET_ERR_SV> the I<err>, I<errstr>, I<state>, and I<method>
+parameters are C<SV*>.
+
+For C<DBIh_SET_ERR_CHAR> the I<err_c>, I<errstr>, I<state>, I<method>
+parameters are C<char*>.
+
+The I<err_i> parameter is an C<IV> that's used instead of I<err_c> if
+I<err_c> is C<Null>.
+
+The I<method> parameter can be ignored.
+
+The C<DBIh_SET_ERR_CHAR> macro is usually the simplest to use when you
+just have an integer error code and an error message string:
+
+ DBIh_SET_ERR_CHAR(h, imp_xxh, Nullch, rc, what, Nullch, Nullch);
+
+As you can see, any parameters that aren't relevant to you can be C<Null>.
+
+To make drivers compatible with B<DBI> < 1.41 you should be using F<dbivport.h>
+as described in L</Driver.h> above.
+
+The (obsolete) macros such as C<DBIh_EVENT2> should be removed from drivers.
+
+The names C<dbis> and C<DBIS>, which were used in previous versions of
+this document, should be replaced with the C<DBIc_STATE(imp_xxh)> macro.
+
+The name C<DBILOGFP>, which was also used in previous versions of this
+document, should be replaced by C<DBIc_LOGPIO(imp_xxh)>.
+
+Your code should not call the C C<E<lt>stdio.hE<gt>> I/O functions; you
+should use C<PerlIO_printf()> as shown:
+
+ if (DBIc_TRACE_LEVEL(imp_xxh) >= 2)
+ PerlIO_printf(DBIc_LOGPIO(imp_xxh), "foobar %s: %s\n",
+ foo, neatsvpv(errstr,0));
+
+That's the first time we see how tracing works within a B<DBI> driver. Make
+use of this as often as you can, but don't output anything at a trace
+level less than 3. Levels 1 and 2 are reserved for the B<DBI>.
+
+You can define up to 8 private trace flags using the top 8 bits
+of C<DBIc_TRACE_FLAGS(imp)>, that is: C<0xFF000000>. See the
+C<parse_trace_flag()> method elsewhere in this document.
+
+=head3 The dbd_dr_data_sources method
+
+This method is optional; the support for it was added in B<DBI> v1.33.
+
+As noted in the discussion of F<Driver.pm>, if the data sources
+can be determined by pure Perl code, do it that way. If, as in
+B<DBD::Informix>, the information is obtained by a C function call, then
+you need to define a function that matches the prototype:
+
+ extern AV *dbd_dr_data_sources(SV *drh, imp_drh_t *imp_drh, SV *attrs);
+
+An outline implementation for B<DBD::Informix> follows, assuming that the
+C<sqgetdbs()> function call shown will return up to 100 databases names,
+with the pointers to each name in the array dbsname and the name strings
+themselves being stores in dbsarea.
+
+ AV *dbd_dr_data_sources(SV *drh, imp_drh_t *imp_drh, SV *attr)
+ {
+ int ndbs;
+ int i;
+ char *dbsname[100];
+ char dbsarea[10000];
+ AV *av = Nullav;
+
+ if (sqgetdbs(&ndbs, dbsname, 100, dbsarea, sizeof(dbsarea)) == 0)
+ {
+ av = NewAV();
+ av_extend(av, (I32)ndbs);
+ sv_2mortal((SV *)av);
+ for (i = 0; i < ndbs; i++)
+ av_store(av, i, newSVpvf("dbi:Informix:%s", dbsname[i]));
+ }
+ return(av);
+ }
+
+The actual B<DBD::Informix> implementation has a number of extra lines of
+code, logs function entry and exit, reports the error from C<sqgetdbs()>,
+and uses C<#define>'d constants for the array sizes.
+
+=head3 The dbd_db_login6 method
+
+ int dbd_db_login6_sv(SV* dbh, imp_dbh_t* imp_dbh, SV* dbname,
+ SV* user, SV* auth, SV *attr);
+
+ or
+
+ int dbd_db_login6(SV* dbh, imp_dbh_t* imp_dbh, char* dbname,
+ char* user, char* auth, SV *attr);
+
+This function will really connect to the database. The argument I<dbh>
+is the database handle. I<imp_dbh> is the pointer to the handles private
+data, as is I<imp_xxx> in C<dbd_drv_error()> above. The arguments
+I<dbname>, I<user>, I<auth> and I<attr> correspond to the arguments of
+the driver handle's C<connect()> method.
+
+You will quite often use database specific attributes here, that are
+specified in the DSN. I recommend you parse the DSN (using Perl) within
+the C<connect()> method and pass the segments of the DSN via the
+attributes parameter through C<_login()> to C<dbd_db_login6()>.
+
+Here's how you fetch them; as an example we use I<hostname> attribute,
+which can be up to 12 characters long excluding null terminator:
+
+ SV** svp;
+ STRLEN len;
+ char* hostname;
+
+ if ( (svp = DBD_ATTRIB_GET_SVP(attr, "drv_hostname", 12)) && SvTRUE(*svp)) {
+ hostname = SvPV(*svp, len);
+ DBD_ATTRIB_DELETE(attr, "drv_hostname", 12); /* avoid later STORE */
+ } else {
+ hostname = "localhost";
+ }
+
+If you handle any driver specific attributes in the dbd_db_login6
+method you probably want to delete them from C<attr> (as above with
+DBD_ATTRIB_DELETE). If you don't delete your handled attributes DBI
+will call C<STORE> for each attribute after the connect/login and this
+is at best redundant for attributes you have already processed.
+
+B<Note: Until revision 11605 (post DBI 1.607), there was a problem with
+DBD_ATTRIBUTE_DELETE so unless you require a DBI version after 1.607
+you need to replace each DBD_ATTRIBUTE_DELETE call with:>
+
+ hv_delete((HV*)SvRV(attr), key, key_len, G_DISCARD)
+
+Note that you can also obtain standard attributes such as I<AutoCommit> and
+I<ChopBlanks> from the attributes parameter, using C<DBD_ATTRIB_GET_IV> for
+integer attributes.
+
+If, for example, your database does not support transactions but
+I<AutoCommit> is set off (requesting transaction support), then you can
+emulate a 'failure to connect'.
+
+Now you should really connect to the database. In general, if the
+connection fails, it is best to ensure that all allocated resources are
+released so that the handle does not need to be destroyed separately. If
+you are successful (and possibly even if you fail but you have allocated
+some resources), you should use the following macros:
+
+ DBIc_IMPSET_on(imp_dbh);
+
+This indicates that the driver (implementor) has allocated resources in
+the I<imp_dbh> structure and that the implementors private C<dbd_db_destroy()>
+function should be called when the handle is destroyed.
+
+ DBIc_ACTIVE_on(imp_dbh);
+
+This indicates that the handle has an active connection to the server
+and that the C<dbd_db_disconnect()> function should be called before the
+handle is destroyed.
+
+Note that if you do need to fail, you should report errors via the I<drh>
+or I<imp_drh> rather than via I<dbh> or I<imp_dbh> because I<imp_dbh> will be
+destroyed by the failure, so errors recorded in that handle will not be
+visible to B<DBI>, and hence not the user either.
+
+Note too, that the function is passed I<dbh> and I<imp_dbh>, and there
+is a macro C<D_imp_drh_from_dbh> which can recover the I<imp_drh> from
+the I<imp_dbh>. However, there is no B<DBI> macro to provide you with the
+I<drh> given either the I<imp_dbh> or the I<dbh> or the I<imp_drh> (and
+there's no way to recover the I<dbh> given just the I<imp_dbh>).
+
+This suggests that, despite the above notes about C<dbd_drv_error()>
+taking an C<SV *>, it may be better to have two error routines, one
+taking I<imp_dbh> and one taking I<imp_drh> instead. With care, you can
+factor most of the formatting code out so that these are small routines
+calling a common error formatter. See the code in B<DBD::Informix>
+1.05.00 for more information.
+
+The C<dbd_db_login6()> function should return I<TRUE> for success,
+I<FALSE> otherwise.
+
+Drivers implemented long ago may define the five-argument function
+C<dbd_db_login()> instead of C<dbd_db_login6()>. The missing argument is
+the attributes. There are ways to work around the missing attributes,
+but they are ungainly; it is much better to use the 6-argument form.
+Even later drivers will use C<dbd_db_login6_sv()> which provides the
+dbname, username and password as SVs.
+
+=head3 The dbd_db_commit and dbd_db_rollback methods
+
+ int dbd_db_commit(SV *dbh, imp_dbh_t *imp_dbh);
+ int dbd_db_rollback(SV* dbh, imp_dbh_t* imp_dbh);
+
+These are used for commit and rollback. They should return I<TRUE> for
+success, I<FALSE> for error.
+
+The arguments I<dbh> and I<imp_dbh> are the same as for C<dbd_db_login6()>
+above; I will omit describing them in what follows, as they appear
+always.
+
+These functions should return I<TRUE> for success, I<FALSE> otherwise.
+
+=head3 The dbd_db_disconnect method
+
+This is your private part of the C<disconnect()> method. Any I<dbh> with
+the I<ACTIVE> flag on must be disconnected. (Note that you have to set
+it in C<dbd_db_connect()> above.)
+
+ int dbd_db_disconnect(SV* dbh, imp_dbh_t* imp_dbh);
+
+The database handle will return I<TRUE> for success, I<FALSE> otherwise.
+In any case it should do a:
+
+ DBIc_ACTIVE_off(imp_dbh);
+
+before returning so B<DBI> knows that C<dbd_db_disconnect()> was executed.
+
+Note that there's nothing to stop a I<dbh> being I<disconnected> while
+it still have active children. If your database API reacts badly to
+trying to use an I<sth> in this situation then you'll need to add code
+like this to all I<sth> methods:
+
+ if (!DBIc_ACTIVE(DBIc_PARENT_COM(imp_sth)))
+ return 0;
+
+Alternatively, you can add code to your driver to keep explicit track of
+the statement handles that exist for each database handle and arrange
+to destroy those handles before disconnecting from the database. There
+is code to do this in B<DBD::Informix>. Similar comments apply to the
+driver handle keeping track of all the database handles.
+
+Note that the code which destroys the subordinate handles should only
+release the associated database resources and mark the handles inactive;
+it does not attempt to free the actual handle structures.
+
+This function should return I<TRUE> for success, I<FALSE> otherwise, but
+it is not clear what anything can do about a failure.
+
+=head3 The dbd_db_discon_all method
+
+ int dbd_discon_all (SV *drh, imp_drh_t *imp_drh);
+
+This function may be called at shutdown time. It should make
+best-efforts to disconnect all database handles - if possible. Some
+databases don't support that, in which case you can do nothing
+but return 'success'.
+
+This function should return I<TRUE> for success, I<FALSE> otherwise, but
+it is not clear what anything can do about a failure.
+
+=head3 The dbd_db_destroy method
+
+This is your private part of the database handle destructor. Any I<dbh> with
+the I<IMPSET> flag on must be destroyed, so that you can safely free
+resources. (Note that you have to set it in C<dbd_db_connect()> above.)
+
+ void dbd_db_destroy(SV* dbh, imp_dbh_t* imp_dbh)
+ {
+ DBIc_IMPSET_off(imp_dbh);
+ }
+
+The B<DBI> F<Driver.xst> code will have called C<dbd_db_disconnect()> for you,
+if the handle is still 'active', before calling C<dbd_db_destroy()>.
+
+Before returning the function must switch I<IMPSET> to off, so B<DBI> knows
+that the destructor was called.
+
+A B<DBI> handle doesn't keep references to its children. But children
+do keep references to their parents. So a database handle won't be
+C<DESTROY>'d until all its children have been C<DESTROY>'d.
+
+=head3 The dbd_db_STORE_attrib method
+
+This function handles
+
+ $dbh->{$key} = $value;
+
+Its prototype is:
+
+ int dbd_db_STORE_attrib(SV* dbh, imp_dbh_t* imp_dbh, SV* keysv,
+ SV* valuesv);
+
+You do not handle all attributes; on the contrary, you should not handle
+B<DBI> attributes here: leave this to B<DBI>. (There are two exceptions,
+I<AutoCommit> and I<ChopBlanks>, which you should care about.)
+
+The return value is I<TRUE> if you have handled the attribute or I<FALSE>
+otherwise. If you are handling an attribute and something fails, you
+should call C<dbd_drv_error()>, so B<DBI> can raise exceptions, if desired.
+If C<dbd_drv_error()> returns, however, you have a problem: the user will
+never know about the error, because he typically will not check
+C<$dbh-E<gt>errstr()>.
+
+I cannot recommend a general way of going on, if C<dbd_drv_error()> returns,
+but there are examples where even the B<DBI> specification expects that
+you C<croak()>. (See the I<AutoCommit> method in L<DBI>.)
+
+If you have to store attributes, you should either use your private
+data structure I<imp_xxx>, the handle hash (via C<(HV*)SvRV(dbh)>), or use
+the private I<imp_data>.
+
+The first is best for internal C values like integers or pointers and
+where speed is important within the driver. The handle hash is best for
+values the user may want to get/set via driver-specific attributes.
+The private I<imp_data> is an additional C<SV> attached to the handle. You
+could think of it as an unnamed handle attribute. It's not normally used.
+
+=head3 The dbd_db_FETCH_attrib method
+
+This is the counterpart of C<dbd_db_STORE_attrib()>, needed for:
+
+ $value = $dbh->{$key};
+
+Its prototype is:
+
+ SV* dbd_db_FETCH_attrib(SV* dbh, imp_dbh_t* imp_dbh, SV* keysv);
+
+Unlike all previous methods this returns an C<SV> with the value. Note
+that you should normally execute C<sv_2mortal()>, if you return a nonconstant
+value. (Constant values are C<&sv_undef>, C<&sv_no> and C<&sv_yes>.)
+
+Note, that B<DBI> implements a caching algorithm for attribute values.
+If you think, that an attribute may be fetched, you store it in the
+I<dbh> itself:
+
+ if (cacheit) /* cache value for later DBI 'quick' fetch? */
+ hv_store((HV*)SvRV(dbh), key, kl, cachesv, 0);
+
+=head3 The dbd_st_prepare method
+
+This is the private part of the C<prepare()> method. Note that you
+B<must not> really execute the statement here. You may, however,
+preparse and validate the statement, or do similar things.
+
+ int dbd_st_prepare(SV* sth, imp_sth_t* imp_sth, char* statement,
+ SV* attribs);
+
+A typical, simple, possibility is to do nothing and rely on the perl
+C<prepare()> code that set the I<Statement> attribute on the handle. This
+attribute can then be used by C<dbd_st_execute()>.
+
+If the driver supports placeholders then the I<NUM_OF_PARAMS> attribute
+must be set correctly by C<dbd_st_prepare()>:
+
+ DBIc_NUM_PARAMS(imp_sth) = ...
+
+If you can, you should also setup attributes like I<NUM_OF_FIELDS>, I<NAME>,
+etc. here, but B<DBI> doesn't require that - they can be deferred until
+execute() is called. However, if you do, document it.
+
+In any case you should set the I<IMPSET> flag, as you did in
+C<dbd_db_connect()> above:
+
+ DBIc_IMPSET_on(imp_sth);
+
+=head3 The dbd_st_execute method
+
+This is where a statement will really be executed.
+
+ int dbd_st_execute(SV* sth, imp_sth_t* imp_sth);
+
+Note that you must be aware a statement may be executed repeatedly.
+Also, you should not expect that C<finish()> will be called between two
+executions, so you might need code, like the following, near the start
+of the function:
+
+ if (DBIc_ACTIVE(imp_sth))
+ dbd_st_finish(h, imp_sth);
+
+If your driver supports the binding of parameters (it should!), but the
+database doesn't, you must do it here. This can be done as follows:
+
+ SV *svp;
+ char* statement = DBD_ATTRIB_GET_PV(h, "Statement", 9, svp, "");
+ int numParam = DBIc_NUM_PARAMS(imp_sth);
+ int i;
+
+ for (i = 0; i < numParam; i++)
+ {
+ char* value = dbd_db_get_param(sth, imp_sth, i);
+ /* It is your drivers task to implement dbd_db_get_param, */
+ /* it must be setup as a counterpart of dbd_bind_ph. */
+ /* Look for '?' and replace it with 'value'. Difficult */
+ /* task, note that you may have question marks inside */
+ /* quotes and comments the like ... :-( */
+ /* See DBD::mysql for an example. (Don't look too deep into */
+ /* the example, you will notice where I was lazy ...) */
+ }
+
+The next thing is to really execute the statement.
+
+Note that you must set the attributes I<NUM_OF_FIELDS>, I<NAME>, etc
+when the statement is successfully executed if the driver has not
+already done so: they may be used even before a potential C<fetchrow()>.
+In particular you have to tell B<DBI> the number of fields that the
+statement has, because it will be used by B<DBI> internally. Thus the
+function will typically ends with:
+
+ if (isSelectStatement) {
+ DBIc_NUM_FIELDS(imp_sth) = numFields;
+ DBIc_ACTIVE_on(imp_sth);
+ }
+
+It is important that the I<ACTIVE> flag only be set for C<SELECT>
+statements (or any other statements that can return many
+values from the database using a cursor-like mechanism). See
+C<dbd_db_connect()> above for more explanations.
+
+There plans for a preparse function to be provided by B<DBI>, but this has
+not reached fruition yet.
+Meantime, if you want to know how ugly it can get, try looking at the
+C<dbd_ix_preparse()> in B<DBD::Informix> F<dbdimp.ec> and the related
+functions in F<iustoken.c> and F<sqltoken.c>.
+
+=head3 The dbd_st_fetch method
+
+This function fetches a row of data. The row is stored in in an array,
+of C<SV>'s that B<DBI> prepares for you. This has two advantages: it is fast
+(you even reuse the C<SV>'s, so they don't have to be created after the
+first C<fetchrow()>), and it guarantees that B<DBI> handles C<bind_cols()> for
+you.
+
+What you do is the following:
+
+ AV* av;
+ int numFields = DBIc_NUM_FIELDS(imp_sth); /* Correct, if NUM_FIELDS
+ is constant for this statement. There are drivers where this is
+ not the case! */
+ int chopBlanks = DBIc_is(imp_sth, DBIcf_ChopBlanks);
+ int i;
+
+ if (!fetch_new_row_of_data(...)) {
+ ... /* check for error or end-of-data */
+ DBIc_ACTIVE_off(imp_sth); /* turn off Active flag automatically */
+ return Nullav;
+ }
+ /* get the fbav (field buffer array value) for this row */
+ /* it is very important to only call this after you know */
+ /* that you have a row of data to return. */
+ av = DBIc_DBISTATE(imp_sth)->get_fbav(imp_sth);
+ for (i = 0; i < numFields; i++) {
+ SV* sv = fetch_a_field(..., i);
+ if (chopBlanks && SvOK(sv) && type_is_blank_padded(field_type[i])) {
+ /* Remove white space from end (only) of sv */
+ }
+ sv_setsv(AvARRAY(av)[i], sv); /* Note: (re)use! */
+ }
+ return av;
+
+There's no need to use a C<fetch_a_field()> function returning an C<SV*>.
+It's more common to use your database API functions to fetch the
+data as character strings and use code like this:
+
+ sv_setpvn(AvARRAY(av)[i], char_ptr, char_count);
+
+C<NULL> values must be returned as C<undef>. You can use code like this:
+
+ SvOK_off(AvARRAY(av)[i]);
+
+The function returns the C<AV> prepared by B<DBI> for success or C<Nullav>
+otherwise.
+
+ *FIX ME* Discuss what happens when there's no more data to fetch.
+ Are errors permitted if another fetch occurs after the first fetch
+ that reports no more data. (Permitted, not required.)
+
+If an error occurs which leaves the I<$sth> in a state where remaining
+rows can't be fetched then I<Active> should be turned off before the
+method returns.
+
+=head3 The dbd_st_finish3 method
+
+The C<$sth-E<gt>finish()> method can be called if the user wishes to
+indicate that no more rows will be fetched even if the database has more
+rows to offer, and the B<DBI> code can call the function when handles are
+being destroyed. See the B<DBI> specification for more background details.
+
+In both circumstances, the B<DBI> code ends up calling the
+C<dbd_st_finish3()> method (if you provide a mapping for
+C<dbd_st_finish3()> in F<dbdimp.h>), or C<dbd_st_finish()> otherwise.
+The difference is that C<dbd_st_finish3()> takes a third argument which
+is an C<int> with the value 1 if it is being called from a C<destroy()>
+method and 0 otherwise.
+
+Note that B<DBI> v1.32 and earlier test on C<dbd_db_finish3()> to call
+C<dbd_st_finish3()>; if you provide C<dbd_st_finish3()>, either define
+C<dbd_db_finish3()> too, or insist on B<DBI> v1.33 or later.
+
+All it I<needs> to do is turn off the I<Active> flag for the I<sth>.
+It will only be called by F<Driver.xst> code, if the driver has set I<ACTIVE>
+to on for the I<sth>.
+
+Outline example:
+
+ int dbd_st_finish3(SV* sth, imp_sth_t* imp_sth, int from_destroy) {
+ if (DBIc_ACTIVE(imp_sth))
+ {
+ /* close cursor or equivalent action */
+ DBIc_ACTIVE_off(imp_sth);
+ }
+ return 1;
+ }
+
+The from_destroy parameter is true if C<dbd_st_finish3()> is being called
+from C<DESTROY()> - and so the statement is about to be destroyed.
+For many drivers there is no point in doing anything more than turning off
+the I<Active> flag in this case.
+
+The function returns I<TRUE> for success, I<FALSE> otherwise, but there isn't
+a lot anyone can do to recover if there is an error.
+
+=head3 The dbd_st_destroy method
+
+This function is the private part of the statement handle destructor.
+
+ void dbd_st_destroy(SV* sth, imp_sth_t* imp_sth) {
+ ... /* any clean-up that's needed */
+ DBIc_IMPSET_off(imp_sth); /* let DBI know we've done it */
+ }
+
+The B<DBI> F<Driver.xst> code will call C<dbd_st_finish()> for you, if the
+I<sth> has the I<ACTIVE> flag set, before calling C<dbd_st_destroy()>.
+
+=head3 The dbd_st_STORE_attrib and dbd_st_FETCH_attrib methods
+
+These functions correspond to C<dbd_db_STORE()> and C<dbd_db_FETCH()> attrib
+above, except that they are for statement handles.
+See above.
+
+ int dbd_st_STORE_attrib(SV* sth, imp_sth_t* imp_sth, SV* keysv,
+ SV* valuesv);
+ SV* dbd_st_FETCH_attrib(SV* sth, imp_sth_t* imp_sth, SV* keysv);
+
+=head3 The dbd_bind_ph method
+
+This function is internally used by the C<bind_param()> method, the
+C<bind_param_inout()> method and by the B<DBI> F<Driver.xst> code if
+C<execute()> is called with any bind parameters.
+
+ int dbd_bind_ph (SV *sth, imp_sth_t *imp_sth, SV *param,
+ SV *value, IV sql_type, SV *attribs,
+ int is_inout, IV maxlen);
+
+The I<param> argument holds an C<IV> with the parameter number (1, 2, ...).
+The I<value> argument is the parameter value and I<sql_type> is its type.
+
+If your driver does not support C<bind_param_inout()> then you should
+ignore I<maxlen> and croak if I<is_inout> is I<TRUE>.
+
+If your driver I<does> support C<bind_param_inout()> then you should
+note that I<value> is the C<SV> I<after> dereferencing the reference
+passed to C<bind_param_inout()>.
+
+In drivers of simple databases the function will, for example, store
+the value in a parameter array and use it later in C<dbd_st_execute()>.
+See the B<DBD::mysql> driver for an example.
+
+=head3 Implementing bind_param_inout support
+
+To provide support for parameters bound by reference rather than by
+value, the driver must do a number of things. First, and most
+importantly, it must note the references and stash them in its own
+driver structure. Secondly, when a value is bound to a column, the
+driver must discard any previous reference bound to the column. On
+each execute, the driver must evaluate the references and internally
+bind the values resulting from the references. This is only applicable
+if the user writes:
+
+ $sth->execute;
+
+If the user writes:
+
+ $sth->execute(@values);
+
+then B<DBI> automatically calls the binding code for each element of
+I<@values>. These calls are indistinguishable from explicit user calls to
+C<bind_param()>.
+
+=head2 C/XS version of Makefile.PL
+
+The F<Makefile.PL> file for a C/XS driver is similar to the code needed
+for a pure Perl driver, but there are a number of extra bits of
+information needed by the build system.
+
+For example, the attributes list passed to C<WriteMakefile()> needs
+to specify the object files that need to be compiled and built into
+the shared object (DLL). This is often, but not necessarily, just
+F<dbdimp.o> (unless that should be F<dbdimp.obj> because you're building
+on MS Windows).
+
+Note that you can reliably determine the extension of the object files
+from the I<$Config{obj_ext}> values, and there are many other useful pieces
+of configuration information lurking in that hash.
+You get access to it with:
+
+ use Config;
+
+=head2 Methods which do not need to be written
+
+The B<DBI> code implements the majority of the methods which are accessed
+using the notation C<DBI-E<gt>function()>, the only exceptions being
+C<DBI-E<gt>connect()> and C<DBI-E<gt>data_sources()> which require
+support from the driver.
+
+The B<DBI> code implements the following documented driver, database and
+statement functions which do not need to be written by the B<DBD> driver
+writer.
+
+=over 4
+
+=item $dbh->do()
+
+The default implementation of this function prepares, executes and
+destroys the statement. This can be replaced if there is a better
+way to implement this, such as C<EXECUTE IMMEDIATE> which can
+sometimes be used if there are no parameters.
+
+=item $h->errstr()
+
+=item $h->err()
+
+=item $h->state()
+
+=item $h->trace()
+
+The B<DBD> driver does not need to worry about these routines at all.
+
+=item $h->{ChopBlanks}
+
+This attribute needs to be honored during C<fetch()> operations, but does
+not need to be handled by the attribute handling code.
+
+=item $h->{RaiseError}
+
+The B<DBD> driver does not need to worry about this attribute at all.
+
+=item $h->{PrintError}
+
+The B<DBD> driver does not need to worry about this attribute at all.
+
+=item $sth->bind_col()
+
+Assuming the driver uses the C<DBIc_DBISTATE(imp_xxh)-E<gt>get_fbav()>
+function (C drivers, see below), or the C<$sth-E<gt>_set_fbav($data)>
+method (Perl drivers) the driver does not need to do anything about this
+routine.
+
+=item $sth->bind_columns()
+
+Regardless of whether the driver uses
+C<DBIc_DBISTATE(imp_xxh)-E<gt>get_fbav()>, the driver does not need
+to do anything about this routine as it simply iteratively calls
+C<$sth-E<gt>bind_col()>.
+
+=back
+
+The B<DBI> code implements a default implementation of the following
+functions which do not need to be written by the B<DBD> driver writer
+unless the default implementation is incorrect for the Driver.
+
+=over 4
+
+=item $dbh->quote()
+
+This should only be written if the database does not accept the ANSI
+SQL standard for quoting strings, with the string enclosed in single
+quotes and any embedded single quotes replaced by two consecutive
+single quotes.
+
+For the two argument form of quote, you need to implement the
+C<type_info()> method to provide the information that quote needs.
+
+=item $dbh->ping()
+
+This should be implemented as a simple efficient way to determine
+whether the connection to the database is still alive. Typically
+code like this:
+
+ sub ping {
+ my $dbh = shift;
+ $sth = $dbh->prepare_cached(q{
+ select * from A_TABLE_NAME where 1=0
+ }) or return 0;
+ $sth->execute or return 0;
+ $sth->finish;
+ return 1;
+ }
+
+where I<A_TABLE_NAME> is the name of a table that always exists (such as a
+database system catalogue).
+
+=back
+
+=head1 METADATA METHODS
+
+The exposition above ignores the B<DBI> MetaData methods.
+The metadata methods are all associated with a database handle.
+
+=head2 Using DBI::DBD::Metadata
+
+The B<DBI::DBD::Metadata> module is a good semi-automatic way for the
+developer of a B<DBD> module to write the C<get_info()> and C<type_info()>
+functions quickly and accurately.
+
+=head3 Generating the get_info method
+
+Prior to B<DBI> v1.33, this existed as the method C<write_getinfo_pm()>
+in the B<DBI::DBD> module. From B<DBI> v1.33, it exists as the method
+C<write_getinfo_pm()> in the B<DBI::DBD::Metadata> module. This
+discussion assumes you have B<DBI> v1.33 or later.
+
+You examine the documentation for C<write_getinfo_pm()> using:
+
+ perldoc DBI::DBD::Metadata
+
+To use it, you need a Perl B<DBI> driver for your database which implements
+the C<get_info()> method. In practice, this means you need to install
+B<DBD::ODBC>, an ODBC driver manager, and an ODBC driver for your
+database.
+
+With the pre-requisites in place, you might type:
+
+ perl -MDBI::DBD::Metadata -we \
+ "write_getinfo_pm (qw{ dbi:ODBC:foo_db username password Driver })"
+
+The procedure writes to standard output the code that should be added to
+your F<Driver.pm> file and the code that should be written to
+F<lib/DBD/Driver/GetInfo.pm>.
+
+You should review the output to ensure that it is sensible.
+
+=head3 Generating the type_info method
+
+Given the idea of the C<write_getinfo_pm()> method, it was not hard
+to devise a parallel method, C<write_typeinfo_pm()>, which does the
+analogous job for the B<DBI> C<type_info_all()> metadata method. The
+C<write_typeinfo_pm()> method was added to B<DBI> v1.33.
+
+You examine the documentation for C<write_typeinfo_pm()> using:
+
+ perldoc DBI::DBD::Metadata
+
+The setup is exactly analogous to the mechanism described in
+L</Generating the get_info method>.
+
+With the pre-requisites in place, you might type:
+
+ perl -MDBI::DBD::Metadata -we \
+ "write_typeinfo (qw{ dbi:ODBC:foo_db username password Driver })"
+
+The procedure writes to standard output the code that should be added to
+your F<Driver.pm> file and the code that should be written to
+F<lib/DBD/Driver/TypeInfo.pm>.
+
+You should review the output to ensure that it is sensible.
+
+=head2 Writing DBD::Driver::db::get_info
+
+If you use the B<DBI::DBD::Metadata> module, then the code you need is
+generated for you.
+
+If you decide not to use the B<DBI::DBD::Metadata> module, you
+should probably borrow the code from a driver that has done so (eg
+B<DBD::Informix> from version 1.05 onwards) and crib the code from
+there, or look at the code that generates that module and follow
+that. The method in F<Driver.pm> will be very simple; the method in
+F<lib/DBD/Driver/GetInfo.pm> is not very much more complex unless your
+DBMS itself is much more complex.
+
+Note that some of the B<DBI> utility methods rely on information from the
+C<get_info()> method to perform their operations correctly. See, for
+example, the C<quote_identifier()> and quote methods, discussed below.
+
+=head2 Writing DBD::Driver::db::type_info_all
+
+If you use the C<DBI::DBD::Metadata> module, then the code you need is
+generated for you.
+
+If you decide not to use the C<DBI::DBD::Metadata> module, you
+should probably borrow the code from a driver that has done so (eg
+C<DBD::Informix> from version 1.05 onwards) and crib the code from
+there, or look at the code that generates that module and follow
+that. The method in F<Driver.pm> will be very simple; the method in
+F<lib/DBD/Driver/TypeInfo.pm> is not very much more complex unless your
+DBMS itself is much more complex.
+
+=head2 Writing DBD::Driver::db::type_info
+
+The guidelines on writing this method are still not really clear.
+No sample implementation is available.
+
+=head2 Writing DBD::Driver::db::table_info
+
+ *FIX ME* The guidelines on writing this method have not been written yet.
+ No sample implementation is available.
+
+=head2 Writing DBD::Driver::db::column_info
+
+ *FIX ME* The guidelines on writing this method have not been written yet.
+ No sample implementation is available.
+
+=head2 Writing DBD::Driver::db::primary_key_info
+
+ *FIX ME* The guidelines on writing this method have not been written yet.
+ No sample implementation is available.
+
+=head2 Writing DBD::Driver::db::primary_key
+
+ *FIX ME* The guidelines on writing this method have not been written yet.
+ No sample implementation is available.
+
+=head2 Writing DBD::Driver::db::foreign_key_info
+
+ *FIX ME* The guidelines on writing this method have not been written yet.
+ No sample implementation is available.
+
+=head2 Writing DBD::Driver::db::tables
+
+This method generates an array of names in a format suitable for being
+embedded in SQL statements in places where a table name is expected.
+
+If your database hews close enough to the SQL standard or if you have
+implemented an appropriate C<table_info()> function and and the appropriate
+C<quote_identifier()> function, then the B<DBI> default version of this method
+will work for your driver too.
+
+Otherwise, you have to write a function yourself, such as:
+
+ sub tables
+ {
+ my($dbh, $cat, $sch, $tab, $typ) = @_;
+ my(@res);
+ my($sth) = $dbh->table_info($cat, $sch, $tab, $typ);
+ my(@arr);
+ while (@arr = $sth->fetchrow_array)
+ {
+ push @res, $dbh->quote_identifier($arr[0], $arr[1], $arr[2]);
+ }
+ return @res;
+ }
+
+See also the default implementation in F<DBI.pm>.
+
+=head2 Writing DBD::Driver::db::quote
+
+This method takes a value and converts it into a string suitable for
+embedding in an SQL statement as a string literal.
+
+If your DBMS accepts the SQL standard notation for strings (single
+quotes around the string as a whole with any embedded single quotes
+doubled up), then you do not need to write this method as B<DBI> provides a
+default method that does it for you.
+
+If your DBMS uses an alternative notation or escape mechanism, then you
+need to provide an equivalent function. For example, suppose your DBMS
+used C notation with double quotes around the string and backslashes
+escaping both double quotes and backslashes themselves. Then you might
+write the function as:
+
+ sub quote
+ {
+ my($dbh, $str) = @_;
+ $str =~ s/["\\]/\\$&/gmo;
+ return qq{"$str"};
+ }
+
+Handling newlines and other control characters is left as an exercise
+for the reader.
+
+This sample method ignores the I<$data_type> indicator which is the
+optional second argument to the method.
+
+=head2 Writing DBD::Driver::db::quote_identifier
+
+This method is called to ensure that the name of the given table (or
+other database object) can be embedded into an SQL statement without
+danger of misinterpretation. The result string should be usable in the
+text of an SQL statement as the identifier for a table.
+
+If your DBMS accepts the SQL standard notation for quoted identifiers
+(which uses double quotes around the identifier as a whole, with any
+embedded double quotes doubled up) and accepts I<"schema"."identifier">
+(and I<"catalog"."schema"."identifier"> when a catalog is specified), then
+you do not need to write this method as B<DBI> provides a default method
+that does it for you.
+
+In fact, even if your DBMS does not handle exactly that notation but
+you have implemented the C<get_info()> method and it gives the correct
+responses, then it will work for you. If your database is fussier, then
+you need to implement your own version of the function.
+
+For example, B<DBD::Informix> has to deal with an environment variable
+I<DELIMIDENT>. If it is not set, then the DBMS treats names enclosed in
+double quotes as strings rather than names, which is usually a syntax
+error. Additionally, the catalog portion of the name is separated from
+the schema and table by a different delimiter (colon instead of dot),
+and the catalog portion is never enclosed in quotes. (Fortunately,
+valid strings for the catalog will never contain weird characters that
+might need to be escaped, unless you count dots, dashes, slashes and
+at-signs as weird.) Finally, an Informix database can contain objects
+that cannot be accessed because they were created by a user with the
+I<DELIMIDENT> environment variable set, but the current user does not
+have it set. By design choice, the C<quote_identifier()> method encloses
+those identifiers in double quotes anyway, which generally triggers a
+syntax error, and the metadata methods which generate lists of tables
+etc omit those identifiers from the result sets.
+
+ sub quote_identifier
+ {
+ my($dbh, $cat, $sch, $obj) = @_;
+ my($rv) = "";
+ my($qq) = (defined $ENV{DELIMIDENT}) ? '"' : '';
+ $rv .= qq{$cat:} if (defined $cat);
+ if (defined $sch)
+ {
+ if ($sch !~ m/^\w+$/o)
+ {
+ $qq = '"';
+ $sch =~ s/$qq/$qq$qq/gm;
+ }
+ $rv .= qq{$qq$sch$qq.};
+ }
+ if (defined $obj)
+ {
+ if ($obj !~ m/^\w+$/o)
+ {
+ $qq = '"';
+ $obj =~ s/$qq/$qq$qq/gm;
+ }
+ $rv .= qq{$qq$obj$qq};
+ }
+ return $rv;
+ }
+
+Handling newlines and other control characters is left as an exercise
+for the reader.
+
+Note that there is an optional fourth parameter to this function which
+is a reference to a hash of attributes; this sample implementation
+ignores that.
+
+This sample implementation also ignores the single-argument variant of
+the method.
+
+=head1 TRACING
+
+Tracing in DBI is controlled with a combination of a trace level and a
+set of flags which together are known as the trace settings. The trace
+settings are stored in a single integer and divided into levels and
+flags by a set of masks (C<DBIc_TRACE_LEVEL_MASK> and
+C<DBIc_TRACE_FLAGS_MASK>).
+
+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 Level
+
+The trace level is the first 4 bits of the trace settings (masked by
+C<DBIc_TRACE_FLAGS_MASK>) and represents trace levels of 1 to 15. Do
+not output anything at trace levels less than 3 as they are reserved
+for DBI.
+
+For advice on what to output at each level see "Trace Levels" in
+L<DBI>.
+
+To test for a trace level you can use the C<DBIc_TRACE_LEVEL> macro
+like this:
+
+ if (DBIc_TRACE_LEVEL(imp_xxh) >= 2) {
+ PerlIO_printf(DBIc_LOGPIO(imp_xxh), "foobar");
+ }
+
+Also B<note> the use of PerlIO_printf which you should always use for
+tracing and never the C C<stdio.h> I/O functions.
+
+=head2 Trace Flags
+
+Trace 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. For a list of DBI
+defined trace flags see "Trace Flags" in L<DBI>.
+
+If you want to use private trace flags you'll probably want to be able
+to set them by name. Drivers are expected to override the
+parse_trace_flag (note the singular) and check if $trace_flag_name is
+a driver specific trace flags and, if not, then call the DBIs default
+parse_trace_flag(). To do that you'll need to define a
+parse_trace_flag() method like this:
+
+ sub parse_trace_flag {
+ my ($h, $name) = @_;
+ return 0x01000000 if $name eq 'foo';
+ return 0x02000000 if $name eq 'bar';
+ return 0x04000000 if $name eq 'baz';
+ return 0x08000000 if $name eq 'boo';
+ return 0x10000000 if $name eq 'bop';
+ return $h->SUPER::parse_trace_flag($name);
+ }
+
+All private flag names must be lowercase, and all private flags must
+be in the top 8 of the 32 bits of C<DBIc_TRACE_FLAGS(imp)> i.e.,
+0xFF000000.
+
+If you've defined a parse_trace_flag() method in ::db you'll also want
+it in ::st, so just alias it in:
+
+ *parse_trace_flag = \&DBD::foo:db::parse_trace_flag;
+
+You may want to act on the current 'SQL' trace flag that DBI defines
+to output SQL prepared/executed as DBI currently does not do SQL
+tracing.
+
+=head2 Trace Macros
+
+Access to the trace level and trace flags is via a set of macros.
+
+ DBIc_TRACE_SETTINGS(imp) returns the trace settings
+ DBIc_TRACE_LEVEL(imp) returns the trace level
+ DBIc_TRACE_FLAGS(imp) returns the trace flags
+ DBIc_TRACE(imp, flags, flaglevel, level)
+
+ e.g.,
+
+ DBIc_TRACE(imp, 0, 0, 4)
+ if level >= 4
+
+ DBIc_TRACE(imp, DBDtf_FOO, 2, 4)
+ if tracing DBDtf_FOO & level>=2 or level>=4
+
+ DBIc_TRACE(imp, DBDtf_FOO, 2, 0)
+ as above but never trace just due to level
+
+=head1 WRITING AN EMULATION LAYER FOR AN OLD PERL INTERFACE
+
+Study F<Oraperl.pm> (supplied with B<DBD::Oracle>) and F<Ingperl.pm> (supplied
+with B<DBD::Ingres>) and the corresponding I<dbdimp.c> files for ideas.
+
+Note that the emulation code sets C<$dbh-E<gt>{CompatMode} = 1;> for each
+connection so that the internals of the driver can implement behaviour
+compatible with the old interface when dealing with those handles.
+
+=head2 Setting emulation perl variables
+
+For example, ingperl has a I<$sql_rowcount> variable. Rather than try
+to manually update this in F<Ingperl.pm> it can be done faster in C code.
+In C<dbd_init()>:
+
+ sql_rowcount = perl_get_sv("Ingperl::sql_rowcount", GV_ADDMULTI);
+
+In the relevant places do:
+
+ if (DBIc_COMPAT(imp_sth)) /* only do this for compatibility mode handles */
+ sv_setiv(sql_rowcount, the_row_count);
+
+=head1 OTHER MISCELLANEOUS INFORMATION
+
+=head2 The imp_xyz_t types
+
+Any handle has a corresponding C structure filled with private data.
+Some of this data is reserved for use by B<DBI> (except for using the
+DBIc macros below), some is for you. See the description of the
+F<dbdimp.h> file above for examples. Most functions in F<dbdimp.c>
+are passed both the handle C<xyz> and a pointer to C<imp_xyz>. In
+rare cases, however, you may use the following macros:
+
+=over 4
+
+=item D_imp_dbh(dbh)
+
+Given a function argument I<dbh>, declare a variable I<imp_dbh> and
+initialize it with a pointer to the handles private data. Note: This
+must be a part of the function header, because it declares a variable.
+
+=item D_imp_sth(sth)
+
+Likewise for statement handles.
+
+=item D_imp_xxx(h)
+
+Given any handle, declare a variable I<imp_xxx> and initialize it
+with a pointer to the handles private data. It is safe, for example,
+to cast I<imp_xxx> to C<imp_dbh_t*>, if C<DBIc_TYPE(imp_xxx) == DBIt_DB>.
+(You can also call C<sv_derived_from(h, "DBI::db")>, but that's much
+slower.)
+
+=item D_imp_dbh_from_sth
+
+Given a I<imp_sth>, declare a variable I<imp_dbh> and initialize it with a
+pointer to the parent database handle's implementors structure.
+
+=back
+
+=head2 Using DBIc_IMPSET_on
+
+The driver code which initializes a handle should use C<DBIc_IMPSET_on()>
+as soon as its state is such that the cleanup code must be called.
+When this happens is determined by your driver code.
+
+B<Failure to call this can lead to corruption of data structures.>
+
+For example, B<DBD::Informix> maintains a linked list of database
+handles in the driver, and within each handle, a linked list of
+statements. Once a statement is added to the linked list, it is crucial
+that it is cleaned up (removed from the list). When I<DBIc_IMPSET_on()>
+was being called too late, it was able to cause all sorts of problems.
+
+=head2 Using DBIc_is(), DBIc_has(), DBIc_on() and DBIc_off()
+
+Once upon a long time ago, the only way of handling the internal B<DBI>
+boolean flags/attributes was through macros such as:
+
+ DBIc_WARN DBIc_WARN_on DBIc_WARN_off
+ DBIc_COMPAT DBIc_COMPAT_on DBIc_COMPAT_off
+
+Each of these took an I<imp_xxh> pointer as an argument.
+
+Since then, new attributes have been added such as I<ChopBlanks>,
+I<RaiseError> and I<PrintError>, and these do not have the full set of
+macros. The approved method for handling these is now the four macros:
+
+ DBIc_is(imp, flag)
+ DBIc_has(imp, flag) an alias for DBIc_is
+ DBIc_on(imp, flag)
+ DBIc_off(imp, flag)
+ DBIc_set(imp, flag, on) set if on is true, else clear
+
+Consequently, the C<DBIc_XXXXX> family of macros is now mostly deprecated
+and new drivers should avoid using them, even though the older drivers
+will probably continue to do so for quite a while yet. However...
+
+There is an I<important exception> to that. The I<ACTIVE> and I<IMPSET>
+flags should be set via the C<DBIc_ACTIVE_on()> and C<DBIc_IMPSET_on()> macros,
+and unset via the C<DBIc_ACTIVE_off()> and C<DBIc_IMPSET_off()> macros.
+
+=head2 Using the get_fbav() method
+
+B<THIS IS CRITICAL for C/XS drivers>.
+
+The C<$sth-E<gt>bind_col()> and C<$sth-E<gt>bind_columns()> documented
+in the B<DBI> specification do not have to be implemented by the driver
+writer because B<DBI> takes care of the details for you.
+
+However, the key to ensuring that bound columns work is to call the
+function C<DBIc_DBISTATE(imp_xxh)-E<gt>get_fbav()> in the code which
+fetches a row of data.
+
+This returns an C<AV>, and each element of the C<AV> contains the C<SV> which
+should be set to contain the returned data.
+
+The pure Perl equivalent is the C<$sth-E<gt>_set_fbav($data)> method, as
+described in the part on pure Perl drivers.
+
+=head1 SUBCLASSING DBI DRIVERS
+
+This is definitely an open subject. It can be done, as demonstrated by
+the B<DBD::File> driver, but it is not as simple as one might think.
+
+(Note that this topic is different from subclassing the B<DBI>. For an
+example of that, see the F<t/subclass.t> file supplied with the B<DBI>.)
+
+The main problem is that the I<dbh>'s and I<sth>'s that your C<connect()> and
+C<prepare()> methods return are not instances of your B<DBD::Driver::db>
+or B<DBD::Driver::st> packages, they are not even derived from it.
+Instead they are instances of the B<DBI::db> or B<DBI::st> classes or
+a derived subclass. Thus, if you write a method C<mymethod()> and do a
+
+ $dbh->mymethod()
+
+then the autoloader will search for that method in the package B<DBI::db>.
+Of course you can instead to a
+
+ $dbh->func('mymethod')
+
+and that will indeed work, even if C<mymethod()> is inherited, but not
+without additional work. Setting I<@ISA> is not sufficient.
+
+=head2 Overwriting methods
+
+The first problem is, that the C<connect()> method has no idea of
+subclasses. For example, you cannot implement base class and subclass
+in the same file: The C<install_driver()> method wants to do a
+
+ require DBD::Driver;
+
+In particular, your subclass B<has> to be a separate driver, from
+the view of B<DBI>, and you cannot share driver handles.
+
+Of course that's not much of a problem. You should even be able
+to inherit the base classes C<connect()> method. But you cannot
+simply overwrite the method, unless you do something like this,
+quoted from B<DBD::CSV>:
+
+ sub connect ($$;$$$) {
+ my ($drh, $dbname, $user, $auth, $attr) = @_;
+
+ my $this = $drh->DBD::File::dr::connect($dbname, $user, $auth, $attr);
+ if (!exists($this->{csv_tables})) {
+ $this->{csv_tables} = {};
+ }
+
+ $this;
+ }
+
+Note that we cannot do a
+
+ $drh->SUPER::connect($dbname, $user, $auth, $attr);
+
+as we would usually do in a an OO environment, because I<$drh> is an instance
+of B<DBI::dr>. And note, that the C<connect()> method of B<DBD::File> is
+able to handle subclass attributes. See the description of Pure Perl
+drivers above.
+
+It is essential that you always call superclass method in the above
+manner. However, that should do.
+
+=head2 Attribute handling
+
+Fortunately the B<DBI> specifications allow a simple, but still
+performant way of handling attributes. The idea is based on the
+convention that any driver uses a prefix I<driver_> for its private
+methods. Thus it's always clear whether to pass attributes to the super
+class or not. For example, consider this C<STORE()> method from the
+B<DBD::CSV> class:
+
+ sub STORE {
+ my ($dbh, $attr, $val) = @_;
+ if ($attr !~ /^driver_/) {
+ return $dbh->DBD::File::db::STORE($attr, $val);
+ }
+ if ($attr eq 'driver_foo') {
+ ...
+ }
+
+=cut
+
+use Exporter ();
+use Config qw(%Config);
+use Carp;
+use Cwd;
+use File::Spec;
+use strict;
+use vars qw(
+ @ISA @EXPORT
+ $is_dbi
+);
+
+BEGIN {
+ if ($^O eq 'VMS') {
+ require vmsish;
+ import vmsish;
+ require VMS::Filespec;
+ import VMS::Filespec;
+ }
+ else {
+ *vmsify = sub { return $_[0] };
+ *unixify = sub { return $_[0] };
+ }
+}
+
+@ISA = qw(Exporter);
+
+@EXPORT = qw(
+ dbd_dbi_dir
+ dbd_dbi_arch_dir
+ dbd_edit_mm_attribs
+ dbd_postamble
+);
+
+BEGIN {
+ $is_dbi = (-r 'DBI.pm' && -r 'DBI.xs' && -r 'DBIXS.h');
+ require DBI unless $is_dbi;
+}
+
+my $done_inst_checks;
+
+sub _inst_checks {
+ return if $done_inst_checks++;
+ my $cwd = cwd();
+ if ($cwd =~ /\Q$Config{path_sep}/) {
+ warn "*** Warning: Path separator characters (`$Config{path_sep}') ",
+ "in the current directory path ($cwd) may cause problems\a\n\n";
+ sleep 2;
+ }
+ if ($cwd =~ /\s/) {
+ warn "*** Warning: whitespace characters ",
+ "in the current directory path ($cwd) may cause problems\a\n\n";
+ sleep 2;
+ }
+ if ( $^O eq 'MSWin32'
+ && $Config{cc} eq 'cl'
+ && !(exists $ENV{'LIB'} && exists $ENV{'INCLUDE'}))
+ {
+ die <<EOT;
+*** You're using Microsoft Visual C++ compiler or similar but
+ the LIB and INCLUDE environment variables are not both set.
+
+ You need to run the VCVARS32.BAT batch file that was supplied
+ with the compiler before you can use it.
+
+ A copy of vcvars32.bat can typically be found in the following
+ directories under your Visual Studio install directory:
+ Visual C++ 6.0: vc98\\bin
+ Visual Studio .NET: vc7\\bin
+
+ Find it, run it, then retry this.
+
+ If you think this error is not correct then just set the LIB and
+ INCLUDE environment variables to some value to disable the check.
+EOT
+ }
+}
+
+sub dbd_edit_mm_attribs {
+ # this both edits the attribs in-place and returns the flattened attribs
+ my $mm_attr = shift;
+ my $dbd_attr = shift || {};
+ croak "dbd_edit_mm_attribs( \%makemaker [, \%other ]): too many parameters"
+ if @_;
+ _inst_checks();
+
+ # decide what needs doing
+
+ # do whatever needs doing
+ if ($dbd_attr->{create_pp_tests}) {
+ # XXX need to convert this to work within the generated Makefile
+ # so 'make' creates them and 'make clean' deletes them
+ my %test_variants = (
+ p => { name => "DBI::PurePerl",
+ add => [ '$ENV{DBI_PUREPERL} = 2' ],
+ },
+ g => { name => "DBD::Gofer",
+ add => [ q{$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'} ],
+ },
+ xgp => { name => "PurePerl & Gofer",
+ add => [ q{$ENV{DBI_PUREPERL} = 2; $ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'} ],
+ },
+ # mx => { name => "DBD::Multiplex",
+ # add => [ q{local $ENV{DBI_AUTOPROXY} = 'dbi:Multiplex:';} ],
+ # }
+ # px => { name => "DBD::Proxy",
+ # need mechanism for starting/stopping the proxy server
+ # add => [ q{local $ENV{DBI_AUTOPROXY} = 'dbi:Proxy:XXX';} ],
+ # }
+ );
+
+ opendir DIR, 't' or die "Can't read 't' directory: $!";
+ my @tests = grep { /\.t$/ } readdir DIR;
+ closedir DIR;
+
+ while ( my ($v_type, $v_info) = each %test_variants ) {
+ printf "Creating test wrappers for $v_info->{name}:\n";
+
+ foreach my $test (sort @tests) {
+ next if $test !~ /^\d/;
+ my $usethr = ($test =~ /(\d+|\b)thr/ && $] >= 5.008 && $Config{useithreads});
+ my $v_test = "t/zv${v_type}_$test";
+ my $v_perl = ($test =~ /taint/) ? "perl -wT" : "perl -w";
+ printf "%s %s\n", $v_test, ($usethr) ? "(use threads)" : "";
+ open PPT, ">$v_test" or warn "Can't create $v_test: $!";
+ print PPT "#!$v_perl\n";
+ print PPT "use threads;\n" if $usethr;
+ print PPT "$_;\n" foreach @{$v_info->{add}};
+ print PPT "require './t/$test'; # or warn \$!;\n";
+ close PPT or warn "Error writing $v_test: $!";
+ }
+ }
+ }
+ return %$mm_attr;
+}
+
+sub dbd_dbi_dir {
+ _inst_checks();
+ return '.' if $is_dbi;
+ my $dbidir = $INC{'DBI.pm'} || die "DBI.pm not in %INC!";
+ $dbidir =~ s:/DBI\.pm$::;
+ return $dbidir;
+}
+
+sub dbd_dbi_arch_dir {
+ _inst_checks();
+ return '$(INST_ARCHAUTODIR)' if $is_dbi;
+ my $dbidir = dbd_dbi_dir();
+ my %seen;
+ my @try = grep { not $seen{$_}++ } map { vmsify( unixify($_) . "/auto/DBI/" ) } @INC;
+ my @xst = grep { -f vmsify( unixify($_) . "/Driver.xst" ) } @try;
+ Carp::croak("Unable to locate Driver.xst in @try") unless @xst;
+ Carp::carp( "Multiple copies of Driver.xst found in: @xst") if @xst > 1;
+ print "Using DBI $DBI::VERSION (for perl $] on $Config{archname}) installed in $xst[0]\n";
+ return File::Spec->canonpath($xst[0]);
+}
+
+sub dbd_postamble {
+ my $self = shift;
+ _inst_checks();
+ my $dbi_instarch_dir = ($is_dbi) ? "." : dbd_dbi_arch_dir();
+ my $dbi_driver_xst= File::Spec->catfile($dbi_instarch_dir, 'Driver.xst');
+ my $xstf_h = File::Spec->catfile($dbi_instarch_dir, 'Driver_xst.h');
+
+ # we must be careful of quotes, expecially for Win32 here.
+ return '
+# --- This section was generated by DBI::DBD::dbd_postamble()
+DBI_INSTARCH_DIR='.$dbi_instarch_dir.'
+DBI_DRIVER_XST='.$dbi_driver_xst.'
+
+# The main dependancy (technically correct but probably not used)
+$(BASEEXT).c: $(BASEEXT).xsi
+
+# This dependancy is needed since MakeMaker uses the .xs.o rule
+$(BASEEXT)$(OBJ_EXT): $(BASEEXT).xsi
+
+$(BASEEXT).xsi: $(DBI_DRIVER_XST) '.$xstf_h.'
+ $(PERL) -p -e "s/~DRIVER~/$(BASEEXT)/g" $(DBI_DRIVER_XST) > $(BASEEXT).xsi
+
+# ---
+';
+}
+
+package DBDI; # just to reserve it via PAUSE for the future
+
+1;
+
+__END__
+
+=head1 AUTHORS
+
+Jonathan Leffler <jleffler@us.ibm.com> (previously <jleffler@informix.com>),
+Jochen Wiedmann <joe@ispsoft.de>,
+Steffen Goeldner <sgoeldner@cpan.org>,
+and Tim Bunce <dbi-users@perl.org>.
+
+=cut