PostgreSQL sends int2/int4/int8 values in text format in canonical
decimal form: an optional minus sign followed by digits without leading
zeros. That is exactly what ZEND_HANDLE_NUMERIC_STR() accepts for
numeric array keys, including the range check. Use it instead of
calling strtoll() through ZEND_ATOL() for every value, and keep
ZEND_ATOL() as fallback for anything else.
fetchAll(PDO::FETCH_ASSOC) of 1M rows with 4 integer columns:
-11% instructions, -9% cycles.
Close GH-24385
The destructor of a statement created with
[PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL] tried to close the cursor even
when it did not exist. The attempted close causes an error on the server
that the destructor discards, so it cannot be observed by the user, but
inside a transaction it leaves subsequent statements failing for a reason
nobody can see.
is_prepared was overloaded to also mean "cursor declared" and was never
reset, so the cursor state now has its own flag. A close that fails no
longer aborts the caller's transaction.
Close GH-23490
Generalizes the lazy fetch added in GH-15287 by letting a statement choose
how many rows it fetches per chunk, trading memory for speed. ext/pgsql
already exposed this as pg_set_chunked_rows_size(); ext/pdo_pgsql had no
way to reach it.
ATTR_PREFETCH and ATTR_CHUNK_SIZE replace each other: setting one on the
connection clears the other, a statement given either does not inherit the
connection's value, and a chunk size of 1 or more wins when both are set on
the same statement. A chunk size cannot be combined with a statement-level
PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL, which throws a ValueError; a
connection-level chunk size is simply disabled by a scrollable statement.
Requires libpq 17 or later.
Close GH-23210
With PDO::ATTR_PREFETCH => 0 a statement streams its result set, and the
cleanup reads the rest of it by calling PQgetResult() until it returns
NULL. That never happens while the connection is copying: PQgetResult()
hands out a fresh COPY result every time. A COPY run through a lazy fetch
has therefore spun at 100% CPU since 8.5.0, as soon as another lazy fetch
takes the connection over. The copy has to be ended first: a copy in with
PQputCopyEnd(), a copy out by draining PQgetCopyData().
The drain was skipped as well, because is_running_unbuffered was cleared
first, both in the cleanup's own abort path and in pgsql_stmt_fetch()
before it calls the cleanup. With PDO::ATTR_EMULATE_PREPARES or
Pdo\Pgsql::ATTR_DISABLE_PREPARES the connection then stayed busy and the
next lazy fetch failed with "another command is already in progress".
The connection's pointer to the statement streaming on it was only cleared
while closing a server-side prepared statement, which those two modes do
not create, so destroying one left the pointer dangling for the next lazy
fetch to read. And a statement whose stream was taken over kept its row
counters after its result had been freed, so fetch() returned a row of
NULLs rather than false.
Close GH-23065
As stated in the UPGRADING, using the passthrough ("single-row") mode of libpq (introduced in #15287)
forbids passing a new query while the current one's results have not been entirely consumed.
… But I didn't notice that ext/pdo_pgsql internally used new queries to fetch metadata (example use case:
a call to getColumnMeta() while fetch()ing row by row will interleave the getColumnMeta()-triggered
internal query to the database, with the results fetching for the user-called query).
This PR makes those internal calls return NULL for non-essential metadata, instead of letting libpq abort the user-called query.
It moreover includes a small tweak to table oid-to-name translation, with a 1-slot cache.
This may by chance allow the internal call to return something instead of NULL,
but it will nonetheless avoid 30 server calls to get the table name of 30 columns of the same table.
optimize calls to foreach(columns of the same table) getColumnMeta()
- each call queried the DB to know the name associated with the table's OID:
cache the result between two calls
- make pdo_pgsql_translate_oid_to_table higher-level,
with the last parameter being the handle instead of the raw connection;
thus the statement is cleaner, letting the handle do all memory handling on the table oid-to-name translation cache
(which by the way is a driver feature more than a statement one)
close GH-16249
Make Pdo\PgSql accept Pdo::setAttribute(PDO::ATTR_PREFETCH, 0) to enter libpq's single row mode.
This avoids storing the whole result set in memory before being able to call the first fetch().
close GH-15750
PQclosePrepared allows the statement's name to be reused thus allowing
cache solutions to work properly ; whereas, for now, the `DEALLOCATE
<statement>` query is used which free entirely the statement's resources.
close GH-13316
* Include from build dir first
This fixes out of tree builds by ensuring that configure artifacts are included
from the build dir.
Before, out of tree builds would preferably include files from the src dir, as
the include path was defined as follows (ignoring includes from ext/ and sapi/) :
-I$(top_builddir)/main
-I$(top_srcdir)
-I$(top_builddir)/TSRM
-I$(top_builddir)/Zend
-I$(top_srcdir)/main
-I$(top_srcdir)/Zend
-I$(top_srcdir)/TSRM
-I$(top_builddir)/
As a result, an out of tree build would include configure artifacts such as
`main/php_config.h` from the src dir.
After this change, the include path is defined as follows:
-I$(top_builddir)/main
-I$(top_builddir)
-I$(top_srcdir)/main
-I$(top_srcdir)
-I$(top_builddir)/TSRM
-I$(top_builddir)/Zend
-I$(top_srcdir)/Zend
-I$(top_srcdir)/TSRM
* Fix extension include path for out of tree builds
* Include config.h with the brackets form
`#include "config.h"` searches in the directory containing the including-file
before any other include path. This can include the wrong config.h when building
out of tree and a config.h exists in the source tree.
Using `#include <config.h>` uses exclusively the include path, and gives
priority to the build dir.
PDO include paths can be simplified and synced as done in other
extensions: either the project root directory or the phpincludedir (for
the system installation). The 'ext' include is automatically appended
when doing phpize build. In php-src it is only present on Windows build.
The PHP_CHECK_PDO_INCLUDES is left intact working as before and checks
if PDO headers are found.
S->cols is already freed in the statement destructor and since
caa710037e the column data is only
populated on the first execute() which means that on subsequent
execute()s after closeCursor was called, all meta-data for column types
was removed and never restored
Closes GH-7355.
1. Update: http://www.php.net/license/3_01.txt to https, as there is anyway server header "Location:" to https.
2. Update few license 3.0 to 3.01 as 3.0 states "php 5.1.1, 4.1.1, and earlier".
3. In some license comments is "at through the world-wide-web" while most is without "at", so deleted.
4. fixed indentation in some files before |
We're starting to see a mix between uses of zend_bool and bool.
Replace all usages with the standard bool type everywhere.
Of course, zend_bool is retained as an alias.
Historically, the _ex variants separated the zval first, if a
conversion was necessary. This distinction no longer makes sense
since PHP 7.
The only difference that was still left is that _ex checked whether
the type is the same first, but the usage of these macros did not
actually distinguish on whether such an inlined check is valuable
or not in a given context.
Also drop the unused convert_to_explicit_type macros.
Instead of requiring the type to be determined in advance by the
describer function and then requiring get_col to return a buffer
of appropriate type, allow get_col to return an arbitrary zval.
See UPGRADING.INTERNALS for a more detailed description of the
change.
This makes the result fetching simpler, more efficient and more
flexible. The general possibility already existed via the special
PDO_PARAM_ZVAL type, but the usage was very inconvenient and/or
inefficient. Now it's possible to easily implement behavior like
"return int if it fits, otherwise string" and to avoid any kind
of complex management of temporary buffers.
This also fixes bug #40913 (our second highest voted bug of all
time, for some reason). PARAM_LOB result bindings will now
consistently return a stream resource, independently of the used
database driver.
I've tried my best to update all PDO drivers for this change, but
some of the changes may be broken, as I cannot test or even build
some of these drivers (in particular PDO dblib and PDO oci).
Fixes are appreciated -- a working CI setup would be even more
appreciated ;)
This allows reusing an existing zend_string inside a memory stream
without reallocating. For non-readonly streams, the string will
only get separated on write.
When a driver reports an error during EVT_ALLOC (and some over EVTs),
make sure we handle it as usual, i.e. warn or throw.
This requires some adjustments in PDO PgSQL to stop manually doing
this through an impl error.
Unfortunately the PDO PgSQL error messages regress because of this,
as they now include a completely arbitrary error code. There doesn't
seem to be an ability to skip it right now.
Added new flags that allow skipping param_evt(s) that are not used by drivers,
in a backwards and forward compatible manner. Updated the pgsql, mysql, sqlite
and oci drivers to properly use the new flags. I've left out pdo_dblib, which
doesn't have a param_hook, and pdo_firebird, which seems to be using
PARAM_EVT_NORMALIZE in a wrong context (param type vs event type).
Added new flags that allow skipping param_evt(s) that are not used by drivers,
in a backwards and forward compatible manner. Updated the pgsql, mysql, sqlite
and oci drivers to properly use the new flags. I've left out pdo_dblib, which
doesn't have a param_hook, and pdo_firebird, which seems to be using
PARAM_EVT_NORMALIZE in a wrong context (param type vs event type).