File Coverage

inc/DBI.pm
Criterion Covered Total %
statement 19 27 70.3
branch 1 6 16.6
condition 0 5 0.0
subroutine 5 5 100.0
pod n/a
total 25 43 58.1


line stmt bran cond sub pod time code
1             #line 1
2             # $Id: DBI.pm 14568 2010-12-14 15:23:58Z mjevans $
3             # vim: ts=8:sw=4:et
4             #
5             # Copyright (c) 1994-2010 Tim Bunce Ireland
6             #
7             # See COPYRIGHT section in pod text below for usage and distribution rights.
8             #
9              
10             require 5.008_001;
11              
12 2     2   58 BEGIN {
13             $DBI::VERSION = "1.616"; # ==> ALSO update the version in the pod text below!
14             }
15              
16             #line 152
17              
18             # The POD text continues at the end of the file.
19              
20              
21             package DBI;
22              
23             use Carp();
24             use DynaLoader ();
25             use Exporter ();
26              
27             BEGIN {
28             @ISA = qw(Exporter DynaLoader);
29              
30             # Make some utility functions available if asked for
31             @EXPORT = (); # we export nothing by default
32             @EXPORT_OK = qw(%DBI %DBI_methods hash); # also populated by export_ok_tags:
33             %EXPORT_TAGS = (
34             sql_types => [ qw(
35             SQL_GUID
36             SQL_WLONGVARCHAR
37             SQL_WVARCHAR
38             SQL_WCHAR
39             SQL_BIGINT
40             SQL_BIT
41             SQL_TINYINT
42             SQL_LONGVARBINARY
43             SQL_VARBINARY
44             SQL_BINARY
45             SQL_LONGVARCHAR
46             SQL_UNKNOWN_TYPE
47             SQL_ALL_TYPES
48             SQL_CHAR
49             SQL_NUMERIC
50             SQL_DECIMAL
51             SQL_INTEGER
52             SQL_SMALLINT
53             SQL_FLOAT
54             SQL_REAL
55             SQL_DOUBLE
56             SQL_DATETIME
57             SQL_DATE
58             SQL_INTERVAL
59             SQL_TIME
60             SQL_TIMESTAMP
61             SQL_VARCHAR
62             SQL_BOOLEAN
63             SQL_UDT
64             SQL_UDT_LOCATOR
65             SQL_ROW
66             SQL_REF
67             SQL_BLOB
68             SQL_BLOB_LOCATOR
69             SQL_CLOB
70             SQL_CLOB_LOCATOR
71             SQL_ARRAY
72             SQL_ARRAY_LOCATOR
73             SQL_MULTISET
74             SQL_MULTISET_LOCATOR
75             SQL_TYPE_DATE
76             SQL_TYPE_TIME
77             SQL_TYPE_TIMESTAMP
78             SQL_TYPE_TIME_WITH_TIMEZONE
79             SQL_TYPE_TIMESTAMP_WITH_TIMEZONE
80             SQL_INTERVAL_YEAR
81             SQL_INTERVAL_MONTH
82             SQL_INTERVAL_DAY
83             SQL_INTERVAL_HOUR
84             SQL_INTERVAL_MINUTE
85             SQL_INTERVAL_SECOND
86             SQL_INTERVAL_YEAR_TO_MONTH
87             SQL_INTERVAL_DAY_TO_HOUR
88             SQL_INTERVAL_DAY_TO_MINUTE
89             SQL_INTERVAL_DAY_TO_SECOND
90             SQL_INTERVAL_HOUR_TO_MINUTE
91             SQL_INTERVAL_HOUR_TO_SECOND
92             SQL_INTERVAL_MINUTE_TO_SECOND
93             DBIstcf_DISCARD_STRING
94             DBIstcf_STRICT
95             ) ],
96             sql_cursor_types => [ qw(
97             SQL_CURSOR_FORWARD_ONLY
98             SQL_CURSOR_KEYSET_DRIVEN
99             SQL_CURSOR_DYNAMIC
100             SQL_CURSOR_STATIC
101             SQL_CURSOR_TYPE_DEFAULT
102             ) ], # for ODBC cursor types
103             utils => [ qw(
104             neat neat_list $neat_maxlen dump_results looks_like_number
105             data_string_diff data_string_desc data_diff sql_type_cast
106             ) ],
107             profile => [ qw(
108             dbi_profile dbi_profile_merge dbi_profile_merge_nodes dbi_time
109             ) ], # notionally "in" DBI::Profile and normally imported from there
110             );
111              
112             $DBI::dbi_debug = 0;
113             $DBI::neat_maxlen = 1000;
114             $DBI::stderr = 2_000_000_000; # a very round number below 2**31
115              
116             # If you get an error here like "Can't find loadable object ..."
117             # then you haven't installed the DBI correctly. Read the README
118             # then install it again.
119             if ( $ENV{DBI_PUREPERL} ) {
120             eval { bootstrap DBI } if $ENV{DBI_PUREPERL} == 1;
121             require DBI::PurePerl if $@ or $ENV{DBI_PUREPERL} >= 2;
122             $DBI::PurePerl ||= 0; # just to silence "only used once" warnings
123             }
124             else {
125             bootstrap DBI;
126             }
127              
128             $EXPORT_TAGS{preparse_flags} = [ grep { /^DBIpp_\w\w_/ } keys %{__PACKAGE__."::"} ];
129              
130             Exporter::export_ok_tags(keys %EXPORT_TAGS);
131              
132             }
133              
134             # Alias some handle methods to also be DBI class methods
135             for (qw(trace_msg set_err parse_trace_flag parse_trace_flags)) {
136             no strict;
137             *$_ = \&{"DBD::_::common::$_"};
138             }
139              
140             use strict;
141              
142             DBI->trace(split /=/, $ENV{DBI_TRACE}, 2) if $ENV{DBI_TRACE};
143              
144             $DBI::connect_via ||= "connect";
145              
146             # check if user wants a persistent database connection ( Apache + mod_perl )
147             if ($INC{'Apache/DBI.pm'} && $ENV{MOD_PERL}) {
148             $DBI::connect_via = "Apache::DBI::connect";
149             DBI->trace_msg("DBI connect via $DBI::connect_via in $INC{'Apache/DBI.pm'}\n");
150             }
151              
152             # check for weaken support, used by ChildHandles
153             my $HAS_WEAKEN = eval {
154             require Scalar::Util;
155             # this will croak() if this Scalar::Util doesn't have a working weaken().
156             Scalar::Util::weaken( \my $test ); # same test as in t/72childhandles.t
157             1;
158 2     2   10 };
  2         4  
  2         28  
159 2     2   9  
  2         4  
  2         38  
160 2     2   15 %DBI::installed_drh = (); # maps driver names to installed driver handles
  2         9  
  2         718  
161             sub installed_drivers { %DBI::installed_drh }
162             %DBI::installed_methods = (); # XXX undocumented, may change
163 2     2   38 sub installed_methods { %DBI::installed_methods }
164              
165             # Setup special DBI dynamic variables. See DBI::var::FETCH for details.
166 2         4 # These are dynamically associated with the last handle used.
167 2         6 tie $DBI::err, 'DBI::var', '*err'; # special case: referenced via IHA list
168 2         66 tie $DBI::state, 'DBI::var', '"state'; # special case: referenced via IHA list
169             tie $DBI::lasth, 'DBI::var', '!lasth'; # special case: return boolean
170             tie $DBI::errstr, 'DBI::var', '&errstr'; # call &errstr in last used pkg
171             tie $DBI::rows, 'DBI::var', '&rows'; # call &rows in last used pkg
172             sub DBI::var::TIESCALAR{ my $var = $_[1]; bless \$var, 'DBI::var'; }
173             sub DBI::var::STORE { Carp::croak("Can't modify \$DBI::${$_[0]} special variable") }
174              
175             { # used to catch DBI->{Attrib} mistake
176             sub DBI::DBI_tie::TIEHASH { bless {} }
177             sub DBI::DBI_tie::STORE { Carp::carp("DBI->{$_[1]} is invalid syntax (you probably want \$h->{$_[1]})");}
178             *DBI::DBI_tie::FETCH = \&DBI::DBI_tie::STORE;
179             }
180             tie %DBI::DBI => 'DBI::DBI_tie';
181              
182             # --- Driver Specific Prefix Registry ---
183              
184             my $dbd_prefix_registry = {
185             ad_ => { class => 'DBD::AnyData', },
186             ado_ => { class => 'DBD::ADO', },
187             amzn_ => { class => 'DBD::Amazon', },
188             best_ => { class => 'DBD::BestWins', },
189             csv_ => { class => 'DBD::CSV', },
190             db2_ => { class => 'DBD::DB2', },
191             dbi_ => { class => 'DBI', },
192             dbm_ => { class => 'DBD::DBM', },
193             df_ => { class => 'DBD::DF', },
194             f_ => { class => 'DBD::File', },
195             file_ => { class => 'DBD::TextFile', },
196             go_ => { class => 'DBD::Gofer', },
197             ib_ => { class => 'DBD::InterBase', },
198             ing_ => { class => 'DBD::Ingres', },
199             ix_ => { class => 'DBD::Informix', },
200             jdbc_ => { class => 'DBD::JDBC', },
201             monetdb_ => { class => 'DBD::monetdb', },
202             msql_ => { class => 'DBD::mSQL', },
203             mvsftp_ => { class => 'DBD::MVS_FTPSQL', },
204             mysql_ => { class => 'DBD::mysql', },
205             mx_ => { class => 'DBD::Multiplex', },
206             nullp_ => { class => 'DBD::NullP', },
207             odbc_ => { class => 'DBD::ODBC', },
208             ora_ => { class => 'DBD::Oracle', },
209             pg_ => { class => 'DBD::Pg', },
210             pgpp_ => { class => 'DBD::PgPP', },
211             plb_ => { class => 'DBD::Plibdata', },
212             po_ => { class => 'DBD::PO', },
213             proxy_ => { class => 'DBD::Proxy', },
214             ram_ => { class => 'DBD::RAM', },
215             rdb_ => { class => 'DBD::RDB', },
216             sapdb_ => { class => 'DBD::SAP_DB', },
217             solid_ => { class => 'DBD::Solid', },
218             sponge_ => { class => 'DBD::Sponge', },
219             sql_ => { class => 'DBI::DBD::SqlEngine', },
220             sqlite_ => { class => 'DBD::SQLite', },
221             syb_ => { class => 'DBD::Sybase', },
222             sys_ => { class => 'DBD::Sys', },
223             tdat_ => { class => 'DBD::Teradata', },
224             tmpl_ => { class => 'DBD::Template', },
225             tmplss_ => { class => 'DBD::TemplateSS', },
226             tuber_ => { class => 'DBD::Tuber', },
227             uni_ => { class => 'DBD::Unify', },
228             vt_ => { class => 'DBD::Vt', },
229             wmi_ => { class => 'DBD::WMI', },
230             x_ => { }, # for private use
231             xbase_ => { class => 'DBD::XBase', },
232             xl_ => { class => 'DBD::Excel', },
233             yaswi_ => { class => 'DBD::Yaswi', },
234             };
235              
236             my %dbd_class_registry = map { $dbd_prefix_registry->{$_}->{class} => { prefix => $_ } }
237             grep { exists $dbd_prefix_registry->{$_}->{class} }
238             keys %{$dbd_prefix_registry};
239              
240             sub dump_dbd_registry {
241             require Data::Dumper;
242             local $Data::Dumper::Sortkeys=1;
243             local $Data::Dumper::Indent=1;
244             print Data::Dumper->Dump([$dbd_prefix_registry], [qw($dbd_prefix_registry)]);
245             }
246              
247 2         4 # --- Dynamically create the DBI Standard Interface
248 2         2  
249 2         4 my $keeperr = { O=>0x0004 };
250              
251             %DBI::DBI_methods = ( # Define the DBI interface methods per class:
252              
253             common => { # Interface methods common to all DBI handle classes
254 2 50       9 'DESTROY' => { O=>0x004|0x10000 },
255 0 0       0 'CLEAR' => $keeperr,
  0         0  
256 0 0 0     0 'EXISTS' => $keeperr,
257 0   0     0 'FETCH' => { O=>0x0404 },
258             'FETCH_many' => { O=>0x0404 },
259             'FIRSTKEY' => $keeperr,
260 2         1568 'NEXTKEY' => $keeperr,
261             'STORE' => { O=>0x0418 | 0x4 },
262             _not_impl => undef,
263 0           can => { O=>0x0100 }, # special case, see dispatch
  0            
  0            
264             debug => { U =>[1,2,'[$debug_level]'], O=>0x0004 }, # old name for trace
265 0           dump_handle => { U =>[1,3,'[$message [, $level]]'], O=>0x0004 },
266             err => $keeperr,
267             errstr => $keeperr,
268             state => $keeperr,
269             func => { O=>0x0006 },
270             parse_trace_flag => { U =>[2,2,'$name'], O=>0x0404, T=>8 },
271             parse_trace_flags => { U =>[2,2,'$flags'], O=>0x0404, T=>8 },
272             private_data => { U =>[1,1], O=>0x0004 },
273             set_err => { U =>[3,6,'$err, $errmsg [, $state, $method, $rv]'], O=>0x0010 },
274             trace => { U =>[1,3,'[$trace_level, [$filename]]'], O=>0x0004 },
275             trace_msg => { U =>[2,3,'$message_text [, $min_level ]' ], O=>0x0004, T=>8 },
276             swap_inner_handle => { U =>[2,3,'$h [, $allow_reparent ]'] },
277             private_attribute_info => { },
278             visit_child_handles => { U => [2,3,'$coderef [, $info ]'], O=>0x0404, T=>4 },
279             },
280             dr => { # Database Driver Interface
281             'connect' => { U =>[1,5,'[$db [,$user [,$passwd [,\%attr]]]]'], H=>3, O=>0x8000 },
282             'connect_cached'=>{U=>[1,5,'[$db [,$user [,$passwd [,\%attr]]]]'], H=>3, O=>0x8000 },
283             'disconnect_all'=>{ U =>[1,1], O=>0x0800 },
284             data_sources => { U =>[1,2,'[\%attr]' ], O=>0x0800 },
285             default_user => { U =>[3,4,'$user, $pass [, \%attr]' ] },
286             dbixs_revision => $keeperr,
287             },
288             db => { # Database Session Class Interface
289             data_sources => { U =>[1,2,'[\%attr]' ], O=>0x0200 },
290             take_imp_data => { U =>[1,1], O=>0x10000 },
291             clone => { U =>[1,2,'[\%attr]'] },
292             connected => { U =>[1,0], O => 0x0004 },
293             begin_work => { U =>[1,2,'[ \%attr ]'], O=>0x0400 },
294             commit => { U =>[1,1], O=>0x0480|0x0800 },
295             rollback => { U =>[1,1], O=>0x0480|0x0800 },
296             'do' => { U =>[2,0,'$statement [, \%attr [, @bind_params ] ]'], O=>0x3200 },
297             last_insert_id => { U =>[5,6,'$catalog, $schema, $table_name, $field_name [, \%attr ]'], O=>0x2800 },
298             preparse => { }, # XXX
299             prepare => { U =>[2,3,'$statement [, \%attr]'], O=>0xA200 },
300             prepare_cached => { U =>[2,4,'$statement [, \%attr [, $if_active ] ]'], O=>0xA200 },
301             selectrow_array => { U =>[2,0,'$statement [, \%attr [, @bind_params ] ]'], O=>0x2000 },
302             selectrow_arrayref=>{U =>[2,0,'$statement [, \%attr [, @bind_params ] ]'], O=>0x2000 },
303             selectrow_hashref=>{ U =>[2,0,'$statement [, \%attr [, @bind_params ] ]'], O=>0x2000 },
304             selectall_arrayref=>{U =>[2,0,'$statement [, \%attr [, @bind_params ] ]'], O=>0x2000 },
305             selectall_hashref=>{ U =>[3,0,'$statement, $keyfield [, \%attr [, @bind_params ] ]'], O=>0x2000 },
306             selectcol_arrayref=>{U =>[2,0,'$statement [, \%attr [, @bind_params ] ]'], O=>0x2000 },
307             ping => { U =>[1,1], O=>0x0404 },
308             disconnect => { U =>[1,1], O=>0x0400|0x0800|0x10000 },
309             quote => { U =>[2,3, '$string [, $data_type ]' ], O=>0x0430 },
310             quote_identifier=> { U =>[2,6, '$name [, ...] [, \%attr ]' ], O=>0x0430 },
311             rows => $keeperr,
312              
313             tables => { U =>[1,6,'$catalog, $schema, $table, $type [, \%attr ]' ], O=>0x2200 },
314             table_info => { U =>[1,6,'$catalog, $schema, $table, $type [, \%attr ]' ], O=>0x2200|0x8800 },
315             column_info => { U =>[5,6,'$catalog, $schema, $table, $column [, \%attr ]'],O=>0x2200|0x8800 },
316             primary_key_info=> { U =>[4,5,'$catalog, $schema, $table [, \%attr ]' ], O=>0x2200|0x8800 },
317             primary_key => { U =>[4,5,'$catalog, $schema, $table [, \%attr ]' ], O=>0x2200 },
318             foreign_key_info=> { U =>[7,8,'$pk_catalog, $pk_schema, $pk_table, $fk_catalog, $fk_schema, $fk_table [, \%attr ]' ], O=>0x2200|0x8800 },
319             statistics_info => { U =>[6,7,'$catalog, $schema, $table, $unique_only, $quick, [, \%attr ]' ], O=>0x2200|0x8800 },
320             type_info_all => { U =>[1,1], O=>0x2200|0x0800 },
321             type_info => { U =>[1,2,'$data_type'], O=>0x2200 },
322             get_info => { U =>[2,2,'$info_type'], O=>0x2200|0x0800 },
323             },
324             st => { # Statement Class Interface
325             bind_col => { U =>[3,4,'$column, \\$var [, \%attr]'] },
326             bind_columns => { U =>[2,0,'\\$var1 [, \\$var2, ...]'] },
327             bind_param => { U =>[3,4,'$parameter, $var [, \%attr]'] },
328             bind_param_inout=> { U =>[4,5,'$parameter, \\$var, $maxlen, [, \%attr]'] },
329             execute => { U =>[1,0,'[@args]'], O=>0x1040 },
330              
331             bind_param_array => { U =>[3,4,'$parameter, $var [, \%attr]'] },
332             bind_param_inout_array => { U =>[4,5,'$parameter, \\@var, $maxlen, [, \%attr]'] },
333             execute_array => { U =>[2,0,'\\%attribs [, @args]'], O=>0x1040|0x4000 },
334             execute_for_fetch => { U =>[2,3,'$fetch_sub [, $tuple_status]'], O=>0x1040|0x4000 },
335              
336             fetch => undef, # alias for fetchrow_arrayref
337             fetchrow_arrayref => undef,
338             fetchrow_hashref => undef,
339             fetchrow_array => undef,
340             fetchrow => undef, # old alias for fetchrow_array
341              
342             fetchall_arrayref => { U =>[1,3, '[ $slice [, $max_rows]]'] },
343             fetchall_hashref => { U =>[2,2,'$key_field'] },
344              
345             blob_read => { U =>[4,5,'$field, $offset, $len [, \\$buf [, $bufoffset]]'] },
346             blob_copy_to_file => { U =>[3,3,'$field, $filename_or_handleref'] },
347             dump_results => { U =>[1,5,'$maxfieldlen, $linesep, $fieldsep, $filehandle'] },
348             more_results => { U =>[1,1] },
349             finish => { U =>[1,1] },
350             cancel => { U =>[1,1], O=>0x0800 },
351             rows => $keeperr,
352              
353             _get_fbav => undef,
354             _set_fbav => { T=>6 },
355             },
356             );
357              
358             while ( my ($class, $meths) = each %DBI::DBI_methods ) {
359             my $ima_trace = 0+($ENV{DBI_IMA_TRACE}||0);
360             while ( my ($method, $info) = each %$meths ) {
361             my $fullmeth = "DBI::${class}::$method";
362             if ($DBI::dbi_debug >= 15) { # quick hack to list DBI methods
363             # and optionally filter by IMA flags
364             my $O = $info->{O}||0;
365             printf "0x%04x %-20s\n", $O, $fullmeth
366             unless $ima_trace && !($O & $ima_trace);
367             }
368             DBI->_install_method($fullmeth, 'DBI.pm', $info);
369             }
370             }
371              
372             {
373             package DBI::common;
374             @DBI::dr::ISA = ('DBI::common');
375             @DBI::db::ISA = ('DBI::common');
376             @DBI::st::ISA = ('DBI::common');
377             }
378              
379             # End of init code
380              
381              
382             END {
383             return unless defined &DBI::trace_msg; # return unless bootstrap'd ok
384             local ($!,$?);
385             DBI->trace_msg(sprintf(" -- DBI::END (\$\@: %s, \$!: %s)\n", $@||'', $!||''), 2);
386             # Let drivers know why we are calling disconnect_all:
387             $DBI::PERL_ENDING = $DBI::PERL_ENDING = 1; # avoid typo warning
388             DBI->disconnect_all() if %DBI::installed_drh;
389             }
390              
391              
392             sub CLONE {
393             my $olddbis = $DBI::_dbistate;
394             _clone_dbis() unless $DBI::PurePerl; # clone the DBIS structure
395             DBI->trace_msg(sprintf "CLONE DBI for new thread %s\n",
396             $DBI::PurePerl ? "" : sprintf("(dbis %x -> %x)",$olddbis, $DBI::_dbistate));
397             while ( my ($driver, $drh) = each %DBI::installed_drh) {
398             no strict 'refs';
399             next if defined &{"DBD::${driver}::CLONE"};
400             warn("$driver has no driver CLONE() function so is unsafe threaded\n");
401             }
402             %DBI::installed_drh = (); # clear loaded drivers so they have a chance to reinitialize
403             }
404              
405             sub parse_dsn {
406             my ($class, $dsn) = @_;
407             $dsn =~ s/^(dbi):(\w*?)(?:\((.*?)\))?://i or return;
408             my ($scheme, $driver, $attr, $attr_hash) = (lc($1), $2, $3);
409             $driver ||= $ENV{DBI_DRIVER} || '';
410             $attr_hash = { split /\s*=>?\s*|\s*,\s*/, $attr, -1 } if $attr;
411             return ($scheme, $driver, $attr, $attr_hash, $dsn);
412             }
413              
414             sub visit_handles {
415             my ($class, $code, $outer_info) = @_;
416             $outer_info = {} if not defined $outer_info;
417             my %drh = DBI->installed_drivers;
418             for my $h (values %drh) {
419             my $child_info = $code->($h, $outer_info)
420             or next;
421             $h->visit_child_handles($code, $child_info);
422             }
423             return $outer_info;
424             }
425              
426              
427             # --- The DBI->connect Front Door methods
428              
429             sub connect_cached {
430             # For library code using connect_cached() with mod_perl
431             # we redirect those calls to Apache::DBI::connect() as well
432             my ($class, $dsn, $user, $pass, $attr) = @_;
433             my $dbi_connect_method = ($DBI::connect_via eq "Apache::DBI::connect")
434             ? 'Apache::DBI::connect' : 'connect_cached';
435             $attr = {
436             $attr ? %$attr : (), # clone, don't modify callers data
437             dbi_connect_method => $dbi_connect_method,
438             };
439             return $class->connect($dsn, $user, $pass, $attr);
440             }
441              
442             sub connect {
443             my $class = shift;
444             my ($dsn, $user, $pass, $attr, $old_driver) = my @orig_args = @_;
445             my $driver;
446              
447             if ($attr and !ref($attr)) { # switch $old_driver<->$attr if called in old style
448             Carp::carp("DBI->connect using 'old-style' syntax is deprecated and will be an error in future versions");
449             ($old_driver, $attr) = ($attr, $old_driver);
450             }
451              
452             my $connect_meth = $attr->{dbi_connect_method};
453             $connect_meth ||= $DBI::connect_via; # fallback to default
454              
455             $dsn ||= $ENV{DBI_DSN} || $ENV{DBI_DBNAME} || '' unless $old_driver;
456              
457             if ($DBI::dbi_debug) {
458             local $^W = 0;
459             pop @_ if $connect_meth ne 'connect';
460             my @args = @_; $args[2] = '****'; # hide password
461             DBI->trace_msg(" -> $class->$connect_meth(".join(", ",@args).")\n");
462             }
463             Carp::croak('Usage: $class->connect([$dsn [,$user [,$passwd [,\%attr]]]])')
464             if (ref $old_driver or ($attr and not ref $attr) or ref $pass);
465              
466             # extract dbi:driver prefix from $dsn into $1
467             $dsn =~ s/^dbi:(\w*?)(?:\((.*?)\))?://i
468             or '' =~ /()/; # ensure $1 etc are empty if match fails
469             my $driver_attrib_spec = $2 || '';
470              
471             # Set $driver. Old style driver, if specified, overrides new dsn style.
472             $driver = $old_driver || $1 || $ENV{DBI_DRIVER}
473             or Carp::croak("Can't connect to data source '$dsn' "
474             ."because I can't work out what driver to use "
475             ."(it doesn't seem to contain a 'dbi:driver:' prefix "
476             ."and the DBI_DRIVER env var is not set)");
477              
478             my $proxy;
479             if ($ENV{DBI_AUTOPROXY} && $driver ne 'Proxy' && $driver ne 'Sponge' && $driver ne 'Switch') {
480             my $dbi_autoproxy = $ENV{DBI_AUTOPROXY};
481             $proxy = 'Proxy';
482             if ($dbi_autoproxy =~ s/^dbi:(\w*?)(?:\((.*?)\))?://i) {
483             $proxy = $1;
484             $driver_attrib_spec = join ",",
485             ($driver_attrib_spec) ? $driver_attrib_spec : (),
486             ($2 ) ? $2 : ();
487             }
488             $dsn = "$dbi_autoproxy;dsn=dbi:$driver:$dsn";
489             $driver = $proxy;
490             DBI->trace_msg(" DBI_AUTOPROXY: dbi:$driver($driver_attrib_spec):$dsn\n");
491             }
492             # avoid recursion if proxy calls DBI->connect itself
493             local $ENV{DBI_AUTOPROXY} if $ENV{DBI_AUTOPROXY};
494              
495             my %attributes; # take a copy we can delete from
496             if ($old_driver) {
497             %attributes = %$attr if $attr;
498             }
499             else { # new-style connect so new default semantics
500             %attributes = (
501             PrintError => 1,
502             AutoCommit => 1,
503             ref $attr ? %$attr : (),
504             # attributes in DSN take precedence over \%attr connect parameter
505             $driver_attrib_spec ? (split /\s*=>?\s*|\s*,\s*/, $driver_attrib_spec, -1) : (),
506             );
507             }
508             $attr = \%attributes; # now set $attr to refer to our local copy
509              
510             my $drh = $DBI::installed_drh{$driver} || $class->install_driver($driver)
511             or die "panic: $class->install_driver($driver) failed";
512              
513             # attributes in DSN take precedence over \%attr connect parameter
514             $user = $attr->{Username} if defined $attr->{Username};
515             $pass = $attr->{Password} if defined $attr->{Password};
516             delete $attr->{Password}; # always delete Password as closure stores it securely
517             if ( !(defined $user && defined $pass) ) {
518             ($user, $pass) = $drh->default_user($user, $pass, $attr);
519             }
520             $attr->{Username} = $user; # force the Username to be the actual one used
521              
522             my $connect_closure = sub {
523             my ($old_dbh, $override_attr) = @_;
524              
525             #use Data::Dumper;
526             #warn "connect_closure: ".Data::Dumper::Dumper([$attr,\%attributes, $override_attr]);
527              
528             my $dbh;
529             unless ($dbh = $drh->$connect_meth($dsn, $user, $pass, $attr)) {
530             $user = '' if !defined $user;
531             $dsn = '' if !defined $dsn;
532             # $drh->errstr isn't safe here because $dbh->DESTROY may not have
533             # been called yet and so the dbh errstr would not have been copied
534             # up to the drh errstr. Certainly true for connect_cached!
535             my $errstr = $DBI::errstr;
536             # Getting '(no error string)' here is a symptom of a ref loop
537             $errstr = '(no error string)' if !defined $errstr;
538             my $msg = "$class connect('$dsn','$user',...) failed: $errstr";
539             DBI->trace_msg(" $msg\n");
540             # XXX HandleWarn
541             unless ($attr->{HandleError} && $attr->{HandleError}->($msg, $drh, $dbh)) {
542             Carp::croak($msg) if $attr->{RaiseError};
543             Carp::carp ($msg) if $attr->{PrintError};
544             }
545             $! = 0; # for the daft people who do DBI->connect(...) || die "$!";
546             return $dbh; # normally undef, but HandleError could change it
547             }
548              
549             # merge any attribute overrides but don't change $attr itself (for closure)
550             my $apply = { ($override_attr) ? (%$attr, %$override_attr ) : %$attr };
551              
552             # handle basic RootClass subclassing:
553             my $rebless_class = $apply->{RootClass} || ($class ne 'DBI' ? $class : '');
554             if ($rebless_class) {
555             no strict 'refs';
556             if ($apply->{RootClass}) { # explicit attribute (ie not static methd call class)
557             delete $apply->{RootClass};
558             DBI::_load_class($rebless_class, 0);
559             }
560             unless (@{"$rebless_class\::db::ISA"} && @{"$rebless_class\::st::ISA"}) {
561             Carp::carp("DBI subclasses '$rebless_class\::db' and ::st are not setup, RootClass ignored");
562             $rebless_class = undef;
563             $class = 'DBI';
564             }
565             else {
566             $dbh->{RootClass} = $rebless_class; # $dbh->STORE called via plain DBI::db
567             DBI::_set_isa([$rebless_class], 'DBI'); # sets up both '::db' and '::st'
568             DBI::_rebless($dbh, $rebless_class); # appends '::db'
569             }
570             }
571              
572             if (%$apply) {
573              
574             if ($apply->{DbTypeSubclass}) {
575             my $DbTypeSubclass = delete $apply->{DbTypeSubclass};
576             DBI::_rebless_dbtype_subclass($dbh, $rebless_class||$class, $DbTypeSubclass);
577             }
578             my $a;
579             foreach $a (qw(Profile RaiseError PrintError AutoCommit)) { # do these first
580             next unless exists $apply->{$a};
581             $dbh->{$a} = delete $apply->{$a};
582             }
583             while ( my ($a, $v) = each %$apply) {
584             eval { $dbh->{$a} = $v }; # assign in void context to avoid re-FETCH
585             warn $@ if $@;
586             }
587             }
588              
589             # confirm to driver (ie if subclassed) that we've connected sucessfully
590             # and finished the attribute setup. pass in the original arguments
591             $dbh->connected(@orig_args); #if ref $dbh ne 'DBI::db' or $proxy;
592              
593             DBI->trace_msg(" <- connect= $dbh\n") if $DBI::dbi_debug;
594              
595             return $dbh;
596             };
597              
598             my $dbh = &$connect_closure(undef, undef);
599              
600             $dbh->{dbi_connect_closure} = $connect_closure if $dbh;
601              
602             return $dbh;
603             }
604              
605              
606             sub disconnect_all {
607             keys %DBI::installed_drh; # reset iterator
608             while ( my ($name, $drh) = each %DBI::installed_drh ) {
609             $drh->disconnect_all() if ref $drh;
610             }
611             }
612              
613              
614             sub disconnect { # a regular beginners bug
615             Carp::croak("DBI->disconnect is not a DBI method (read the DBI manual)");
616             }
617              
618              
619             sub install_driver { # croaks on failure
620             my $class = shift;
621             my($driver, $attr) = @_;
622             my $drh;
623              
624             $driver ||= $ENV{DBI_DRIVER} || '';
625              
626             # allow driver to be specified as a 'dbi:driver:' string
627             $driver = $1 if $driver =~ s/^DBI:(.*?)://i;
628              
629             Carp::croak("usage: $class->install_driver(\$driver [, \%attr])")
630             unless ($driver and @_<=3);
631              
632             # already installed
633             return $drh if $drh = $DBI::installed_drh{$driver};
634              
635             $class->trace_msg(" -> $class->install_driver($driver"
636             .") for $^O perl=$] pid=$$ ruid=$< euid=$>\n")
637             if $DBI::dbi_debug;
638              
639             # --- load the code
640             my $driver_class = "DBD::$driver";
641             eval qq{package # hide from PAUSE
642             DBI::_firesafe; # just in case
643             require $driver_class; # load the driver
644             };
645             if ($@) {
646             my $err = $@;
647             my $advice = "";
648             if ($err =~ /Can't find loadable object/) {
649             $advice = "Perhaps DBD::$driver was statically linked into a new perl binary."
650             ."\nIn which case you need to use that new perl binary."
651             ."\nOr perhaps only the .pm file was installed but not the shared object file."
652             }
653             elsif ($err =~ /Can't locate.*?DBD\/$driver\.pm in \@INC/) {
654             my @drv = $class->available_drivers(1);
655             $advice = "Perhaps the DBD::$driver perl module hasn't been fully installed,\n"
656             ."or perhaps the capitalisation of '$driver' isn't right.\n"
657             ."Available drivers: ".join(", ", @drv).".";
658             }
659             elsif ($err =~ /Can't load .*? for module DBD::/) {
660             $advice = "Perhaps a required shared library or dll isn't installed where expected";
661             }
662             elsif ($err =~ /Can't locate .*? in \@INC/) {
663             $advice = "Perhaps a module that DBD::$driver requires hasn't been fully installed";
664             }
665             Carp::croak("install_driver($driver) failed: $err$advice\n");
666             }
667             if ($DBI::dbi_debug) {
668             no strict 'refs';
669             (my $driver_file = $driver_class) =~ s/::/\//g;
670             my $dbd_ver = ${"$driver_class\::VERSION"} || "undef";
671             $class->trace_msg(" install_driver: $driver_class version $dbd_ver"
672             ." loaded from $INC{qq($driver_file.pm)}\n");
673             }
674              
675             # --- do some behind-the-scenes checks and setups on the driver
676             $class->setup_driver($driver_class);
677              
678             # --- run the driver function
679             $drh = eval { $driver_class->driver($attr || {}) };
680             unless ($drh && ref $drh && !$@) {
681             my $advice = "";
682             $@ ||= "$driver_class->driver didn't return a handle";
683             # catch people on case in-sensitive systems using the wrong case
684             $advice = "\nPerhaps the capitalisation of DBD '$driver' isn't right."
685             if $@ =~ /locate object method/;
686             Carp::croak("$driver_class initialisation failed: $@$advice");
687             }
688              
689             $DBI::installed_drh{$driver} = $drh;
690             $class->trace_msg(" <- install_driver= $drh\n") if $DBI::dbi_debug;
691             $drh;
692             }
693              
694             *driver = \&install_driver; # currently an alias, may change
695              
696              
697             sub setup_driver {
698             my ($class, $driver_class) = @_;
699             my $type;
700             foreach $type (qw(dr db st)){
701             my $class = $driver_class."::$type";
702             no strict 'refs';
703             push @{"${class}::ISA"}, "DBD::_::$type"
704             unless UNIVERSAL::isa($class, "DBD::_::$type");
705             my $mem_class = "DBD::_mem::$type";
706             push @{"${class}_mem::ISA"}, $mem_class
707             unless UNIVERSAL::isa("${class}_mem", $mem_class)
708             or $DBI::PurePerl;
709             }
710             }
711              
712              
713             sub _rebless {
714             my $dbh = shift;
715             my ($outer, $inner) = DBI::_handles($dbh);
716             my $class = shift(@_).'::db';
717             bless $inner => $class;
718             bless $outer => $class; # outer last for return
719             }
720              
721              
722             sub _set_isa {
723             my ($classes, $topclass) = @_;
724             my $trace = DBI->trace_msg(" _set_isa([@$classes])\n");
725             foreach my $suffix ('::db','::st') {
726             my $previous = $topclass || 'DBI'; # trees are rooted here
727             foreach my $class (@$classes) {
728             my $base_class = $previous.$suffix;
729             my $sub_class = $class.$suffix;
730             my $sub_class_isa = "${sub_class}::ISA";
731             no strict 'refs';
732             if (@$sub_class_isa) {
733             DBI->trace_msg(" $sub_class_isa skipped (already set to @$sub_class_isa)\n")
734             if $trace;
735             }
736             else {
737             @$sub_class_isa = ($base_class) unless @$sub_class_isa;
738             DBI->trace_msg(" $sub_class_isa = $base_class\n")
739             if $trace;
740             }
741             $previous = $class;
742             }
743             }
744             }
745              
746              
747             sub _rebless_dbtype_subclass {
748             my ($dbh, $rootclass, $DbTypeSubclass) = @_;
749             # determine the db type names for class hierarchy
750             my @hierarchy = DBI::_dbtype_names($dbh, $DbTypeSubclass);
751             # add the rootclass prefix to each ('DBI::' or 'MyDBI::' etc)
752             $_ = $rootclass.'::'.$_ foreach (@hierarchy);
753             # load the modules from the 'top down'
754             DBI::_load_class($_, 1) foreach (reverse @hierarchy);
755             # setup class hierarchy if needed, does both '::db' and '::st'
756             DBI::_set_isa(\@hierarchy, $rootclass);
757             # finally bless the handle into the subclass
758             DBI::_rebless($dbh, $hierarchy[0]);
759             }
760              
761              
762             sub _dbtype_names { # list dbtypes for hierarchy, ie Informix=>ADO=>ODBC
763             my ($dbh, $DbTypeSubclass) = @_;
764              
765             if ($DbTypeSubclass && $DbTypeSubclass ne '1' && ref $DbTypeSubclass ne 'CODE') {
766             # treat $DbTypeSubclass as a comma separated list of names
767             my @dbtypes = split /\s*,\s*/, $DbTypeSubclass;
768             $dbh->trace_msg(" DbTypeSubclass($DbTypeSubclass)=@dbtypes (explicit)\n");
769             return @dbtypes;
770             }
771              
772             # XXX will call $dbh->get_info(17) (=SQL_DBMS_NAME) in future?
773              
774             my $driver = $dbh->{Driver}->{Name};
775             if ( $driver eq 'Proxy' ) {
776             # XXX Looking into the internals of DBD::Proxy is questionable!
777             ($driver) = $dbh->{proxy_client}->{application} =~ /^DBI:(.+?):/i
778             or die "Can't determine driver name from proxy";
779             }
780              
781             my @dbtypes = (ucfirst($driver));
782             if ($driver eq 'ODBC' || $driver eq 'ADO') {
783             # XXX will move these out and make extensible later:
784             my $_dbtype_name_regexp = 'Oracle'; # eg 'Oracle|Foo|Bar'
785             my %_dbtype_name_map = (
786             'Microsoft SQL Server' => 'MSSQL',
787             'SQL Server' => 'Sybase',
788             'Adaptive Server Anywhere' => 'ASAny',
789             'ADABAS D' => 'AdabasD',
790             );
791              
792             my $name;
793             $name = $dbh->func(17, 'GetInfo') # SQL_DBMS_NAME
794             if $driver eq 'ODBC';
795             $name = $dbh->{ado_conn}->Properties->Item('DBMS Name')->Value
796             if $driver eq 'ADO';
797             die "Can't determine driver name! ($DBI::errstr)\n"
798             unless $name;
799              
800             my $dbtype;
801             if ($_dbtype_name_map{$name}) {
802             $dbtype = $_dbtype_name_map{$name};
803             }
804             else {
805             if ($name =~ /($_dbtype_name_regexp)/) {
806             $dbtype = lc($1);
807             }
808             else { # generic mangling for other names:
809             $dbtype = lc($name);
810             }
811             $dbtype =~ s/\b(\w)/\U$1/g;
812             $dbtype =~ s/\W+/_/g;
813             }
814             # add ODBC 'behind' ADO
815             push @dbtypes, 'ODBC' if $driver eq 'ADO';
816             # add discovered dbtype in front of ADO/ODBC
817             unshift @dbtypes, $dbtype;
818             }
819             @dbtypes = &$DbTypeSubclass($dbh, \@dbtypes)
820             if (ref $DbTypeSubclass eq 'CODE');
821             $dbh->trace_msg(" DbTypeSubclass($DbTypeSubclass)=@dbtypes\n");
822             return @dbtypes;
823             }
824              
825             sub _load_class {
826             my ($load_class, $missing_ok) = @_;
827             DBI->trace_msg(" _load_class($load_class, $missing_ok)\n", 2);
828             no strict 'refs';
829             return 1 if @{"$load_class\::ISA"}; # already loaded/exists
830             (my $module = $load_class) =~ s!::!/!g;
831             DBI->trace_msg(" _load_class require $module\n", 2);
832             eval { require "$module.pm"; };
833             return 1 unless $@;
834             return 0 if $missing_ok && $@ =~ /^Can't locate \Q$module.pm\E/;
835             die $@;
836             }
837              
838              
839             sub init_rootclass { # deprecated
840             return 1;
841             }
842              
843              
844             *internal = \&DBD::Switch::dr::driver;
845              
846             sub driver_prefix {
847             my ($class, $driver) = @_;
848             return $dbd_class_registry{$driver}->{prefix} if exists $dbd_class_registry{$driver};
849             return;
850             }
851              
852             sub available_drivers {
853             my($quiet) = @_;
854             my(@drivers, $d, $f);
855             local(*DBI::DIR, $@);
856             my(%seen_dir, %seen_dbd);
857             my $haveFileSpec = eval { require File::Spec };
858             foreach $d (@INC){
859             chomp($d); # Perl 5 beta 3 bug in #!./perl -Ilib from Test::Harness
860             my $dbd_dir =
861             ($haveFileSpec ? File::Spec->catdir($d, 'DBD') : "$d/DBD");
862             next unless -d $dbd_dir;
863             next if $seen_dir{$d};
864             $seen_dir{$d} = 1;
865             # XXX we have a problem here with case insensitive file systems
866             # XXX since we can't tell what case must be used when loading.
867             opendir(DBI::DIR, $dbd_dir) || Carp::carp "opendir $dbd_dir: $!\n";
868             foreach $f (readdir(DBI::DIR)){
869             next unless $f =~ s/\.pm$//;
870             next if $f eq 'NullP';
871             if ($seen_dbd{$f}){
872             Carp::carp "DBD::$f in $d is hidden by DBD::$f in $seen_dbd{$f}\n"
873             unless $quiet;
874             } else {
875             push(@drivers, $f);
876             }
877             $seen_dbd{$f} = $d;
878             }
879             closedir(DBI::DIR);
880             }
881              
882             # "return sort @drivers" will not DWIM in scalar context.
883             return wantarray ? sort @drivers : @drivers;
884             }
885              
886             sub installed_versions {
887             my ($class, $quiet) = @_;
888             my %error;
889             my %version = ( DBI => $DBI::VERSION );
890             $version{"DBI::PurePerl"} = $DBI::PurePerl::VERSION
891             if $DBI::PurePerl;
892             for my $driver ($class->available_drivers($quiet)) {
893             next if $DBI::PurePerl && grep { -d "$_/auto/DBD/$driver" } @INC;
894             my $drh = eval {
895             local $SIG{__WARN__} = sub {};
896             $class->install_driver($driver);
897             };
898             ($error{"DBD::$driver"}=$@),next if $@;
899             no strict 'refs';
900             my $vers = ${"DBD::$driver" . '::VERSION'};
901             $version{"DBD::$driver"} = $vers || '?';
902             }
903             if (wantarray) {
904             return map { m/^DBD::(\w+)/ ? ($1) : () } sort keys %version;
905             }
906             if (!defined wantarray) { # void context
907             require Config; # add more detail
908             $version{OS} = "$^O\t($Config::Config{osvers})";
909             $version{Perl} = "$]\t($Config::Config{archname})";
910             $version{$_} = (($error{$_} =~ s/ \(\@INC.*//s),$error{$_})
911             for keys %error;
912             printf " %-16s: %s\n",$_,$version{$_}
913             for reverse sort keys %version;
914             }
915             return \%version;
916             }
917              
918              
919             sub data_sources {
920             my ($class, $driver, @other) = @_;
921             my $drh = $class->install_driver($driver);
922             my @ds = $drh->data_sources(@other);
923             return @ds;
924             }
925              
926              
927             sub neat_list {
928             my ($listref, $maxlen, $sep) = @_;
929             $maxlen = 0 unless defined $maxlen; # 0 == use internal default
930             $sep = ", " unless defined $sep;
931             join($sep, map { neat($_,$maxlen) } @$listref);
932             }
933              
934              
935             sub dump_results { # also aliased as a method in DBD::_::st
936             my ($sth, $maxlen, $lsep, $fsep, $fh) = @_;
937             return 0 unless $sth;
938             $maxlen ||= 35;
939             $lsep ||= "\n";
940             $fh ||= \*STDOUT;
941             my $rows = 0;
942             my $ref;
943             while($ref = $sth->fetch) {
944             print $fh $lsep if $rows++ and $lsep;
945             my $str = neat_list($ref,$maxlen,$fsep);
946             print $fh $str; # done on two lines to avoid 5.003 errors
947             }
948             print $fh "\n$rows rows".($DBI::err ? " ($DBI::err: $DBI::errstr)" : "")."\n";
949             $rows;
950             }
951              
952              
953             sub data_diff {
954             my ($a, $b, $logical) = @_;
955              
956             my $diff = data_string_diff($a, $b);
957             return "" if $logical and !$diff;
958              
959             my $a_desc = data_string_desc($a);
960             my $b_desc = data_string_desc($b);
961             return "" if !$diff and $a_desc eq $b_desc;
962              
963             $diff ||= "Strings contain the same sequence of characters"
964             if length($a);
965             $diff .= "\n" if $diff;
966             return "a: $a_desc\nb: $b_desc\n$diff";
967             }
968              
969              
970             sub data_string_diff {
971             # Compares 'logical' characters, not bytes, so a latin1 string and an
972             # an equivalent Unicode string will compare as equal even though their
973             # byte encodings are different.
974             my ($a, $b) = @_;
975             unless (defined $a and defined $b) { # one undef
976             return ""
977             if !defined $a and !defined $b;
978             return "String a is undef, string b has ".length($b)." characters"
979             if !defined $a;
980             return "String b is undef, string a has ".length($a)." characters"
981             if !defined $b;
982             }
983              
984             require utf8;
985             # hack to cater for perl 5.6
986             *utf8::is_utf8 = sub { (DBI::neat(shift)=~/^"/) } unless defined &utf8::is_utf8;
987              
988             my @a_chars = (utf8::is_utf8($a)) ? unpack("U*", $a) : unpack("C*", $a);
989             my @b_chars = (utf8::is_utf8($b)) ? unpack("U*", $b) : unpack("C*", $b);
990             my $i = 0;
991             while (@a_chars && @b_chars) {
992             ++$i, shift(@a_chars), shift(@b_chars), next
993             if $a_chars[0] == $b_chars[0];# compare ordinal values
994             my @desc = map {
995             $_ > 255 ? # if wide character...
996             sprintf("\\x{%04X}", $_) : # \x{...}
997             chr($_) =~ /[[:cntrl:]]/ ? # else if control character ...
998             sprintf("\\x%02X", $_) : # \x..
999             chr($_) # else as themselves
1000             } ($a_chars[0], $b_chars[0]);
1001             # highlight probable double-encoding?
1002             foreach my $c ( @desc ) {
1003             next unless $c =~ m/\\x\{08(..)}/;
1004             $c .= "='" .chr(hex($1)) ."'"
1005             }
1006             return sprintf "Strings differ at index $i: a[$i]=$desc[0], b[$i]=$desc[1]";
1007             }
1008             return "String a truncated after $i characters" if @b_chars;
1009             return "String b truncated after $i characters" if @a_chars;
1010             return "";
1011             }
1012              
1013              
1014             sub data_string_desc { # describe a data string
1015             my ($a) = @_;
1016             require bytes;
1017             require utf8;
1018              
1019             # hacks to cater for perl 5.6
1020             *utf8::is_utf8 = sub { (DBI::neat(shift)=~/^"/) } unless defined &utf8::is_utf8;
1021             *utf8::valid = sub { 1 } unless defined &utf8::valid;
1022              
1023             # Give sufficient info to help diagnose at least these kinds of situations:
1024             # - valid UTF8 byte sequence but UTF8 flag not set
1025             # (might be ascii so also need to check for hibit to make it worthwhile)
1026             # - UTF8 flag set but invalid UTF8 byte sequence
1027             # could do better here, but this'll do for now
1028             my $utf8 = sprintf "UTF8 %s%s",
1029             utf8::is_utf8($a) ? "on" : "off",
1030             utf8::valid($a||'') ? "" : " but INVALID encoding";
1031             return "$utf8, undef" unless defined $a;
1032             my $is_ascii = $a =~ m/^[\000-\177]*$/;
1033             return sprintf "%s, %s, %d characters %d bytes",
1034             $utf8, $is_ascii ? "ASCII" : "non-ASCII",
1035             length($a), bytes::length($a);
1036             }
1037              
1038              
1039             sub connect_test_perf {
1040             my($class, $dsn,$dbuser,$dbpass, $attr) = @_;
1041             Carp::croak("connect_test_perf needs hash ref as fourth arg") unless ref $attr;
1042             # these are non standard attributes just for this special method
1043             my $loops ||= $attr->{dbi_loops} || 5;
1044             my $par ||= $attr->{dbi_par} || 1; # parallelism
1045             my $verb ||= $attr->{dbi_verb} || 1;
1046             my $meth ||= $attr->{dbi_meth} || 'connect';
1047             print "$dsn: testing $loops sets of $par connections:\n";
1048             require "FileHandle.pm"; # don't let toke.c create empty FileHandle package
1049             local $| = 1;
1050             my $drh = $class->install_driver($dsn) or Carp::croak("Can't install $dsn driver\n");
1051             # test the connection and warm up caches etc
1052             $drh->connect($dsn,$dbuser,$dbpass) or Carp::croak("connect failed: $DBI::errstr");
1053             my $t1 = dbi_time();
1054             my $loop;
1055             for $loop (1..$loops) {
1056             my @cons;
1057             print "Connecting... " if $verb;
1058             for (1..$par) {
1059             print "$_ ";
1060             push @cons, ($drh->connect($dsn,$dbuser,$dbpass)
1061             or Carp::croak("connect failed: $DBI::errstr\n"));
1062             }
1063             print "\nDisconnecting...\n" if $verb;
1064             for (@cons) {
1065             $_->disconnect or warn "disconnect failed: $DBI::errstr"
1066             }
1067             }
1068             my $t2 = dbi_time();
1069             my $td = $t2 - $t1;
1070             printf "$meth %d and disconnect them, %d times: %.4fs / %d = %.4fs\n",
1071             $par, $loops, $td, $loops*$par, $td/($loops*$par);
1072             return $td;
1073             }
1074              
1075              
1076             # Help people doing DBI->errstr, might even document it one day
1077             # XXX probably best moved to cheaper XS code if this gets documented
1078             sub err { $DBI::err }
1079             sub errstr { $DBI::errstr }
1080              
1081              
1082             # --- Private Internal Function for Creating New DBI Handles
1083              
1084             # XXX move to PurePerl?
1085             *DBI::dr::TIEHASH = \&DBI::st::TIEHASH;
1086             *DBI::db::TIEHASH = \&DBI::st::TIEHASH;
1087              
1088              
1089             # These three special constructors are called by the drivers
1090             # The way they are called is likely to change.
1091              
1092             our $shared_profile;
1093              
1094             sub _new_drh { # called by DBD::::driver()
1095             my ($class, $initial_attr, $imp_data) = @_;
1096             # Provide default storage for State,Err and Errstr.
1097             # Note that these are shared by all child handles by default! XXX
1098             # State must be undef to get automatic faking in DBI::var::FETCH
1099             my ($h_state_store, $h_err_store, $h_errstr_store) = (undef, 0, '');
1100             my $attr = {
1101             # these attributes get copied down to child handles by default
1102             'State' => \$h_state_store, # Holder for DBI::state
1103             'Err' => \$h_err_store, # Holder for DBI::err
1104             'Errstr' => \$h_errstr_store, # Holder for DBI::errstr
1105             'TraceLevel' => 0,
1106             FetchHashKeyName=> 'NAME',
1107             %$initial_attr,
1108             };
1109             my ($h, $i) = _new_handle('DBI::dr', '', $attr, $imp_data, $class);
1110              
1111             # XXX DBI_PROFILE unless DBI::PurePerl because for some reason
1112             # it kills the t/zz_*_pp.t tests (they silently exit early)
1113             if (($ENV{DBI_PROFILE} && !$DBI::PurePerl) || $shared_profile) {
1114             # The profile object created here when the first driver is loaded
1115             # is shared by all drivers so we end up with just one set of profile
1116             # data and thus the 'total time in DBI' is really the true total.
1117             if (!$shared_profile) { # first time
1118             $h->{Profile} = $ENV{DBI_PROFILE}; # write string
1119             $shared_profile = $h->{Profile}; # read and record object
1120             }
1121             else {
1122             $h->{Profile} = $shared_profile;
1123             }
1124             }
1125             return $h unless wantarray;
1126             ($h, $i);
1127             }
1128              
1129             sub _new_dbh { # called by DBD::::dr::connect()
1130             my ($drh, $attr, $imp_data) = @_;
1131             my $imp_class = $drh->{ImplementorClass}
1132             or Carp::croak("DBI _new_dbh: $drh has no ImplementorClass");
1133             substr($imp_class,-4,4) = '::db';
1134             my $app_class = ref $drh;
1135             substr($app_class,-4,4) = '::db';
1136             $attr->{Err} ||= \my $err;
1137             $attr->{Errstr} ||= \my $errstr;
1138             $attr->{State} ||= \my $state;
1139             _new_handle($app_class, $drh, $attr, $imp_data, $imp_class);
1140             }
1141              
1142             sub _new_sth { # called by DBD::::db::prepare)
1143             my ($dbh, $attr, $imp_data) = @_;
1144             my $imp_class = $dbh->{ImplementorClass}
1145             or Carp::croak("DBI _new_sth: $dbh has no ImplementorClass");
1146             substr($imp_class,-4,4) = '::st';
1147             my $app_class = ref $dbh;
1148             substr($app_class,-4,4) = '::st';
1149             _new_handle($app_class, $dbh, $attr, $imp_data, $imp_class);
1150             }
1151              
1152              
1153             # end of DBI package
1154              
1155              
1156              
1157             # --------------------------------------------------------------------
1158             # === The internal DBI Switch pseudo 'driver' class ===
1159              
1160             { package # hide from PAUSE
1161             DBD::Switch::dr;
1162             DBI->setup_driver('DBD::Switch'); # sets up @ISA
1163              
1164             $DBD::Switch::dr::imp_data_size = 0;
1165             $DBD::Switch::dr::imp_data_size = 0; # avoid typo warning
1166             my $drh;
1167              
1168             sub driver {
1169             return $drh if $drh; # a package global
1170              
1171             my $inner;
1172             ($drh, $inner) = DBI::_new_drh('DBD::Switch::dr', {
1173             'Name' => 'Switch',
1174             'Version' => $DBI::VERSION,
1175             'Attribution' => "DBI $DBI::VERSION by Tim Bunce",
1176             });
1177             Carp::croak("DBD::Switch init failed!") unless ($drh && $inner);
1178             return $drh;
1179             }
1180             sub CLONE {
1181             undef $drh;
1182             }
1183              
1184             sub FETCH {
1185             my($drh, $key) = @_;
1186             return DBI->trace if $key eq 'DebugDispatch';
1187             return undef if $key eq 'DebugLog'; # not worth fetching, sorry
1188             return $drh->DBD::_::dr::FETCH($key);
1189             undef;
1190             }
1191             sub STORE {
1192             my($drh, $key, $value) = @_;
1193             if ($key eq 'DebugDispatch') {
1194             DBI->trace($value);
1195             } elsif ($key eq 'DebugLog') {
1196             DBI->trace(-1, $value);
1197             } else {
1198             $drh->DBD::_::dr::STORE($key, $value);
1199             }
1200             }
1201             }
1202              
1203              
1204             # --------------------------------------------------------------------
1205             # === OPTIONAL MINIMAL BASE CLASSES FOR DBI SUBCLASSES ===
1206              
1207             # We only define default methods for harmless functions.
1208             # We don't, for example, define a DBD::_::st::prepare()
1209              
1210             { package # hide from PAUSE
1211             DBD::_::common; # ====== Common base class methods ======
1212             use strict;
1213              
1214             # methods common to all handle types:
1215              
1216             sub _not_impl {
1217             my ($h, $method) = @_;
1218             $h->trace_msg("Driver does not implement the $method method.\n");
1219             return; # empty list / undef
1220             }
1221              
1222             # generic TIEHASH default methods:
1223             sub FIRSTKEY { }
1224             sub NEXTKEY { }
1225             sub EXISTS { defined($_[0]->FETCH($_[1])) } # XXX undef?
1226             sub CLEAR { Carp::carp "Can't CLEAR $_[0] (DBI)" }
1227              
1228             sub FETCH_many { # XXX should move to C one day
1229             my $h = shift;
1230             # scalar is needed to workaround drivers that return an empty list
1231             # for some attributes
1232             return map { scalar $h->FETCH($_) } @_;
1233             }
1234              
1235             *dump_handle = \&DBI::dump_handle;
1236              
1237             sub install_method {
1238             # special class method called directly by apps and/or drivers
1239             # to install new methods into the DBI dispatcher
1240             # DBD::Foo::db->install_method("foo_mumble", { usage => [...], options => '...' });
1241             my ($class, $method, $attr) = @_;
1242             Carp::croak("Class '$class' must begin with DBD:: and end with ::db or ::st")
1243             unless $class =~ /^DBD::(\w+)::(dr|db|st)$/;
1244             my ($driver, $subtype) = ($1, $2);
1245             Carp::croak("invalid method name '$method'")
1246             unless $method =~ m/^([a-z]+_)\w+$/;
1247             my $prefix = $1;
1248             my $reg_info = $dbd_prefix_registry->{$prefix};
1249             Carp::carp("method name prefix '$prefix' is not associated with a registered driver") unless $reg_info;
1250              
1251             my $full_method = "DBI::${subtype}::$method";
1252             $DBI::installed_methods{$full_method} = $attr;
1253              
1254             my (undef, $filename, $line) = caller;
1255             # XXX reformat $attr as needed for _install_method
1256             my %attr = %{$attr||{}}; # copy so we can edit
1257             DBI->_install_method("DBI::${subtype}::$method", "$filename at line $line", \%attr);
1258             }
1259              
1260             sub parse_trace_flags {
1261             my ($h, $spec) = @_;
1262             my $level = 0;
1263             my $flags = 0;
1264             my @unknown;
1265             for my $word (split /\s*[|&,]\s*/, $spec) {
1266             if (DBI::looks_like_number($word) && $word <= 0xF && $word >= 0) {
1267             $level = $word;
1268             } elsif ($word eq 'ALL') {
1269             $flags = 0x7FFFFFFF; # XXX last bit causes negative headaches
1270             last;
1271             } elsif (my $flag = $h->parse_trace_flag($word)) {
1272             $flags |= $flag;
1273             }
1274             else {
1275             push @unknown, $word;
1276             }
1277             }
1278             if (@unknown && (ref $h ? $h->FETCH('Warn') : 1)) {
1279             Carp::carp("$h->parse_trace_flags($spec) ignored unknown trace flags: ".
1280             join(" ", map { DBI::neat($_) } @unknown));
1281             }
1282             $flags |= $level;
1283             return $flags;
1284             }
1285              
1286             sub parse_trace_flag {
1287             my ($h, $name) = @_;
1288             # 0xddDDDDrL (driver, DBI, reserved, Level)
1289             return 0x00000100 if $name eq 'SQL';
1290             return;
1291             }
1292              
1293             sub private_attribute_info {
1294             return undef;
1295             }
1296              
1297             sub visit_child_handles {
1298             my ($h, $code, $info) = @_;
1299             $info = {} if not defined $info;
1300             for my $ch (@{ $h->{ChildHandles} || []}) {
1301             next unless $ch;
1302             my $child_info = $code->($ch, $info)
1303             or next;
1304             $ch->visit_child_handles($code, $child_info);
1305             }
1306             return $info;
1307             }
1308             }
1309              
1310              
1311             { package # hide from PAUSE
1312             DBD::_::dr; # ====== DRIVER ======
1313             @DBD::_::dr::ISA = qw(DBD::_::common);
1314             use strict;
1315              
1316             sub default_user {
1317             my ($drh, $user, $pass, $attr) = @_;
1318             $user = $ENV{DBI_USER} unless defined $user;
1319             $pass = $ENV{DBI_PASS} unless defined $pass;
1320             return ($user, $pass);
1321             }
1322              
1323             sub connect { # normally overridden, but a handy default
1324             my ($drh, $dsn, $user, $auth) = @_;
1325             my ($this) = DBI::_new_dbh($drh, {
1326             'Name' => $dsn,
1327             });
1328             # XXX debatable as there's no "server side" here
1329             # (and now many uses would trigger warnings on DESTROY)
1330             # $this->STORE(Active => 1);
1331             # so drivers should set it in their own connect
1332             $this;
1333             }
1334              
1335              
1336             sub connect_cached {
1337             my $drh = shift;
1338             my ($dsn, $user, $auth, $attr) = @_;
1339              
1340             my $cache = $drh->{CachedKids} ||= {};
1341             my $key = do { local $^W;
1342             join "!\001", $dsn, $user, $auth, DBI::_concat_hash_sorted($attr, "=\001", ",\001", 0, 0)
1343             };
1344             my $dbh = $cache->{$key};
1345             $drh->trace_msg(sprintf(" connect_cached: key '$key', cached dbh $dbh\n", DBI::neat($key), DBI::neat($dbh)))
1346             if $DBI::dbi_debug >= 4;
1347              
1348             my $cb = $attr->{Callbacks}; # take care not to autovivify
1349             if ($dbh && $dbh->FETCH('Active') && eval { $dbh->ping }) {
1350             # If the caller has provided a callback then call it
1351             if ($cb and $cb = $cb->{"connect_cached.reused"}) {
1352             local $_ = "connect_cached.reused";
1353             $cb->($dbh, $dsn, $user, $auth, $attr);
1354             }
1355             return $dbh;
1356             }
1357              
1358             # If the caller has provided a callback then call it
1359             if ($cb and $cb = $cb->{"connect_cached.new"}) {
1360             local $_ = "connect_cached.new";
1361             $cb->($dbh, $dsn, $user, $auth, $attr);
1362             }
1363              
1364             $dbh = $drh->connect(@_);
1365             $cache->{$key} = $dbh; # replace prev entry, even if connect failed
1366             return $dbh;
1367             }
1368              
1369             }
1370              
1371              
1372             { package # hide from PAUSE
1373             DBD::_::db; # ====== DATABASE ======
1374             @DBD::_::db::ISA = qw(DBD::_::common);
1375             use strict;
1376              
1377             sub clone {
1378             my ($old_dbh, $attr) = @_;
1379             my $closure = $old_dbh->{dbi_connect_closure} or return;
1380             unless ($attr) {
1381             # copy attributes visible in the attribute cache
1382             keys %$old_dbh; # reset iterator
1383             while ( my ($k, $v) = each %$old_dbh ) {
1384             # ignore non-code refs, i.e., caches, handles, Err etc
1385             next if ref $v && ref $v ne 'CODE'; # HandleError etc
1386             $attr->{$k} = $v;
1387             }
1388             # explicitly set attributes which are unlikely to be in the
1389             # attribute cache, i.e., boolean's and some others
1390             $attr->{$_} = $old_dbh->FETCH($_) for (qw(
1391             AutoCommit ChopBlanks InactiveDestroy AutoInactiveDestroy
1392             LongTruncOk PrintError PrintWarn Profile RaiseError
1393             ShowErrorStatement TaintIn TaintOut
1394             ));
1395             }
1396             # use Data::Dumper; warn Dumper([$old_dbh, $attr]);
1397             my $new_dbh = &$closure($old_dbh, $attr);
1398             unless ($new_dbh) {
1399             # need to copy err/errstr from driver back into $old_dbh
1400             my $drh = $old_dbh->{Driver};
1401             return $old_dbh->set_err($drh->err, $drh->errstr, $drh->state);
1402             }
1403             return $new_dbh;
1404             }
1405              
1406             sub quote_identifier {
1407             my ($dbh, @id) = @_;
1408             my $attr = (@id > 3 && ref($id[-1])) ? pop @id : undef;
1409              
1410             my $info = $dbh->{dbi_quote_identifier_cache} ||= [
1411             $dbh->get_info(29) || '"', # SQL_IDENTIFIER_QUOTE_CHAR
1412             $dbh->get_info(41) || '.', # SQL_CATALOG_NAME_SEPARATOR
1413             $dbh->get_info(114) || 1, # SQL_CATALOG_LOCATION
1414             ];
1415              
1416             my $quote = $info->[0];
1417             foreach (@id) { # quote the elements
1418             next unless defined;
1419             s/$quote/$quote$quote/g; # escape embedded quotes
1420             $_ = qq{$quote$_$quote};
1421             }
1422              
1423             # strip out catalog if present for special handling
1424             my $catalog = (@id >= 3) ? shift @id : undef;
1425              
1426             # join the dots, ignoring any null/undef elements (ie schema)
1427             my $quoted_id = join '.', grep { defined } @id;
1428              
1429             if ($catalog) { # add catalog correctly
1430             $quoted_id = ($info->[2] == 2) # SQL_CL_END
1431             ? $quoted_id . $info->[1] . $catalog
1432             : $catalog . $info->[1] . $quoted_id;
1433             }
1434             return $quoted_id;
1435             }
1436              
1437             sub quote {
1438             my ($dbh, $str, $data_type) = @_;
1439              
1440             return "NULL" unless defined $str;
1441             unless ($data_type) {
1442             $str =~ s/'/''/g; # ISO SQL2
1443             return "'$str'";
1444             }
1445              
1446             my $dbi_literal_quote_cache = $dbh->{'dbi_literal_quote_cache'} ||= [ {} , {} ];
1447             my ($prefixes, $suffixes) = @$dbi_literal_quote_cache;
1448              
1449             my $lp = $prefixes->{$data_type};
1450             my $ls = $suffixes->{$data_type};
1451              
1452             if ( ! defined $lp || ! defined $ls ) {
1453             my $ti = $dbh->type_info($data_type);
1454             $lp = $prefixes->{$data_type} = $ti ? $ti->{LITERAL_PREFIX} || "" : "'";
1455             $ls = $suffixes->{$data_type} = $ti ? $ti->{LITERAL_SUFFIX} || "" : "'";
1456             }
1457             return $str unless $lp || $ls; # no quoting required
1458              
1459             # XXX don't know what the standard says about escaping
1460             # in the 'general case' (where $lp != "'").
1461             # So we just do this and hope:
1462             $str =~ s/$lp/$lp$lp/g
1463             if $lp && $lp eq $ls && ($lp eq "'" || $lp eq '"');
1464             return "$lp$str$ls";
1465             }
1466              
1467             sub rows { -1 } # here so $DBI::rows 'works' after using $dbh
1468              
1469             sub do {
1470             my($dbh, $statement, $attr, @params) = @_;
1471             my $sth = $dbh->prepare($statement, $attr) or return undef;
1472             $sth->execute(@params) or return undef;
1473             my $rows = $sth->rows;
1474             ($rows == 0) ? "0E0" : $rows;
1475             }
1476              
1477             sub _do_selectrow {
1478             my ($method, $dbh, $stmt, $attr, @bind) = @_;
1479             my $sth = ((ref $stmt) ? $stmt : $dbh->prepare($stmt, $attr))
1480             or return;
1481             $sth->execute(@bind)
1482             or return;
1483             my $row = $sth->$method()
1484             and $sth->finish;
1485             return $row;
1486             }
1487              
1488             sub selectrow_hashref { return _do_selectrow('fetchrow_hashref', @_); }
1489              
1490             # XXX selectrow_array/ref also have C implementations in Driver.xst
1491             sub selectrow_arrayref { return _do_selectrow('fetchrow_arrayref', @_); }
1492             sub selectrow_array {
1493             my $row = _do_selectrow('fetchrow_arrayref', @_) or return;
1494             return $row->[0] unless wantarray;
1495             return @$row;
1496             }
1497              
1498             # XXX selectall_arrayref also has C implementation in Driver.xst
1499             # which fallsback to this if a slice is given
1500             sub selectall_arrayref {
1501             my ($dbh, $stmt, $attr, @bind) = @_;
1502             my $sth = (ref $stmt) ? $stmt : $dbh->prepare($stmt, $attr)
1503             or return;
1504             $sth->execute(@bind) || return;
1505             my $slice = $attr->{Slice}; # typically undef, else hash or array ref
1506             if (!$slice and $slice=$attr->{Columns}) {
1507             if (ref $slice eq 'ARRAY') { # map col idx to perl array idx
1508             $slice = [ @{$attr->{Columns}} ]; # take a copy
1509             for (@$slice) { $_-- }
1510             }
1511             }
1512             my $rows = $sth->fetchall_arrayref($slice, my $MaxRows = $attr->{MaxRows});
1513             $sth->finish if defined $MaxRows;
1514             return $rows;
1515             }
1516              
1517             sub selectall_hashref {
1518             my ($dbh, $stmt, $key_field, $attr, @bind) = @_;
1519             my $sth = (ref $stmt) ? $stmt : $dbh->prepare($stmt, $attr);
1520             return unless $sth;
1521             $sth->execute(@bind) || return;
1522             return $sth->fetchall_hashref($key_field);
1523             }
1524              
1525             sub selectcol_arrayref {
1526             my ($dbh, $stmt, $attr, @bind) = @_;
1527             my $sth = (ref $stmt) ? $stmt : $dbh->prepare($stmt, $attr);
1528             return unless $sth;
1529             $sth->execute(@bind) || return;
1530             my @columns = ($attr->{Columns}) ? @{$attr->{Columns}} : (1);
1531             my @values = (undef) x @columns;
1532             my $idx = 0;
1533             for (@columns) {
1534             $sth->bind_col($_, \$values[$idx++]) || return;
1535             }
1536             my @col;
1537             if (my $max = $attr->{MaxRows}) {
1538             push @col, @values while 0 < $max-- && $sth->fetch;
1539             }
1540             else {
1541             push @col, @values while $sth->fetch;
1542             }
1543             return \@col;
1544             }
1545              
1546             sub prepare_cached {
1547             my ($dbh, $statement, $attr, $if_active) = @_;
1548              
1549             # Needs support at dbh level to clear cache before complaining about
1550             # active children. The XS template code does this. Drivers not using
1551             # the template must handle clearing the cache themselves.
1552             my $cache = $dbh->{CachedKids} ||= {};
1553             my $key = do { local $^W;
1554             join "!\001", $statement, DBI::_concat_hash_sorted($attr, "=\001", ",\001", 0, 0)
1555             };
1556             my $sth = $cache->{$key};
1557              
1558             if ($sth) {
1559             return $sth unless $sth->FETCH('Active');
1560             Carp::carp("prepare_cached($statement) statement handle $sth still Active")
1561             unless ($if_active ||= 0);
1562             $sth->finish if $if_active <= 1;
1563             return $sth if $if_active <= 2;
1564             }
1565              
1566             $sth = $dbh->prepare($statement, $attr);
1567             $cache->{$key} = $sth if $sth;
1568              
1569             return $sth;
1570             }
1571              
1572             sub ping {
1573             my $dbh = shift;
1574             $dbh->_not_impl('ping');
1575             # "0 but true" is a special kind of true 0 that is used here so
1576             # applications can check if the ping was a real ping or not
1577             ($dbh->FETCH('Active')) ? "0 but true" : 0;
1578             }
1579              
1580             sub begin_work {
1581             my $dbh = shift;
1582             return $dbh->set_err($DBI::stderr, "Already in a transaction")
1583             unless $dbh->FETCH('AutoCommit');
1584             $dbh->STORE('AutoCommit', 0); # will croak if driver doesn't support it
1585             $dbh->STORE('BegunWork', 1); # trigger post commit/rollback action
1586             return 1;
1587             }
1588              
1589             sub primary_key {
1590             my ($dbh, @args) = @_;
1591             my $sth = $dbh->primary_key_info(@args) or return;
1592             my ($row, @col);
1593             push @col, $row->[3] while ($row = $sth->fetch);
1594             Carp::croak("primary_key method not called in list context")
1595             unless wantarray; # leave us some elbow room
1596             return @col;
1597             }
1598              
1599             sub tables {
1600             my ($dbh, @args) = @_;
1601             my $sth = $dbh->table_info(@args[0,1,2,3,4]) or return;
1602             my $tables = $sth->fetchall_arrayref or return;
1603             my @tables;
1604             if ($dbh->get_info(29)) { # SQL_IDENTIFIER_QUOTE_CHAR
1605             @tables = map { $dbh->quote_identifier( @{$_}[0,1,2] ) } @$tables;
1606             }
1607             else { # temporary old style hack (yeach)
1608             @tables = map {
1609             my $name = $_->[2];
1610             if ($_->[1]) {
1611             my $schema = $_->[1];
1612             # a sad hack (mostly for Informix I recall)
1613             my $quote = ($schema eq uc($schema)) ? '' : '"';
1614             $name = "$quote$schema$quote.$name"
1615             }
1616             $name;
1617             } @$tables;
1618             }
1619             return @tables;
1620             }
1621              
1622             sub type_info { # this should be sufficient for all drivers
1623             my ($dbh, $data_type) = @_;
1624             my $idx_hash;
1625             my $tia = $dbh->{dbi_type_info_row_cache};
1626             if ($tia) {
1627             $idx_hash = $dbh->{dbi_type_info_idx_cache};
1628             }
1629             else {
1630             my $temp = $dbh->type_info_all;
1631             return unless $temp && @$temp;
1632             # we cache here because type_info_all may be expensive to call
1633             # (and we take a copy so the following shift can't corrupt
1634             # the data that may be returned by future calls to type_info_all)
1635             $tia = $dbh->{dbi_type_info_row_cache} = [ @$temp ];
1636             $idx_hash = $dbh->{dbi_type_info_idx_cache} = shift @$tia;
1637             }
1638              
1639             my $dt_idx = $idx_hash->{DATA_TYPE} || $idx_hash->{data_type};
1640             Carp::croak("type_info_all returned non-standard DATA_TYPE index value ($dt_idx != 1)")
1641             if $dt_idx && $dt_idx != 1;
1642              
1643             # --- simple DATA_TYPE match filter
1644             my @ti;
1645             my @data_type_list = (ref $data_type) ? @$data_type : ($data_type);
1646             foreach $data_type (@data_type_list) {
1647             if (defined($data_type) && $data_type != DBI::SQL_ALL_TYPES()) {
1648             push @ti, grep { $_->[$dt_idx] == $data_type } @$tia;
1649             }
1650             else { # SQL_ALL_TYPES
1651             push @ti, @$tia;
1652             }
1653             last if @ti; # found at least one match
1654             }
1655              
1656             # --- format results into list of hash refs
1657             my $idx_fields = keys %$idx_hash;
1658             my @idx_names = map { uc($_) } keys %$idx_hash;
1659             my @idx_values = values %$idx_hash;
1660             Carp::croak "type_info_all result has $idx_fields keys but ".(@{$ti[0]})." fields"
1661             if @ti && @{$ti[0]} != $idx_fields;
1662             my @out = map {
1663             my %h; @h{@idx_names} = @{$_}[ @idx_values ]; \%h;
1664             } @ti;
1665             return $out[0] unless wantarray;
1666             return @out;
1667             }
1668              
1669             sub data_sources {
1670             my ($dbh, @other) = @_;
1671             my $drh = $dbh->{Driver}; # XXX proxy issues?
1672             return $drh->data_sources(@other);
1673             }
1674              
1675             }
1676              
1677              
1678             { package # hide from PAUSE
1679             DBD::_::st; # ====== STATEMENT ======
1680             @DBD::_::st::ISA = qw(DBD::_::common);
1681             use strict;
1682              
1683             sub bind_param { Carp::croak("Can't bind_param, not implement by driver") }
1684              
1685             #
1686             # ********************************************************
1687             #
1688             # BEGIN ARRAY BINDING
1689             #
1690             # Array binding support for drivers which don't support
1691             # array binding, but have sufficient interfaces to fake it.
1692             # NOTE: mixing scalars and arrayrefs requires using bind_param_array
1693             # for *all* params...unless we modify bind_param for the default
1694             # case...
1695             #
1696             # 2002-Apr-10 D. Arnold
1697              
1698             sub bind_param_array {
1699             my $sth = shift;
1700             my ($p_id, $value_array, $attr) = @_;
1701              
1702             return $sth->set_err($DBI::stderr, "Value for parameter $p_id must be a scalar or an arrayref, not a ".ref($value_array))
1703             if defined $value_array and ref $value_array and ref $value_array ne 'ARRAY';
1704              
1705             return $sth->set_err($DBI::stderr, "Can't use named placeholder '$p_id' for non-driver supported bind_param_array")
1706             unless DBI::looks_like_number($p_id); # because we rely on execute(@ary) here
1707              
1708             return $sth->set_err($DBI::stderr, "Placeholder '$p_id' is out of range")
1709             if $p_id <= 0; # can't easily/reliably test for too big
1710              
1711             # get/create arrayref to hold params
1712             my $hash_of_arrays = $sth->{ParamArrays} ||= { };
1713              
1714             # If the bind has attribs then we rely on the driver conforming to
1715             # the DBI spec in that a single bind_param() call with those attribs
1716             # makes them 'sticky' and apply to all later execute(@values) calls.
1717             # Since we only call bind_param() if we're given attribs then
1718             # applications using drivers that don't support bind_param can still
1719             # use bind_param_array() so long as they don't pass any attribs.
1720              
1721             $$hash_of_arrays{$p_id} = $value_array;
1722             return $sth->bind_param($p_id, undef, $attr)
1723             if $attr;
1724             1;
1725             }
1726              
1727             sub bind_param_inout_array {
1728             my $sth = shift;
1729             # XXX not supported so we just call bind_param_array instead
1730             # and then return an error
1731             my ($p_num, $value_array, $attr) = @_;
1732             $sth->bind_param_array($p_num, $value_array, $attr);
1733             return $sth->set_err($DBI::stderr, "bind_param_inout_array not supported");
1734             }
1735              
1736             sub bind_columns {
1737             my $sth = shift;
1738             my $fields = $sth->FETCH('NUM_OF_FIELDS') || 0;
1739             if ($fields <= 0 && !$sth->{Active}) {
1740             return $sth->set_err($DBI::stderr, "Statement has no result columns to bind"
1741             ." (perhaps you need to successfully call execute first)");
1742             }
1743             # Backwards compatibility for old-style call with attribute hash
1744             # ref as first arg. Skip arg if undef or a hash ref.
1745             my $attr;
1746             $attr = shift if !defined $_[0] or ref($_[0]) eq 'HASH';
1747              
1748             my $idx = 0;
1749             $sth->bind_col(++$idx, shift, $attr) or return
1750             while (@_ and $idx < $fields);
1751              
1752             return $sth->set_err($DBI::stderr, "bind_columns called with ".($idx+@_)." values but $fields are needed")
1753             if @_ or $idx != $fields;
1754              
1755             return 1;
1756             }
1757              
1758             sub execute_array {
1759             my $sth = shift;
1760             my ($attr, @array_of_arrays) = @_;
1761             my $NUM_OF_PARAMS = $sth->FETCH('NUM_OF_PARAMS'); # may be undef at this point
1762              
1763             # get tuple status array or hash attribute
1764             my $tuple_sts = $attr->{ArrayTupleStatus};
1765             return $sth->set_err($DBI::stderr, "ArrayTupleStatus attribute must be an arrayref")
1766             if $tuple_sts and ref $tuple_sts ne 'ARRAY';
1767              
1768             # bind all supplied arrays
1769             if (@array_of_arrays) {
1770             $sth->{ParamArrays} = { }; # clear out old params
1771             return $sth->set_err($DBI::stderr,
1772             @array_of_arrays." bind values supplied but $NUM_OF_PARAMS expected")
1773             if defined ($NUM_OF_PARAMS) && @array_of_arrays != $NUM_OF_PARAMS;
1774             $sth->bind_param_array($_, $array_of_arrays[$_-1]) or return
1775             foreach (1..@array_of_arrays);
1776             }
1777              
1778             my $fetch_tuple_sub;
1779              
1780             if ($fetch_tuple_sub = $attr->{ArrayTupleFetch}) { # fetch on demand
1781              
1782             return $sth->set_err($DBI::stderr,
1783             "Can't use both ArrayTupleFetch and explicit bind values")
1784             if @array_of_arrays; # previous bind_param_array calls will simply be ignored
1785              
1786             if (UNIVERSAL::isa($fetch_tuple_sub,'DBI::st')) {
1787             my $fetch_sth = $fetch_tuple_sub;
1788             return $sth->set_err($DBI::stderr,
1789             "ArrayTupleFetch sth is not Active, need to execute() it first")
1790             unless $fetch_sth->{Active};
1791             # check column count match to give more friendly message
1792             my $NUM_OF_FIELDS = $fetch_sth->{NUM_OF_FIELDS};
1793             return $sth->set_err($DBI::stderr,
1794             "$NUM_OF_FIELDS columns from ArrayTupleFetch sth but $NUM_OF_PARAMS expected")
1795             if defined($NUM_OF_FIELDS) && defined($NUM_OF_PARAMS)
1796             && $NUM_OF_FIELDS != $NUM_OF_PARAMS;
1797             $fetch_tuple_sub = sub { $fetch_sth->fetchrow_arrayref };
1798             }
1799             elsif (!UNIVERSAL::isa($fetch_tuple_sub,'CODE')) {
1800             return $sth->set_err($DBI::stderr, "ArrayTupleFetch '$fetch_tuple_sub' is not a code ref or statement handle");
1801             }
1802              
1803             }
1804             else {
1805             my $NUM_OF_PARAMS_given = keys %{ $sth->{ParamArrays} || {} };
1806             return $sth->set_err($DBI::stderr,
1807             "$NUM_OF_PARAMS_given bind values supplied but $NUM_OF_PARAMS expected")
1808             if defined($NUM_OF_PARAMS) && $NUM_OF_PARAMS != $NUM_OF_PARAMS_given;
1809              
1810             # get the length of a bound array
1811             my $maxlen;
1812             my %hash_of_arrays = %{$sth->{ParamArrays}};
1813             foreach (keys(%hash_of_arrays)) {
1814             my $ary = $hash_of_arrays{$_};
1815             next unless ref $ary eq 'ARRAY';
1816             $maxlen = @$ary if !$maxlen || @$ary > $maxlen;
1817             }
1818             # if there are no arrays then execute scalars once
1819             $maxlen = 1 unless defined $maxlen;
1820             my @bind_ids = 1..keys(%hash_of_arrays);
1821              
1822             my $tuple_idx = 0;
1823             $fetch_tuple_sub = sub {
1824             return if $tuple_idx >= $maxlen;
1825             my @tuple = map {
1826             my $a = $hash_of_arrays{$_};
1827             ref($a) ? $a->[$tuple_idx] : $a
1828             } @bind_ids;
1829             ++$tuple_idx;
1830             return \@tuple;
1831             };
1832             }
1833             # pass thru the callers scalar or list context
1834             return $sth->execute_for_fetch($fetch_tuple_sub, $tuple_sts);
1835             }
1836              
1837             sub execute_for_fetch {
1838             my ($sth, $fetch_tuple_sub, $tuple_status) = @_;
1839             # start with empty status array
1840             ($tuple_status) ? @$tuple_status = () : $tuple_status = [];
1841              
1842             my $rc_total = 0;
1843             my $err_count;
1844             while ( my $tuple = &$fetch_tuple_sub() ) {
1845             if ( my $rc = $sth->execute(@$tuple) ) {
1846             push @$tuple_status, $rc;
1847             $rc_total = ($rc >= 0 && $rc_total >= 0) ? $rc_total + $rc : -1;
1848             }
1849             else {
1850             $err_count++;
1851             push @$tuple_status, [ $sth->err, $sth->errstr, $sth->state ];
1852             # XXX drivers implementing execute_for_fetch could opt to "last;" here
1853             # if they know the error code means no further executes will work.
1854             }
1855             }
1856             my $tuples = @$tuple_status;
1857             return $sth->set_err($DBI::stderr, "executing $tuples generated $err_count errors")
1858             if $err_count;
1859             $tuples ||= "0E0";
1860             return $tuples unless wantarray;
1861             return ($tuples, $rc_total);
1862             }
1863              
1864              
1865             sub fetchall_arrayref { # ALSO IN Driver.xst
1866             my ($sth, $slice, $max_rows) = @_;
1867              
1868             # when batch fetching with $max_rows were very likely to try to
1869             # fetch the 'next batch' after the previous batch returned
1870             # <=$max_rows. So don't treat that as an error.
1871             return undef if $max_rows and not $sth->FETCH('Active');
1872              
1873             my $mode = ref($slice) || 'ARRAY';
1874             my @rows;
1875             my $row;
1876             if ($mode eq 'ARRAY') {
1877             # we copy the array here because fetch (currently) always
1878             # returns the same array ref. XXX
1879             if ($slice && @$slice) {
1880             $max_rows = -1 unless defined $max_rows;
1881             push @rows, [ @{$row}[ @$slice] ]
1882             while($max_rows-- and $row = $sth->fetch);
1883             }
1884             elsif (defined $max_rows) {
1885             push @rows, [ @$row ]
1886             while($max_rows-- and $row = $sth->fetch);
1887             }
1888             else {
1889             push @rows, [ @$row ] while($row = $sth->fetch);
1890             }
1891             }
1892             elsif ($mode eq 'HASH') {
1893             $max_rows = -1 unless defined $max_rows;
1894             if (keys %$slice) {
1895             my @o_keys = keys %$slice;
1896             my @i_keys = map { lc } keys %$slice;
1897             # XXX this could be made faster by pre-binding a local hash
1898             # using bind_columns and then copying it per row
1899             while ($max_rows-- and $row = $sth->fetchrow_hashref('NAME_lc')) {
1900             my %hash;
1901             @hash{@o_keys} = @{$row}{@i_keys};
1902             push @rows, \%hash;
1903             }
1904             }
1905             else {
1906             # XXX assumes new ref each fetchhash
1907             push @rows, $row
1908             while ($max_rows-- and $row = $sth->fetchrow_hashref());
1909             }
1910             }
1911             else { Carp::croak("fetchall_arrayref($mode) invalid") }
1912             return \@rows;
1913             }
1914              
1915             sub fetchall_hashref {
1916             my ($sth, $key_field) = @_;
1917              
1918             my $hash_key_name = $sth->{FetchHashKeyName} || 'NAME';
1919             my $names_hash = $sth->FETCH("${hash_key_name}_hash");
1920             my @key_fields = (ref $key_field) ? @$key_field : ($key_field);
1921             my @key_indexes;
1922             my $num_of_fields = $sth->FETCH('NUM_OF_FIELDS');
1923             foreach (@key_fields) {
1924             my $index = $names_hash->{$_}; # perl index not column
1925             $index = $_ - 1 if !defined $index && DBI::looks_like_number($_) && $_>=1 && $_ <= $num_of_fields;
1926             return $sth->set_err($DBI::stderr, "Field '$_' does not exist (not one of @{[keys %$names_hash]})")
1927             unless defined $index;
1928             push @key_indexes, $index;
1929             }
1930             my $rows = {};
1931             my $NAME = $sth->FETCH($hash_key_name);
1932             my @row = (undef) x $num_of_fields;
1933             $sth->bind_columns(\(@row));
1934             while ($sth->fetch) {
1935             my $ref = $rows;
1936             $ref = $ref->{$row[$_]} ||= {} for @key_indexes;
1937             @{$ref}{@$NAME} = @row;
1938             }
1939             return $rows;
1940             }
1941              
1942             *dump_results = \&DBI::dump_results;
1943              
1944             sub blob_copy_to_file { # returns length or undef on error
1945             my($self, $field, $filename_or_handleref, $blocksize) = @_;
1946             my $fh = $filename_or_handleref;
1947             my($len, $buf) = (0, "");
1948             $blocksize ||= 512; # not too ambitious
1949             local(*FH);
1950             unless(ref $fh) {
1951             open(FH, ">$fh") || return undef;
1952             $fh = \*FH;
1953             }
1954             while(defined($self->blob_read($field, $len, $blocksize, \$buf))) {
1955             print $fh $buf;
1956             $len += length $buf;
1957             }
1958             close(FH);
1959             $len;
1960             }
1961              
1962             sub more_results {
1963             shift->{syb_more_results}; # handy grandfathering
1964             }
1965              
1966             }
1967              
1968             unless ($DBI::PurePerl) { # See install_driver
1969             { @DBD::_mem::dr::ISA = qw(DBD::_mem::common); }
1970             { @DBD::_mem::db::ISA = qw(DBD::_mem::common); }
1971             { @DBD::_mem::st::ISA = qw(DBD::_mem::common); }
1972             # DBD::_mem::common::DESTROY is implemented in DBI.xs
1973             }
1974              
1975             1;
1976             __END__