Author: timbo
Date: Sat Jul 10 14:15:09 2004
New Revision: 379
Modified:
dbi/trunk/Changes
dbi/trunk/DBI.pm
dbi/trunk/ToDo
dbi/trunk/t/15array.t
Log:
Changed bind_param_array() so it doesn't require all bind arrays
to have the same number of elements.
Changed execute_array() definition, and default implementation,
to effectively NULL-pad shorter bind arrays.
Changed execute_array() to return "0E0" for 0 as per the docs.
Changed execute_for_fetch() definition, and default implementation,
to return "0E0" for 0 like execute() and execute_array().
Modified: dbi/trunk/Changes
==============================================================================
--- dbi/trunk/Changes (original)
+++ dbi/trunk/Changes Sat Jul 10 14:15:09 2004
@@ -4,6 +4,16 @@
=cut
+=head1 CHANGES in DBI 1.44 (svn rev ???), XXX
+
+ Changed bind_param_array() so it doesn't require all bind arrays
+ to have the same number of elements.
+ Changed execute_array() definition, and default implementation,
+ to effectively NULL-pad shorter bind arrays.
+ Changed execute_array() to return "0E0" for 0 as per the docs.
+ Changed execute_for_fetch() definition, and default implementation,
+ to return "0E0" for 0 like execute() and execute_array().
+
=head1 CHANGES in DBI 1.43 (svn rev 377), 2nd July 2004
Fixed connect() and connect_cached() RaiseError/PrintError
@@ -30,7 +40,7 @@
Changed all tests to use Test::More and enhanced the tests thanks
to Stevan Little and Andy Lester. See http://qa.perl.org/phalanx/
Changed Test::More minimum prerequisite version to 0.40 (2001).
- Change DBI::Profile header to include timestamp.
+ Changed DBI::Profile header to include the date and time.
Added DBI->parse_dsn($dsn) method.
Added warning if build directory path contains whitespace.
Modified: dbi/trunk/DBI.pm
==============================================================================
--- dbi/trunk/DBI.pm (original)
+++ dbi/trunk/DBI.pm Sat Jul 10 14:15:09 2004
@@ -1655,19 +1655,6 @@
# get/create arrayref to hold params
my $hash_of_arrays = $sth->{ParamArrays} ||= { };
- if (ref $value_array eq 'ARRAY') {
- # check that input has same length as existing
- # find first arrayref entry (if any)
- foreach (keys %$hash_of_arrays) {
- my $v = $$hash_of_arrays{$_};
- next unless ref $v eq 'ARRAY';
- return $sth->set_err(1,
- "Arrayref for parameter $p_id has "[EMAIL PROTECTED]" elements"
- ." but parameter $_ has "[EMAIL PROTECTED])
- if @$value_array != @$v;
- }
- }
-
# If the bind has attribs then we rely on the driver conforming to
# the DBI spec in that a single bind_param() call with those attribs
# makes them 'sticky' and apply to all later execute(@values) calls.
@@ -1763,17 +1750,18 @@
if defined($NUM_OF_PARAMS) && $NUM_OF_PARAMS != $NUM_OF_PARAMS_given;
# get the length of a bound array
- my $len = 1; # in case all are scalars
+ my $maxlen = 0;
my %hash_of_arrays = %{$sth->{ParamArrays}};
foreach (keys(%hash_of_arrays)) {
my $ary = $hash_of_arrays{$_};
- $len = @$ary if ref $ary eq 'ARRAY';
+ my $len = (ref $ary eq 'ARRAY') ? @$ary : 1;
+ $maxlen = $len if $len > $maxlen;
}
my @bind_ids = 1..keys(%hash_of_arrays);
my $tuple_idx = 0;
$fetch_tuple_sub = sub {
- return if $tuple_idx >= $len;
+ return if $tuple_idx >= $maxlen;
my @tuple = map {
my $a = $hash_of_arrays{$_};
ref($a) ? $a->[$tuple_idx] : $a
@@ -1802,7 +1790,7 @@
push @$tuple_status, [ $err, $errstr_cache{$err} ||= $sth->errstr,
$sth->state ];
}
}
- return ($err_count) ? undef : scalar @$tuple_status;
+ return ($err_count) ? undef : scalar(@$tuple_status)||"0E0";
}
@@ -4884,10 +4872,6 @@
WHERE bar IN (?)". A placeholder can only ever represent one value
per execution.)
-Each array bound to the statement must have the same number of
-elements. Some drivers may define a method attribute to relax this
-safety check.
-
Scalar values, including C<undef>, may also be bound by
C<bind_param_array>. In which case the same value will be used for each
L</execute> call. Driver-specific implementations may behave
@@ -4903,7 +4887,7 @@
documentation as there may be driver specific issues to consider.
Note that the default implementation currently only supports non-data
-returning statements (insert, update, but not select). Also,
+returning statements (INSERT, UPDATE, but not SELECT). Also,
C<bind_param_array> and L</bind_param> cannot be mixed in the same
statement execution, and C<bind_param_array> must be used with
L</execute_array>; using C<bind_param_array> will have no effect
@@ -4963,9 +4947,16 @@
attribute below for how to determine the execution status for each
tuple.
-Bind values for the tuples to be executed may be supplied by an
-C<ArrayTupleFetch> attribute, or else in the C<@bind_values> argument,
-or else by prior calls to L</bind_param_array>.
+Bind values for the tuples to be executed may be supplied row-wise
+by an C<ArrayTupleFetch> attribute, or else column-wise in the
+C<@bind_values> argument, or else column-wise by prior calls to
+L</bind_param_array>.
+
+Where column-wise binding is used (via the C<@bind_values> argument
+or calls to bind_param_array()) the maximum number of elements in
+any one of the bound value arrays determines the number of tuples
+executed. Placeholders with fewer values in their parameter arrays
+are treated as if padded with undef (NULL) values.
The C<ArrayTupleFetch> attribute can be used to specify a reference
to a subroutine that will be called to provide the bind values for
@@ -5031,7 +5022,7 @@
}
}
-Support for data returning statements, i.e., select, is driver-specific
+Support for data returning statements such as SELECT is driver-specific
and subject to change. At present, the default implementation
provided by DBI only supports non-data returning statements.
@@ -5071,9 +5062,11 @@
parameters, until it returns a false value. Each tuple returned is
used to provide bind values for an $sth->execute(@$tuple) call.
-The number of tuples executed is returned I<only if> there were no errors.
If there were any errors then C<undef> is returned and the @tuple_status
array can be used to discover which tuples failed and with what errors.
+If there were no errors then execute_for_fetch() returns the number
+of tuples executed. Like execute() and execute_array() a zero is
+returned as "0E0" so execute_for_fetch() is only false on error.
If [EMAIL PROTECTED] is passed then the execute_for_fetch method uses
it to return status information. The tuple_status array holds one
Modified: dbi/trunk/ToDo
==============================================================================
--- dbi/trunk/ToDo (original)
+++ dbi/trunk/ToDo Sat Jul 10 14:15:09 2004
@@ -415,8 +415,12 @@
Add %time to per-node DBI::Profile dump
-DBI::Profile: some way to get count of 'executions' only, not all method calls.
-So avg time is totaltime/executions not totaltime/methodcalls.
+Add 'executer' and 'fetcher' method attributes and increment
+corresponding counters in DBIS when method with those attributes
+are called. When profiling record in the profile data the amount
+they have incremented.
+Add DBI_PROFILE option so count is executions and avg time can be
+totaltime/executions not totaltime/methodcalls.
DBI::Profile: add simple way to normalise the sql (convert constants
to placeholders) so profiling is more effective for drivers/applications
Modified: dbi/trunk/t/15array.t
==============================================================================
--- dbi/trunk/t/15array.t (original)
+++ dbi/trunk/t/15array.t Sat Jul 10 14:15:09 2004
@@ -2,7 +2,7 @@
use strict;
-use Test::More tests => 42;
+use Test::More tests => 47;
## ----------------------------------------------------------------------------
## 15array.t
@@ -24,6 +24,7 @@
# check that our db handle is good
isa_ok($dbh, "DBI::db");
+my $rv;
my $rows = [];
my $tuple_status = [];
my $dumped;
@@ -97,12 +98,26 @@
# --- with no values for bind params, should execute zero times
@$rows = ();
-ok(!$sth->execute_array( { ArrayTupleStatus => $tuple_status }, [], [], [], []), '...
execute_array should return false');
+$rv = $sth->execute_array( { ArrayTupleStatus => $tuple_status }, [], [], [], []);
+ok($rv, '... execute_array should return true');
+ok(!($rv+0), '... execute_array should return 0 (but true)');
cmp_ok(scalar @{$rows}, '==', 0, '... we should have 0 rows');
cmp_ok(scalar @{$tuple_status}, '==', 0,'... we should have 0 tuple_status');
# -----------------------------------------------
+# --- with only scalar values for bind params, should execute just once
+
[EMAIL PROTECTED] = ();
+$rv = $sth->execute_array( { ArrayTupleStatus => $tuple_status }, 5, 6, 7, 8);
+cmp_ok($rv, '==', 1, '... execute_array should return 1');
+
+cmp_ok(scalar @{$rows}, '==', 1, '... we should have 1 rows');
+ok(eq_array( $rows, [ [5,6,7,8] ]), '... our rows are as expected');
+cmp_ok(scalar @{$tuple_status}, '==', 1,'... we should have 1 tuple_status');
+ok(eq_array( $tuple_status, [1]), '... our tuple_status is as expected');
+
+# -----------------------------------------------
# --- catch 'undefined value' bug with zero bind values
@$rows = ();
@@ -113,7 +128,9 @@
isa_ok($sth_other, "DBI::st");
-ok(!$sth_other->execute_array( {}, [] ), '... execute_array should return false');
+$rv = $sth_other->execute_array( {}, [] );
+ok($rv, '... execute_array should return true');
+ok(!($rv+0), '... execute_array should return 0 (but true)');
# no ArrayTupleStatus
cmp_ok(scalar @{$rows}, '==', 0, '... we should have 0 rows');
@@ -206,9 +223,6 @@
ok(!defined $sth->execute_array( { ArrayTupleStatus => $tuple_status }, 1,{},3,4),
'... execute_array should return undef');
is( $sth->errstr, 'Value for parameter 2 must be a scalar or an arrayref, not a
HASH', '... errstr is as expected');
-ok(!defined $sth->execute_array( { ArrayTupleStatus => $tuple_status },
1,[1],[2,2],3), '... execute_array should return undef');
-is( $sth->errstr, 'Arrayref for parameter 3 has 2 elements but parameter 2 has 1',
'... errstr is as expected');
-
ok(!defined $sth->bind_param_array(":foo", [ qw(a b c) ]), '... bind_param_array
should return undef');
is( $sth->errstr, "Can't use named placeholders for non-driver supported
bind_param_array", '... errstr is as expected');