From 479ff8cb464f065fdf9b8e20cd9fde0fcd77eaf3 Mon Sep 17 00:00:00 2001 From: "H.Merijn Brand - Tux" Date: Sun, 25 Aug 2024 12:44:41 +0200 Subject: [PATCH] Developer tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - new tests in xt/ : two still FAIL (see TODO) - move pod tests t → xt - fix MANIFEST issues - move toplevel snippets to sandbox TODO • Re-write Changes to conform CPAN::Changes::Spec • Write tool to generate DBD::Changes.pm frm new Changes • Complete doc coverage --- Changes | 4 + DBI.pm | 9 +- MANIFEST | 4 +- MANIFEST.SKIP | 37 +- Makefile.PL | 338 +++++------ dumpmethods.pl | 49 -- goferperf.pl | 142 ----- lib/DBI/FAQ.pm | 967 -------------------------------- sandbox/dumpmethods.pl | 51 ++ sandbox/goferperf.pl | 148 +++++ t/pod-coverage.t | 8 - t/pod.t | 8 - xt/00_perlversion.t | 35 ++ xt/00_pod.t | 12 + xt/01_pod.t | 10 + t/pod-cm.t => xt/02_pod-spell.t | 0 xt/10_perm.t | 15 + xt/20_kwalitee.t | 39 ++ xt/30_links.t | 10 + xt/40_filenames.t | 13 + xt/50_manifest.t | 10 + xt/60_changelog.t | 12 + xt/README | 2 +- 23 files changed, 568 insertions(+), 1355 deletions(-) delete mode 100644 dumpmethods.pl delete mode 100755 goferperf.pl delete mode 100644 lib/DBI/FAQ.pm create mode 100644 sandbox/dumpmethods.pl create mode 100755 sandbox/goferperf.pl delete mode 100644 t/pod-coverage.t delete mode 100644 t/pod.t create mode 100644 xt/00_perlversion.t create mode 100644 xt/00_pod.t create mode 100644 xt/01_pod.t rename t/pod-cm.t => xt/02_pod-spell.t (100%) create mode 100644 xt/10_perm.t create mode 100644 xt/20_kwalitee.t create mode 100644 xt/30_links.t create mode 100644 xt/40_filenames.t create mode 100644 xt/50_manifest.t create mode 100644 xt/60_changelog.t diff --git a/Changes b/Changes index 3cbaa721..3c552c4c 100644 --- a/Changes +++ b/Changes @@ -6,6 +6,10 @@ DBI::Changes - List of significant changes to the DBI =cut +=head2 Changes in DBI 1.645 - TBD + + • Move developer tests to xt/ + =head2 Changes in DBI 1.644 - 2024-08-23 Update Devel::PPPort, diff --git a/DBI.pm b/DBI.pm index 5127a8b9..ac4ace92 100644 --- a/DBI.pm +++ b/DBI.pm @@ -8286,11 +8286,11 @@ Security, especially the "SQL Injection" attack: =head2 FAQ -See L +See L =head1 AUTHORS -DBI by Tim Bunce, L +DBI by Tim Bunce (1994-2024), The DBI developer group (2024..) This pod text by Tim Bunce, J. Douglas Dunlop, Jonathan Leffler and others. Perl by Larry Wall and the C. @@ -8298,7 +8298,7 @@ Perl by Larry Wall and the C. =head1 COPYRIGHT The DBI module is Copyright (c) 1994-2024 Tim Bunce. Ireland. -All rights reserved. +The DBI developer group (2024-2024) All rights reserved. You may distribute under the terms of either the GNU General Public License or the Artistic License, as specified in the Perl 5.10.0 README file. @@ -8353,8 +8353,7 @@ A couple of specific DBI features have been sponsored by enlightened companies: The development of the swap_inner_handle() method was sponsored by BizRate.com (L) -The development of DBD::Gofer and related modules was sponsored by -Shopzilla.com (L), where I currently work. +The development of DBD::Gofer and related modules was sponsored by Shopzilla.com (L). =head1 CONTRIBUTING diff --git a/MANIFEST b/MANIFEST index 3893f954..a75425cf 100644 --- a/MANIFEST +++ b/MANIFEST @@ -8,6 +8,7 @@ INSTALL LICENSE MANIFEST Makefile.PL The Makefile generator +cpanfile Perl.xs Test harness (currently) for Driver.xst README.md dbd_xsh.h Prototypes for standard Driver.xst interface @@ -22,6 +23,7 @@ dbixs_rev.pl Utility to write dbixs_rev.h ex/perl_dbi_nulls_test.pl A test script for forms of IS NULL qualification in SQL ex/profile.pl A test script for DBI::Profile ex/corogofer.pl A test script for DBD::Gofer::Transport::corostream +ex/unicode_test.pl lib/Bundle/DBI.pm A bundle for automatic installation via CPAN. lib/DBD/DBM.pm A driver for DBM files (uses DBD::File) lib/DBD/ExampleP.pm A very simple example Driver module @@ -118,6 +120,4 @@ t/87gofer_cache.t t/90sql_type_cast.t t/91_store_warning.t t/lib.pl Utility functions for test scripts -t/pod.t -t/pod-coverage.t typemap diff --git a/MANIFEST.SKIP b/MANIFEST.SKIP index bcf3f7cc..c0c3b486 100644 --- a/MANIFEST.SKIP +++ b/MANIFEST.SKIP @@ -1,26 +1,45 @@ ^MANIFEST\. ^Makefile$ +^MYMETA ~$ -^\.aspell\.local\.pws$ ^\.appveyor\.yml +^\.aspell\.local\.pws$ +^\.DS_Store +^\.gdbinit ^\.git ^\.github -^\.gdbinit -^\.DS_Store +^\.releaserc +^_Inline/ +\.bs$ \.html$ +\.log$ \.old$ +\.prev$ +\.prt$ +\.tmp$ +\.xsi$ +\.[co]$ +^appveyor\.yml ^blib/ ^DBI-\d ^dbi.tiddlyspot.com.html +^dbilogstrip$ +^dbiprof$ +^dbiproxy$ +^devel/ ^doc/ ^err/ ^err_ -^_Inline/ +^lib/DBD/Multiplex\.pm +^lib/DBD/Multiplex/Logic/Default\.pm +^make-doc\.pl +^Old/ +^pm_to_blib ^ppport.h$ -^t/z -^t/pod-cm.t +^sandbox/ ^t-mock/ -^devel/ -^Old/ +^t/z ^test_output_*/ -^used_by +^used-by-t/ +^used_by/ +^xt/ diff --git a/Makefile.PL b/Makefile.PL index fc292260..4fcfe91e 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -4,6 +4,7 @@ # $Id$ # # Copyright (c) 1994-2024 Tim Bunce Ireland +# Copyright (c) 2024-2024 DBI team # # See COPYRIGHT section in DBI.pm for usage and distribution rights. @@ -16,7 +17,7 @@ use File::Find; use File::Spec; use strict; -use lib 'lib'; # for use DBI::DBD +use lib "lib"; # for use DBI::DBD use DBI::DBD; $| = 1; @@ -24,21 +25,19 @@ $^W = 1; my $os = $^O; my $osvers = $Config{osvers}; $osvers =~ s/^\s*(\d+\.\d+).*/$1/; # drop sub-sub-version: 2.5.1 -> 2.5 -my $ext_pl = $^O eq 'VMS' ? '.pl' : ''; +my $ext_pl = $^O eq "VMS" ? ".pl" : ""; my $is_developer = ((-d ".svn" || -d ".git") && -f "MANIFEST.SKIP"); $::opt_v = 0; $::opt_thread = $Config{useithreads}; # thread if we can, use "-nothread" to disable $::opt_g = 0; -$::opt_g = 1 if $is_developer && $ENV{LOGNAME} && $ENV{LOGNAME} eq 'timbo'; # it's me! (probably) +$::opt_g = 1 if $is_developer && $ENV{LOGNAME} && $ENV{LOGNAME} eq "timbo"; # it's me! (probably) -GetOptions(qw(v! g! thread!)) - or die "Invalid arguments\n"; +GetOptions (qw(v! g! thread!)) or die "Invalid arguments\n"; -$::opt_g &&= '-g'; # convert to actual string +$::opt_g &&= "-g"; # convert to actual string - -if (($ENV{LANG}||'') =~ m/utf-?8/i) { +if (($ENV{LANG}||"") =~ m/utf-?8/i) { print "\n"; print "*** Your LANG environment variable is set to '$ENV{LANG}'\n"; print "*** This may cause problems for some perl installations.\n"; @@ -47,116 +46,119 @@ if (($ENV{LANG}||'') =~ m/utf-?8/i) { print "*** including the output of 'perl -V'\n"; print "\n"; sleep 1; -} + } my %opts = ( - NAME => 'DBI', - AUTHOR => 'Tim Bunce (dbi-users@perl.org)', - VERSION_FROM => 'DBI.pm', - ABSTRACT_FROM => 'DBI.pm', - MIN_PERL_VERSION => '5.008001', - BUILD_REQUIRES => { - 'ExtUtils::MakeMaker' => '6.48', - 'Test::Simple' => '0.90', - }, - META_MERGE => { - resources => { - repository => 'https://github.com/perl5-dbi/dbi', - MailingList => 'mailto:dbi-dev@perl.org', - license => 'http://dev.perl.org/licenses/', - homepage => 'http://dbi.perl.org/', - IRC => 'irc://irc.perl.org/#dbi', + NAME => "DBI", + AUTHOR => 'DBI team (dbi-users@perl.org)', + VERSION_FROM => "DBI.pm", + ABSTRACT_FROM => "DBI.pm", + MIN_PERL_VERSION => "5.008001", + BUILD_REQUIRES => { + "ExtUtils::MakeMaker" => "6.48", + "Test::Simple" => "0.90", + }, + META_MERGE => { + resources => { + repository => "https://github.com/perl5-dbi/dbi", + MailingList => 'mailto:dbi-dev@perl.org', + license => "http://dev.perl.org/licenses/", + homepage => "http://dbi.perl.org/", + IRC => "irc://irc.perl.org/#dbi", + }, + suggests => { + "RPC::PlServer" => 0.2001, + "Net::Daemon" => 0, + "SQL::Statement" => 1.402, + "Clone" => 0.34, + "MLDBM" => 0, + "DB_File" => 0, + }, + }, + PREREQ_PM => { + $^O eq "MSWin32" + ? ("File::Spec" => 3.31) + : (), }, - suggests => { - 'RPC::PlServer' => 0.2001, - 'Net::Daemon' => 0, - 'SQL::Statement' => 1.402, - 'Clone' => 0.34, - 'MLDBM' => 0, - 'DB_File' => 0, + CONFLICTS => { + "SQL::Statement" => "1.33", + "DBD::AnyData" => "0.110", + "DBD::CSV" => "0.36", + "DBD::RAM" => "0.072", + "DBD::PO" => "2.10", + "DBD::Google" => "0.51", + "DBD::Amazon" => "0.10", }, - }, - PREREQ_PM => { - ( $^O eq 'MSWin32' ? ( 'File::Spec' => 3.31, ) : () ), - }, - CONFLICTS => { - 'SQL::Statement' => '1.33', - 'DBD::AnyData' => '0.110', - 'DBD::CSV' => '0.36', - 'DBD::RAM' => '0.072', - 'DBD::PO' => '2.10', - 'DBD::Google' => '0.51', - 'DBD::Amazon' => '0.10', - }, - LICENSE => 'perl', - EXE_FILES => [ "dbiproxy$ext_pl", "dbiprof$ext_pl", "dbilogstrip$ext_pl" ], - DIR => [ ], - dynamic_lib => { OTHERLDFLAGS => "$::opt_g" }, - clean => { FILES=> "\$(DISTVNAME) Perl.xsi t/zv*_*.t dbi__null_test_tmp* test_output_*" + LICENSE => "perl", + EXE_FILES => [ "dbiproxy$ext_pl", "dbiprof$ext_pl", "dbilogstrip$ext_pl" ], + DIR => [ ], + dynamic_lib => { + OTHERLDFLAGS => "$::opt_g", + }, + clean => { + FILES => "\$(DISTVNAME) Perl.xsi t/zv*_*.t dbi__null_test_tmp* test_output_*" ." dbiproxy$ext_pl dbiprof$ext_pl dbilogstrip$ext_pl dbiproxy.*log dbitrace.log dbi*.prof ndtest.prt" }, - dist => { - DIST_DEFAULT=> 'clean distcheck disttest tardist', - PREOP => '$(MAKE) -f Makefile.old distdir', - COMPRESS => 'gzip -v9', SUFFIX => 'gz', - }, -); -$opts{CAPI} = 'TRUE' if $Config{archname} =~ /-object\b/i; + dist => { + DIST_DEFAULT => "clean distcheck disttest tardist", + PREOP => '$(MAKE) -f Makefile.old distdir', + COMPRESS => "gzip -v9", SUFFIX => "gz", + }, + ); +$opts{CAPI} = "TRUE" if $Config{archname} =~ /-object\b/i; if (my $gccversion = $Config{gccversion}) { # ask gcc to be more pedantic if ($gccversion =~ m/ clang ([0-9][-0-9.]*)/i) { - print "Your perl was compiled with Clang (version $1). As this is not GCC, version checking is skipped.\n"; - # https://clang.llvm.org/docs/DiagnosticsReference.html - $opts{DEFINE} .= ' -W -Wall -Wpointer-arith -Wbad-function-cast'; - $opts{DEFINE} .= ' -Wno-comment -Wno-sign-compare -Wno-cast-qual'; - $opts{DEFINE} .= ' -Wmissing-noreturn -Wno-unused-parameter'; - $opts{DEFINE} .= ' -Wno-compound-token-split-by-macro -Wno-constant-conversion'; - $opts{DEFINE} .= ' -Wno-implicit-const-int-float-conversion'; - if ($is_developer && $::opt_g) { - $opts{DEFINE} .= ' -Wmissing-prototypes'; - } - } else { - warn "WARNING: Your GNU C $gccversion compiler is very old. Please upgrade it and rebuild perl.\n" - if $gccversion =~ m/^\D*(1|2\.[1-8])\b/; - print "Your perl was compiled with gcc (version $Config{gccversion}), okay.\n"; - $gccversion =~ s/[^\d\.]//g; # just a number please - $opts{DEFINE} .= ' -W -Wall -Wpointer-arith -Wbad-function-cast'; - $opts{DEFINE} .= ' -Wno-comment -Wno-sign-compare -Wno-cast-qual'; - $opts{DEFINE} .= ' -Wmissing-noreturn -Wno-unused-parameter' if $gccversion ge "3.0"; - if ($is_developer && $::opt_g) { - $opts{DEFINE} .= ' -DPERL_GCC_PEDANTIC -ansi -pedantic' if $gccversion ge "3.0"; - $opts{DEFINE} .= ' -Wdisabled-optimization -Wformat' if $gccversion ge "3.0"; - $opts{DEFINE} .= ' -Wmissing-prototypes'; - } + print "Your perl was compiled with Clang (version $1). As this is not GCC, version checking is skipped.\n"; + # https://clang.llvm.org/docs/DiagnosticsReference.html + $opts{DEFINE} .= " -W -Wall -Wpointer-arith -Wbad-function-cast"; + $opts{DEFINE} .= " -Wno-comment -Wno-sign-compare -Wno-cast-qual"; + $opts{DEFINE} .= " -Wmissing-noreturn -Wno-unused-parameter"; + $opts{DEFINE} .= " -Wno-compound-token-split-by-macro -Wno-constant-conversion"; + $opts{DEFINE} .= " -Wno-implicit-const-int-float-conversion"; + if ($is_developer && $::opt_g) { + $opts{DEFINE} .= " -Wmissing-prototypes"; + } + } + else { + warn "WARNING: Your GNU C $gccversion compiler is very old. Please upgrade it and rebuild perl.\n" + if $gccversion =~ m/^\D*(1|2\.[1-8])\b/; + print "Your perl was compiled with gcc (version $Config{gccversion}), okay.\n"; + $gccversion =~ s/[^\d\.]//g; # just a number please + $opts{DEFINE} .= " -W -Wall -Wpointer-arith -Wbad-function-cast"; + $opts{DEFINE} .= " -Wno-comment -Wno-sign-compare -Wno-cast-qual"; + $opts{DEFINE} .= " -Wmissing-noreturn -Wno-unused-parameter" if $gccversion ge "3.0"; + if ($is_developer && $::opt_g) { + $opts{DEFINE} .= " -DPERL_GCC_PEDANTIC -ansi -pedantic" if $gccversion ge "3.0"; + $opts{DEFINE} .= " -Wdisabled-optimization -Wformat" if $gccversion ge "3.0"; + $opts{DEFINE} .= " -Wmissing-prototypes"; + } + } } -} -$opts{DEFINE} .= ' -DDBI_NO_THREADS' unless $::opt_thread; +$opts{DEFINE} .= " -DDBI_NO_THREADS" unless $::opt_thread; # HP-UX 9 cannot link a non-PIC object file into a shared library. # Since the # .a libs that Oracle supplies contain non-PIC object # files, we sadly have to build static on HP-UX 9 :( -if ($os eq 'hpux' and $osvers < 10) { - $opts{LINKTYPE} = 'static'; +if ($os eq "hpux" and $osvers < 10) { + $opts{LINKTYPE} = "static"; print "Warning: Forced to build static not dynamic on $os $osvers.\a\n"; print "** Note: DBI will be built *into* a NEW perl binary. You MUST use that new perl.\n"; print " See README and Makefile.PL for more information.\a\n"; -} + } -if ($os eq 'MSWin32' && $Config{libs} =~ /\bPerlCRT.lib\b/ - && -f "$Config{archlib}/CORE/PerlCRT.lib") { +if ($os eq "MSWin32" && $Config{libs} =~ /\bPerlCRT.lib\b/ && -f "$Config{archlib}/CORE/PerlCRT.lib") { # ActiveState Perl needs this; should better be done in MakeMaker, but # as a temporary workaround it seems ok. $opts{LIBS} = "-L$Config{archlib}/CORE"; -} + } # Set aside some values for post_initialize() in package MY -my ( $cfg_privlibexp, $cfg_archlibexp, $cfg_sitelibexp, $cfg_sitearchexp, - $cfg_man3direxp ) = - @Config{qw( privlibexp archlibexp sitelibexp sitearchexp man3direxp ) }; -for ( $cfg_privlibexp, $cfg_archlibexp, $cfg_sitelibexp, $cfg_sitearchexp, - $cfg_man3direxp ) { - $_ = '' unless defined $_; -} +my ($cfg_privlibexp, $cfg_archlibexp, $cfg_sitelibexp, $cfg_sitearchexp, $cfg_man3direxp) = + @Config{qw( privlibexp archlibexp sitelibexp sitearchexp man3direxp )}; +for ($cfg_privlibexp, $cfg_archlibexp, $cfg_sitelibexp, $cfg_sitearchexp, $cfg_man3direxp) { + $_ = "" unless defined $_; + } my $conflictMsg = < 1, +WriteMakefile1 ( + dbd_edit_mm_attribs (\%opts, { + create_pp_tests => 1, create_nano_tests => 1, - create_gap_tests => 1, - }) -); + create_gap_tests => 1, + }) + ); # WriteMakefile call is last thing executed # so return value is propagated - # ===================================================================== package MY; @@ -250,50 +252,59 @@ warn <= 5.024 && -d "xt" && -d "sandbox" && ($ENV{AUTOMATED_TESTING} || 0) != 1) + ? join "\n" => + 'test ::', + ' -@env TEST_FILES="xt/*.t" make -e test_dynamic', + '' + : ""; + + return join "\n" => + $min_vsn; + } # postamble sub libscan { my($self, $path) = @_; ($path =~ /\~$|\B\.(svn|git)\b/) ? undef : $path; -} + } # libscan sub const_cccmd { my $self = shift; - local($_) = $self->SUPER::const_cccmd(@_); + local ($_) = $self->SUPER::const_cccmd (@_); # If perl Makefile.PL *-g* then switch on debugging if ($::opt_g) { s/\s-O\d?\b//; # delete optimise option s/\s-/ -g -/; # add -g option - } + } $_; -} - + } # const_cccmd sub post_initialize { - my($self) = shift; + my $self = shift; if ($cfg_privlibexp ne $cfg_sitelibexp) { # this block could probably be removed now my %old; - File::Find::find( sub { + File::Find::find (sub { local $_ = $File::Find::name; - s:\\:/:g if $os eq 'MSWin32'; + s{\\}{/}g if $os eq "MSWin32"; $File::Find::prune = 1, return - if -d $_ && ( $_ eq $cfg_sitelibexp || - $_ eq $cfg_sitearchexp || - $_ eq $cfg_man3direxp ); - ++$old{$_} if m:\bDB(I|D$):; # DBI files, but just DBD dirs - }, $cfg_privlibexp, $cfg_archlibexp ); - if ( %old ) { - warn " + if -d $_ && ($_ eq $cfg_sitelibexp || + $_ eq $cfg_sitearchexp || + $_ eq $cfg_man3direxp); + ++$old{$_} if m{\bDB(I|D$)}; # DBI files, but just DBD dirs + }, $cfg_privlibexp, $cfg_archlibexp); + if (%old) { + warn " Warning: By default new modules are installed into your 'site_lib' directories. Since site_lib directories come after the normal library directories you must delete old DBI files and directories from your @@ -303,32 +314,31 @@ Reinstall DBI and your DBD::* drivers after deleting the old directories. Here's a list of probable old files and directories: - " . join( "\n ", ( sort keys %old ), "\n" ); + " . join ("\n ", (sort keys %old), "\n" ); + } } - } # install files that DBD's may need - File::Find::find( sub { + File::Find::find (sub { # may be '.' or '[]' depending on File::Find version - $_ = '.' if $^O eq 'VMS' && $_ eq File::Spec->curdir; + $_ = "." if $^O eq "VMS" && $_ eq File::Spec->curdir; - $File::Find::prune = 1, return if -d $_ && '.' ne $_; - $self->{PM}->{$_} = File::Spec->catfile($self->{INST_ARCHAUTODIR}, $_) - if '.h' eq substr( $_, -2 ) || '.xst' eq substr( $_, -4 ); - }, '.' ); + $File::Find::prune = 1, return if -d $_ && "." ne $_; + $self->{PM}->{$_} = File::Spec->catfile ($self->{INST_ARCHAUTODIR}, $_) + if ".h" eq substr ($_, -2) || ".xst" eq substr ($_, -4); + }, "."); delete $self->{$_}{"git-svn-vsn.pl"} for qw( PM MAN3PODS ); - return ''; -} - + return ""; + } # post_initialize sub post_constants { - my($self) = shift; + my $self = shift; # ensure that Driver.xst and related code gets tested - my $xst = main::dbd_postamble(); + my $xst = main::dbd_postamble (); $xst =~ s/\$\(BASEEXT\)/Perl/g; $xst .= ' dbixs_rev.h: DBIXS.h Driver_xst.h dbipport.h dbivport.h dbixs_rev.pl @@ -378,6 +388,6 @@ checkpod: }; return $xst; -} + } # post_constants -# end. +1; diff --git a/dumpmethods.pl b/dumpmethods.pl deleted file mode 100644 index 4e21e29d..00000000 --- a/dumpmethods.pl +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/perl - -package DBI; - -use warnings; - -use Data::Dumper; - -BEGIN { $ENV{DBI_PUREPERL} = 2 } -use DBI; - -no strict qw(subs refs); # build name and code to value mappings introspectively -my @ima_n = grep { /^IMA_.*/ } keys %{"DBI::"}; -warn "@ima_n"; -my %ima_n2v = map { /^(IMA_.*)/ ? ($1=>&$_) : () } @ima_n; -warn Dumper \%ima_n2v; -my %ima_v2n = reverse %ima_n2v; - -my @bit2hex_bitkeys = map { 1<<$_ } 0..31; -my @bit2hex_bitvals = map { sprintf("%s", $ima_v2n{$_}||'') } @bit2hex_bitkeys; -my %bit2hex; @bit2hex{ @bit2hex_bitkeys } = @bit2hex_bitvals; -my @bit2hex_values = ("0x00000000", @bit2hex_bitvals); - -#warn Dumper \%DBI::DBI_methods; -for (0..31) { - my $bit = 1 << $_; - my @ima_flags = map { ($bit & $_) ? $bit2hex{$_} : () } @bit2hex_bitkeys; - printf "%20s => %04x\n", "@ima_flags", $bit; -} - -while ( my ($class, $meths) = each %DBI::DBI_methods ) { - - for my $method (sort keys %$meths) { - my $info = $meths->{$method}; - my $fullmeth = "DBI::${class}::$method"; - - my $proto = $info->{U}[2]; - unless (defined $proto) { - $proto = '$' x ($info->{U}[0]||0); - $proto .= ";" . ('$' x $info->{U}[1]) if $info->{U}[1]; - } - - my $O = $info->{O}||0; - my @ima_flags = map { ($O & $_) ? $bit2hex{$_} : () } @bit2hex_bitkeys; - - printf "\$h->%s(%s) %s # 0x%04x\n", $fullmeth, $proto, "@ima_flags", $O; - } -} - diff --git a/goferperf.pl b/goferperf.pl deleted file mode 100755 index 15cfe29c..00000000 --- a/goferperf.pl +++ /dev/null @@ -1,142 +0,0 @@ -#!/usr/bin/perl -# vim:sw=4:ts=8 -$|=1; - -use strict; -use warnings; - -use Cwd; -use Time::HiRes qw(time); -use Data::Dumper; -use Getopt::Long; - -use DBI; - -GetOptions( - 'c|count=i' => \(my $opt_count = 100), - 'dsn=s' => \(my $opt_dsn), - 'timeout=i' => \(my $opt_timeout = 10), - 'p|policy=s' => \(my $opt_policy = "pedantic,classic,rush"), -) or exit 1; - -if ($ENV{DBI_AUTOPROXY}) { - # this means we have DBD::Gofer => DBD::Gofer => DBD::DBM! - # rather than disable it we let it run because we're twisted - # and because it helps find more bugs (though debugging can be painful) - warn "\n$0 is running with DBI_AUTOPROXY enabled ($ENV{DBI_AUTOPROXY})\n"; -} - -# ensure subprocess (for pipeone and stream transport) will use the same modules as us, ie ./blib -local $ENV{PERL5LIB} = join ":", @INC; - -my %durations; -my $username = eval { getpwuid($>) } || ''; # fails on windows -my $can_ssh = ($username && $username eq 'timbo' && -d '.svn'); -my $perl = "$^X"; # ensure sameperl and our blib (note two spaces) - # ensure blib (note two spaces) - $perl .= sprintf " -Mblib=%s/blib", getcwd() if $ENV{PERL5LIB} =~ m{/blib/}; - -my %trials = ( - null => {}, - null_ha => { DBI => "DBIx::HA" }, - pipeone => { perl=>$perl, timeout=>$opt_timeout }, - stream => { perl=>$perl, timeout=>$opt_timeout }, - stream_ssh => ($can_ssh) - ? { perl=>$perl, timeout=>$opt_timeout, url => "ssh:$username\@localhost" } - : undef, - http => { url => "http://localhost:8001/gofer" }, -); - -# to get baseline for comparisons -run_tests('no', {}, 'no'); - -for my $trial (@ARGV) { - (my $transport = $trial) =~ s/_.*//; - my $trans_attr = $trials{$trial} or do { - warn "No trial '$trial' defined - skipped"; - next; - }; - - for my $policy_name (split /\s*,\s*/, $opt_policy) { - eval { run_tests($transport, $trans_attr, $policy_name) }; - warn $@ if $@; - } -} - -while ( my ($activity, $stats_hash) = each %durations ) { - print "\n"; - $stats_hash->{'~baseline~'} = delete $stats_hash->{"no+no"}; - for my $perf_tag (reverse sort keys %$stats_hash) { - my $dur = $stats_hash->{$perf_tag}; - printf " %6s %-16s: %.6fsec (%5d/sec)", - $activity, $perf_tag, $dur/$opt_count, $opt_count/$dur; - my $baseline_dur = $stats_hash->{'~baseline~'}; - printf " %+6.2fms", (($dur-$baseline_dur)/$opt_count)*1000 - unless $perf_tag eq '~baseline~'; - print "\n"; - } -} - - -sub run_tests { - my ($transport, $trans_attr, $policy_name) = @_; - - my $connect_attr = delete $trans_attr->{connect_attr} || {}; - my $DBI = delete $trans_attr->{DBI} || "DBI"; - _load_class($DBI) if $DBI ne "DBI"; - - my $test_run_tag = "Testing $transport transport with $policy_name policy @{[ %$connect_attr ]}"; - print "\n$test_run_tag\n"; - - my $dsn = $opt_dsn || $trans_attr->{dsn} || "dbi:NullP:"; - if ($policy_name ne 'no') { - my $driver_dsn = "transport=$transport;policy=$policy_name"; - $driver_dsn .= join ";", '', map { "$_=$trans_attr->{$_}" } keys %$trans_attr - if %$trans_attr; - $dsn = "dbi:Gofer:$driver_dsn;dsn=$dsn"; - } - print " $dsn\n"; - - my $dbh = $DBI->connect($dsn, undef, undef, { %$connect_attr, RaiseError => 1 } ); - - $dbh->do("DROP TABLE IF EXISTS fruit"); - $dbh->do("CREATE TABLE fruit (dKey INT, dVal VARCHAR(10))"); - my $ins_sth = $dbh->prepare("INSERT INTO fruit VALUES (?,?)"); - $ins_sth->execute(1, 'apples'); - $ins_sth->execute(2, 'oranges'); - $ins_sth->execute(3, 'lemons'); - $ins_sth->execute(4, 'limes'); - - my $start = time(); - $dbh->selectall_arrayref("SELECT dKey, dVal FROM fruit") - for (1000..1000+$opt_count); - $durations{select}{"$transport+$policy_name"} = time() - $start; - - # insert some rows in to get a (*very* rough) idea of overheads - $start = time(); - $ins_sth->execute($_, 'speed') - for (1000..1000+$opt_count); - $durations{insert}{"$transport+$policy_name"} = time() - $start; - - $dbh->do("DROP TABLE fruit"); - $dbh->disconnect; -} - -sub get_policy { - my ($policy_class) = @_; - $policy_class = "DBD::Gofer::Policy::$policy_class" unless $policy_class =~ /::/; - _load_class($policy_class) or die $@; - return $policy_class->new(); -} - -sub _load_class { # return true or false+$@ - my $class = shift; - (my $pm = $class) =~ s{::}{/}g; - $pm .= ".pm"; - return 1 if eval { require $pm }; - delete $INC{$pm}; # shouldn't be needed (perl bug?) and assigning undef isn't enough - undef; # error in $@ -} - - -1; diff --git a/lib/DBI/FAQ.pm b/lib/DBI/FAQ.pm deleted file mode 100644 index 40e1310d..00000000 --- a/lib/DBI/FAQ.pm +++ /dev/null @@ -1,967 +0,0 @@ -### -### $Id: FAQ.pm 14934 2011-09-14 10:02:25Z Tim $ -### -### DBI Frequently Asked Questions POD -### -### Copyright section reproduced from below. -### -### This document is Copyright (c)1994-2000 Alligator Descartes, with portions -### Copyright (c)1994-2000 their original authors. This module is released under -### the 'Artistic' license which you can find in the perl distribution. -### -### This document is Copyright (c)1997-2000 Alligator Descartes. All rights reserved. -### Permission to distribute this document, in full or in part, via email, -### Usenet, ftp archives or http is granted providing that no charges are involved, -### reasonable attempt is made to use the most current version and all credits -### and copyright notices are retained ( the I and I sections ). -### Requests for other distribution rights, including incorporation into -### commercial products, such as books, magazine articles or CD-ROMs should be -### made to Alligator Descartes. -### -use strict; -use warnings; - -package DBI::FAQ; - -our $VERSION = "1.014935"; - -=head1 NAME - -DBI::FAQ -- The Frequently Asked Questions for the Perl5 Database Interface - -=for html - - -
- -DBI Frequently Asked Questions v.0.38 - -
- -Last updated: February 8th, 2000 - -
-

- -=head1 SYNOPSIS - - perldoc DBI::FAQ - -=head1 VERSION - -This document is currently at version I<0.38>, as of I. - -That's B old. A newer FAQ can be found at L - -Neither this document nor that web site are actively maintained. -Volunteers are welcome. - -=head1 DESCRIPTION - -This document serves to answer the most frequently asked questions on both -the DBI Mailing Lists and personally to members of the DBI development team. - -=head1 Basic Information & Information Sources - -=head2 1.1 What is DBI, DBperl, Oraperl and *perl? - -To quote Tim Bunce, the architect and author of DBI: - - DBI is a database access Application Programming Interface (API) - for the Perl Language. The DBI API Specification defines a set - of functions, variables and conventions that provide a consistent - database interface independent of the actual database being used. - -In simple language, the DBI interface allows users to access multiple database -types transparently. So, if you connecting to an Oracle, Informix, mSQL, Sybase -or whatever database, you don't need to know the underlying mechanics of the -3GL layer. The API defined by DBI will work on I these database types. - -A similar benefit is gained by the ability to connect to two I -databases of different vendor within the one perl script, I, I want -to read data from an Oracle database and insert it back into an Informix -database all within one program. The DBI layer allows you to do this simply -and powerfully. - - -=for html -Here's a diagram that demonstrates the principle: -

-

-[ DBI Architecture ] -
-

- -I is the old name for the interface specification. It's usually -now used to denote perlI<4> modules on database interfacing, such as, -I, I, I and so on. These interfaces -didn't have a standard API and are generally I supported. - -Here's a list of DBperl modules, their corresponding DBI counterparts and -support information. I, the author's listed here generally -I maintain the DBI module for the same database. These email -addresses are unverified and should only be used for queries concerning the -perl4 modules listed below. DBI driver queries should be directed to the -I mailing list. - - Module Name Database Required Author DBI - ----------- ----------------- ------ --- - Sybperl Sybase Michael Peppler DBD::Sybase - - Oraperl Oracle 6 & 7 Kevin Stock DBD::Oracle - - Ingperl Ingres Tim Bunce & DBD::Ingres - Ted Lemon - - Interperl Interbase Buzz Moschetti DBD::Interbase - - Uniperl Unify 5.0 Rick Wargo None - - Pgperl Postgres Igor Metz DBD::Pg - - Btreeperl NDBM John Conover SDBM? - - Ctreeperl C-Tree John Conover None - - Cisamperl Informix C-ISAM Mathias Koerber None - - Duaperl X.500 Directory Eric Douglas None - User Agent - -However, some DBI modules have DBperl emulation layers, so, I -comes with an Oraperl emulation layer, which allows you to run legacy oraperl -scripts without modification. The emulation layer translates the oraperl API -calls into DBI calls and executes them through the DBI switch. - -Here's a table of emulation layer information: - - Module Emulation Layer Status - ------ --------------- ------ - DBD::Oracle Oraperl Complete - DBD::Informix Isqlperl Under development - DBD::Ingres Ingperl Complete? - DBD::Sybase Sybperl Working? ( Needs verification ) - DBD::mSQL Msqlperl Experimentally released with - DBD::mSQL-0.61 - -The I emulation is a special case. I is a perl5 driver -for I databases, but does not conform to the DBI Specification. It's -use is being deprecated in favour of I. I may be downloaded -from CPAN I: - - http://www.perl.com/cgi-bin/cpan_mod?module=Msqlperl - -=head2 1.2. Where can I get it from? - -The Comprehensive Perl Archive Network -resources should be used for retrieving up-to-date versions of the DBI -and drivers. CPAN may be accessed I Tom Christiansen's splendid -I program located at: - - http://www.perl.com/CPAN/ - -For more specific version information and exact URLs of drivers, please see -the DBI drivers list and the DBI module pages which can be found on: - - http://dbi.perl.org/ - -This list is automatically generated on a nightly basis from CPAN and should -be up-to-date. - -=head2 1.3. Where can I get more information? - -There are a few information sources on DBI. - -=over 4 - -=item I<"Programming the Perl DBI"> - -"Programming the Perl DBI" is the I book on the DBI written by -Alligator Descartes and Tim Bunce and published by O'Reilly & Associates. -The book was released on February 9th, 2000. - -The table of contents is: - - Preface - 1. Introduction - From Mainframes to Workstations - Perl - DBI in the Real World - A Historical Interlude and Standing Stones - 2. Basic Non-DBI Databases - Storage Managers and Layers - Query Languages and Data Functions - Standing Stones and the Sample Database - Flat-File Databases - Putting Complex Data into Flat Files - Concurrent Database Access and Locking - DBM Files and the Berkeley Database Manager - The MLDBM Module - Summary - 3. SQL and Relational Databases - The Relational Database Methodology - Datatypes and NULL Values - Querying Data - Modifying Data Within Tables - Creating and Destroying Tables - 4. Programming with the DBI - DBI Architecture - Handles - Data Source Names - Connection and Disconnection - Error Handling - Utility Methods and Functions - 5. Interacting with the Database - Issuing Simple Queries - Executing Non-SELECT Statements - Binding Parameters to Statements - Binding Output Columns - do() Versus prepare() - Atomic and Batch Fetching - 6. Advanced DBI - Handle Attributes and Metadata - Handling LONG/LOB Data - Transactions, Locking, and Isolation - 7. ODBC and the DBI - ODBC -- Embraced and Extended - DBI -- Thrashed and Mutated - The Nuts and Bolts of ODBC - ODBC from Perl - The Marriage of DBI and ODBC - Questions and Choices - Moving Between Win32::ODBC and the DBI - And What About ADO? - 8. DBI Shell and Database Proxying - dbish -- The DBI Shell - Database Proxying - A. DBI Specification - B. Driver and Database Characteristics - C. ASLaN Sacred Site Charter - Index - -The book should be available from all good bookshops and can be ordered online -either via O'Reilly & Associates - - http://www.oreilly.com/catalog/perldbi - -or Amazon - - http://www.amazon.com/exec/obidos/ASIN/1565926994/dbi - -=item I - -Is are chunks of documentation usually embedded within perl programs -that document the code ``I'', providing a useful resource for -programmers and users of modules. POD for DBI and drivers is beginning to -become more commonplace, and documentation for these modules can be read -with the C program included with Perl. - -=over 4 - -=item The DBI Specification - -The POD for the DBI Specification can be read with the: - - perldoc DBI - -command. The Specification also forms Appendix A of "Programming the Perl -DBI". - -=item Oraperl - -Users of the Oraperl emulation layer bundled with I, may read -up on how to program with the Oraperl interface by typing: - - perldoc Oraperl - -This will produce an updated copy of the original oraperl man page written by -Kevin Stock for perl4. The oraperl API is fully listed and described there. - -=item Drivers - -Users of the DBD modules may read about some of the private functions -and quirks of that driver by typing: - - perldoc - -For example, the I driver is bundled with driver-specific -documentation that can be accessed by typing - - perldoc DBD::mSQL - -=item Frequently Asked Questions - -This document, the I is also available as POD -documentation! You can read this on your own system by typing: - - perldoc DBI::FAQ - -This may be more convenient to persons not permanently, or conveniently, -connected to the Internet. The I module should be downloaded and -installed for the more up-to-date version. - -The version of I shipped with the C module may be slightly out -of date. - -=item POD in general - -Information on writing POD, and on the philosophy of POD in general, can be -read by typing: - - perldoc perlpod - -Users with the Tk module installed may be interested to learn there is a -Tk-based POD reader available called C, which formats POD in a convenient -and readable way. This is available I CPAN as the module called -I and is highly recommended. - -=back - -=item I - -The driver summaries that were produced for Appendix B of "Programming the -Perl DBI" are available online at: - - http://dbi.perl.org/ - -in the driver information table. These summaries contain standardised -information on each driver and database which should aid you in selecting -a database to use. It will also inform you quickly of any issues within -drivers or whether a driver is not fully compliant with the DBI Specification. - -=item I - - http://dbi.perl.org/tidbits - -There are a series of occasional rambles from various people on the -DBI mailing lists who, in an attempt to clear up a simple point, end up -drafting fairly comprehensive documents. These are quite often varying in -quality, but do provide some insights into the workings of the interfaces. - -=item I - -A list of articles discussing the DBI can be found on the DBI WWW page at: - - http://dbi.perl.org/ - -These articles are of varying quality and age, from the original Perl Journal -article written by Alligator and Tim, to more recent debacles published online -from about.com. - -=item I - -The I files included with each driver occasionally contains -some useful information ( no, really! ) that may be pertinent to the user. -Please read them. It makes our worthless existences more bearable. These -can all be read from the main DBI WWW page at: - - http://dbi.perl.org/ - -=item I - -There are three mailing lists for DBI: - - dbi-announce@perl.org -- for announcements, very low traffic - dbi-users@perl.org -- general user support - dbi-dev@perl.org -- for driver developers (no user support) - -For information on how to subscribe, set digest mode etc, and unsubscribe, -send an email message (the content will be ignored) to: - - dbi-announce-help@perl.org - dbi-users-help@perl.org - dbi-dev-help@perl.org - -=item I - -=over 4 - -=item I - - http://outside.organic.com/mail-archives/dbi-users/ - -Searchable hypermail archives of the three mailing lists, and some of the -much older traffic have been set up for users to browse. - -=item I - - http://www.rosat.mpe-garching.mpg.de/mailing-lists/PerlDB-Interest - -As per the US archive above. - -=back - -=back - -=head1 Compilation Problems - -=head2 2.1. Compilation problems or "It fails the test!" - -First off, consult the README for that driver in case there is useful -information about the problem. It may be a known problem for your given -architecture and operating system or database. You can check the README -files for each driver in advance online at: - - http://dbi.perl.org/ - -If it's a known problem, you'll probably have to wait till it gets fixed. If -you're I needing it fixed, try the following: - -=over 4 - -=item I - -This technique is generally I recommended to the faint-hearted. -If you do think you have managed to fix it, then, send a patch file -( context diff ) to the author with an explanation of: - -=over 4 - -=item * - -What the problem was, and test cases, if possible. - -=item * - -What you needed to do to fix it. Please make sure you mention everything. - -=item * - -Platform information, database version, perl version, module version and -DBI version. - -=back - -=item I Do I whinge! - -Please email the address listed in the WWW pages for whichever driver you -are having problems with. Do I directly email the author at a -known address unless it corresponds with the one listed. - -We tend to have real jobs to do, and we do read the mailing lists for -problems. Besides, we may not have access to > and couldn't be of any -assistance anyway! Apologies for sounding harsh, but that's the way of it! - -However, you might catch one of these creative genii at 3am when we're -doing this sort of stuff anyway, and get a patch within 5 minutes. The -atmosphere in the DBI circle is that we I appreciate the users' -problems, since we work in similar environments. - -If you are planning to email the author, please furnish as much information -as possible, I: - -=over 4 - -=item * - -I the information asked for in the README file in -the problematic module. And we mean I of it. We don't -put lines like that in documentation for the good of our health, or -to meet obscure README file standards of length. - -=item * - -If you have a core dump, try the I module for -generating a stack trace from the core dump. Send us that too. -I can be found on CPAN at: - - http://www.perl.com/cgi-bin/cpan_mod?module=Devel::CoreStack - -=item * - -Module versions, perl version, test cases, operating system versions -and I. - -=back - -Remember, the more information you send us, the quicker we can track -problems down. If you send us no useful information, expect nothing back. - -Finally, please be aware that some authors, including Tim Bunce, specifically -request that you do I mail them directly. Please respect their wishes and -use the email addresses listed in the appropriate module C file. - -=item I - -It's usually a fairly intelligent idea to I the mailing list -anyway with problems. The authors all read the lists, so you lose nothing -by mailing there. - -=back - -=head1 Platform and Driver Issues - -=head2 3.1 What's the difference between ODBC and DBI? - -In terms of architecture - not much: Both define programming -interfaces. Both allow multiple drivers to be loaded to do the -actual work. - -In terms of ease of use - much: The DBI is a 'high level' interface -that, like Perl itself, strives to make the simple things easy while -still making the hard things possible. The ODBC is a 'low level' -interface. All nuts-bolts-knobs-and-dials. - -Now there's an ODBC driver for the DBI (DBD::ODBC) the "What's the -difference" question is more usefully rephrased as: - -Chapter 7 of "Programming the Perl DBI" covers this topic in far more -detail and should be consulted. - -=head2 3.2 What's the difference between Win32::ODBC and DBD::ODBC? - -The DBI, and thus DBD::ODBC, has a different philosophy from the -Win32::ODBC module: - -The Win32::ODBC module is a 'thin' layer over the low-level ODBC API. -The DBI defines a simpler 'higher level' interface. - -The Win32::ODBC module gives you access to more of the ODBC API. -The DBI and DBD::ODBC give you access to only the essentials. -(But, unlike Win32::ODBC, the DBI and DBD::ODBC do support parameter -binding and multiple prepared statements which reduces the load on -the database server and can dramatically increase performance.) - -The Win32::ODBC module only works on Win32 systems. -The DBI and DBD::ODBC are very portable and work on Win32 and Unix. - -The DBI and DBD::ODBC modules are supplied as a standard part of the -Perl 5.004 binary distribution for Win32 (they don't work with the -older, non-standard, ActiveState port). - -Scripts written with the DBI and DBD::ODBC are faster than Win32::ODBC -on Win32 and are trivially portable to other supported database types. - -The DBI offers optional automatic printing or die()ing on errors which -makes applications simpler and more robust. - -The current DBD::ODBC driver version 0.16 is new and not yet fully stable. -A new release is due soon [relative to the date of the next TPJ issue :-] -and will be much improved and offer more ODBC functionality. - -To summarise: The Win32::ODBC module is your best choice if you need -access to more of the ODBC API than the DBI gives you. Otherwise, the -DBI and DBD::ODBC combination may be your best bet. - -Chapter 7 of "Programming the Perl DBI" covers this topic in far more -detail and should be consulted. - -=head2 3.3 Is DBI supported under Windows 95 / NT platforms? - -Finally, yes! Jeff Urlwin has been working diligently on building -I and I under these platforms, and, with the -advent of a stabler perl and a port of I, the project has -come on by great leaps and bounds. - -The I and I Win32 ports are now a standard part of DBI, -so, downloading I of version higher than I<0.81> should work fine as -should using the most recent I version. - -=head2 3.4 Can I access Microsoft Access or SQL-Server databases with DBI? - -Yes, use the I driver. - -=head2 3.5 Is there a DBD for >? - -First check if a driver is available on CPAN by searching for the name of the -database (including common abbreviations and aliases). - -Here's a general query that'll match all distributions: - - http://search.cpan.org/search?query=DBD&mode=dist - -If you can't find a driver that way, you could check if the database supports -ODBC drivers. If so then you could probably use the DBD::ODBC driver: - - http://search.cpan.org/dist/DBD-ODBC/ - -If not, then try asking on the dbi-users mailing list. - -=head2 3.6 What's DBM? And why should I use DBI instead? - -Extracted from ``I'': - - ``UNIX was originally blessed with simple file-based ``databases'', namely - the dbm system. dbm lets you store data in files, and retrieve - that data quickly. However, it also has serious drawbacks. - - File Locking - - The dbm systems did not allow particularly robust file locking - capabilities, nor any capability for correcting problems arising through - simultaneous writes [ to the database ]. - - Arbitrary Data Structures - - The dbm systems only allows a single fixed data structure: - key-value pairs. That value could be a complex object, such as a - [ C ] struct, but the key had to be unique. This was a large - limitation on the usefulness of dbm systems. - - However, dbm systems still provide a useful function for users with - simple datasets and limited resources, since they are fast, robust and - extremely well-tested. Perl modules to access dbm systems have now - been integrated into the core Perl distribution via the - AnyDBM_File module.'' - -To sum up, DBM is a perfectly satisfactory solution for essentially read-only -databases, or small and simple datasets. However, for more -scalable dataset handling, not to mention robust transactional locking, -users are recommended to use a more powerful database engine I I. - -Chapter 2 of "Programming the Perl DBI" discusses DBM files in detail. - -=head2 3.7 What database do you recommend me using? - -This is a particularly thorny area in which an objective answer is difficult -to come by, since each dataset, proposed usage and system configuration -differs from person to person. - -From the current author's point of view, if the dataset is relatively -small, being tables of less than 1 million rows, and less than 1000 tables -in a given database, then I is a perfectly acceptable solution -to your problem. This database is extremely cheap, is wonderfully robust -and has excellent support. More information is available on the Hughes -Technology WWW site at: - - http://www.hughes.com.au - -You may also wish to look at MySQL which is a more powerful database engine -that has a similar feel to mSQL. - - http://www.tcx.se - -If the dataset is larger than 1 million row tables or 1000 tables, or if you -have either more money, or larger machines, I would recommend I. -Oracle's WWW site is an excellent source of more information. - - http://www.oracle.com - -I is another high-end RDBMS that is worth considering. There are -several differences between Oracle and Informix which are too complex for -this document to detail. Information on Informix can be found on their -WWW site at: - - http://www.informix.com - -In the case of WWW fronted applications, I may be a better option -due to slow connection times between a CGI script and the Oracle RDBMS and -also the amount of resource each Oracle connection will consume. I -is lighter resource-wise and faster. - -These views are not necessarily representative of anyone else's opinions, -and do not reflect any corporate sponsorship or views. They are provided -I. - -=head2 3.8 Is > supported in DBI? - -Given that we're making the assumption that the feature you have requested -is a non-standard database-specific feature, then the answer will be I. - -DBI reflects a I API that will work for most databases, and has -no database-specific functionality. - -However, driver authors may, if they so desire, include hooks to database-specific -functionality through the C method defined in the DBI API. -Script developers should note that use of functionality provided I -the C methods is very unlikely to be portable across databases. - -=head1 Programming Questions - -=head2 4.1 Is DBI any use for CGI programming? - -In a word, yes! DBI is hugely useful for CGI programming! In fact, I would -tentatively say that CGI programming is one of two top uses for DBI. - -DBI confers the ability to CGI programmers to power WWW-fronted databases -to their users, which provides users with vast quantities of ordered -data to play with. DBI also provides the possibility that, if a site is -receiving far too much traffic than their database server can cope with, they -can upgrade the database server behind the scenes with no alterations to -the CGI scripts. - -=head2 4.2 How do I get faster connection times with DBD::Oracle and CGI? - - Contributed by John D. Groenveld - -The Apache C maintains a pool of C children to service client -requests. - -Using the Apache I module by I, the perl -interpreter is embedded with the C children. The CGI, DBI, and your -other favorite modules can be loaded at the startup of each child. These -modules will not be reloaded unless changed on disk. - -For more information on Apache, see the Apache Project's WWW site: - - http://www.apache.org - -The I module can be downloaded from CPAN I: - - http://www.perl.com/cgi-bin/cpan_mod?module=Apache - -=head2 4.3 How do I get persistent connections with DBI and CGI? - - Contributed by John D. Groenveld - -Using Edmund Mergl's I module, database logins are stored in a -hash with each of these C child. If your application is based on a -single database user, this connection can be started with each child. -Currently, database connections cannot be shared between C children. - -I can be downloaded from CPAN I: - - http://www.perl.com/cgi-bin/cpan_mod?module=Apache::DBI - -=head2 4.4 ``When I run a perl script from the command line, it works, but, when I run it under the C, it fails!'' Why? - -Basically, a good chance this is occurring is due to the fact that the user -that you ran it from the command line as has a correctly configured set of -environment variables, in the case of I, variables like -C, C or C. - -The C process usually runs under the user id of C, -which implies there is no configured environment. Any scripts attempting to -execute in this situation will correctly fail. - -One way to solve this problem is to set the environment for your database in a -C block at the top of your script. Another technique is to configure -your WWW server to pass-through certain environment variables to your CGI -scripts. - -Similarly, you should check your C error logfile for any clues, -as well as the ``Idiot's Guide To Solving Perl / CGI Problems'' and -``Perl CGI Programming FAQ'' for further information. It is -unlikely the problem is DBI-related. - -The ``Idiot's Guide To Solving Perl / CGI Problems'' can be located at: - - http://www.perl.com/perl/faq/index.html - -as can the ``Perl CGI Programming FAQ''. Read I these documents -carefully! - -=head2 4.5 How do I get the number of rows returned from a C