[php-src] master: ext/pdo_pgsql: Convert integer columns without strtoll()

From: Date: Thu, 22 Oct 2026 13:25:40 +0000
Subject: [php-src] master: ext/pdo_pgsql: Convert integer columns without strtoll()
Groups: php.cvs 
Request: Send a blank email to php-cvs+get-142574@lists.php.net to get a copy of this message
Author: Matthias Dötsch (brainexe) Committer: David Carlier (devnexen) Date: 2026-10-22T14:25:10+01:00 Commit: https://github.com/php/php-src/commit/c0018beb1185031bcf40cffa2ffd00d66873f517 Raw diff: https://github.com/php/php-src/commit/c0018beb1185031bcf40cffa2ffd00d66873f517.diff ext/pdo_pgsql: Convert integer columns without strtoll() 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 Changed paths: A ext/pdo_pgsql/tests/fetch_integers.phpt M NEWS M UPGRADING M ext/pdo_pgsql/pgsql_statement.c Diff: diff --git a/NEWS b/NEWS index 67896bb73a85..5155d8ede346 100644 --- a/NEWS +++ b/NEWS @@ -91,6 +91,7 @@ PHP NEWS - PDO_PGSQL: . Improved performance of the SQL parser that handles placeholders. (brainexe) + . Improved performance of fetching integer columns. (brainexe) - PGSQL: . Fixed pg_lo_write() rejecting data containing null bytes. (Ilia Alshanetsky) diff --git a/UPGRADING b/UPGRADING index 60b7020cb1e3..a232e35aa00c 100644 --- a/UPGRADING +++ b/UPGRADING @@ -176,3 +176,4 @@ PHP 8.7 UPGRADE NOTES - PDO_PGSQL: . Improved performance of the SQL parser that handles placeholders in PDO::prepare() and, with emulated prepares, PDOStatement::execute(). + . Improved performance of fetching integer columns. diff --git a/ext/pdo_pgsql/pgsql_statement.c b/ext/pdo_pgsql/pgsql_statement.c index de7d03bc7264..15d9916a5c2e 100644 --- a/ext/pdo_pgsql/pgsql_statement.c +++ b/ext/pdo_pgsql/pgsql_statement.c @@ -758,8 +758,17 @@ static int pgsql_stmt_get_col(pdo_stmt_t *stmt, int colno, zval *result, enum pd #if SIZEOF_ZEND_LONG >= 8 case INT8OID: #endif - ZVAL_LONG(result, ZEND_ATOL(ptr)); + { + /* PostgreSQL sends integers in canonical decimal form, which the numeric array key + * parser handles without the overhead of strtoll() */ + zend_ulong lval; + if (EXPECTED(ZEND_HANDLE_NUMERIC_STR(ptr, len, lval))) { + ZVAL_LONG(result, (zend_long) lval); + } else { + ZVAL_LONG(result, ZEND_ATOL(ptr)); + } break; + } case FLOAT4OID: case FLOAT8OID: if (strncmp(ptr, "Infinity", len) == 0) { diff --git a/ext/pdo_pgsql/tests/fetch_integers.phpt b/ext/pdo_pgsql/tests/fetch_integers.phpt new file mode 100644 index 000000000000..54287dc200ea --- /dev/null +++ b/ext/pdo_pgsql/tests/fetch_integers.phpt @@ -0,0 +1,56 @@ +--TEST-- +PDO PgSQL: integer columns at their boundaries +--EXTENSIONS-- +pdo_pgsql +--SKIPIF-- +<?php +if (PHP_INT_SIZE < 8) die('skip 64-bit only'); +require __DIR__ . '/config.inc'; +require dirname(__DIR__, 2) . '/pdo/tests/pdo_test.inc'; +PDOTest::skip(); +?> +--FILE-- +<?php +require __DIR__ . '/../../../ext/pdo/tests/pdo_test.inc'; +$db = PDOTest::test_factory(__DIR__ . '/common.phpt'); +$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); +$db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false); + +$stmt = $db->query(<<<'SQL' +SELECT 0::int2, (-1)::int2, (-32768)::int2, 32767::int2, + (-2147483648)::int4, 2147483647::int4, 7::int4, + 999999999999999999::int8, (-999999999999999999)::int8, + 1000000000000000000::int8, (-1000000000000000000)::int8, + 9223372036854775807::int8, '-9223372036854775808'::int8 +SQL); +var_dump($stmt->fetch(PDO::FETCH_NUM)); +?> +--EXPECT-- +array(13) { + [0]=> + int(0) + [1]=> + int(-1) + [2]=> + int(-32768) + [3]=> + int(32767) + [4]=> + int(-2147483648) + [5]=> + int(2147483647) + [6]=> + int(7) + [7]=> + int(999999999999999999) + [8]=> + int(-999999999999999999) + [9]=> + int(1000000000000000000) + [10]=> + int(-1000000000000000000) + [11]=> + int(9223372036854775807) + [12]=> + int(-9223372036854775808) +}

« previous php.cvs (#142574) next »