dispatch_param_event iterates bound_params with ZEND_HASH_FOREACH
while sqlite's EXEC_PRE hook can run __toString; execute() then
destroys the table and bindValue() replaces buckets. Steal one
_reserved bit as in_param_event (no layout size change; the header
is installed) and throw Error from bindParam, bindValue, bindColumn,
execute, and closeCursor while the hook is running. fetch is left
unguarded: nested FOREACH is read-only and FETCH_POST writes column
zvals, not the HashTable. 8.5/master already have a uint16_t
bitfield with in_fetch; the forward merge needs in_param_event:1
and reserved:11.
Closes GH-23252
PDOStatement::execute() returned false on a bind, parse, or driver
failure without clearing stmt->executed, so a later fetch returned rows
from the previous success. Close the previous result on entry, before
the error state is cleared, so a cursor closer that records an error
cannot replace the SQLSTATE of the failure execute() reports.
Closes GH-23938
A column name that is not in the result set is a programming error, so
report it the way the method already reports an empty name or an index
below one, rather than through PDO::ATTR_ERRMODE. The equivalent parameter
failure in bindParam() and bindValue() stays an ERRMODE error: its site in
rewrite_name_to_position() is only reachable once execute() has populated
bound_param_map, never from the bind methods themselves.
Closes GH-23835
bindParam() and bindColumn() copied the driver options zval and then
addref'd it again. The extra reference kept the value alive after the
statement was destroyed. Keep the single reference from the copy.
Closes GH-23936
zend_call_function() ran the callback with fci_cache->object as $this
without holding a reference, so a callback that released the last
reference to its own receiver (an autoloader unregistering itself, a
SQLite3 authorizer calling setAuthorizer(null)) freed $this while its
frame was still executing. Take the reference where the receiver is
selected rather than after argument setup, so the error handlers
reachable from the deprecation notice and the by-reference warning
cannot free it first, and release it on every early exit.
Fixes GH-22060
Fixes GH-22122
pdo_raise_impl_error stored the SQLSTATE then still emitted E_WARNING
even when the handle error mode was SILENT. The early return for SILENT
was present but disabled (#if 0). Copy the error code first so
errorInfo() remains valid, then return without warning.
Closes GH-23070
This is the pdo equivalent of GH-22045. Notably it does not include a
change for the blob call because ZVAL_STRINGL_FAST already takes care of
that implicitly.
Negate after casting to unsigned instead of before, avoiding signed
integer overflow when offset is ZEND_LONG_MIN. The same pattern existed
in the pdo_sqlite and sqlite3 stream seek handlers.
Closes GH-20964
Closes GH-20927
- Added SKIPIF sections for tests that use Pdo\Sqlite::DETERMINISTIC
as it is available since libsqlite 3.8.3.
- Removed outdated SKIPIF sections for libsqlite versions 3.7.4
When using libsqlite 3.7.17 there are two more failing tests due to
different warning messages:
- ext/sqlite3/tests/sqlite3_38_extended_error.phpt
- ext/sqlite3/tests/sqlite3_39_toggleExtended.phpt
This fix doesn't address these as minimum required libsqlite will be
updated in the future PHP versions anyway at some point and this won't
be an issue anymore then.
Disable resource-heavy tests by default (>1GB of memory usage), unless the
RUN_RESOURCE_HEAVY_TESTS env variable is set.
Fixes GH-20762
Closes GH-20935
As of PHP 8.5 the minimum required SQLite library is 3.7.17, and this
removes the following preprocessor macros checks:
- HAVE_SQLITE3_CLOSE_V2 (sqlite3_close_v2() function is available since
SQLite 3.7.14.)
- HAVE_SQLITE3_ERRSTR (sqlite3_errstr() function is available since
SQLite 3.7.15)
- SQLITE_VERSION_NUMBER should be now always greater than 3006011
(3.6.11).
From what I see the incorrect scope is not observable in any other way. The
mixin methods are completely invisible to Reflection and a SQLite function
referring to a private method is still properly called as before.
Fixesphp/php-src#20095.
* Reduce code bloat in arginfo by using specialised string releases
Comparing this patch to master (c7da728574),
with a plain configure command without any options:
```
text data bss dec hex filename
20683738 1592400 137712 22413850 156021a sapi/cli/php
20688522 1592400 137712 22418634 15614ca sapi/cli/php_old
```
We see a minor reduction of 0.023% in code size.
* Also use true for the other initialization line
* Also use specialized code for consts
This commit implements GH-8967.
SQLite supports multiple transaction modes. These include:
- DEFERRED (default) only acquires a lock when you start a read/write
- IMMEDIATE acquires a reserved lock
- EXCLUSIVE acquires an exclusive lock (stricter than immediate)
In WAL mode IMMEDIATE and EXCLUSIVE are identical.
One reason for wanting to specify a transaction mode is that SQLite
doesn't respect busy_timeout when a DEFERRED transaction tries to
upgrade a read lock to a write lock. Normally if you try to acquire a
lock and have busy_timeout configured, SQLite will wait for that period
until giving up and erroring out (SQLITE_BUSY). With DEFERRED, if you
have a transaction that first reads and there's a concurrent writer
while it's trying to upgrade to a write lock, you will immediately get
SQLITE_BUSY regardless of your busy_timeout.
Prior to this commit, the only available workarounds were:
- Using $pdo->exec("BEGIN IMMEDIATE TRANSACTION") instead of
$pdo->beginTransaction()
- Doing a dummy write at the start of each transaction so you don't get
stuck with a read lock
Both of those aren't very usable, especially in a framework context
where the user doesn't have complete control over how transactions are
started.
To address that, this commit adds four class constants to Pdo\Sqlite:
- ATTR_TRANSACTION_MODE -- a new attribute
- TRANSACTION_MODE_DEFERRED = 0
- TRANSACTION_MODE_IMMEDIATE = 1
- TRANSACTION_MODE_EXCLUSIVE = 2
These can be used as:
$pdo->setAttribute(
$pdo::ATTR_TRANSACTION_MODE,
$pdo::TRANSACTION_MODE_IMMEDIATE
);
When global constants' or class constants' availability is based on some
preprocessor condition, the generated arginfo header files wrap the
declarations in the preprocessor `#if` conditional blocks, one per declaration,
even if they are in the same conditional block based on comments in the stub
file. Instead of having multiple conditional blocks one after the other with
the same condition, combine them into a single conditional block.