DBI

 view release on metacpan or  search on metacpan

lib/DBI/DBD.pm  view on Meta::CPAN


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).



( run in 0.864 second using v1.01-cache-2.11-cpan-437f7b0c052 )