From 2e97b020699a46ebe808e274f4159af1cfbd0361 Mon Sep 17 00:00:00 2001 From: Jesper Noordsij Date: Wed, 24 Sep 2025 21:03:39 +0200 Subject: [PATCH 01/10] Add polyfill for PDO driver specific sub class constants --- src/Php84/Resources/stubs/Pdo/Dblib.php | 26 +++++ src/Php84/Resources/stubs/Pdo/Firebird.php | 22 +++++ src/Php84/Resources/stubs/Pdo/Mysql.php | 38 +++++++ src/Php84/Resources/stubs/Pdo/Odbc.php | 24 +++++ src/Php84/Resources/stubs/Pdo/Pgsql.php | 20 ++++ src/Php84/Resources/stubs/Pdo/Sqlite.php | 26 +++++ tests/Php84/PdoTest.php | 109 +++++++++++++++++++++ 7 files changed, 265 insertions(+) create mode 100644 src/Php84/Resources/stubs/Pdo/Dblib.php create mode 100644 src/Php84/Resources/stubs/Pdo/Firebird.php create mode 100644 src/Php84/Resources/stubs/Pdo/Mysql.php create mode 100644 src/Php84/Resources/stubs/Pdo/Odbc.php create mode 100644 src/Php84/Resources/stubs/Pdo/Pgsql.php create mode 100644 src/Php84/Resources/stubs/Pdo/Sqlite.php create mode 100644 tests/Php84/PdoTest.php diff --git a/src/Php84/Resources/stubs/Pdo/Dblib.php b/src/Php84/Resources/stubs/Pdo/Dblib.php new file mode 100644 index 00000000..539089b3 --- /dev/null +++ b/src/Php84/Resources/stubs/Pdo/Dblib.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace Pdo; + +use PDO; + +if (\PHP_VERSION_ID < 80400) { + class Dblib + { + public const ATTR_CONNECTION_TIMEOUT = PDO::DBLIB_ATTR_CONNECTION_TIMEOUT; + public const ATTR_QUERY_TIMEOUT = PDO::DBLIB_ATTR_QUERY_TIMEOUT; + public const ATTR_STRINGIFY_UNIQUEIDENTIFIER = PDO::DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER; + public const ATTR_VERSION = PDO::DBLIB_ATTR_VERSION; + public const ATTR_TDS_VERSION = PDO::DBLIB_ATTR_TDS_VERSION; + public const ATTR_SKIP_EMPTY_ROWSETS = PDO::DBLIB_ATTR_SKIP_EMPTY_ROWSETS; + public const ATTR_DATETIME_CONVERT = PDO::DBLIB_ATTR_DATETIME_CONVERT; + } +} diff --git a/src/Php84/Resources/stubs/Pdo/Firebird.php b/src/Php84/Resources/stubs/Pdo/Firebird.php new file mode 100644 index 00000000..a39f089c --- /dev/null +++ b/src/Php84/Resources/stubs/Pdo/Firebird.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace Pdo; + +use PDO; + +if (\PHP_VERSION_ID < 80400) { + class Firebird + { + public const ATTR_DATE_FORMAT = PDO::FB_ATTR_DATE_FORMAT; + public const ATTR_TIME_FORMAT = PDO::FB_ATTR_TIME_FORMAT; + public const ATTR_TIMESTAMP_FORMAT = PDO::FB_ATTR_TIMESTAMP_FORMAT; + } +} diff --git a/src/Php84/Resources/stubs/Pdo/Mysql.php b/src/Php84/Resources/stubs/Pdo/Mysql.php new file mode 100644 index 00000000..c44597fc --- /dev/null +++ b/src/Php84/Resources/stubs/Pdo/Mysql.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace Pdo; + +use PDO; + +if (\PHP_VERSION_ID < 80400) { + class Mysql + { + public const ATTR_COMPRESS = PDO::MYSQL_ATTR_COMPRESS; + public const ATTR_DIRECT_QUERY = PDO::MYSQL_ATTR_DIRECT_QUERY; + public const ATTR_FOUND_ROWS = PDO::MYSQL_ATTR_FOUND_ROWS; + public const ATTR_IGNORE_SPACE = PDO::MYSQL_ATTR_IGNORE_SPACE; + public const ATTR_INIT_COMMAND = PDO::MYSQL_ATTR_INIT_COMMAND; + public const ATTR_LOCAL_INFILE = PDO::MYSQL_ATTR_LOCAL_INFILE; + public const ATTR_LOCAL_INFILE_DIRECTORY = PDO::MYSQL_ATTR_LOCAL_INFILE_DIRECTORY; + public const ATTR_MAX_BUFFER_SIZE = PDO::MYSQL_ATTR_MAX_BUFFER_SIZE; + public const ATTR_MULTI_STATEMENTS = PDO::MYSQL_ATTR_MULTI_STATEMENTS; + public const ATTR_READ_DEFAULT_FILE = PDO::MYSQL_ATTR_READ_DEFAULT_FILE; + public const ATTR_READ_DEFAULT_GROUP = PDO::MYSQL_ATTR_READ_DEFAULT_GROUP; + public const ATTR_SERVER_PUBLIC_KEY = PDO::MYSQL_ATTR_SERVER_PUBLIC_KEY; + public const ATTR_SSL_CA = PDO::MYSQL_ATTR_SSL_CA; + public const ATTR_SSL_CAPATH = PDO::MYSQL_ATTR_SSL_CAPATH; + public const ATTR_SSL_CERT = PDO::MYSQL_ATTR_SSL_CERT; + public const ATTR_SSL_CIPHER = PDO::MYSQL_ATTR_SSL_CIPHER; + public const ATTR_SSL_KEY = PDO::MYSQL_ATTR_SSL_KEY; + public const ATTR_SSL_VERIFY_SERVER_CERT = PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT; + public const ATTR_USE_BUFFERED_QUERY = PDO::MYSQL_ATTR_USE_BUFFERED_QUERY; + } +} diff --git a/src/Php84/Resources/stubs/Pdo/Odbc.php b/src/Php84/Resources/stubs/Pdo/Odbc.php new file mode 100644 index 00000000..f32cae48 --- /dev/null +++ b/src/Php84/Resources/stubs/Pdo/Odbc.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace Pdo; + +use PDO; + +if (\PHP_VERSION_ID < 80400) { + class Odbc + { + public const ATTR_USE_CURSOR_LIBRARY = PDO::ODBC_ATTR_USE_CURSOR_LIBRARY; + public const ATTR_ASSUME_UTF8 = PDO::ODBC_ATTR_ASSUME_UTF8; + public const SQL_USE_IF_NEEDED = PDO::ODBC_SQL_USE_IF_NEEDED; + public const SQL_USE_DRIVER = PDO::ODBC_SQL_USE_DRIVER; + public const SQL_USE_ODBC = PDO::ODBC_SQL_USE_ODBC; + } +} diff --git a/src/Php84/Resources/stubs/Pdo/Pgsql.php b/src/Php84/Resources/stubs/Pdo/Pgsql.php new file mode 100644 index 00000000..36256f2c --- /dev/null +++ b/src/Php84/Resources/stubs/Pdo/Pgsql.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace Pdo; + +use PDO; + +if (\PHP_VERSION_ID < 80400) { + class Pgsql + { + public const ATTR_DISABLE_PREPARES = PDO::PGSQL_ATTR_DISABLE_PREPARES; + } +} diff --git a/src/Php84/Resources/stubs/Pdo/Sqlite.php b/src/Php84/Resources/stubs/Pdo/Sqlite.php new file mode 100644 index 00000000..66c7a3ff --- /dev/null +++ b/src/Php84/Resources/stubs/Pdo/Sqlite.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace Pdo; + +use PDO; + +if (\PHP_VERSION_ID < 80400) { + class Sqlite + { + public const ATTR_EXTENDED_RESULT_CODES = PDO::SQLITE_ATTR_EXTENDED_RESULT_CODES; + public const ATTR_OPEN_FLAGS = PDO::SQLITE_ATTR_OPEN_FLAGS; + public const ATTR_READONLY_STATEMENT = PDO::SQLITE_ATTR_READONLY_STATEMENT; + public const DETERMINISTIC = PDO::SQLITE_DETERMINISTIC; + public const OPEN_READONLY = PDO::SQLITE_OPEN_READONLY; + public const OPEN_READWRITE = PDO::SQLITE_OPEN_READWRITE; + public const OPEN_CREATE = PDO::SQLITE_OPEN_CREATE; + } +} diff --git a/tests/Php84/PdoTest.php b/tests/Php84/PdoTest.php new file mode 100644 index 00000000..3c42a04b --- /dev/null +++ b/tests/Php84/PdoTest.php @@ -0,0 +1,109 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Polyfill\Tests\Php84; + +use PHPUnit\Framework\TestCase; + +class PdoTest extends TestCase +{ + /** + * @requires extension pdo_dblib + */ + public function testDblibConstants() + { + $this->assertSame(1000, \Pdo\Dblib::ATTR_CONNECTION_TIMEOUT); + $this->assertSame(1001, \Pdo\Dblib::ATTR_QUERY_TIMEOUT); + $this->assertSame(1002, \Pdo\Dblib::ATTR_STRINGIFY_UNIQUEIDENTIFIER); + $this->assertSame(1003, \Pdo\Dblib::ATTR_VERSION); + $this->assertSame(1004, \Pdo\Dblib::ATTR_TDS_VERSION); + $this->assertSame(1005, \Pdo\Dblib::ATTR_SKIP_EMPTY_ROWSETS); + $this->assertSame(1006, \Pdo\Dblib::ATTR_DATETIME_CONVERT); + } + + /** + * @requires extension pdo_firebird + */ + public function testFirebirdConstants() + { + $this->assertSame(1000, \Pdo\Firebird::ATTR_DATE_FORMAT); + $this->assertSame(1001, \Pdo\Firebird::ATTR_TIME_FORMAT); + $this->assertSame(1002, \Pdo\Firebird::ATTR_TIMESTAMP_FORMAT); + } + + /** + * @requires extension pdo_mysql + */ + public function testMysqlConstants() + { + $this->assertSame(1000, \Pdo\Mysql::ATTR_USE_BUFFERED_QUERY); + $this->assertSame(1001, \Pdo\Mysql::ATTR_LOCAL_INFILE); + $this->assertSame(1002, \Pdo\Mysql::ATTR_INIT_COMMAND); + $this->assertSame(1003, \Pdo\Mysql::ATTR_COMPRESS); + $this->assertSame(1004, \Pdo\Mysql::ATTR_DIRECT_QUERY); + $this->assertSame(1005, \Pdo\Mysql::ATTR_FOUND_ROWS); + $this->assertSame(1006, \Pdo\Mysql::ATTR_IGNORE_SPACE); + $this->assertSame(1007, \Pdo\Mysql::ATTR_SSL_KEY); + $this->assertSame(1008, \Pdo\Mysql::ATTR_SSL_CERT); + $this->assertSame(1009, \Pdo\Mysql::ATTR_SSL_CA); + $this->assertSame(1010, \Pdo\Mysql::ATTR_SSL_CAPATH); + $this->assertSame(1011, \Pdo\Mysql::ATTR_SSL_CIPHER); + $this->assertSame(1012, \Pdo\Mysql::ATTR_SERVER_PUBLIC_KEY); + $this->assertSame(1013, \Pdo\Mysql::ATTR_MULTI_STATEMENTS); + $this->assertSame(1014, \Pdo\Mysql::ATTR_SSL_VERIFY_SERVER_CERT); + $this->assertSame(1015, \Pdo\Mysql::ATTR_LOCAL_INFILE_DIRECTORY); + } + + /** + * @requires extension pdo_mysql + * @requires extension libmysqlclient + */ + public function testMysqlConstantsMysqlnd() + { + $this->assertSame(1003, \Pdo\Mysql::ATTR_READ_DEFAULT_FILE); + $this->assertSame(1004, \Pdo\Mysql::ATTR_READ_DEFAULT_GROUP); + $this->assertSame(1005, \Pdo\Mysql::ATTR_MAX_BUFFER_SIZE); + } + + /** + * @requires extension pdo_odbc + */ + public function testOdbcConstants() + { + $this->assertSame(0, \Pdo\Odbc::SQL_USE_IF_NEEDED); + $this->assertSame(1, \Pdo\Odbc::SQL_USE_ODBC); + $this->assertSame(2, \Pdo\Odbc::SQL_USE_DRIVER); + $this->assertSame(1000, \Pdo\Odbc::ATTR_USE_CURSOR_LIBRARY); + $this->assertSame(1001, \Pdo\Odbc::ATTR_ASSUME_UTF8); + } + + /** + * @requires extension pdo_pgsql + */ + public function testPgsqlConstants() + { + $this->assertSame(1000, \Pdo\Pgsql::ATTR_DISABLE_PREPARES); + } + + /** + * @requires extension pdo_sqlite + */ + public function testSqliteConstants() + { + $this->assertSame(1, \Pdo\Sqlite::OPEN_READONLY); + $this->assertSame(2, \Pdo\Sqlite::OPEN_READWRITE); + $this->assertSame(4, \Pdo\Sqlite::OPEN_CREATE); + $this->assertSame(1000, \Pdo\Sqlite::ATTR_OPEN_FLAGS); + $this->assertSame(1001, \Pdo\Sqlite::ATTR_READONLY_STATEMENT); + $this->assertSame(1002, \Pdo\Sqlite::ATTR_EXTENDED_RESULT_CODES); + $this->assertSame(2048, \Pdo\Sqlite::DETERMINISTIC); + } +} From edce4e34e85747f4c4030480f414134baa363b08 Mon Sep 17 00:00:00 2001 From: Jesper Noordsij Date: Wed, 24 Sep 2025 21:42:54 +0200 Subject: [PATCH 02/10] Fix compatibility with older PHP versions --- src/Php84/Resources/stubs/Pdo/Dblib.php | 6 +++--- src/Php84/Resources/stubs/Pdo/Mysql.php | 2 +- src/Php84/Resources/stubs/Pdo/Sqlite.php | 12 ++++++------ 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Php84/Resources/stubs/Pdo/Dblib.php b/src/Php84/Resources/stubs/Pdo/Dblib.php index 539089b3..d9fefd7a 100644 --- a/src/Php84/Resources/stubs/Pdo/Dblib.php +++ b/src/Php84/Resources/stubs/Pdo/Dblib.php @@ -19,8 +19,8 @@ class Dblib public const ATTR_QUERY_TIMEOUT = PDO::DBLIB_ATTR_QUERY_TIMEOUT; public const ATTR_STRINGIFY_UNIQUEIDENTIFIER = PDO::DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER; public const ATTR_VERSION = PDO::DBLIB_ATTR_VERSION; - public const ATTR_TDS_VERSION = PDO::DBLIB_ATTR_TDS_VERSION; - public const ATTR_SKIP_EMPTY_ROWSETS = PDO::DBLIB_ATTR_SKIP_EMPTY_ROWSETS; - public const ATTR_DATETIME_CONVERT = PDO::DBLIB_ATTR_DATETIME_CONVERT; + public const ATTR_TDS_VERSION = \PHP_VERSION_ID >= 70300 ? PDO::DBLIB_ATTR_TDS_VERSION : 1004; + public const ATTR_SKIP_EMPTY_ROWSETS = \PHP_VERSION_ID >= 70300 ? PDO::DBLIB_ATTR_SKIP_EMPTY_ROWSETS : 1005; + public const ATTR_DATETIME_CONVERT = \PHP_VERSION_ID >= 70300 ? \PDO::DBLIB_ATTR_DATETIME_CONVERT : 1006; } } diff --git a/src/Php84/Resources/stubs/Pdo/Mysql.php b/src/Php84/Resources/stubs/Pdo/Mysql.php index c44597fc..b4b22747 100644 --- a/src/Php84/Resources/stubs/Pdo/Mysql.php +++ b/src/Php84/Resources/stubs/Pdo/Mysql.php @@ -21,7 +21,7 @@ class Mysql public const ATTR_IGNORE_SPACE = PDO::MYSQL_ATTR_IGNORE_SPACE; public const ATTR_INIT_COMMAND = PDO::MYSQL_ATTR_INIT_COMMAND; public const ATTR_LOCAL_INFILE = PDO::MYSQL_ATTR_LOCAL_INFILE; - public const ATTR_LOCAL_INFILE_DIRECTORY = PDO::MYSQL_ATTR_LOCAL_INFILE_DIRECTORY; + public const ATTR_LOCAL_INFILE_DIRECTORY = \PHP_VERSION_ID >= 80100 ? \PDO::MYSQL_ATTR_LOCAL_INFILE_DIRECTORY : 1015; public const ATTR_MAX_BUFFER_SIZE = PDO::MYSQL_ATTR_MAX_BUFFER_SIZE; public const ATTR_MULTI_STATEMENTS = PDO::MYSQL_ATTR_MULTI_STATEMENTS; public const ATTR_READ_DEFAULT_FILE = PDO::MYSQL_ATTR_READ_DEFAULT_FILE; diff --git a/src/Php84/Resources/stubs/Pdo/Sqlite.php b/src/Php84/Resources/stubs/Pdo/Sqlite.php index 66c7a3ff..580d9111 100644 --- a/src/Php84/Resources/stubs/Pdo/Sqlite.php +++ b/src/Php84/Resources/stubs/Pdo/Sqlite.php @@ -15,12 +15,12 @@ if (\PHP_VERSION_ID < 80400) { class Sqlite { - public const ATTR_EXTENDED_RESULT_CODES = PDO::SQLITE_ATTR_EXTENDED_RESULT_CODES; - public const ATTR_OPEN_FLAGS = PDO::SQLITE_ATTR_OPEN_FLAGS; - public const ATTR_READONLY_STATEMENT = PDO::SQLITE_ATTR_READONLY_STATEMENT; + public const ATTR_EXTENDED_RESULT_CODES = \PHP_VERSION_ID >= 70400 ? \PDO::SQLITE_ATTR_EXTENDED_RESULT_CODES : 1002; + public const ATTR_OPEN_FLAGS = \PHP_VERSION_ID >= 70300 ? \PDO::SQLITE_ATTR_OPEN_FLAGS : 1000; + public const ATTR_READONLY_STATEMENT = \PHP_VERSION_ID >= 70400 ? \PDO::SQLITE_ATTR_READONLY_STATEMENT : 1001; public const DETERMINISTIC = PDO::SQLITE_DETERMINISTIC; - public const OPEN_READONLY = PDO::SQLITE_OPEN_READONLY; - public const OPEN_READWRITE = PDO::SQLITE_OPEN_READWRITE; - public const OPEN_CREATE = PDO::SQLITE_OPEN_CREATE; + public const OPEN_READONLY = \PHP_VERSION_ID >= 70300 ? \PDO::SQLITE_OPEN_READONLY : 1; + public const OPEN_READWRITE = \PHP_VERSION_ID >= 70300 ? \PDO::SQLITE_OPEN_READWRITE : 2; + public const OPEN_CREATE = \PHP_VERSION_ID >= 70300 ? \PDO::SQLITE_OPEN_CREATE : 4; } } From 4fa7faa04345c69350b3e3ec742d3888ec19ae27 Mon Sep 17 00:00:00 2001 From: Jesper Noordsij Date: Thu, 16 Oct 2025 14:20:25 +0200 Subject: [PATCH 03/10] Turn Pdo subclasses into functional polyfills --- src/Php84/Resources/stubs/Pdo/Dblib.php | 18 +++++- src/Php84/Resources/stubs/Pdo/Firebird.php | 18 +++++- src/Php84/Resources/stubs/Pdo/Mysql.php | 18 +++++- src/Php84/Resources/stubs/Pdo/Odbc.php | 18 +++++- src/Php84/Resources/stubs/Pdo/Pgsql.php | 18 +++++- src/Php84/Resources/stubs/Pdo/Sqlite.php | 18 +++++- tests/Php84/PdoTest.php | 65 ++++++++++++++++++++++ 7 files changed, 167 insertions(+), 6 deletions(-) diff --git a/src/Php84/Resources/stubs/Pdo/Dblib.php b/src/Php84/Resources/stubs/Pdo/Dblib.php index d9fefd7a..9e38297c 100644 --- a/src/Php84/Resources/stubs/Pdo/Dblib.php +++ b/src/Php84/Resources/stubs/Pdo/Dblib.php @@ -11,9 +11,10 @@ namespace Pdo; use PDO; +use PDOException; if (\PHP_VERSION_ID < 80400) { - class Dblib + class Dblib extends PDO { public const ATTR_CONNECTION_TIMEOUT = PDO::DBLIB_ATTR_CONNECTION_TIMEOUT; public const ATTR_QUERY_TIMEOUT = PDO::DBLIB_ATTR_QUERY_TIMEOUT; @@ -22,5 +23,20 @@ class Dblib public const ATTR_TDS_VERSION = \PHP_VERSION_ID >= 70300 ? PDO::DBLIB_ATTR_TDS_VERSION : 1004; public const ATTR_SKIP_EMPTY_ROWSETS = \PHP_VERSION_ID >= 70300 ? PDO::DBLIB_ATTR_SKIP_EMPTY_ROWSETS : 1005; public const ATTR_DATETIME_CONVERT = \PHP_VERSION_ID >= 70300 ? \PDO::DBLIB_ATTR_DATETIME_CONVERT : 1006; + + public function __construct( + string $dsn, + ?string $username = null, + ?string $password = null, + ?array $options = null + ) + { + parent::__construct($dsn, $username, $password, $options); + + if (($driver = $this->getAttribute(PDO::ATTR_DRIVER_NAME)) !== 'dblib') + { + throw new PDOException("Pdo\Dblib::__construct() cannot be used for connecting to the \"$driver\" driver"); + } + } } } diff --git a/src/Php84/Resources/stubs/Pdo/Firebird.php b/src/Php84/Resources/stubs/Pdo/Firebird.php index a39f089c..d8ba5c64 100644 --- a/src/Php84/Resources/stubs/Pdo/Firebird.php +++ b/src/Php84/Resources/stubs/Pdo/Firebird.php @@ -11,12 +11,28 @@ namespace Pdo; use PDO; +use PDOException; if (\PHP_VERSION_ID < 80400) { - class Firebird + class Firebird extends PDO { public const ATTR_DATE_FORMAT = PDO::FB_ATTR_DATE_FORMAT; public const ATTR_TIME_FORMAT = PDO::FB_ATTR_TIME_FORMAT; public const ATTR_TIMESTAMP_FORMAT = PDO::FB_ATTR_TIMESTAMP_FORMAT; + + public function __construct( + string $dsn, + ?string $username = null, + ?string $password = null, + ?array $options = null + ) + { + parent::__construct($dsn, $username, $password, $options); + + if (($driver = $this->getAttribute(PDO::ATTR_DRIVER_NAME)) !== 'firebird') + { + throw new PDOException("Pdo\Firebird::__construct() cannot be used for connecting to the \"$driver\" driver"); + } + } } } diff --git a/src/Php84/Resources/stubs/Pdo/Mysql.php b/src/Php84/Resources/stubs/Pdo/Mysql.php index b4b22747..7fb11d64 100644 --- a/src/Php84/Resources/stubs/Pdo/Mysql.php +++ b/src/Php84/Resources/stubs/Pdo/Mysql.php @@ -11,9 +11,10 @@ namespace Pdo; use PDO; +use PDOException; if (\PHP_VERSION_ID < 80400) { - class Mysql + class Mysql extends PDO { public const ATTR_COMPRESS = PDO::MYSQL_ATTR_COMPRESS; public const ATTR_DIRECT_QUERY = PDO::MYSQL_ATTR_DIRECT_QUERY; @@ -34,5 +35,20 @@ class Mysql public const ATTR_SSL_KEY = PDO::MYSQL_ATTR_SSL_KEY; public const ATTR_SSL_VERIFY_SERVER_CERT = PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT; public const ATTR_USE_BUFFERED_QUERY = PDO::MYSQL_ATTR_USE_BUFFERED_QUERY; + + public function __construct( + string $dsn, + ?string $username = null, + ?string $password = null, + ?array $options = null + ) + { + parent::__construct($dsn, $username, $password, $options); + + if (($driver = $this->getAttribute(PDO::ATTR_DRIVER_NAME)) !== 'mysql') + { + throw new PDOException("Pdo\Mysql::__construct() cannot be used for connecting to the \"$driver\" driver"); + } + } } } diff --git a/src/Php84/Resources/stubs/Pdo/Odbc.php b/src/Php84/Resources/stubs/Pdo/Odbc.php index f32cae48..d8598496 100644 --- a/src/Php84/Resources/stubs/Pdo/Odbc.php +++ b/src/Php84/Resources/stubs/Pdo/Odbc.php @@ -11,14 +11,30 @@ namespace Pdo; use PDO; +use PDOException; if (\PHP_VERSION_ID < 80400) { - class Odbc + class Odbc extends PDO { public const ATTR_USE_CURSOR_LIBRARY = PDO::ODBC_ATTR_USE_CURSOR_LIBRARY; public const ATTR_ASSUME_UTF8 = PDO::ODBC_ATTR_ASSUME_UTF8; public const SQL_USE_IF_NEEDED = PDO::ODBC_SQL_USE_IF_NEEDED; public const SQL_USE_DRIVER = PDO::ODBC_SQL_USE_DRIVER; public const SQL_USE_ODBC = PDO::ODBC_SQL_USE_ODBC; + + public function __construct( + string $dsn, + ?string $username = null, + ?string $password = null, + ?array $options = null + ) + { + parent::__construct($dsn, $username, $password, $options); + + if (($driver = $this->getAttribute(PDO::ATTR_DRIVER_NAME)) !== 'odbc') + { + throw new PDOException("Pdo\Odbc::__construct() cannot be used for connecting to the \"$driver\" driver"); + } + } } } diff --git a/src/Php84/Resources/stubs/Pdo/Pgsql.php b/src/Php84/Resources/stubs/Pdo/Pgsql.php index 36256f2c..c0091111 100644 --- a/src/Php84/Resources/stubs/Pdo/Pgsql.php +++ b/src/Php84/Resources/stubs/Pdo/Pgsql.php @@ -11,10 +11,26 @@ namespace Pdo; use PDO; +use PDOException; if (\PHP_VERSION_ID < 80400) { - class Pgsql + class Pgsql extends PDO { public const ATTR_DISABLE_PREPARES = PDO::PGSQL_ATTR_DISABLE_PREPARES; + + public function __construct( + string $dsn, + ?string $username = null, + ?string $password = null, + ?array $options = null + ) + { + parent::__construct($dsn, $username, $password, $options); + + if (($driver = $this->getAttribute(PDO::ATTR_DRIVER_NAME)) !== 'pgsql') + { + throw new PDOException("Pdo\Pgsql::__construct() cannot be used for connecting to the \"$driver\" driver"); + } + } } } diff --git a/src/Php84/Resources/stubs/Pdo/Sqlite.php b/src/Php84/Resources/stubs/Pdo/Sqlite.php index 580d9111..ae0a9716 100644 --- a/src/Php84/Resources/stubs/Pdo/Sqlite.php +++ b/src/Php84/Resources/stubs/Pdo/Sqlite.php @@ -11,9 +11,10 @@ namespace Pdo; use PDO; +use PDOException; if (\PHP_VERSION_ID < 80400) { - class Sqlite + class Sqlite extends PDO { public const ATTR_EXTENDED_RESULT_CODES = \PHP_VERSION_ID >= 70400 ? \PDO::SQLITE_ATTR_EXTENDED_RESULT_CODES : 1002; public const ATTR_OPEN_FLAGS = \PHP_VERSION_ID >= 70300 ? \PDO::SQLITE_ATTR_OPEN_FLAGS : 1000; @@ -22,5 +23,20 @@ class Sqlite public const OPEN_READONLY = \PHP_VERSION_ID >= 70300 ? \PDO::SQLITE_OPEN_READONLY : 1; public const OPEN_READWRITE = \PHP_VERSION_ID >= 70300 ? \PDO::SQLITE_OPEN_READWRITE : 2; public const OPEN_CREATE = \PHP_VERSION_ID >= 70300 ? \PDO::SQLITE_OPEN_CREATE : 4; + + public function __construct( + string $dsn, + ?string $username = null, + ?string $password = null, + ?array $options = null + ) + { + parent::__construct($dsn, $username, $password, $options); + + if (($driver = $this->getAttribute(PDO::ATTR_DRIVER_NAME)) !== 'sqlite') + { + throw new PDOException("Pdo\Sqlite::__construct() cannot be used for connecting to the \"$driver\" driver"); + } + } } } diff --git a/tests/Php84/PdoTest.php b/tests/Php84/PdoTest.php index 3c42a04b..4061c5e4 100644 --- a/tests/Php84/PdoTest.php +++ b/tests/Php84/PdoTest.php @@ -11,10 +11,75 @@ namespace Symfony\Polyfill\Tests\Php84; +use PDOException; use PHPUnit\Framework\TestCase; class PdoTest extends TestCase { + /** + * @requires extension pdo_dblib + * @requires extension pdo_sqlite + */ + public function testDblibConstructor() + { + $this->expectException(PDOException::class); + $this->expectExceptionMessage("Pdo\Dblib::__construct() cannot be used for connecting to the \"sqlite\" driver"); + new \Pdo\Dblib("sqlite:"); + } + + /** + * @requires extension pdo_firebird + * @requires extension pdo_sqlite + */ + public function testFirebirdConstructor() + { + $this->expectException(PDOException::class); + $this->expectExceptionMessage("Pdo\Firebird::__construct() cannot be used for connecting to the \"sqlite\" driver"); + new \Pdo\Firebird("sqlite:"); + } + + /** + * @requires extension pdo_mysql + * @requires extension pdo_sqlite + */ + public function testMysqlConstructor() + { + $this->expectException(PDOException::class); + $this->expectExceptionMessage("Pdo\Mysql::__construct() cannot be used for connecting to the \"sqlite\" driver"); + new \Pdo\Mysql("sqlite:"); + } + + /** + * @requires extension pdo_odbc + * @requires extension pdo_sqlite + */ + public function testOdbcConstructor() + { + $this->expectException(PDOException::class); + $this->expectExceptionMessage("Pdo\Odbc::__construct() cannot be used for connecting to the \"sqlite\" driver"); + new \Pdo\Odbc("sqlite:"); + } + + /** + * @requires extension pdo_pgsql + * @requires extension pdo_sqlite + */ + public function testPgsqlConstructor() + { + $this->expectException(PDOException::class); + $this->expectExceptionMessage("Pdo\Pgsql::__construct() cannot be used for connecting to the \"sqlite\" driver"); + new \Pdo\Pgsql("sqlite:"); + } + + /** + * @requires extension pdo_sqlite + */ + public function testSqliteConstructor() + { + $sqlite = new \Pdo\Sqlite("sqlite:"); + $this->assertInstanceOf(\Pdo\Sqlite::class, $sqlite); + } + /** * @requires extension pdo_dblib */ From f9fdfa5c4ae28946a80ffcf5856fdabfbca95133 Mon Sep 17 00:00:00 2001 From: Jesper Noordsij Date: Thu, 16 Oct 2025 14:36:01 +0200 Subject: [PATCH 04/10] Add polyfilling for Pdo subclass methods --- src/Php84/Resources/stubs/Pdo/Pgsql.php | 80 ++++++++++++++++++++++++ src/Php84/Resources/stubs/Pdo/Sqlite.php | 25 ++++++++ 2 files changed, 105 insertions(+) diff --git a/src/Php84/Resources/stubs/Pdo/Pgsql.php b/src/Php84/Resources/stubs/Pdo/Pgsql.php index c0091111..fd0c366b 100644 --- a/src/Php84/Resources/stubs/Pdo/Pgsql.php +++ b/src/Php84/Resources/stubs/Pdo/Pgsql.php @@ -32,5 +32,85 @@ public function __construct( throw new PDOException("Pdo\Pgsql::__construct() cannot be used for connecting to the \"$driver\" driver"); } } + + public function copyFromArray( + string $tableName, + array $rows, + string $separator = "\t", + string $nullAs = "\\\\N", + ?string $fields = null + ): bool + { + return $this->pgsqlCopyFromArray($tableName, $rows, $separator, $nullAs, $fields); + } + + public function copyFromFile( + string $tableName, + string $filename, + string $separator = "\t", + string $nullAs = "\\\\N", + ?string $fields = null + ): bool + { + return $this->pgsqlCopyFromFile($tableName, $filename, $separator, $nullAs, $fields); + } + + /** + * @return array|false + */ + public function copyToArray( + string $tableName, + string $separator = "\t", + string $nullAs = "\\\\N", + ?string $fields = null + ) + { + return $this->pgsqlCopyToArray($tableName, $separator, $nullAs, $fields); + } + + public function copyToFile( + string $tableName, + string $filename, + string $separator = "\t", + string $nullAs = "\\\\N", + ?string $fields = null + ): bool + { + return $this->pgsqlCopyToFile($tableName, $filename, $separator, $nullAs, $fields); + } + + /** + * @return array|false + */ + public function getNotify(int $fetchMode = PDO::FETCH_DEFAULT, int $timeoutMilliseconds = 0) + { + return $this->pgsqlGetNotify($fetchMode, $timeoutMilliseconds); + } + + public function getPid(): int + { + return $this->pgsqlGetPid(); + } + + /** + * @return string|false + */ + public function lobCreate() + { + return $this->pgsqlLOBCreate(); + } + + /** + * @return resource|false + */ + public function lobOpen(string $oid, string $mode = "rb") + { + return $this->pgsqlLOBOpen($oid, $mode); + } + + public function lobUnlink(string $oid): bool + { + return $this->pgsqlLOBUnlink($oid); + } } } diff --git a/src/Php84/Resources/stubs/Pdo/Sqlite.php b/src/Php84/Resources/stubs/Pdo/Sqlite.php index ae0a9716..f167f460 100644 --- a/src/Php84/Resources/stubs/Pdo/Sqlite.php +++ b/src/Php84/Resources/stubs/Pdo/Sqlite.php @@ -38,5 +38,30 @@ public function __construct( throw new PDOException("Pdo\Sqlite::__construct() cannot be used for connecting to the \"$driver\" driver"); } } + + public function createAggregate( + string $name, + callable $step, + callable $finalize, + int $numArgs = -1 + ): bool + { + return $this->sqliteCreateAggregate($name, $step, $finalize, $numArgs); + } + + public function createCollation(string $name, callable $callback): bool + { + return $this->sqliteCreateCollation($name, $callback); + } + + public function createFunction( + string $function_name, + callable $callback, + int $num_args = -1, + int $flags = 0 + ): bool + { + return $this->sqliteCreateFunction($function_name, $callback, $num_args, $flags); + } } } From 3a70b81506ff924c350479fb16e0c1d907067eac Mon Sep 17 00:00:00 2001 From: Jesper Noordsij Date: Thu, 16 Oct 2025 15:27:11 +0200 Subject: [PATCH 05/10] Fixup constant values for PHP 8.5 --- tests/Php84/PdoTest.php | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/Php84/PdoTest.php b/tests/Php84/PdoTest.php index 4061c5e4..732de41a 100644 --- a/tests/Php84/PdoTest.php +++ b/tests/Php84/PdoTest.php @@ -113,18 +113,18 @@ public function testMysqlConstants() $this->assertSame(1001, \Pdo\Mysql::ATTR_LOCAL_INFILE); $this->assertSame(1002, \Pdo\Mysql::ATTR_INIT_COMMAND); $this->assertSame(1003, \Pdo\Mysql::ATTR_COMPRESS); - $this->assertSame(1004, \Pdo\Mysql::ATTR_DIRECT_QUERY); - $this->assertSame(1005, \Pdo\Mysql::ATTR_FOUND_ROWS); - $this->assertSame(1006, \Pdo\Mysql::ATTR_IGNORE_SPACE); - $this->assertSame(1007, \Pdo\Mysql::ATTR_SSL_KEY); - $this->assertSame(1008, \Pdo\Mysql::ATTR_SSL_CERT); - $this->assertSame(1009, \Pdo\Mysql::ATTR_SSL_CA); - $this->assertSame(1010, \Pdo\Mysql::ATTR_SSL_CAPATH); - $this->assertSame(1011, \Pdo\Mysql::ATTR_SSL_CIPHER); - $this->assertSame(1012, \Pdo\Mysql::ATTR_SERVER_PUBLIC_KEY); - $this->assertSame(1013, \Pdo\Mysql::ATTR_MULTI_STATEMENTS); - $this->assertSame(1014, \Pdo\Mysql::ATTR_SSL_VERIFY_SERVER_CERT); - $this->assertSame(1015, \Pdo\Mysql::ATTR_LOCAL_INFILE_DIRECTORY); + $this->assertSame(\PHP_VERSION_ID < 80500 ? 1004 : 20, \Pdo\Mysql::ATTR_DIRECT_QUERY); + $this->assertSame(\PHP_VERSION_ID < 80500 ? 1005 : 1004, \Pdo\Mysql::ATTR_FOUND_ROWS); + $this->assertSame(\PHP_VERSION_ID < 80500 ? 1006 : 1005, \Pdo\Mysql::ATTR_IGNORE_SPACE); + $this->assertSame(\PHP_VERSION_ID < 80500 ? 1007 : 1006, \Pdo\Mysql::ATTR_SSL_KEY); + $this->assertSame(\PHP_VERSION_ID < 80500 ? 1008 : 1007, \Pdo\Mysql::ATTR_SSL_CERT); + $this->assertSame(\PHP_VERSION_ID < 80500 ? 1009 : 1008, \Pdo\Mysql::ATTR_SSL_CA); + $this->assertSame(\PHP_VERSION_ID < 80500 ? 1010 : 1009, \Pdo\Mysql::ATTR_SSL_CAPATH); + $this->assertSame(\PHP_VERSION_ID < 80500 ? 1011 : 1010, \Pdo\Mysql::ATTR_SSL_CIPHER); + $this->assertSame(\PHP_VERSION_ID < 80500 ? 1012 : 1011, \Pdo\Mysql::ATTR_SERVER_PUBLIC_KEY); + $this->assertSame(\PHP_VERSION_ID < 80500 ? 1013 : 1012, \Pdo\Mysql::ATTR_MULTI_STATEMENTS); + $this->assertSame(\PHP_VERSION_ID < 80500 ? 1014 : 1013, \Pdo\Mysql::ATTR_SSL_VERIFY_SERVER_CERT); + $this->assertSame(\PHP_VERSION_ID < 80500 ? 1015 : 1014, \Pdo\Mysql::ATTR_LOCAL_INFILE_DIRECTORY); } /** From b7444cf700e5d230e581a61697743a11c4d026aa Mon Sep 17 00:00:00 2001 From: Jesper Noordsij Date: Thu, 16 Oct 2025 15:31:30 +0200 Subject: [PATCH 06/10] Add conditional Pdo/Mysql class declaration --- src/Php84/Resources/stubs/Pdo/Mysql.php | 100 +++++++++++++++++------- tests/Php84/PdoTest.php | 17 ++-- 2 files changed, 77 insertions(+), 40 deletions(-) diff --git a/src/Php84/Resources/stubs/Pdo/Mysql.php b/src/Php84/Resources/stubs/Pdo/Mysql.php index 7fb11d64..9bd9f3c9 100644 --- a/src/Php84/Resources/stubs/Pdo/Mysql.php +++ b/src/Php84/Resources/stubs/Pdo/Mysql.php @@ -14,40 +14,82 @@ use PDOException; if (\PHP_VERSION_ID < 80400) { - class Mysql extends PDO + // Feature detection for non-mysqlnd; see also https://www.php.net/manual/en/class.pdo-mysql.php#pdo-mysql.constants.attr-max-buffer-size + if (defined('PDO::MYSQL_ATTR_MAX_BUFFER_SIZE') && defined('PDO::MYSQL_ATTR_READ_DEFAULT_FILE') && defined('PDO::MYSQL_ATTR_READ_DEFAULT_GROUP')) { - public const ATTR_COMPRESS = PDO::MYSQL_ATTR_COMPRESS; - public const ATTR_DIRECT_QUERY = PDO::MYSQL_ATTR_DIRECT_QUERY; - public const ATTR_FOUND_ROWS = PDO::MYSQL_ATTR_FOUND_ROWS; - public const ATTR_IGNORE_SPACE = PDO::MYSQL_ATTR_IGNORE_SPACE; - public const ATTR_INIT_COMMAND = PDO::MYSQL_ATTR_INIT_COMMAND; - public const ATTR_LOCAL_INFILE = PDO::MYSQL_ATTR_LOCAL_INFILE; - public const ATTR_LOCAL_INFILE_DIRECTORY = \PHP_VERSION_ID >= 80100 ? \PDO::MYSQL_ATTR_LOCAL_INFILE_DIRECTORY : 1015; - public const ATTR_MAX_BUFFER_SIZE = PDO::MYSQL_ATTR_MAX_BUFFER_SIZE; - public const ATTR_MULTI_STATEMENTS = PDO::MYSQL_ATTR_MULTI_STATEMENTS; - public const ATTR_READ_DEFAULT_FILE = PDO::MYSQL_ATTR_READ_DEFAULT_FILE; - public const ATTR_READ_DEFAULT_GROUP = PDO::MYSQL_ATTR_READ_DEFAULT_GROUP; - public const ATTR_SERVER_PUBLIC_KEY = PDO::MYSQL_ATTR_SERVER_PUBLIC_KEY; - public const ATTR_SSL_CA = PDO::MYSQL_ATTR_SSL_CA; - public const ATTR_SSL_CAPATH = PDO::MYSQL_ATTR_SSL_CAPATH; - public const ATTR_SSL_CERT = PDO::MYSQL_ATTR_SSL_CERT; - public const ATTR_SSL_CIPHER = PDO::MYSQL_ATTR_SSL_CIPHER; - public const ATTR_SSL_KEY = PDO::MYSQL_ATTR_SSL_KEY; - public const ATTR_SSL_VERIFY_SERVER_CERT = PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT; - public const ATTR_USE_BUFFERED_QUERY = PDO::MYSQL_ATTR_USE_BUFFERED_QUERY; + class Mysql extends PDO + { + public const ATTR_COMPRESS = PDO::MYSQL_ATTR_COMPRESS; + public const ATTR_DIRECT_QUERY = PDO::MYSQL_ATTR_DIRECT_QUERY; + public const ATTR_FOUND_ROWS = PDO::MYSQL_ATTR_FOUND_ROWS; + public const ATTR_IGNORE_SPACE = PDO::MYSQL_ATTR_IGNORE_SPACE; + public const ATTR_INIT_COMMAND = PDO::MYSQL_ATTR_INIT_COMMAND; + public const ATTR_LOCAL_INFILE = PDO::MYSQL_ATTR_LOCAL_INFILE; + public const ATTR_LOCAL_INFILE_DIRECTORY = \PHP_VERSION_ID >= 80100 ? \PDO::MYSQL_ATTR_LOCAL_INFILE_DIRECTORY : 1015; + public const ATTR_MAX_BUFFER_SIZE = PDO::MYSQL_ATTR_MAX_BUFFER_SIZE; + public const ATTR_MULTI_STATEMENTS = PDO::MYSQL_ATTR_MULTI_STATEMENTS; + public const ATTR_READ_DEFAULT_FILE = PDO::MYSQL_ATTR_READ_DEFAULT_FILE; + public const ATTR_READ_DEFAULT_GROUP = PDO::MYSQL_ATTR_READ_DEFAULT_GROUP; + public const ATTR_SERVER_PUBLIC_KEY = PDO::MYSQL_ATTR_SERVER_PUBLIC_KEY; + public const ATTR_SSL_CA = PDO::MYSQL_ATTR_SSL_CA; + public const ATTR_SSL_CAPATH = PDO::MYSQL_ATTR_SSL_CAPATH; + public const ATTR_SSL_CERT = PDO::MYSQL_ATTR_SSL_CERT; + public const ATTR_SSL_CIPHER = PDO::MYSQL_ATTR_SSL_CIPHER; + public const ATTR_SSL_KEY = PDO::MYSQL_ATTR_SSL_KEY; + public const ATTR_SSL_VERIFY_SERVER_CERT = PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT; + public const ATTR_USE_BUFFERED_QUERY = PDO::MYSQL_ATTR_USE_BUFFERED_QUERY; + + public function __construct( + string $dsn, + ?string $username = null, + ?string $password = null, + ?array $options = null + ) + { + parent::__construct($dsn, $username, $password, $options); - public function __construct( - string $dsn, - ?string $username = null, - ?string $password = null, - ?array $options = null - ) + if (($driver = $this->getAttribute(PDO::ATTR_DRIVER_NAME)) !== 'mysql') + { + throw new PDOException("Pdo\Mysql::__construct() cannot be used for connecting to the \"$driver\" driver"); + } + } + } + } else { + class Mysql extends PDO { - parent::__construct($dsn, $username, $password, $options); + public const ATTR_COMPRESS = PDO::MYSQL_ATTR_COMPRESS; + public const ATTR_DIRECT_QUERY = PDO::MYSQL_ATTR_DIRECT_QUERY; + public const ATTR_FOUND_ROWS = PDO::MYSQL_ATTR_FOUND_ROWS; + public const ATTR_IGNORE_SPACE = PDO::MYSQL_ATTR_IGNORE_SPACE; + public const ATTR_INIT_COMMAND = PDO::MYSQL_ATTR_INIT_COMMAND; + public const ATTR_LOCAL_INFILE = PDO::MYSQL_ATTR_LOCAL_INFILE; + public const ATTR_LOCAL_INFILE_DIRECTORY = \PHP_VERSION_ID >= 80100 ? \PDO::MYSQL_ATTR_LOCAL_INFILE_DIRECTORY : 1015; + // public const ATTR_MAX_BUFFER_SIZE = PDO::MYSQL_ATTR_MAX_BUFFER_SIZE; // disabled for mysqlnd + public const ATTR_MULTI_STATEMENTS = PDO::MYSQL_ATTR_MULTI_STATEMENTS; + // public const ATTR_READ_DEFAULT_FILE = PDO::MYSQL_ATTR_READ_DEFAULT_FILE; // disabled for mysqlnd + // public const ATTR_READ_DEFAULT_GROUP = PDO::MYSQL_ATTR_READ_DEFAULT_GROUP; // disabled for mysqlnd + public const ATTR_SERVER_PUBLIC_KEY = PDO::MYSQL_ATTR_SERVER_PUBLIC_KEY; + public const ATTR_SSL_CA = PDO::MYSQL_ATTR_SSL_CA; + public const ATTR_SSL_CAPATH = PDO::MYSQL_ATTR_SSL_CAPATH; + public const ATTR_SSL_CERT = PDO::MYSQL_ATTR_SSL_CERT; + public const ATTR_SSL_CIPHER = PDO::MYSQL_ATTR_SSL_CIPHER; + public const ATTR_SSL_KEY = PDO::MYSQL_ATTR_SSL_KEY; + public const ATTR_SSL_VERIFY_SERVER_CERT = PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT; + public const ATTR_USE_BUFFERED_QUERY = PDO::MYSQL_ATTR_USE_BUFFERED_QUERY; - if (($driver = $this->getAttribute(PDO::ATTR_DRIVER_NAME)) !== 'mysql') + public function __construct( + string $dsn, + ?string $username = null, + ?string $password = null, + ?array $options = null + ) { - throw new PDOException("Pdo\Mysql::__construct() cannot be used for connecting to the \"$driver\" driver"); + parent::__construct($dsn, $username, $password, $options); + + if (($driver = $this->getAttribute(PDO::ATTR_DRIVER_NAME)) !== 'mysql') + { + throw new PDOException("Pdo\Mysql::__construct() cannot be used for connecting to the \"$driver\" driver"); + } } } } diff --git a/tests/Php84/PdoTest.php b/tests/Php84/PdoTest.php index 732de41a..d7d2ddeb 100644 --- a/tests/Php84/PdoTest.php +++ b/tests/Php84/PdoTest.php @@ -125,17 +125,12 @@ public function testMysqlConstants() $this->assertSame(\PHP_VERSION_ID < 80500 ? 1013 : 1012, \Pdo\Mysql::ATTR_MULTI_STATEMENTS); $this->assertSame(\PHP_VERSION_ID < 80500 ? 1014 : 1013, \Pdo\Mysql::ATTR_SSL_VERIFY_SERVER_CERT); $this->assertSame(\PHP_VERSION_ID < 80500 ? 1015 : 1014, \Pdo\Mysql::ATTR_LOCAL_INFILE_DIRECTORY); - } - - /** - * @requires extension pdo_mysql - * @requires extension libmysqlclient - */ - public function testMysqlConstantsMysqlnd() - { - $this->assertSame(1003, \Pdo\Mysql::ATTR_READ_DEFAULT_FILE); - $this->assertSame(1004, \Pdo\Mysql::ATTR_READ_DEFAULT_GROUP); - $this->assertSame(1005, \Pdo\Mysql::ATTR_MAX_BUFFER_SIZE); + if (defined('PDO::MYSQL_ATTR_MAX_BUFFER_SIZE') && defined('PDO::MYSQL_ATTR_READ_DEFAULT_FILE') && defined('PDO::MYSQL_ATTR_READ_DEFAULT_GROUP')) + { + $this->assertSame(1003, \Pdo\Mysql::ATTR_READ_DEFAULT_FILE); + $this->assertSame(1004, \Pdo\Mysql::ATTR_READ_DEFAULT_GROUP); + $this->assertSame(1005, \Pdo\Mysql::ATTR_MAX_BUFFER_SIZE); + } } /** From 15a7a4bdc0c7bf62b0e349591e738f01fa3b27e1 Mon Sep 17 00:00:00 2001 From: Jesper Noordsij Date: Thu, 16 Oct 2025 15:36:48 +0200 Subject: [PATCH 07/10] CS: method signatures to single line --- src/Php84/Resources/stubs/Pdo/Dblib.php | 7 +--- src/Php84/Resources/stubs/Pdo/Firebird.php | 7 +--- src/Php84/Resources/stubs/Pdo/Mysql.php | 14 ++------ src/Php84/Resources/stubs/Pdo/Odbc.php | 7 +--- src/Php84/Resources/stubs/Pdo/Pgsql.php | 38 +++------------------- src/Php84/Resources/stubs/Pdo/Sqlite.php | 21 ++---------- 6 files changed, 13 insertions(+), 81 deletions(-) diff --git a/src/Php84/Resources/stubs/Pdo/Dblib.php b/src/Php84/Resources/stubs/Pdo/Dblib.php index 9e38297c..e3a363c6 100644 --- a/src/Php84/Resources/stubs/Pdo/Dblib.php +++ b/src/Php84/Resources/stubs/Pdo/Dblib.php @@ -24,12 +24,7 @@ class Dblib extends PDO public const ATTR_SKIP_EMPTY_ROWSETS = \PHP_VERSION_ID >= 70300 ? PDO::DBLIB_ATTR_SKIP_EMPTY_ROWSETS : 1005; public const ATTR_DATETIME_CONVERT = \PHP_VERSION_ID >= 70300 ? \PDO::DBLIB_ATTR_DATETIME_CONVERT : 1006; - public function __construct( - string $dsn, - ?string $username = null, - ?string $password = null, - ?array $options = null - ) + public function __construct(string $dsn, ?string $username = null, ?string $password = null, ?array $options = null) { parent::__construct($dsn, $username, $password, $options); diff --git a/src/Php84/Resources/stubs/Pdo/Firebird.php b/src/Php84/Resources/stubs/Pdo/Firebird.php index d8ba5c64..3d8dbc28 100644 --- a/src/Php84/Resources/stubs/Pdo/Firebird.php +++ b/src/Php84/Resources/stubs/Pdo/Firebird.php @@ -20,12 +20,7 @@ class Firebird extends PDO public const ATTR_TIME_FORMAT = PDO::FB_ATTR_TIME_FORMAT; public const ATTR_TIMESTAMP_FORMAT = PDO::FB_ATTR_TIMESTAMP_FORMAT; - public function __construct( - string $dsn, - ?string $username = null, - ?string $password = null, - ?array $options = null - ) + public function __construct(string $dsn, ?string $username = null, ?string $password = null, ?array $options = null) { parent::__construct($dsn, $username, $password, $options); diff --git a/src/Php84/Resources/stubs/Pdo/Mysql.php b/src/Php84/Resources/stubs/Pdo/Mysql.php index 9bd9f3c9..bc28bca6 100644 --- a/src/Php84/Resources/stubs/Pdo/Mysql.php +++ b/src/Php84/Resources/stubs/Pdo/Mysql.php @@ -39,12 +39,7 @@ class Mysql extends PDO public const ATTR_SSL_VERIFY_SERVER_CERT = PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT; public const ATTR_USE_BUFFERED_QUERY = PDO::MYSQL_ATTR_USE_BUFFERED_QUERY; - public function __construct( - string $dsn, - ?string $username = null, - ?string $password = null, - ?array $options = null - ) + public function __construct(string $dsn, ?string $username = null, ?string $password = null, ?array $options = null) { parent::__construct($dsn, $username, $password, $options); @@ -77,12 +72,7 @@ class Mysql extends PDO public const ATTR_SSL_VERIFY_SERVER_CERT = PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT; public const ATTR_USE_BUFFERED_QUERY = PDO::MYSQL_ATTR_USE_BUFFERED_QUERY; - public function __construct( - string $dsn, - ?string $username = null, - ?string $password = null, - ?array $options = null - ) + public function __construct(string $dsn, ?string $username = null, ?string $password = null, ?array $options = null) { parent::__construct($dsn, $username, $password, $options); diff --git a/src/Php84/Resources/stubs/Pdo/Odbc.php b/src/Php84/Resources/stubs/Pdo/Odbc.php index d8598496..82adb6ba 100644 --- a/src/Php84/Resources/stubs/Pdo/Odbc.php +++ b/src/Php84/Resources/stubs/Pdo/Odbc.php @@ -22,12 +22,7 @@ class Odbc extends PDO public const SQL_USE_DRIVER = PDO::ODBC_SQL_USE_DRIVER; public const SQL_USE_ODBC = PDO::ODBC_SQL_USE_ODBC; - public function __construct( - string $dsn, - ?string $username = null, - ?string $password = null, - ?array $options = null - ) + public function __construct(string $dsn, ?string $username = null, ?string $password = null, ?array $options = null) { parent::__construct($dsn, $username, $password, $options); diff --git a/src/Php84/Resources/stubs/Pdo/Pgsql.php b/src/Php84/Resources/stubs/Pdo/Pgsql.php index fd0c366b..dba65413 100644 --- a/src/Php84/Resources/stubs/Pdo/Pgsql.php +++ b/src/Php84/Resources/stubs/Pdo/Pgsql.php @@ -18,12 +18,7 @@ class Pgsql extends PDO { public const ATTR_DISABLE_PREPARES = PDO::PGSQL_ATTR_DISABLE_PREPARES; - public function __construct( - string $dsn, - ?string $username = null, - ?string $password = null, - ?array $options = null - ) + public function __construct(string $dsn, ?string $username = null, ?string $password = null, ?array $options = null) { parent::__construct($dsn, $username, $password, $options); @@ -33,24 +28,12 @@ public function __construct( } } - public function copyFromArray( - string $tableName, - array $rows, - string $separator = "\t", - string $nullAs = "\\\\N", - ?string $fields = null - ): bool + public function copyFromArray(string $tableName, array $rows, string $separator = "\t", string $nullAs = "\\\\N", ?string $fields = null): bool { return $this->pgsqlCopyFromArray($tableName, $rows, $separator, $nullAs, $fields); } - public function copyFromFile( - string $tableName, - string $filename, - string $separator = "\t", - string $nullAs = "\\\\N", - ?string $fields = null - ): bool + public function copyFromFile(string $tableName, string $filename, string $separator = "\t", string $nullAs = "\\\\N", ?string $fields = null): bool { return $this->pgsqlCopyFromFile($tableName, $filename, $separator, $nullAs, $fields); } @@ -58,23 +41,12 @@ public function copyFromFile( /** * @return array|false */ - public function copyToArray( - string $tableName, - string $separator = "\t", - string $nullAs = "\\\\N", - ?string $fields = null - ) + public function copyToArray(string $tableName, string $separator = "\t", string $nullAs = "\\\\N", ?string $fields = null) { return $this->pgsqlCopyToArray($tableName, $separator, $nullAs, $fields); } - public function copyToFile( - string $tableName, - string $filename, - string $separator = "\t", - string $nullAs = "\\\\N", - ?string $fields = null - ): bool + public function copyToFile(string $tableName, string $filename, string $separator = "\t", string $nullAs = "\\\\N", ?string $fields = null): bool { return $this->pgsqlCopyToFile($tableName, $filename, $separator, $nullAs, $fields); } diff --git a/src/Php84/Resources/stubs/Pdo/Sqlite.php b/src/Php84/Resources/stubs/Pdo/Sqlite.php index f167f460..02e3589a 100644 --- a/src/Php84/Resources/stubs/Pdo/Sqlite.php +++ b/src/Php84/Resources/stubs/Pdo/Sqlite.php @@ -24,12 +24,7 @@ class Sqlite extends PDO public const OPEN_READWRITE = \PHP_VERSION_ID >= 70300 ? \PDO::SQLITE_OPEN_READWRITE : 2; public const OPEN_CREATE = \PHP_VERSION_ID >= 70300 ? \PDO::SQLITE_OPEN_CREATE : 4; - public function __construct( - string $dsn, - ?string $username = null, - ?string $password = null, - ?array $options = null - ) + public function __construct(string $dsn, ?string $username = null, ?string $password = null, ?array $options = null) { parent::__construct($dsn, $username, $password, $options); @@ -39,12 +34,7 @@ public function __construct( } } - public function createAggregate( - string $name, - callable $step, - callable $finalize, - int $numArgs = -1 - ): bool + public function createAggregate(string $name, callable $step, callable $finalize, int $numArgs = -1): bool { return $this->sqliteCreateAggregate($name, $step, $finalize, $numArgs); } @@ -54,12 +44,7 @@ public function createCollation(string $name, callable $callback): bool return $this->sqliteCreateCollation($name, $callback); } - public function createFunction( - string $function_name, - callable $callback, - int $num_args = -1, - int $flags = 0 - ): bool + public function createFunction(string $function_name, callable $callback, int $num_args = -1, int $flags = 0): bool { return $this->sqliteCreateFunction($function_name, $callback, $num_args, $flags); } From a70cf2c43dbeb95319bcc5cbac4541317299ee6e Mon Sep 17 00:00:00 2001 From: Jesper Noordsij Date: Mon, 20 Oct 2025 10:58:16 +0200 Subject: [PATCH 08/10] Add static connect method to PDO subclass polyfills --- src/Php84/Resources/stubs/Pdo/Dblib.php | 11 ++++ src/Php84/Resources/stubs/Pdo/Firebird.php | 11 ++++ src/Php84/Resources/stubs/Pdo/Mysql.php | 22 ++++++++ src/Php84/Resources/stubs/Pdo/Odbc.php | 11 ++++ src/Php84/Resources/stubs/Pdo/Pgsql.php | 11 ++++ src/Php84/Resources/stubs/Pdo/Sqlite.php | 13 +++-- tests/Php84/PdoTest.php | 64 ++++++++++++++++++++++ 7 files changed, 137 insertions(+), 6 deletions(-) diff --git a/src/Php84/Resources/stubs/Pdo/Dblib.php b/src/Php84/Resources/stubs/Pdo/Dblib.php index e3a363c6..e7b81d14 100644 --- a/src/Php84/Resources/stubs/Pdo/Dblib.php +++ b/src/Php84/Resources/stubs/Pdo/Dblib.php @@ -33,5 +33,16 @@ public function __construct(string $dsn, ?string $username = null, ?string $pass throw new PDOException("Pdo\Dblib::__construct() cannot be used for connecting to the \"$driver\" driver"); } } + + public static function connect(string $dsn, ?string $username = null, ?string $password = null, ?array $options = null): self + { + try { + return new self($dsn, $username, $password, $options); + } catch (PDOException $e) { + throw preg_match('/Pdo\\\\Dblib::__construct\(\) cannot be used for connecting to the "([a-z]+)" driver/', $e->getMessage(), $matches) + ? new PDOException("Pdo\Dblib::connect() cannot be used for connecting to the \"{$matches[1]}\" driver") + : $e; + } + } } } diff --git a/src/Php84/Resources/stubs/Pdo/Firebird.php b/src/Php84/Resources/stubs/Pdo/Firebird.php index 3d8dbc28..8afc5268 100644 --- a/src/Php84/Resources/stubs/Pdo/Firebird.php +++ b/src/Php84/Resources/stubs/Pdo/Firebird.php @@ -29,5 +29,16 @@ public function __construct(string $dsn, ?string $username = null, ?string $pass throw new PDOException("Pdo\Firebird::__construct() cannot be used for connecting to the \"$driver\" driver"); } } + + public static function connect(string $dsn, ?string $username = null, ?string $password = null, ?array $options = null): self + { + try { + return new self($dsn, $username, $password, $options); + } catch (PDOException $e) { + throw preg_match('/Pdo\\\\Firebird::__construct\(\) cannot be used for connecting to the "([a-z]+)" driver/', $e->getMessage(), $matches) + ? new PDOException("Pdo\Firebird::connect() cannot be used for connecting to the \"{$matches[1]}\" driver") + : $e; + } + } } } diff --git a/src/Php84/Resources/stubs/Pdo/Mysql.php b/src/Php84/Resources/stubs/Pdo/Mysql.php index bc28bca6..a4b82521 100644 --- a/src/Php84/Resources/stubs/Pdo/Mysql.php +++ b/src/Php84/Resources/stubs/Pdo/Mysql.php @@ -48,6 +48,17 @@ public function __construct(string $dsn, ?string $username = null, ?string $pass throw new PDOException("Pdo\Mysql::__construct() cannot be used for connecting to the \"$driver\" driver"); } } + + public static function connect(string $dsn, ?string $username = null, ?string $password = null, ?array $options = null): self + { + try { + return new self($dsn, $username, $password, $options); + } catch (PDOException $e) { + throw preg_match('/Pdo\\\\Mysql::__construct\(\) cannot be used for connecting to the "([a-z]+)" driver/', $e->getMessage(), $matches) + ? new PDOException("Pdo\Mysql::connect() cannot be used for connecting to the \"{$matches[1]}\" driver") + : $e; + } + } } } else { class Mysql extends PDO @@ -81,6 +92,17 @@ public function __construct(string $dsn, ?string $username = null, ?string $pass throw new PDOException("Pdo\Mysql::__construct() cannot be used for connecting to the \"$driver\" driver"); } } + + public static function connect(string $dsn, ?string $username = null, ?string $password = null, ?array $options = null): self + { + try { + return new self($dsn, $username, $password, $options); + } catch (PDOException $e) { + throw preg_match('/Pdo\\\\Mysql::__construct\(\) cannot be used for connecting to the "([a-z]+)" driver/', $e->getMessage(), $matches) + ? new PDOException("Pdo\Mysql::connect() cannot be used for connecting to the \"{$matches[1]}\" driver") + : $e; + } + } } } } diff --git a/src/Php84/Resources/stubs/Pdo/Odbc.php b/src/Php84/Resources/stubs/Pdo/Odbc.php index 82adb6ba..1659eaf4 100644 --- a/src/Php84/Resources/stubs/Pdo/Odbc.php +++ b/src/Php84/Resources/stubs/Pdo/Odbc.php @@ -31,5 +31,16 @@ public function __construct(string $dsn, ?string $username = null, ?string $pass throw new PDOException("Pdo\Odbc::__construct() cannot be used for connecting to the \"$driver\" driver"); } } + + public static function connect(string $dsn, ?string $username = null, ?string $password = null, ?array $options = null): self + { + try { + return new self($dsn, $username, $password, $options); + } catch (PDOException $e) { + throw preg_match('/Pdo\\\\Odbc::__construct\(\) cannot be used for connecting to the "([a-z]+)" driver/', $e->getMessage(), $matches) + ? new PDOException("Pdo\Odbc::connect() cannot be used for connecting to the \"{$matches[1]}\" driver") + : $e; + } + } } } diff --git a/src/Php84/Resources/stubs/Pdo/Pgsql.php b/src/Php84/Resources/stubs/Pdo/Pgsql.php index dba65413..8ad751b9 100644 --- a/src/Php84/Resources/stubs/Pdo/Pgsql.php +++ b/src/Php84/Resources/stubs/Pdo/Pgsql.php @@ -28,6 +28,17 @@ public function __construct(string $dsn, ?string $username = null, ?string $pass } } + public static function connect(string $dsn, ?string $username = null, ?string $password = null, ?array $options = null): self + { + try { + return new self($dsn, $username, $password, $options); + } catch (PDOException $e) { + throw preg_match('/Pdo\\\\Pgsql::__construct\(\) cannot be used for connecting to the "([a-z]+)" driver/', $e->getMessage(), $matches) + ? new PDOException("Pdo\Pgsql::connect() cannot be used for connecting to the \"{$matches[1]}\" driver") + : $e; + } + } + public function copyFromArray(string $tableName, array $rows, string $separator = "\t", string $nullAs = "\\\\N", ?string $fields = null): bool { return $this->pgsqlCopyFromArray($tableName, $rows, $separator, $nullAs, $fields); diff --git a/src/Php84/Resources/stubs/Pdo/Sqlite.php b/src/Php84/Resources/stubs/Pdo/Sqlite.php index 02e3589a..71f9dc75 100644 --- a/src/Php84/Resources/stubs/Pdo/Sqlite.php +++ b/src/Php84/Resources/stubs/Pdo/Sqlite.php @@ -24,13 +24,14 @@ class Sqlite extends PDO public const OPEN_READWRITE = \PHP_VERSION_ID >= 70300 ? \PDO::SQLITE_OPEN_READWRITE : 2; public const OPEN_CREATE = \PHP_VERSION_ID >= 70300 ? \PDO::SQLITE_OPEN_CREATE : 4; - public function __construct(string $dsn, ?string $username = null, ?string $password = null, ?array $options = null) + public static function connect(string $dsn, ?string $username = null, ?string $password = null, ?array $options = null): self { - parent::__construct($dsn, $username, $password, $options); - - if (($driver = $this->getAttribute(PDO::ATTR_DRIVER_NAME)) !== 'sqlite') - { - throw new PDOException("Pdo\Sqlite::__construct() cannot be used for connecting to the \"$driver\" driver"); + try { + return new self($dsn, $username, $password, $options); + } catch (PDOException $e) { + throw preg_match('/Pdo\\\\Sqlite::__construct\(\) cannot be used for connecting to the "([a-z]+)" driver/', $e->getMessage(), $matches) + ? new PDOException("Pdo\Sqlite::connect() cannot be used for connecting to the \"{$matches[1]}\" driver") + : $e; } } diff --git a/tests/Php84/PdoTest.php b/tests/Php84/PdoTest.php index d7d2ddeb..f039c5af 100644 --- a/tests/Php84/PdoTest.php +++ b/tests/Php84/PdoTest.php @@ -80,6 +80,70 @@ public function testSqliteConstructor() $this->assertInstanceOf(\Pdo\Sqlite::class, $sqlite); } + /** + * @requires extension pdo_dblib + * @requires extension pdo_sqlite + */ + public function testDblibConnect() + { + $this->expectException(PDOException::class); + $this->expectExceptionMessage("Pdo\Dblib::connect() cannot be used for connecting to the \"sqlite\" driver"); + \Pdo\Dblib::connect("sqlite:"); + } + + /** + * @requires extension pdo_firebird + * @requires extension pdo_sqlite + */ + public function testFirebirdConnect() + { + $this->expectException(PDOException::class); + $this->expectExceptionMessage("Pdo\Firebird::connect() cannot be used for connecting to the \"sqlite\" driver"); + \Pdo\Firebird::connect("sqlite:"); + } + + /** + * @requires extension pdo_mysql + * @requires extension pdo_sqlite + */ + public function testMysqlConnect() + { + $this->expectException(PDOException::class); + $this->expectExceptionMessage("Pdo\Mysql::connect() cannot be used for connecting to the \"sqlite\" driver"); + \Pdo\Mysql::connect("sqlite:"); + } + + /** + * @requires extension pdo_odbc + * @requires extension pdo_sqlite + */ + public function testOdbcConnect() + { + $this->expectException(PDOException::class); + $this->expectExceptionMessage("Pdo\Odbc::connect() cannot be used for connecting to the \"sqlite\" driver"); + \Pdo\Odbc::connect("sqlite:"); + } + + /** + * @requires extension pdo_pgsql + * @requires extension pdo_sqlite + */ + public function testPgsqlConnect() + { + $this->expectException(PDOException::class); + $this->expectExceptionMessage("Pdo\Pgsql::connect() cannot be used for connecting to the \"sqlite\" driver"); + \Pdo\Pgsql::connect("sqlite:"); + } + + /** + * @requires extension pdo_sqlite + */ + public function testSqliteConnect() + { + $sqlite = \Pdo\Sqlite::connect("sqlite:"); + $this->assertInstanceOf(\Pdo\Sqlite::class, $sqlite); + } + /** * @requires extension pdo_dblib */ From f42017a6a6de1f3bb7ae042904789e4e91aef17a Mon Sep 17 00:00:00 2001 From: Jesper Noordsij Date: Mon, 20 Oct 2025 11:02:57 +0200 Subject: [PATCH 09/10] Add test for class extension of PDO subclass --- tests/Php84/PdoTest.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/Php84/PdoTest.php b/tests/Php84/PdoTest.php index f039c5af..8d3f32d6 100644 --- a/tests/Php84/PdoTest.php +++ b/tests/Php84/PdoTest.php @@ -144,6 +144,15 @@ public function testSqliteConnect() $this->assertInstanceOf(\Pdo\Sqlite::class, $sqlite); } + /** + * @requires extension pdo_sqlite + */ + public function testSqliteConnectOnClassExtensions() + { + $sqlite = ExtendedPdoSqlite::connect("sqlite:"); + $this->assertInstanceOf(\Pdo\Sqlite::class, $sqlite); + } + /** * @requires extension pdo_dblib */ @@ -231,3 +240,7 @@ public function testSqliteConstants() $this->assertSame(2048, \Pdo\Sqlite::DETERMINISTIC); } } + +class ExtendedPdoSqlite extends \Pdo\Sqlite +{ +} From e04dc06d5d0eae2443759850eb06ffa1c96e7890 Mon Sep 17 00:00:00 2001 From: Jesper Noordsij Date: Mon, 20 Oct 2025 11:21:04 +0200 Subject: [PATCH 10/10] Only load PDO subclass polyfills when corresponding extension is loaded --- src/Php84/Resources/stubs/Pdo/Dblib.php | 2 +- src/Php84/Resources/stubs/Pdo/Firebird.php | 2 +- src/Php84/Resources/stubs/Pdo/Mysql.php | 2 +- src/Php84/Resources/stubs/Pdo/Odbc.php | 2 +- src/Php84/Resources/stubs/Pdo/Pgsql.php | 2 +- src/Php84/Resources/stubs/Pdo/Sqlite.php | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Php84/Resources/stubs/Pdo/Dblib.php b/src/Php84/Resources/stubs/Pdo/Dblib.php index e7b81d14..1b7d0d21 100644 --- a/src/Php84/Resources/stubs/Pdo/Dblib.php +++ b/src/Php84/Resources/stubs/Pdo/Dblib.php @@ -13,7 +13,7 @@ use PDO; use PDOException; -if (\PHP_VERSION_ID < 80400) { +if (\PHP_VERSION_ID < 80400 && extension_loaded('pdo_dblib')) { class Dblib extends PDO { public const ATTR_CONNECTION_TIMEOUT = PDO::DBLIB_ATTR_CONNECTION_TIMEOUT; diff --git a/src/Php84/Resources/stubs/Pdo/Firebird.php b/src/Php84/Resources/stubs/Pdo/Firebird.php index 8afc5268..e7140d57 100644 --- a/src/Php84/Resources/stubs/Pdo/Firebird.php +++ b/src/Php84/Resources/stubs/Pdo/Firebird.php @@ -13,7 +13,7 @@ use PDO; use PDOException; -if (\PHP_VERSION_ID < 80400) { +if (\PHP_VERSION_ID < 80400 && extension_loaded('pdo_firebird')) { class Firebird extends PDO { public const ATTR_DATE_FORMAT = PDO::FB_ATTR_DATE_FORMAT; diff --git a/src/Php84/Resources/stubs/Pdo/Mysql.php b/src/Php84/Resources/stubs/Pdo/Mysql.php index a4b82521..09a60e3b 100644 --- a/src/Php84/Resources/stubs/Pdo/Mysql.php +++ b/src/Php84/Resources/stubs/Pdo/Mysql.php @@ -13,7 +13,7 @@ use PDO; use PDOException; -if (\PHP_VERSION_ID < 80400) { +if (\PHP_VERSION_ID < 80400 && extension_loaded('pdo_mysql')) { // Feature detection for non-mysqlnd; see also https://www.php.net/manual/en/class.pdo-mysql.php#pdo-mysql.constants.attr-max-buffer-size if (defined('PDO::MYSQL_ATTR_MAX_BUFFER_SIZE') && defined('PDO::MYSQL_ATTR_READ_DEFAULT_FILE') && defined('PDO::MYSQL_ATTR_READ_DEFAULT_GROUP')) { diff --git a/src/Php84/Resources/stubs/Pdo/Odbc.php b/src/Php84/Resources/stubs/Pdo/Odbc.php index 1659eaf4..43875910 100644 --- a/src/Php84/Resources/stubs/Pdo/Odbc.php +++ b/src/Php84/Resources/stubs/Pdo/Odbc.php @@ -13,7 +13,7 @@ use PDO; use PDOException; -if (\PHP_VERSION_ID < 80400) { +if (\PHP_VERSION_ID < 80400 && extension_loaded('pdo_odbc')) { class Odbc extends PDO { public const ATTR_USE_CURSOR_LIBRARY = PDO::ODBC_ATTR_USE_CURSOR_LIBRARY; diff --git a/src/Php84/Resources/stubs/Pdo/Pgsql.php b/src/Php84/Resources/stubs/Pdo/Pgsql.php index 8ad751b9..3f31dca6 100644 --- a/src/Php84/Resources/stubs/Pdo/Pgsql.php +++ b/src/Php84/Resources/stubs/Pdo/Pgsql.php @@ -13,7 +13,7 @@ use PDO; use PDOException; -if (\PHP_VERSION_ID < 80400) { +if (\PHP_VERSION_ID < 80400 && extension_loaded('pdo_pgsql')) { class Pgsql extends PDO { public const ATTR_DISABLE_PREPARES = PDO::PGSQL_ATTR_DISABLE_PREPARES; diff --git a/src/Php84/Resources/stubs/Pdo/Sqlite.php b/src/Php84/Resources/stubs/Pdo/Sqlite.php index 71f9dc75..a46149bf 100644 --- a/src/Php84/Resources/stubs/Pdo/Sqlite.php +++ b/src/Php84/Resources/stubs/Pdo/Sqlite.php @@ -13,7 +13,7 @@ use PDO; use PDOException; -if (\PHP_VERSION_ID < 80400) { +if (\PHP_VERSION_ID < 80400 && extension_loaded('pdo_sqlite')) { class Sqlite extends PDO { public const ATTR_EXTENDED_RESULT_CODES = \PHP_VERSION_ID >= 70400 ? \PDO::SQLITE_ATTR_EXTENDED_RESULT_CODES : 1002;