Subject: | $sth->rows() and rowcount correctness |
Issue:
Contrary to DBI specification, DBD::InterBase 0.48 does not return the
count of affected rows for UPDATE/INSERT/DELETE queries.
See "Background," below, for more information.
Fix/Attached Patch:
1) The attached patch modifies do(), execute() and $sth->rows (and so
$DBI::rows) to track the number of affected rows.
2) Current SELECT rowcount behavior is preserved, except that the return
from execute() is now zero ("0E0") rather than -1, which better reflects
the logic of DBD-InterBase (i.e., to return the no. rows fetched so far.
3) An new, approx. eighty point unit test file is added for
rows()/$DBI::rows/execute() behavior.
Existing unit tests are modified slightly to accommodate no. 2. FWIW,
those tests were written assuming that a rowcount after a SELECT would
be all or nothing, that is, a count reflecting every row matched or -1,
neither of which are what DBD-InterBase tries to do.
4) InterBase.pm POD is updated
5) DBD::InterBase::_do is dropped in favor of the implicit DBI+DSQL
prepare/execute pair for all invocations of $dbh->do().
Note that _do() in 0.48 still had an implicit *DSQL* prepare/execute
pair. If this patch is accepted, I'd say a future version should
restore _do() as an *isc_dsql_execute_immediate()* wrapper, supporting
parameters.
6) isc_dsql_execute2() is dropped in favor of isc_dsql_execute(), which
is in line with a scowling remark on the ibpheonix.com website detailing
the history of the IB API.
This broke no tests.
7) The one-time call to determine isc_info_sql_stmt_type is combined
with the first call to determine isc_info_sql_records.
This eliminates a network round-trip on a call to prepare().
Background:
DBD-InterBase's behavior of counting SELECTed rows fetched so far, and
returning -1 (here meaning "unknown") for modified rows is exactly the
opposite of long-standing DBI specification. Tracking SELECTed rows is
a permissible extension to the DBI, but omitting a count of rows
affected is not.
DBI 1.609 says of $sth->rows():
Generally, you can only rely on a row count after a
*non*-"SELECT" "execute" (for some specific operations
like "UPDATE" and "DELETE"), or after fetching all the
rows of a "SELECT" statement.
Emphasis in original.
Interestingly, this behavior is quite deliberate, introduced Aug 2000
and documented in InterBase.pm. The oldest DBI I could find, however,
(0.89) requires rows() to be accurate for modifying queries where possible.
Subject: | dbd-interbase-0_48-rowcount.patch |
Message body is not shown because it is too large.