From 86f5b5316685352fd1f45ec9553c3a448757bcb9 Mon Sep 17 00:00:00 2001 From: Danack Date: Sat, 4 Jun 2022 17:44:12 +0100 Subject: [PATCH 01/35] Adding PDOSQLite in the wrong place. --- ext/pdo/config.m4 | 2 +- ext/pdo/pdo.c | 2 + ext/pdo/pdo_dbh.c | 12 +++ ext/pdo/pdo_sqlite.stub.php | 17 ++++ ext/pdo/pdo_sqlite_arginfo.h | 29 +++++++ ext/pdo/pdosqlite_class.c | 94 +++++++++++++++++++++ ext/pdo/php_pdo_int.h | 1 + ext/pdo/tests/subclasses/pdosqlite_001.phpt | 47 +++++++++++ ext/pdo_sqlite/sqlite_driver.c | 3 +- 9 files changed, 205 insertions(+), 2 deletions(-) create mode 100644 ext/pdo/pdo_sqlite.stub.php create mode 100644 ext/pdo/pdo_sqlite_arginfo.h create mode 100644 ext/pdo/pdosqlite_class.c create mode 100644 ext/pdo/tests/subclasses/pdosqlite_001.phpt diff --git a/ext/pdo/config.m4 b/ext/pdo/config.m4 index 9b9a3e36df7af..18d3ee7d55c92 100644 --- a/ext/pdo/config.m4 +++ b/ext/pdo/config.m4 @@ -9,7 +9,7 @@ if test "$PHP_PDO" != "no"; then dnl Make sure $PHP_PDO is 'yes' when it's not 'no' :) PHP_PDO=yes - PHP_NEW_EXTENSION(pdo, pdo.c pdo_dbh.c pdo_stmt.c pdo_sql_parser.c pdo_sqlstate.c, $ext_shared) + PHP_NEW_EXTENSION(pdo, pdo.c pdo_dbh.c pdo_stmt.c pdo_sql_parser.c pdo_sqlstate.c pdosqlite_class.c, $ext_shared) PHP_ADD_EXTENSION_DEP(pdo, spl, true) PHP_INSTALL_HEADERS(ext/pdo, [php_pdo.h php_pdo_driver.h php_pdo_error.h]) diff --git a/ext/pdo/pdo.c b/ext/pdo/pdo.c index f11b983a9a82f..0e8181ebd10e3 100644 --- a/ext/pdo/pdo.c +++ b/ext/pdo/pdo.c @@ -33,6 +33,8 @@ zend_class_entry *pdo_dbh_ce, *pdo_dbstmt_ce, *pdo_row_ce; +zend_class_entry *pdosqlite_ce; + /* for exceptional circumstances */ zend_class_entry *pdo_exception_ce; diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index 692f187a04df8..587e133ca9712 100644 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -32,6 +32,7 @@ #include "zend_object_handlers.h" #include "zend_hash.h" #include "pdo_dbh_arginfo.h" +#include "pdo_sqlite_arginfo.h" static bool pdo_dbh_attribute_set(pdo_dbh_t *dbh, zend_long attr, zval *value); @@ -1423,6 +1424,17 @@ void pdo_dbh_init(void) REGISTER_PDO_CLASS_CONST_LONG("CURSOR_FWDONLY", (zend_long)PDO_CURSOR_FWDONLY); REGISTER_PDO_CLASS_CONST_LONG("CURSOR_SCROLL", (zend_long)PDO_CURSOR_SCROLL); + + pdosqlite_ce = register_class_PDOSqlite(pdo_dbh_ce); + pdosqlite_ce->create_object = pdo_dbh_new; + + memcpy(&pdo_dbh_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); + pdo_dbh_object_handlers.offset = XtOffsetOf(pdo_dbh_object_t, std); + pdo_dbh_object_handlers.free_obj = pdo_dbh_free_storage; + pdo_dbh_object_handlers.clone_obj = NULL; + pdo_dbh_object_handlers.get_method = dbh_method_get; + pdo_dbh_object_handlers.compare = zend_objects_not_comparable; + pdo_dbh_object_handlers.get_gc = dbh_get_gc; } static void dbh_free(pdo_dbh_t *dbh, bool free_persistent) diff --git a/ext/pdo/pdo_sqlite.stub.php b/ext/pdo/pdo_sqlite.stub.php new file mode 100644 index 0000000000000..6994f0cd28f87 --- /dev/null +++ b/ext/pdo/pdo_sqlite.stub.php @@ -0,0 +1,17 @@ +ce_flags |= ZEND_ACC_NOT_SERIALIZABLE; + + return class_entry; +} diff --git a/ext/pdo/pdosqlite_class.c b/ext/pdo/pdosqlite_class.c new file mode 100644 index 0000000000000..d3ad178821725 --- /dev/null +++ b/ext/pdo/pdosqlite_class.c @@ -0,0 +1,94 @@ + +/* + +----------------------------------------------------------------------+ + | Copyright (c) The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | https://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Wez Furlong | + | Marcus Boerger | + | Sterling Hughes | + +----------------------------------------------------------------------+ +*/ + +/* The PDO Database Handle Class */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php.h" +#include "php_ini.h" +#include "ext/standard/info.h" +#include "php_pdo.h" +#include "php_pdo_driver.h" +#include "php_pdo_int.h" +#include "zend_exceptions.h" +#include "zend_object_handlers.h" +#include "zend_hash.h" + +#include "../pdo_sqlite/php_pdo_sqlite.h" +#include "../pdo_sqlite/php_pdo_sqlite_int.h" + +extern void php_sqlite3_func_callback(sqlite3_context *context, int argc, + sqlite3_value **argv); + +/* {{{ proto bool PDOSqlite::createFunction(string $function_name, callable $callback, int $num_args = -1, int $flags = 0) + Creates a function that can be used +*/ +PHP_METHOD(PDOSqlite, createFunction) +{ + //copied from sqlite_driver.c + + struct pdo_sqlite_func *func; + zend_fcall_info fci; + zend_fcall_info_cache fcc; + char *func_name; + size_t func_name_len; + zend_long argc = -1; + zend_long flags = 0; + pdo_dbh_t *dbh; + pdo_sqlite_db_handle *H; + int ret; + + ZEND_PARSE_PARAMETERS_START(2, 4) + Z_PARAM_STRING(func_name, func_name_len) + Z_PARAM_FUNC(fci, fcc) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(argc) + Z_PARAM_LONG(flags) + ZEND_PARSE_PARAMETERS_END(); + + dbh = Z_PDO_DBH_P(ZEND_THIS); + PDO_CONSTRUCT_CHECK; + + H = (pdo_sqlite_db_handle *)dbh->driver_data; + + func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func)); + + ret = sqlite3_create_function(H->db, func_name, argc, flags | SQLITE_UTF8, + func, php_sqlite3_func_callback, NULL, NULL); + if (ret == SQLITE_OK) { + func->funcname = estrdup(func_name); + + ZVAL_COPY(&func->func, &fci.function_name); + + func->argc = argc; + + func->next = H->funcs; + H->funcs = func; + + RETURN_TRUE; + } + + efree(func); + RETURN_FALSE; +} +/* }}} */ + diff --git a/ext/pdo/php_pdo_int.h b/ext/pdo/php_pdo_int.h index c3d2fe00a1d70..da143c25b9260 100644 --- a/ext/pdo/php_pdo_int.h +++ b/ext/pdo/php_pdo_int.h @@ -31,6 +31,7 @@ void pdo_stmt_init(void); extern zend_object *pdo_dbh_new(zend_class_entry *ce); extern const zend_function_entry pdo_dbh_functions[]; extern zend_class_entry *pdo_dbh_ce; +extern zend_class_entry *pdosqlite_ce; extern ZEND_RSRC_DTOR_FUNC(php_pdo_pdbh_dtor); extern zend_object *pdo_dbstmt_new(zend_class_entry *ce); diff --git a/ext/pdo/tests/subclasses/pdosqlite_001.phpt b/ext/pdo/tests/subclasses/pdosqlite_001.phpt new file mode 100644 index 0000000000000..0ee9cd51ac077 --- /dev/null +++ b/ext/pdo/tests/subclasses/pdosqlite_001.phpt @@ -0,0 +1,47 @@ +--TEST-- +PDOSqlite basic +--EXTENSIONS-- +pdo +--FILE-- +query('CREATE TABLE IF NOT EXISTS foobar (id INT AUTO INCREMENT, name TEXT)'); + +$db->query('INSERT INTO foobar VALUES (NULL, "PHP")'); +$db->query('INSERT INTO foobar VALUES (NULL, "PHP6")'); + + +$db->createFunction('testing', function($v) { return strtolower($v); }, 1, PDO::SQLITE_DETERMINISTIC); + + +foreach ($db->query('SELECT testing(name) FROM foobar') as $row) { + var_dump($row); +} + +$db->query('DROP TABLE foobar'); + +echo "Fin."; +?> +--EXPECT-- +PdoSqlite class exists. +array(2) { + ["testing(name)"]=> + string(3) "php" + [0]=> + string(3) "php" +} +array(2) { + ["testing(name)"]=> + string(4) "php6" + [0]=> + string(4) "php6" +} +Fin. diff --git a/ext/pdo_sqlite/sqlite_driver.c b/ext/pdo_sqlite/sqlite_driver.c index bdad23a581d56..f74b69234c6c6 100644 --- a/ext/pdo_sqlite/sqlite_driver.c +++ b/ext/pdo_sqlite/sqlite_driver.c @@ -453,7 +453,8 @@ static int do_callback(struct pdo_sqlite_fci *fc, zval *cb, return ret; } -static void php_sqlite3_func_callback(sqlite3_context *context, int argc, +// TODO - make static again static +void php_sqlite3_func_callback(sqlite3_context *context, int argc, sqlite3_value **argv) { struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context); From 9d69e0e4e3b6f0b137d51f8137473302b801a2c7 Mon Sep 17 00:00:00 2001 From: Danack Date: Sat, 4 Jun 2022 19:46:35 +0100 Subject: [PATCH 02/35] Version with PDOSqlite apparently working. Which seems unlikely. --- ext/pdo/pdo_dbh.c | 86 ++++++++++++++++++--- ext/pdo/pdo_dbh.stub.php | 7 ++ ext/pdo/pdo_dbh_arginfo.h | 11 ++- ext/pdo/pdosqlite_class.c | 4 +- ext/pdo/tests/subclasses/pdosqlite_002.phpt | 51 ++++++++++++ 5 files changed, 144 insertions(+), 15 deletions(-) create mode 100644 ext/pdo/tests/subclasses/pdosqlite_002.phpt diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index 587e133ca9712..cee14d34d7ed1 100644 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -219,10 +219,29 @@ static char *dsn_from_uri(char *uri, char *buf, size_t buflen) /* {{{ */ } /* }}} */ -/* {{{ */ -PHP_METHOD(PDO, __construct) +static +void create_specific_pdo_object(zval *new_object, const char *driver_name) +{ + if (strcmp("sqlite", driver_name) == 0) { + + object_init_ex(new_object, pdosqlite_ce); +// intern = Z_XMLREADER_P(return_value); +// intern->ptr = reader; +// printf("created pdosqlite object?\n"); + return; + } +//'pgsql' +//'oci' +//'firebird' +//'odbc' + + // No specific DB implementation found + object_init_ex(new_object, pdo_ce); +} + +static +void internal_construct(INTERNAL_FUNCTION_PARAMETERS, zval *object, zval *new_zval_object) { - zval *object = ZEND_THIS; pdo_dbh_t *dbh = NULL; bool is_persistent = 0; char *data_source; @@ -289,7 +308,26 @@ PHP_METHOD(PDO, __construct) RETURN_THROWS(); } - dbh = Z_PDO_DBH_P(object); + // TODO - turn into a function? + if (object == NULL) { + // could this every happen? + if (driver->driver_name == NULL) { + zend_throw_exception_ex(php_pdo_get_exception(), 0, "Driver name is NULL"); + RETURN_THROWS(); + } + + create_specific_pdo_object(new_zval_object, driver->driver_name); + + if (new_zval_object == NULL) { + zend_throw_exception_ex(php_pdo_get_exception(), 0, "Failed to create specific PDO class"); + RETURN_THROWS(); + } + + dbh = Z_PDO_DBH_P(new_zval_object); + } + else { + dbh = Z_PDO_DBH_P(object); + } /* is this supposed to be a persistent connection ? */ if (options) { @@ -430,8 +468,32 @@ PHP_METHOD(PDO, __construct) zend_throw_exception(pdo_exception_ce, "Constructor failed", 0); } } + +/* {{{ */ +PHP_METHOD(PDO, __construct) +{ + zval *object = ZEND_THIS; + internal_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, object, NULL); +} +/* }}} */ + + +/* {{{ */ +PHP_METHOD(PDO, connect) +{ +// zval *new_object = NULL; +// return_value = NULL; + internal_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, NULL, return_value); + + if (return_value == NULL) { + // Fix stuff up here? + printf("Retval is still null.\n"); + exit(-1); + } +} /* }}} */ + static zval *pdo_stmt_instantiate(pdo_dbh_t *dbh, zval *object, zend_class_entry *dbstmt_ce, zval *ctor_args) /* {{{ */ { if (!Z_ISUNDEF_P(ctor_args)) { @@ -1324,6 +1386,8 @@ static HashTable *dbh_get_gc(zend_object *object, zval **gc_data, int *gc_count) } static zend_object_handlers pdo_dbh_object_handlers; +static zend_object_handlers pdosqlite_dbh_object_handlers; + static void pdo_dbh_free_storage(zend_object *std); void pdo_dbh_init(void) @@ -1428,13 +1492,13 @@ void pdo_dbh_init(void) pdosqlite_ce = register_class_PDOSqlite(pdo_dbh_ce); pdosqlite_ce->create_object = pdo_dbh_new; - memcpy(&pdo_dbh_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - pdo_dbh_object_handlers.offset = XtOffsetOf(pdo_dbh_object_t, std); - pdo_dbh_object_handlers.free_obj = pdo_dbh_free_storage; - pdo_dbh_object_handlers.clone_obj = NULL; - pdo_dbh_object_handlers.get_method = dbh_method_get; - pdo_dbh_object_handlers.compare = zend_objects_not_comparable; - pdo_dbh_object_handlers.get_gc = dbh_get_gc; + memcpy(&pdosqlite_dbh_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); + pdosqlite_dbh_object_handlers.offset = XtOffsetOf(pdo_dbh_object_t, std); + pdosqlite_dbh_object_handlers.free_obj = pdo_dbh_free_storage; + pdosqlite_dbh_object_handlers.clone_obj = NULL; + pdosqlite_dbh_object_handlers.get_method = dbh_method_get; + pdosqlite_dbh_object_handlers.compare = zend_objects_not_comparable; + pdosqlite_dbh_object_handlers.get_gc = dbh_get_gc; } static void dbh_free(pdo_dbh_t *dbh, bool free_persistent) diff --git a/ext/pdo/pdo_dbh.stub.php b/ext/pdo/pdo_dbh.stub.php index 7ff52c9696a07..a2589829b7be5 100644 --- a/ext/pdo/pdo_dbh.stub.php +++ b/ext/pdo/pdo_dbh.stub.php @@ -7,6 +7,13 @@ class PDO { 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 + ): PDO|PDOSqlite {} + /** @tentative-return-type */ public function beginTransaction(): bool {} diff --git a/ext/pdo/pdo_dbh_arginfo.h b/ext/pdo/pdo_dbh_arginfo.h index 11d6fac08b577..14fde6d9cbb26 100644 --- a/ext/pdo/pdo_dbh_arginfo.h +++ b/ext/pdo/pdo_dbh_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 7d10dbdfd55eb4a4dc779cbf4fa000cdf4fb3539 */ + * Stub hash: 9ad9db0f01bb0f36d1ff11c15428799d38a1a22f */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_PDO___construct, 0, 0, 1) ZEND_ARG_TYPE_INFO(0, dsn, IS_STRING, 0) @@ -8,6 +8,13 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_PDO___construct, 0, 0, 1) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, options, IS_ARRAY, 1, "null") ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_PDO_connect, 0, 1, PDO|PDOSqlite, 0) + ZEND_ARG_TYPE_INFO(0, dsn, IS_STRING, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, username, IS_STRING, 1, "null") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, password, IS_STRING, 1, "null") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, options, IS_ARRAY, 1, "null") +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_PDO_beginTransaction, 0, 0, _IS_BOOL, 0) ZEND_END_ARG_INFO() @@ -60,6 +67,7 @@ ZEND_END_ARG_INFO() ZEND_METHOD(PDO, __construct); +ZEND_METHOD(PDO, connect); ZEND_METHOD(PDO, beginTransaction); ZEND_METHOD(PDO, commit); ZEND_METHOD(PDO, errorCode); @@ -78,6 +86,7 @@ ZEND_METHOD(PDO, setAttribute); static const zend_function_entry class_PDO_methods[] = { ZEND_ME(PDO, __construct, arginfo_class_PDO___construct, ZEND_ACC_PUBLIC) + ZEND_ME(PDO, connect, arginfo_class_PDO_connect, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) ZEND_ME(PDO, beginTransaction, arginfo_class_PDO_beginTransaction, ZEND_ACC_PUBLIC) ZEND_ME(PDO, commit, arginfo_class_PDO_commit, ZEND_ACC_PUBLIC) ZEND_ME(PDO, errorCode, arginfo_class_PDO_errorCode, ZEND_ACC_PUBLIC) diff --git a/ext/pdo/pdosqlite_class.c b/ext/pdo/pdosqlite_class.c index d3ad178821725..ac1c3cdbf9b6d 100644 --- a/ext/pdo/pdosqlite_class.c +++ b/ext/pdo/pdosqlite_class.c @@ -11,9 +11,7 @@ | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ - | Author: Wez Furlong | - | Marcus Boerger | - | Sterling Hughes | + | Author: Danack +----------------------------------------------------------------------+ */ diff --git a/ext/pdo/tests/subclasses/pdosqlite_002.phpt b/ext/pdo/tests/subclasses/pdosqlite_002.phpt new file mode 100644 index 0000000000000..3bc95149b2570 --- /dev/null +++ b/ext/pdo/tests/subclasses/pdosqlite_002.phpt @@ -0,0 +1,51 @@ +--TEST-- +PDOSqlite create through PDO::connect +--EXTENSIONS-- +pdo +--FILE-- +query('CREATE TABLE IF NOT EXISTS foobar (id INT AUTO INCREMENT, name TEXT)'); +$db->query('INSERT INTO foobar VALUES (NULL, "PHP")'); +$db->query('INSERT INTO foobar VALUES (NULL, "PHP6")'); + + +$db->createFunction('testing', function($v) { return strtolower($v); }, 1, PDO::SQLITE_DETERMINISTIC); + + +foreach ($db->query('SELECT testing(name) FROM foobar') as $row) { + var_dump($row); +} + +$db->query('DROP TABLE foobar'); + +echo "Fin."; +?> +--EXPECT-- +PdoSqlite class exists. +array(2) { + ["testing(name)"]=> + string(3) "php" + [0]=> + string(3) "php" +} +array(2) { + ["testing(name)"]=> + string(4) "php6" + [0]=> + string(4) "php6" +} +Fin. From c5317fccd06d166561717eb4b58c6756ad72069e Mon Sep 17 00:00:00 2001 From: Danack Date: Sat, 4 Jun 2022 20:01:32 +0100 Subject: [PATCH 03/35] Typo on class name. --- ext/pdo/pdo_dbh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index cee14d34d7ed1..db57927c93fab 100644 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -236,7 +236,7 @@ void create_specific_pdo_object(zval *new_object, const char *driver_name) //'odbc' // No specific DB implementation found - object_init_ex(new_object, pdo_ce); + object_init_ex(new_object, pdo_dbh_ce); } static From 357fffab8e669478e448b5d38f5865d746d38fbf Mon Sep 17 00:00:00 2001 From: Danack Date: Tue, 21 Jun 2022 15:42:59 +0100 Subject: [PATCH 04/35] Initial version of PDOSQLite::loadExtension. Needs thinking about ini settings. --- ext/pdo/pdo_sqlite.stub.php | 11 ++- ext/pdo/pdo_sqlite_arginfo.h | 14 ++- ext/pdo/pdosqlite_class.c | 92 ++++++++++++++++++++ ext/pdo/php_pdo.h | 7 ++ ext/pdo/tests/subclasses/pdosqlite_003.phpt | 49 +++++++++++ ext/pdo_mysql/tests/pdo_mysql_interface.phpt | 1 + 6 files changed, 170 insertions(+), 4 deletions(-) create mode 100644 ext/pdo/tests/subclasses/pdosqlite_003.phpt diff --git a/ext/pdo/pdo_sqlite.stub.php b/ext/pdo/pdo_sqlite.stub.php index 6994f0cd28f87..64df07e4c362e 100644 --- a/ext/pdo/pdo_sqlite.stub.php +++ b/ext/pdo/pdo_sqlite.stub.php @@ -5,13 +5,18 @@ /** @not-serializable */ class PDOSqlite extends PDO { -// public function __construct(string $dsn, ?string $username = null, ?string $password = null, ?array $options = null) {} - - public function createFunction( string $function_name, callable $callback, int $num_args = -1, int $flags = 0 ): bool {} + +// Whether SQLITE_OMIT_LOAD_EXTENSION is defined or not depends on how +// SQLite was compiled: https://www.sqlite.org/compile.html + +#ifndef SQLITE_OMIT_LOAD_EXTENSION + public function loadExtension(string $name): bool {} +#endif + } diff --git a/ext/pdo/pdo_sqlite_arginfo.h b/ext/pdo/pdo_sqlite_arginfo.h index 67e300215edfc..2cfcb089ef4ca 100644 --- a/ext/pdo/pdo_sqlite_arginfo.h +++ b/ext/pdo/pdo_sqlite_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 8151524ca99ba6f461e5113fc055a462e0072cb7 */ + * Stub hash: b0396a798b67a578c9d0c7a1f04c6fc3dcd24691 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PDOSqlite_createFunction, 0, 2, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, function_name, IS_STRING, 0) @@ -8,12 +8,24 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PDOSqlite_createFunction, ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, flags, IS_LONG, 0, "0") ZEND_END_ARG_INFO() +#if !defined(SQLITE_OMIT_LOAD_EXTENSION) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PDOSqlite_loadExtension, 0, 1, _IS_BOOL, 0) + ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 0) +ZEND_END_ARG_INFO() +#endif + ZEND_METHOD(PDOSqlite, createFunction); +#if !defined(SQLITE_OMIT_LOAD_EXTENSION) +ZEND_METHOD(PDOSqlite, loadExtension); +#endif static const zend_function_entry class_PDOSqlite_methods[] = { ZEND_ME(PDOSqlite, createFunction, arginfo_class_PDOSqlite_createFunction, ZEND_ACC_PUBLIC) +#if !defined(SQLITE_OMIT_LOAD_EXTENSION) + ZEND_ME(PDOSqlite, loadExtension, arginfo_class_PDOSqlite_loadExtension, ZEND_ACC_PUBLIC) +#endif ZEND_FE_END }; diff --git a/ext/pdo/pdosqlite_class.c b/ext/pdo/pdosqlite_class.c index ac1c3cdbf9b6d..3bf3eb4d1e997 100644 --- a/ext/pdo/pdosqlite_class.c +++ b/ext/pdo/pdosqlite_class.c @@ -34,6 +34,7 @@ #include "../pdo_sqlite/php_pdo_sqlite.h" #include "../pdo_sqlite/php_pdo_sqlite_int.h" +// TODO - define this in appropriate header, not here. extern void php_sqlite3_func_callback(sqlite3_context *context, int argc, sqlite3_value **argv); @@ -90,3 +91,94 @@ PHP_METHOD(PDOSqlite, createFunction) } /* }}} */ +#ifndef SQLITE_OMIT_LOAD_EXTENSION +/* {{{ Attempts to load an SQLite extension library. */ +PHP_METHOD(PDOSqlite, loadExtension) +{ +// php_sqlite3_db_object *db_obj; +// zval *object = ZEND_THIS; + char *extension, *lib_path, *extension_dir, *errtext = NULL; + char fullpath[MAXPATHLEN]; + size_t extension_len;// , extension_dir_len; +// db_obj = Z_SQLITE3_DB_P(object); + + pdo_dbh_t *dbh; + pdo_sqlite_db_handle *db_handle; + + if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "s", &extension, &extension_len)) { + RETURN_THROWS(); + } + + dbh = Z_PDO_DBH_P(ZEND_THIS); + PDO_CONSTRUCT_CHECK; + + db_handle = (pdo_sqlite_db_handle *)dbh->driver_data; + + // SQLITE3_CHECK_INITIALIZED(db_obj, db_obj->initialised, SQLite3) + +#ifdef ZTS + if ((strncmp(sapi_module.name, "cgi", 3) != 0) && + (strcmp(sapi_module.name, "cli") != 0) && + (strncmp(sapi_module.name, "embed", 5) != 0) + ) { + php_sqlite3_error(db_obj, "Not supported in multithreaded Web servers"); + RETURN_FALSE; + } +#endif + +// if (!SQLITE3G(extension_dir)) { +// php_sqlite3_error(db_obj, "SQLite Extension are disabled"); +// RETURN_FALSE; +// } +// +// if (extension_len == 0) { +// php_sqlite3_error(db_obj, "Empty string as an extension"); +// RETURN_FALSE; +// } + +// extension_dir = SQLITE3G(extension_dir); +// extension_dir_len = strlen(SQLITE3G(extension_dir)); + +// if (IS_SLASH(extension_dir[extension_dir_len-1])) { +// spprintf(&lib_path, 0, "%s%s", extension_dir, extension); +// } else { +// spprintf(&lib_path, 0, "%s%c%s", extension_dir, DEFAULT_SLASH, extension); +// } + + spprintf(&lib_path, 0, "%s",extension); + + if (!VCWD_REALPATH(lib_path, fullpath)) { +// php_sqlite3_error(db_obj, "Unable to load extension at '%s'", lib_path); + // TODO - enable this error +// zend_throw_exception_ex(php_pdo_get_exception(), 0, "There is no active transaction"); + efree(lib_path); + RETURN_FALSE; + } + + efree(lib_path); + +// if (strncmp(fullpath, extension_dir, extension_dir_len) != 0) { +// php_sqlite3_error(db_obj, "Unable to open extensions outside the defined directory"); +// RETURN_FALSE; +// } + +// note: expected 'sqlite3 *' but argument is of type 'pdo_sqlite_db_handle *' + sqlite3 *sqlite_handle; + + sqlite_handle = db_handle->db; + + /* Extension loading should only be enabled for when we attempt to load */ + sqlite3_enable_load_extension(sqlite_handle, 1); + if (sqlite3_load_extension(sqlite_handle, fullpath, 0, &errtext) != SQLITE_OK) { + //php_sqlite3_error(db_obj, "%s", errtext); + zend_throw_exception_ex(php_pdo_get_exception(), 0, errtext); + sqlite3_free(errtext); + sqlite3_enable_load_extension(sqlite_handle, 0); + RETURN_FALSE; + } + sqlite3_enable_load_extension(sqlite_handle, 0); + + RETURN_TRUE; +} +/* }}} */ +#endif diff --git a/ext/pdo/php_pdo.h b/ext/pdo/php_pdo.h index 9c278cd40a5cf..bfd8f9d7a5a18 100644 --- a/ext/pdo/php_pdo.h +++ b/ext/pdo/php_pdo.h @@ -22,6 +22,13 @@ extern zend_module_entry pdo_module_entry; #define phpext_pdo_ptr &pdo_module_entry + +// TODO - enable +// ZEND_BEGIN_MODULE_GLOBALS(sqlite3) +// char *extension_dir; +// int dbconfig_defensive; +// ZEND_END_MODULE_GLOBALS(sqlite3) + #include "php_version.h" #define PHP_PDO_VERSION PHP_VERSION diff --git a/ext/pdo/tests/subclasses/pdosqlite_003.phpt b/ext/pdo/tests/subclasses/pdosqlite_003.phpt new file mode 100644 index 0000000000000..eab589c1a7f2e --- /dev/null +++ b/ext/pdo/tests/subclasses/pdosqlite_003.phpt @@ -0,0 +1,49 @@ +--TEST-- +PDOSqlite load extension +--EXTENSIONS-- +pdo +--FILE-- +loadExtension("/usr/lib/x86_64-linux-gnu/mod_spatialite.so"); + +if ($result !== true) { + echo "Failed to load extension."; + exit(-1); +} + +$result = $db->query('SELECT AsText(Buffer(GeomFromText("LINESTRING(0 0, 1 0)"), 0.2)) as geometry_data;'); + +$row = $result->fetch(PDO::FETCH_ASSOC); +if ($row === false) { + echo "Failed to get data from geometry."; + exit(-1); +} + +if (array_key_exists('geometry_data', $row) !== true) { + echo "Data is not under key 'geometry_data'. Available array keys are:"; + var_dump(array_keys($row)); + exit(-1); +} + +echo $row['geometry_data'] . "\n"; + +$row = $result->fetch(PDO::FETCH_ASSOC); + +if ($row !== false) { + echo "We appear to have more data than expected."; + var_dump($row); + exit(-1); +} + +echo "Fin."; +?> +--EXPECT-- +POLYGON((1 0.2, 1.010467 0.199726, 1.020906 0.198904, 1.031287 0.197538, 1.041582 0.19563, 1.051764 0.193185, 1.061803 0.190211, 1.071674 0.186716, 1.081347 0.182709, 1.090798 0.178201, 1.1 0.173205, 1.108928 0.167734, 1.117557 0.161803, 1.125864 0.155429, 1.133826 0.148629, 1.141421 0.141421, 1.148629 0.133826, 1.155429 0.125864, 1.161803 0.117557, 1.167734 0.108928, 1.173205 0.1, 1.178201 0.090798, 1.182709 0.081347, 1.186716 0.071674, 1.190211 0.061803, 1.193185 0.051764, 1.19563 0.041582, 1.197538 0.031287, 1.198904 0.020906, 1.199726 0.010467, 1.2 0, 1.199726 -0.010467, 1.198904 -0.020906, 1.197538 -0.031287, 1.19563 -0.041582, 1.193185 -0.051764, 1.190211 -0.061803, 1.186716 -0.071674, 1.182709 -0.081347, 1.178201 -0.090798, 1.173205 -0.1, 1.167734 -0.108928, 1.161803 -0.117557, 1.155429 -0.125864, 1.148629 -0.133826, 1.141421 -0.141421, 1.133826 -0.148629, 1.125864 -0.155429, 1.117557 -0.161803, 1.108928 -0.167734, 1.1 -0.173205, 1.090798 -0.178201, 1.081347 -0.182709, 1.071674 -0.186716, 1.061803 -0.190211, 1.051764 -0.193185, 1.041582 -0.19563, 1.031287 -0.197538, 1.020906 -0.198904, 1.010467 -0.199726, 1 -0.2, 0 -0.2, -0.010467 -0.199726, -0.020906 -0.198904, -0.031287 -0.197538, -0.041582 -0.19563, -0.051764 -0.193185, -0.061803 -0.190211, -0.071674 -0.186716, -0.081347 -0.182709, -0.090798 -0.178201, -0.1 -0.173205, -0.108928 -0.167734, -0.117557 -0.161803, -0.125864 -0.155429, -0.133826 -0.148629, -0.141421 -0.141421, -0.148629 -0.133826, -0.155429 -0.125864, -0.161803 -0.117557, -0.167734 -0.108928, -0.173205 -0.1, -0.178201 -0.090798, -0.182709 -0.081347, -0.186716 -0.071674, -0.190211 -0.061803, -0.193185 -0.051764, -0.19563 -0.041582, -0.197538 -0.031287, -0.198904 -0.020906, -0.199726 -0.010467, -0.2 0, -0.199726 0.010467, -0.198904 0.020906, -0.197538 0.031287, -0.19563 0.041582, -0.193185 0.051764, -0.190211 0.061803, -0.186716 0.071674, -0.182709 0.081347, -0.178201 0.090798, -0.173205 0.1, -0.167734 0.108928, -0.161803 0.117557, -0.155429 0.125864, -0.148629 0.133826, -0.141421 0.141421, -0.133826 0.148629, -0.125864 0.155429, -0.117557 0.161803, -0.108928 0.167734, -0.1 0.173205, -0.090798 0.178201, -0.081347 0.182709, -0.071674 0.186716, -0.061803 0.190211, -0.051764 0.193185, -0.041582 0.19563, -0.031287 0.197538, -0.020906 0.198904, -0.010467 0.199726, 0 0.2, 1 0.2)) +Fin. diff --git a/ext/pdo_mysql/tests/pdo_mysql_interface.phpt b/ext/pdo_mysql/tests/pdo_mysql_interface.phpt index aeb441bc0363a..5b6db319261b8 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_interface.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_interface.phpt @@ -17,6 +17,7 @@ if (false == MySQLPDOTest::detect_transactional_mysql_engine($db)) $expected = array( '__construct' => true, + 'connect' => true, 'prepare' => true, 'beginTransaction' => true, 'commit' => true, From a3f77ccf26bebef634210fb43308ccafb642e893 Mon Sep 17 00:00:00 2001 From: Danack Date: Fri, 24 Jun 2022 01:43:17 +0100 Subject: [PATCH 05/35] PDOSQLite::blobOpen is working. --- ext/pdo/pdo_sqlite.stub.php | 14 +- ext/pdo/pdo_sqlite_arginfo.h | 12 +- ext/pdo/pdosqlite_class.c | 232 +++++++++++++++++- .../subclasses/pdosqlite_004_blobopen.phpt | 78 ++++++ ext/pdo/tests/subclasses/stream_test.inc | 48 ++++ 5 files changed, 381 insertions(+), 3 deletions(-) create mode 100644 ext/pdo/tests/subclasses/pdosqlite_004_blobopen.phpt create mode 100644 ext/pdo/tests/subclasses/stream_test.inc diff --git a/ext/pdo/pdo_sqlite.stub.php b/ext/pdo/pdo_sqlite.stub.php index 64df07e4c362e..ee9abf9502b02 100644 --- a/ext/pdo/pdo_sqlite.stub.php +++ b/ext/pdo/pdo_sqlite.stub.php @@ -14,9 +14,21 @@ public function createFunction( // Whether SQLITE_OMIT_LOAD_EXTENSION is defined or not depends on how // SQLite was compiled: https://www.sqlite.org/compile.html - #ifndef SQLITE_OMIT_LOAD_EXTENSION public function loadExtension(string $name): bool {} #endif + public function openBlob( + string $table, + string $column, + int $rowid, + ?string $dbname = "main", //null, + int $flags = PDO::SQLITE_OPEN_READONLY + ): mixed /* resource|false */ {} + +//SQLITE_OPEN_READONLY +//SQLITE_OPEN_READWRITE +//SQLITE_OPEN_CREATE + + } diff --git a/ext/pdo/pdo_sqlite_arginfo.h b/ext/pdo/pdo_sqlite_arginfo.h index 2cfcb089ef4ca..13c48f1d4dbaf 100644 --- a/ext/pdo/pdo_sqlite_arginfo.h +++ b/ext/pdo/pdo_sqlite_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: b0396a798b67a578c9d0c7a1f04c6fc3dcd24691 */ + * Stub hash: 9e4de4487e2652b510d91a903ce7267b089a83c1 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PDOSqlite_createFunction, 0, 2, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, function_name, IS_STRING, 0) @@ -14,11 +14,20 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PDOSqlite_loadExtension, 0 ZEND_END_ARG_INFO() #endif +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PDOSqlite_openBlob, 0, 3, IS_MIXED, 0) + ZEND_ARG_TYPE_INFO(0, table, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, column, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, rowid, IS_LONG, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, dbname, IS_STRING, 1, "\"main\"") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, flags, IS_LONG, 0, "PDO::SQLITE_OPEN_READONLY") +ZEND_END_ARG_INFO() + ZEND_METHOD(PDOSqlite, createFunction); #if !defined(SQLITE_OMIT_LOAD_EXTENSION) ZEND_METHOD(PDOSqlite, loadExtension); #endif +ZEND_METHOD(PDOSqlite, openBlob); static const zend_function_entry class_PDOSqlite_methods[] = { @@ -26,6 +35,7 @@ static const zend_function_entry class_PDOSqlite_methods[] = { #if !defined(SQLITE_OMIT_LOAD_EXTENSION) ZEND_ME(PDOSqlite, loadExtension, arginfo_class_PDOSqlite_loadExtension, ZEND_ACC_PUBLIC) #endif + ZEND_ME(PDOSqlite, openBlob, arginfo_class_PDOSqlite_openBlob, ZEND_ACC_PUBLIC) ZEND_FE_END }; diff --git a/ext/pdo/pdosqlite_class.c b/ext/pdo/pdosqlite_class.c index 3bf3eb4d1e997..da76a746eeb49 100644 --- a/ext/pdo/pdosqlite_class.c +++ b/ext/pdo/pdosqlite_class.c @@ -97,7 +97,8 @@ PHP_METHOD(PDOSqlite, loadExtension) { // php_sqlite3_db_object *db_obj; // zval *object = ZEND_THIS; - char *extension, *lib_path, *extension_dir, *errtext = NULL; + char *extension, *lib_path, *errtext = NULL; + // char *extension_dir; char fullpath[MAXPATHLEN]; size_t extension_len;// , extension_dir_len; // db_obj = Z_SQLITE3_DB_P(object); @@ -121,7 +122,10 @@ PHP_METHOD(PDOSqlite, loadExtension) (strcmp(sapi_module.name, "cli") != 0) && (strncmp(sapi_module.name, "embed", 5) != 0) ) { + // TODO - needs test. php_sqlite3_error(db_obj, "Not supported in multithreaded Web servers"); + // and converting to exception zend_throw_exception_ex(php_pdo_get_exception(), 0, errtext); + RETURN_FALSE; } #endif @@ -182,3 +186,229 @@ PHP_METHOD(PDOSqlite, loadExtension) } /* }}} */ #endif + +typedef struct { + sqlite3_blob *blob; + size_t position; + size_t size; + int flags; +} php_stream_pdosqlite3_data; + +static ssize_t php_pdosqlite3_stream_write(php_stream *stream, const char *buf, size_t count) +{ + php_stream_pdosqlite3_data *sqlite3_stream = (php_stream_pdosqlite3_data *) stream->abstract; + + if (sqlite3_stream->flags & SQLITE_OPEN_READONLY) { + php_error_docref(NULL, E_WARNING, "Can't write to blob stream: is open as read only"); + return -1; + } + + if (sqlite3_stream->position + count > sqlite3_stream->size) { + php_error_docref(NULL, E_WARNING, "It is not possible to increase the size of a BLOB"); + return -1; + } + + if (sqlite3_blob_write(sqlite3_stream->blob, buf, count, sqlite3_stream->position) != SQLITE_OK) { + return -1; + } + + if (sqlite3_stream->position + count >= sqlite3_stream->size) { + stream->eof = 1; + sqlite3_stream->position = sqlite3_stream->size; + } + else { + sqlite3_stream->position += count; + } + + return count; +} + +static ssize_t php_pdosqlite3_stream_read(php_stream *stream, char *buf, size_t count) +{ + php_stream_pdosqlite3_data *sqlite3_stream = (php_stream_pdosqlite3_data *) stream->abstract; + + if (sqlite3_stream->position + count >= sqlite3_stream->size) { + count = sqlite3_stream->size - sqlite3_stream->position; + stream->eof = 1; + } + if (count) { + if (sqlite3_blob_read(sqlite3_stream->blob, buf, count, sqlite3_stream->position) != SQLITE_OK) { + return -1; + } + sqlite3_stream->position += count; + } + return count; +} + +static int php_pdosqlite3_stream_close(php_stream *stream, int close_handle) +{ + php_stream_pdosqlite3_data *sqlite3_stream = (php_stream_pdosqlite3_data *) stream->abstract; + + if (sqlite3_blob_close(sqlite3_stream->blob) != SQLITE_OK) { + /* Error occurred, but it still closed */ + } + + efree(sqlite3_stream); + + return 0; +} + +static int php_pdosqlite3_stream_flush(php_stream *stream) +{ + /* do nothing */ + return 0; +} + +/* {{{ */ +static int php_pdosqlite3_stream_seek(php_stream *stream, zend_off_t offset, int whence, zend_off_t *newoffs) +{ + php_stream_pdosqlite3_data *sqlite3_stream = (php_stream_pdosqlite3_data *) stream->abstract; + + switch(whence) { + case SEEK_CUR: + if (offset < 0) { + if (sqlite3_stream->position < (size_t)(-offset)) { + sqlite3_stream->position = 0; + *newoffs = -1; + return -1; + } else { + sqlite3_stream->position = sqlite3_stream->position + offset; + *newoffs = sqlite3_stream->position; + stream->eof = 0; + return 0; + } + } else { + if (sqlite3_stream->position + (size_t)(offset) > sqlite3_stream->size) { + sqlite3_stream->position = sqlite3_stream->size; + *newoffs = -1; + return -1; + } else { + sqlite3_stream->position = sqlite3_stream->position + offset; + *newoffs = sqlite3_stream->position; + stream->eof = 0; + return 0; + } + } + case SEEK_SET: + if (sqlite3_stream->size < (size_t)(offset)) { + sqlite3_stream->position = sqlite3_stream->size; + *newoffs = -1; + return -1; + } else { + sqlite3_stream->position = offset; + *newoffs = sqlite3_stream->position; + stream->eof = 0; + return 0; + } + case SEEK_END: + if (offset > 0) { + sqlite3_stream->position = sqlite3_stream->size; + *newoffs = -1; + return -1; + } else if (sqlite3_stream->size < (size_t)(-offset)) { + sqlite3_stream->position = 0; + *newoffs = -1; + return -1; + } else { + sqlite3_stream->position = sqlite3_stream->size + offset; + *newoffs = sqlite3_stream->position; + stream->eof = 0; + return 0; + } + default: + *newoffs = sqlite3_stream->position; + return -1; + } +} +/* }}} */ + + +static int php_pdosqlite3_stream_cast(php_stream *stream, int castas, void **ret) +{ + return FAILURE; +} + +static int php_pdosqlite3_stream_stat(php_stream *stream, php_stream_statbuf *ssb) +{ + php_stream_pdosqlite3_data *sqlite3_stream = (php_stream_pdosqlite3_data *) stream->abstract; + ssb->sb.st_size = sqlite3_stream->size; + return 0; +} + +static const php_stream_ops php_stream_pdosqlite3_ops = { + php_pdosqlite3_stream_write, + php_pdosqlite3_stream_read, + php_pdosqlite3_stream_close, + php_pdosqlite3_stream_flush, + "PDOSQLite", + php_pdosqlite3_stream_seek, + php_pdosqlite3_stream_cast, + php_pdosqlite3_stream_stat, + NULL +}; + + + +/* {{{ Open a blob as a stream which we can read / write to. */ +PHP_METHOD(PDOSqlite, openBlob) +{ +// php_sqlite3_db_object *db_obj; +// zval *object = ZEND_THIS; + char *table, *column, *dbname = "main", *mode = "rb"; + size_t table_len, column_len, dbname_len; + zend_long rowid, flags = SQLITE_OPEN_READONLY, sqlite_flags = 0; + sqlite3_blob *blob = NULL; + php_stream_pdosqlite3_data *sqlite3_stream; + php_stream *stream; + + pdo_dbh_t *dbh; + pdo_sqlite_db_handle *db_handle; + +// if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "s", &extension, &extension_len)) { +// RETURN_THROWS(); +// } + + dbh = Z_PDO_DBH_P(ZEND_THIS); + PDO_CONSTRUCT_CHECK; + +// db_obj = Z_SQLITE3_DB_P(object); + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "ssl|pl", &table, &table_len, &column, &column_len, &rowid, &dbname, &dbname_len, &flags) == FAILURE) { + RETURN_THROWS(); + } + + db_handle = (pdo_sqlite_db_handle *)dbh->driver_data; + + sqlite3 *sqlite_handle; + + sqlite_handle = db_handle->db; + +// SQLITE3_CHECK_INITIALIZED(db_obj, db_obj->initialised, SQLite3) + + sqlite_flags = (flags & SQLITE_OPEN_READWRITE) ? 1 : 0; + + if (sqlite3_blob_open(sqlite_handle, dbname, table, column, rowid, sqlite_flags, &blob) != SQLITE_OK) { +// php_sqlite3_error(db_obj, "Unable to open blob: %s", sqlite3_errmsg(db_obj->db)); + // and converting to exception zend_throw_exception_ex(php_pdo_get_exception(), 0, errtext); + RETURN_FALSE; + } + + sqlite3_stream = emalloc(sizeof(php_stream_pdosqlite3_data)); + sqlite3_stream->blob = blob; + sqlite3_stream->flags = flags; + sqlite3_stream->position = 0; + sqlite3_stream->size = sqlite3_blob_bytes(blob); + + if (sqlite_flags != 0) { + mode = "r+b"; + } + + stream = php_stream_alloc(&php_stream_pdosqlite3_ops, sqlite3_stream, 0, mode); + + if (stream) { + php_stream_to_zval(stream, return_value); + } else { + RETURN_FALSE; + } +} +/* }}} */ diff --git a/ext/pdo/tests/subclasses/pdosqlite_004_blobopen.phpt b/ext/pdo/tests/subclasses/pdosqlite_004_blobopen.phpt new file mode 100644 index 0000000000000..5976f41a31c6a --- /dev/null +++ b/ext/pdo/tests/subclasses/pdosqlite_004_blobopen.phpt @@ -0,0 +1,78 @@ +--TEST-- +PDOSqlite::blobOpen stream test +--EXTENSIONS-- +pdo +--FILE-- +exec('CREATE TABLE test (id STRING, data BLOB)'); + +echo "PREPARING insert\n"; +$insert_stmt = $db->prepare("INSERT INTO test (id, data) VALUES (?, ?)"); + +echo "BINDING Parameter\n"; +var_dump($insert_stmt->bindValue(1, 'a', PDO::PARAM_STR)); +var_dump($insert_stmt->bindValue(2, 'TEST TEST', PDO::PARAM_LOB)); +$insert_stmt->execute(); +echo "\n"; + +$stream = $db->openBlob('test', 'data', 1); +var_dump($stream); +echo "Stream Contents\n"; +var_dump(stream_get_contents($stream)); +echo "Writing to read-only stream\n"; +var_dump(fwrite($stream, 'ABCD')); +echo "Closing Stream\n"; +var_dump(fclose($stream)); +echo "Opening stream in write mode\n"; +$stream = $db->openBlob('test', 'data', 1, 'main', PDO::SQLITE_OPEN_READWRITE); +var_dump($stream); +echo "Writing to blob\n"; +var_dump(fwrite($stream, 'ABCD')); +echo "Stream Contents\n"; +fseek($stream, 0); +var_dump(stream_get_contents($stream)); +echo "Expanding blob size\n"; +var_dump(fwrite($stream, 'ABCD ABCD ABCD')); +echo "Closing Stream\n"; +var_dump(fclose($stream)); + +echo "Done\n"; +?> +--EXPECTF-- +Creating Table +PREPARING insert +BINDING Parameter +bool(true) +bool(true) + +resource(%d) of type (stream) +Stream Contents +string(9) "TEST TEST" +Writing to read-only stream + +Warning: fwrite(): Can't write to blob stream: is open as read only in %s on line %d +bool(false) +Closing Stream +bool(true) +Opening stream in write mode +resource(%d) of type (stream) +Writing to blob +int(4) +Stream Contents +string(9) "ABCD TEST" +Expanding blob size + +Warning: fwrite(): It is not possible to increase the size of a BLOB in %s on line %d +bool(false) +Closing Stream +bool(true) +Done diff --git a/ext/pdo/tests/subclasses/stream_test.inc b/ext/pdo/tests/subclasses/stream_test.inc new file mode 100644 index 0000000000000..e982173e94614 --- /dev/null +++ b/ext/pdo/tests/subclasses/stream_test.inc @@ -0,0 +1,48 @@ +position = 0; + return true; + } + + public function stream_read($count) + { + $ret = substr(self::$string, $this->position, $count); + $this->position += strlen($ret); + return $ret; + } + + public function stream_write($data) + { + return 0; + } + + public function stream_stat() + { + return array('size' => self::$string_length); + } + + public function stream_tell() + { + return $this->position; + } + + public function stream_eof() + { + return ($this->position >= self::$string_length); + } +} + +stream_wrapper_register('pdosqliteBlobTest', PDOSQLite_Test_Stream::class) or die("Unable to register pdosqliteBlobTest stream"); + +?> From b60f67858aa4b37ac7191418eb828b2a537efe4b Mon Sep 17 00:00:00 2001 From: Danack Date: Fri, 3 Mar 2023 18:30:58 +0000 Subject: [PATCH 06/35] Improve test to search for sqlite extension location. --- ext/pdo/tests/subclasses/pdosqlite_003.phpt | 22 +++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/ext/pdo/tests/subclasses/pdosqlite_003.phpt b/ext/pdo/tests/subclasses/pdosqlite_003.phpt index eab589c1a7f2e..931c32c34a83e 100644 --- a/ext/pdo/tests/subclasses/pdosqlite_003.phpt +++ b/ext/pdo/tests/subclasses/pdosqlite_003.phpt @@ -11,10 +11,28 @@ if (!$db instanceof PdoSqlite) { echo "Wrong class type. Should be PdoSqlite but is [" .get_class($db) . "\n"; } -$result = $db->loadExtension("/usr/lib/x86_64-linux-gnu/mod_spatialite.so"); +$extension_location = null; +$locations = [ + '/usr/lib/aarch64-linux-gnu/mod_spatialite.so', + "/usr/lib/x86_64-linux-gnu/mod_spatialite.so" +]; + +foreach ($locations as $location) { + if (file_exists($location)) { + $extension_location = $location; + } +} + +// This should be in a skip +if ($extension_location === null) { + echo "Failed to find mod_spatialite.so Did you install libsqlite3-mod-spatialite ?"; + exit(-1); +} + +$result = $db->loadExtension($extension_location); if ($result !== true) { - echo "Failed to load extension."; + echo "Failed to load extension mod_spatialite.so"; exit(-1); } From d95dbfb131ae13640d7c6930b7137d395bbbc179 Mon Sep 17 00:00:00 2001 From: Danack Date: Sat, 4 Mar 2023 19:21:59 +0000 Subject: [PATCH 07/35] Moved code to a more correct place. Added ability to register driver specific classes. --- ext/pdo/config.m4 | 2 +- ext/pdo/pdo.c | 2 -- ext/pdo/pdo_dbh.c | 33 +++++++++++-------- ext/pdo/php_pdo.h | 8 ++--- ext/pdo/php_pdo_driver.h | 8 +++++ ext/pdo/php_pdo_int.h | 3 -- ext/pdo_sqlite/config.m4 | 2 +- ext/pdo_sqlite/pdo_sqlite.c | 12 +++++++ ext/{pdo => pdo_sqlite}/pdo_sqlite.stub.php | 0 ext/{pdo => pdo_sqlite}/pdo_sqlite_arginfo.h | 0 .../pdo_sqlite_class.c} | 6 ++-- .../tests/subclasses/pdosqlite_001.phpt | 0 .../tests/subclasses/pdosqlite_002.phpt | 0 .../tests/subclasses/pdosqlite_003.phpt | 0 .../subclasses/pdosqlite_004_blobopen.phpt | 0 .../tests/subclasses/stream_test.inc | 0 16 files changed, 46 insertions(+), 30 deletions(-) rename ext/{pdo => pdo_sqlite}/pdo_sqlite.stub.php (100%) rename ext/{pdo => pdo_sqlite}/pdo_sqlite_arginfo.h (100%) rename ext/{pdo/pdosqlite_class.c => pdo_sqlite/pdo_sqlite_class.c} (99%) rename ext/{pdo => pdo_sqlite}/tests/subclasses/pdosqlite_001.phpt (100%) rename ext/{pdo => pdo_sqlite}/tests/subclasses/pdosqlite_002.phpt (100%) rename ext/{pdo => pdo_sqlite}/tests/subclasses/pdosqlite_003.phpt (100%) rename ext/{pdo => pdo_sqlite}/tests/subclasses/pdosqlite_004_blobopen.phpt (100%) rename ext/{pdo => pdo_sqlite}/tests/subclasses/stream_test.inc (100%) diff --git a/ext/pdo/config.m4 b/ext/pdo/config.m4 index 18d3ee7d55c92..9b9a3e36df7af 100644 --- a/ext/pdo/config.m4 +++ b/ext/pdo/config.m4 @@ -9,7 +9,7 @@ if test "$PHP_PDO" != "no"; then dnl Make sure $PHP_PDO is 'yes' when it's not 'no' :) PHP_PDO=yes - PHP_NEW_EXTENSION(pdo, pdo.c pdo_dbh.c pdo_stmt.c pdo_sql_parser.c pdo_sqlstate.c pdosqlite_class.c, $ext_shared) + PHP_NEW_EXTENSION(pdo, pdo.c pdo_dbh.c pdo_stmt.c pdo_sql_parser.c pdo_sqlstate.c, $ext_shared) PHP_ADD_EXTENSION_DEP(pdo, spl, true) PHP_INSTALL_HEADERS(ext/pdo, [php_pdo.h php_pdo_driver.h php_pdo_error.h]) diff --git a/ext/pdo/pdo.c b/ext/pdo/pdo.c index 0e8181ebd10e3..f11b983a9a82f 100644 --- a/ext/pdo/pdo.c +++ b/ext/pdo/pdo.c @@ -33,8 +33,6 @@ zend_class_entry *pdo_dbh_ce, *pdo_dbstmt_ce, *pdo_row_ce; -zend_class_entry *pdosqlite_ce; - /* for exceptional circumstances */ zend_class_entry *pdo_exception_ce; diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index db57927c93fab..3c860367fab21 100644 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -32,7 +32,6 @@ #include "zend_object_handlers.h" #include "zend_hash.h" #include "pdo_dbh_arginfo.h" -#include "pdo_sqlite_arginfo.h" static bool pdo_dbh_attribute_set(pdo_dbh_t *dbh, zend_long attr, zval *value); @@ -219,21 +218,29 @@ static char *dsn_from_uri(char *uri, char *buf, size_t buflen) /* {{{ */ } /* }}} */ + + +static int number_of_pdo_driver_class_entries = 0; +static pdo_driver_class_entry *pdo_driver_class_entries[64]; + +// TODO - remove this and roll it into the standard driver class entries +void pdo_register_driver_specific_class(pdo_driver_class_entry *driver_class_entry) +{ + pdo_driver_class_entries[number_of_pdo_driver_class_entries] = driver_class_entry; + number_of_pdo_driver_class_entries += 1; +} + + static void create_specific_pdo_object(zval *new_object, const char *driver_name) { - if (strcmp("sqlite", driver_name) == 0) { - - object_init_ex(new_object, pdosqlite_ce); -// intern = Z_XMLREADER_P(return_value); -// intern->ptr = reader; -// printf("created pdosqlite object?\n"); - return; + for (int i=0; i < number_of_pdo_driver_class_entries; i += 1) { + pdo_driver_class_entry *driver_class_entry = pdo_driver_class_entries[i]; + if (strcmp(driver_class_entry->driver_name, driver_name) == 0) { + object_init_ex(new_object, driver_class_entry->driver_ce); + return; + } } -//'pgsql' -//'oci' -//'firebird' -//'odbc' // No specific DB implementation found object_init_ex(new_object, pdo_dbh_ce); @@ -1489,8 +1496,6 @@ void pdo_dbh_init(void) REGISTER_PDO_CLASS_CONST_LONG("CURSOR_FWDONLY", (zend_long)PDO_CURSOR_FWDONLY); REGISTER_PDO_CLASS_CONST_LONG("CURSOR_SCROLL", (zend_long)PDO_CURSOR_SCROLL); - pdosqlite_ce = register_class_PDOSqlite(pdo_dbh_ce); - pdosqlite_ce->create_object = pdo_dbh_new; memcpy(&pdosqlite_dbh_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); pdosqlite_dbh_object_handlers.offset = XtOffsetOf(pdo_dbh_object_t, std); diff --git a/ext/pdo/php_pdo.h b/ext/pdo/php_pdo.h index bfd8f9d7a5a18..85b4282569eab 100644 --- a/ext/pdo/php_pdo.h +++ b/ext/pdo/php_pdo.h @@ -22,12 +22,8 @@ extern zend_module_entry pdo_module_entry; #define phpext_pdo_ptr &pdo_module_entry - -// TODO - enable -// ZEND_BEGIN_MODULE_GLOBALS(sqlite3) -// char *extension_dir; -// int dbconfig_defensive; -// ZEND_END_MODULE_GLOBALS(sqlite3) +extern zend_class_entry *pdo_dbh_ce; +extern zend_object *pdo_dbh_new(zend_class_entry *ce); #include "php_version.h" #define PHP_PDO_VERSION PHP_VERSION diff --git a/ext/pdo/php_pdo_driver.h b/ext/pdo/php_pdo_driver.h index c832284627750..25327fbc6e378 100644 --- a/ext/pdo/php_pdo_driver.h +++ b/ext/pdo/php_pdo_driver.h @@ -215,6 +215,14 @@ typedef struct { } pdo_driver_t; +// TODO - remove this separate struct, and roll it into pdo_driver_t +typedef struct { + char *driver_name; + zend_class_entry *driver_ce; +} pdo_driver_class_entry; + +void pdo_register_driver_specific_class(pdo_driver_class_entry *driver_class_entry); + /* {{{ methods for a database handle */ /* close or otherwise disconnect the database */ diff --git a/ext/pdo/php_pdo_int.h b/ext/pdo/php_pdo_int.h index da143c25b9260..f50925325ea0f 100644 --- a/ext/pdo/php_pdo_int.h +++ b/ext/pdo/php_pdo_int.h @@ -28,10 +28,7 @@ int php_pdo_list_entry(void); void pdo_dbh_init(void); void pdo_stmt_init(void); -extern zend_object *pdo_dbh_new(zend_class_entry *ce); extern const zend_function_entry pdo_dbh_functions[]; -extern zend_class_entry *pdo_dbh_ce; -extern zend_class_entry *pdosqlite_ce; extern ZEND_RSRC_DTOR_FUNC(php_pdo_pdbh_dtor); extern zend_object *pdo_dbstmt_new(zend_class_entry *ce); diff --git a/ext/pdo_sqlite/config.m4 b/ext/pdo_sqlite/config.m4 index 64311eaa6436e..382958114f497 100644 --- a/ext/pdo_sqlite/config.m4 +++ b/ext/pdo_sqlite/config.m4 @@ -27,7 +27,7 @@ if test "$PHP_PDO_SQLITE" != "no"; then ], [], [$PDO_SQLITE_SHARED_LIBADD]) PHP_SUBST(PDO_SQLITE_SHARED_LIBADD) - PHP_NEW_EXTENSION(pdo_sqlite, pdo_sqlite.c sqlite_driver.c sqlite_statement.c, + PHP_NEW_EXTENSION(pdo_sqlite, pdo_sqlite.c pdo_sqlite_class.c sqlite_driver.c sqlite_statement.c, $ext_shared,,-I$pdo_cv_inc_path) PHP_ADD_EXTENSION_DEP(pdo_sqlite, pdo) diff --git a/ext/pdo_sqlite/pdo_sqlite.c b/ext/pdo_sqlite/pdo_sqlite.c index 81761b1370937..47d1b86d9de44 100644 --- a/ext/pdo_sqlite/pdo_sqlite.c +++ b/ext/pdo_sqlite/pdo_sqlite.c @@ -25,8 +25,11 @@ #include "pdo/php_pdo_driver.h" #include "php_pdo_sqlite.h" #include "php_pdo_sqlite_int.h" +#include "pdo_sqlite_arginfo.h" #include "zend_exceptions.h" +zend_class_entry *pdosqlite_ce; + /* {{{ pdo_sqlite_deps */ static const zend_module_dep pdo_sqlite_deps[] = { ZEND_MOD_REQUIRED("pdo") @@ -50,6 +53,8 @@ zend_module_entry pdo_sqlite_module_entry = { }; /* }}} */ +static pdo_driver_class_entry pdosqlite_pdo_driver_class_entry; + #if defined(COMPILE_DL_PDO_SQLITE) || defined(COMPILE_DL_PDO_SQLITE_EXTERNAL) ZEND_GET_MODULE(pdo_sqlite) #endif @@ -68,6 +73,13 @@ PHP_MINIT_FUNCTION(pdo_sqlite) REGISTER_PDO_CLASS_CONST_LONG("SQLITE_ATTR_READONLY_STATEMENT", (zend_long)PDO_SQLITE_ATTR_READONLY_STATEMENT); REGISTER_PDO_CLASS_CONST_LONG("SQLITE_ATTR_EXTENDED_RESULT_CODES", (zend_long)PDO_SQLITE_ATTR_EXTENDED_RESULT_CODES); + pdosqlite_ce = register_class_PDOSqlite(pdo_dbh_ce); + pdosqlite_ce->create_object = pdo_dbh_new; + + pdosqlite_pdo_driver_class_entry.driver_name = "sqlite"; + pdosqlite_pdo_driver_class_entry.driver_ce = pdosqlite_ce; + pdo_register_driver_specific_class(&pdosqlite_pdo_driver_class_entry); + return php_pdo_register_driver(&pdo_sqlite_driver); } /* }}} */ diff --git a/ext/pdo/pdo_sqlite.stub.php b/ext/pdo_sqlite/pdo_sqlite.stub.php similarity index 100% rename from ext/pdo/pdo_sqlite.stub.php rename to ext/pdo_sqlite/pdo_sqlite.stub.php diff --git a/ext/pdo/pdo_sqlite_arginfo.h b/ext/pdo_sqlite/pdo_sqlite_arginfo.h similarity index 100% rename from ext/pdo/pdo_sqlite_arginfo.h rename to ext/pdo_sqlite/pdo_sqlite_arginfo.h diff --git a/ext/pdo/pdosqlite_class.c b/ext/pdo_sqlite/pdo_sqlite_class.c similarity index 99% rename from ext/pdo/pdosqlite_class.c rename to ext/pdo_sqlite/pdo_sqlite_class.c index da76a746eeb49..2e34215a639c6 100644 --- a/ext/pdo/pdosqlite_class.c +++ b/ext/pdo_sqlite/pdo_sqlite_class.c @@ -24,9 +24,9 @@ #include "php.h" #include "php_ini.h" #include "ext/standard/info.h" -#include "php_pdo.h" -#include "php_pdo_driver.h" -#include "php_pdo_int.h" +#include "../pdo/php_pdo.h" +#include "../pdo/php_pdo_driver.h" +#include "../pdo/php_pdo_int.h" #include "zend_exceptions.h" #include "zend_object_handlers.h" #include "zend_hash.h" diff --git a/ext/pdo/tests/subclasses/pdosqlite_001.phpt b/ext/pdo_sqlite/tests/subclasses/pdosqlite_001.phpt similarity index 100% rename from ext/pdo/tests/subclasses/pdosqlite_001.phpt rename to ext/pdo_sqlite/tests/subclasses/pdosqlite_001.phpt diff --git a/ext/pdo/tests/subclasses/pdosqlite_002.phpt b/ext/pdo_sqlite/tests/subclasses/pdosqlite_002.phpt similarity index 100% rename from ext/pdo/tests/subclasses/pdosqlite_002.phpt rename to ext/pdo_sqlite/tests/subclasses/pdosqlite_002.phpt diff --git a/ext/pdo/tests/subclasses/pdosqlite_003.phpt b/ext/pdo_sqlite/tests/subclasses/pdosqlite_003.phpt similarity index 100% rename from ext/pdo/tests/subclasses/pdosqlite_003.phpt rename to ext/pdo_sqlite/tests/subclasses/pdosqlite_003.phpt diff --git a/ext/pdo/tests/subclasses/pdosqlite_004_blobopen.phpt b/ext/pdo_sqlite/tests/subclasses/pdosqlite_004_blobopen.phpt similarity index 100% rename from ext/pdo/tests/subclasses/pdosqlite_004_blobopen.phpt rename to ext/pdo_sqlite/tests/subclasses/pdosqlite_004_blobopen.phpt diff --git a/ext/pdo/tests/subclasses/stream_test.inc b/ext/pdo_sqlite/tests/subclasses/stream_test.inc similarity index 100% rename from ext/pdo/tests/subclasses/stream_test.inc rename to ext/pdo_sqlite/tests/subclasses/stream_test.inc From 6377bb070e9701f19b4de76b5c76d4d0dfdd578e Mon Sep 17 00:00:00 2001 From: Danack Date: Fri, 5 May 2023 12:48:05 +0100 Subject: [PATCH 08/35] First draft of pdo_dblib extension class. Tests don't currently work due to mssql server not running on my computer. --- ext/pdo_dblib/pdo_dblib.c | 11 +++++ ext/pdo_dblib/pdo_dblib.stub.php | 9 ++++ .../tests/subclassing/pdodblib_001.phpt | 48 +++++++++++++++++++ .../tests/subclassing/pdodblib_002.phpt | 48 +++++++++++++++++++ ext/pdo_sqlite/pdo_sqlite_arginfo.h | 2 +- 5 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 ext/pdo_dblib/pdo_dblib.stub.php create mode 100644 ext/pdo_dblib/tests/subclassing/pdodblib_001.phpt create mode 100644 ext/pdo_dblib/tests/subclassing/pdodblib_002.phpt diff --git a/ext/pdo_dblib/pdo_dblib.c b/ext/pdo_dblib/pdo_dblib.c index e0f204cb39be9..27a1c5eef520a 100644 --- a/ext/pdo_dblib/pdo_dblib.c +++ b/ext/pdo_dblib/pdo_dblib.c @@ -27,10 +27,14 @@ #include "php_pdo_dblib.h" #include "php_pdo_dblib_int.h" #include "zend_exceptions.h" +#include "pdo_dblib_arginfo.h" ZEND_DECLARE_MODULE_GLOBALS(dblib) static PHP_GINIT_FUNCTION(dblib); +zend_class_entry *pdodblib_ce; +static pdo_driver_class_entry pdodblib_pdo_driver_class_entry; + static const zend_module_dep pdo_dblib_deps[] = { ZEND_MOD_REQUIRED("pdo") ZEND_MOD_END @@ -201,6 +205,13 @@ PHP_MINIT_FUNCTION(pdo_dblib) return FAILURE; } + pdodblib_ce = register_class_PDODBLIB(pdo_dbh_ce); + pdodblib_ce->create_object = pdo_dbh_new; + + pdodblib_pdo_driver_class_entry.driver_name = "dblib"; + pdodblib_pdo_driver_class_entry.driver_ce = pdodblib_ce; + pdo_register_driver_specific_class(&pdodblib_pdo_driver_class_entry); + if (FAILURE == php_pdo_register_driver(&pdo_dblib_driver)) { return FAILURE; } diff --git a/ext/pdo_dblib/pdo_dblib.stub.php b/ext/pdo_dblib/pdo_dblib.stub.php new file mode 100644 index 0000000000000..1804e5bd3b9b2 --- /dev/null +++ b/ext/pdo_dblib/pdo_dblib.stub.php @@ -0,0 +1,9 @@ +query('CREATE TABLE IF NOT EXISTS foobar (id INT AUTO INCREMENT, name TEXT)'); + +$db->query('INSERT INTO foobar VALUES (NULL, "PHP")'); +$db->query('INSERT INTO foobar VALUES (NULL, "PHP6")'); + +foreach ($db->query('SELECT testing(name) FROM foobar') as $row) { + var_dump($row); +} + +$db->query('DROP TABLE foobar'); + +echo "Fin."; +?> +--EXPECT-- +PdoSqlite class exists. +array(2) { + ["testing(name)"]=> + string(3) "php" + [0]=> + string(3) "php" +} +array(2) { + ["testing(name)"]=> + string(4) "php6" + [0]=> + string(4) "php6" +} +Fin. diff --git a/ext/pdo_dblib/tests/subclassing/pdodblib_002.phpt b/ext/pdo_dblib/tests/subclassing/pdodblib_002.phpt new file mode 100644 index 0000000000000..743bde535989c --- /dev/null +++ b/ext/pdo_dblib/tests/subclassing/pdodblib_002.phpt @@ -0,0 +1,48 @@ +--TEST-- +PdoDblib create through PDO::connect +--EXTENSIONS-- +pdo +--FILE-- +exec('CREATE TABLE test(id int NOT NULL PRIMARY KEY, val VARCHAR(10))'); +$db->exec("INSERT INTO test VALUES(1, 'A')"); +$db->exec("INSERT INTO test VALUES(2, 'B')"); +$db->exec("INSERT INTO test VALUES(3, 'C')"); + +$stmt = $db->prepare('SELECT * from test'); +$stmt->execute(); + +var_dump($stmt->fetchAll(PDO::FETCH_OBJ)); + + +$db->query('DROP TABLE foobar'); + +echo "Fin."; +?> +--EXPECT-- +PdoDblib class exists. +array(2) { + ["testing(name)"]=> + string(3) "php" + [0]=> + string(3) "php" +} +array(2) { + ["testing(name)"]=> + string(4) "php6" + [0]=> + string(4) "php6" +} +Fin. diff --git a/ext/pdo_sqlite/pdo_sqlite_arginfo.h b/ext/pdo_sqlite/pdo_sqlite_arginfo.h index 13c48f1d4dbaf..dee9c3f0937d5 100644 --- a/ext/pdo_sqlite/pdo_sqlite_arginfo.h +++ b/ext/pdo_sqlite/pdo_sqlite_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 9e4de4487e2652b510d91a903ce7267b089a83c1 */ + * Stub hash: 67ac1b8b7e4ff45e18f8bfcd4d458ab0961b0d4c */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PDOSqlite_createFunction, 0, 2, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, function_name, IS_STRING, 0) From 479859ef837e56d667d1ba953d84b3c2c7ce463a Mon Sep 17 00:00:00 2001 From: Danack Date: Fri, 5 May 2023 18:18:20 +0100 Subject: [PATCH 09/35] Added PDOMySql class and a driver specific method. --- .../tests/subclassing/pdodblib_002.phpt | 5 +- ext/pdo_mysql/config.m4 | 2 +- ext/pdo_mysql/pdo_mysql.c | 11 ++++ ext/pdo_mysql/pdo_mysql.stub.php | 9 +++ ext/pdo_mysql/pdo_mysql_arginfo.h | 25 ++++++++ ext/pdo_mysql/pdo_mysql_class.c | 47 +++++++++++++++ ext/pdo_mysql/tests/mysql_pdo_test.inc | 29 +++++++++ .../tests/subclassing/pdomysql_001.phpt | 48 +++++++++++++++ .../tests/subclassing/pdomysql_002.phpt | 60 +++++++++++++++++++ .../tests/subclassing/pdomysql_003.phpt | 32 ++++++++++ .../tests/subclasses/pdosqlite_002.phpt | 4 +- 11 files changed, 268 insertions(+), 4 deletions(-) create mode 100644 ext/pdo_mysql/pdo_mysql.stub.php create mode 100644 ext/pdo_mysql/pdo_mysql_arginfo.h create mode 100644 ext/pdo_mysql/pdo_mysql_class.c create mode 100644 ext/pdo_mysql/tests/subclassing/pdomysql_001.phpt create mode 100644 ext/pdo_mysql/tests/subclassing/pdomysql_002.phpt create mode 100644 ext/pdo_mysql/tests/subclassing/pdomysql_003.phpt diff --git a/ext/pdo_dblib/tests/subclassing/pdodblib_002.phpt b/ext/pdo_dblib/tests/subclassing/pdodblib_002.phpt index 743bde535989c..bac3aacce8858 100644 --- a/ext/pdo_dblib/tests/subclassing/pdodblib_002.phpt +++ b/ext/pdo_dblib/tests/subclassing/pdodblib_002.phpt @@ -14,7 +14,10 @@ echo "PdoDblib class exists.\n"; $db = Pdo::connect('dblib::memory:'); -$db = PDOTest::factory(); + +if (!$db instanceof PdoDblib) { + echo "Wrong class type. Should be PdoDblib but is [" . get_class($db) . "\n"; +} $db->exec('CREATE TABLE test(id int NOT NULL PRIMARY KEY, val VARCHAR(10))'); $db->exec("INSERT INTO test VALUES(1, 'A')"); diff --git a/ext/pdo_mysql/config.m4 b/ext/pdo_mysql/config.m4 index 7f09aabefa73a..c1047dd1488f9 100644 --- a/ext/pdo_mysql/config.m4 +++ b/ext/pdo_mysql/config.m4 @@ -99,7 +99,7 @@ if test "$PHP_PDO_MYSQL" != "no"; then AC_DEFINE_UNQUOTED(PDO_MYSQL_UNIX_ADDR, "$PDO_MYSQL_SOCKET", [ ]) fi - PHP_NEW_EXTENSION(pdo_mysql, pdo_mysql.c mysql_driver.c mysql_statement.c, $ext_shared,,-I$pdo_cv_inc_path -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1) + PHP_NEW_EXTENSION(pdo_mysql, pdo_mysql.c pdo_mysql_class.c mysql_driver.c mysql_statement.c, $ext_shared,,-I$pdo_cv_inc_path -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1) PHP_ADD_EXTENSION_DEP(pdo_mysql, pdo) diff --git a/ext/pdo_mysql/pdo_mysql.c b/ext/pdo_mysql/pdo_mysql.c index 2d94b71fef782..4f3720ad2a569 100644 --- a/ext/pdo_mysql/pdo_mysql.c +++ b/ext/pdo_mysql/pdo_mysql.c @@ -26,6 +26,10 @@ #include "pdo/php_pdo_driver.h" #include "php_pdo_mysql.h" #include "php_pdo_mysql_int.h" +#include "pdo_mysql_arginfo.h" + +zend_class_entry *pdomysql_ce; +static pdo_driver_class_entry pdomysql_pdo_driver_class_entry; #ifdef COMPILE_DL_PDO_MYSQL #ifdef ZTS @@ -132,6 +136,13 @@ static PHP_MINIT_FUNCTION(pdo_mysql) mysqlnd_reverse_api_register_api(&pdo_mysql_reverse_api); #endif + pdomysql_ce = register_class_PDOMySql(pdo_dbh_ce); + pdomysql_ce->create_object = pdo_dbh_new; + + pdomysql_pdo_driver_class_entry.driver_name = "mysql"; + pdomysql_pdo_driver_class_entry.driver_ce = pdomysql_ce; + pdo_register_driver_specific_class(&pdomysql_pdo_driver_class_entry); + return php_pdo_register_driver(&pdo_mysql_driver); } /* }}} */ diff --git a/ext/pdo_mysql/pdo_mysql.stub.php b/ext/pdo_mysql/pdo_mysql.stub.php new file mode 100644 index 0000000000000..82d95a83f8420 --- /dev/null +++ b/ext/pdo_mysql/pdo_mysql.stub.php @@ -0,0 +1,9 @@ +ce_flags |= ZEND_ACC_NOT_SERIALIZABLE; + + return class_entry; +} diff --git a/ext/pdo_mysql/pdo_mysql_class.c b/ext/pdo_mysql/pdo_mysql_class.c new file mode 100644 index 0000000000000..9be995a9c5eeb --- /dev/null +++ b/ext/pdo_mysql/pdo_mysql_class.c @@ -0,0 +1,47 @@ + +/* + +----------------------------------------------------------------------+ + | Copyright (c) The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | https://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Danack + +----------------------------------------------------------------------+ +*/ + +/* The PDO Database Handle Class */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php.h" +#include "php_ini.h" +#include "ext/standard/info.h" +#include "../pdo/php_pdo.h" +#include "../pdo/php_pdo_driver.h" +#include "../pdo/php_pdo_int.h" +#include "php_pdo_mysql.h" +#include "php_pdo_mysql_int.h" + +/* {{{ proto string PDO::mysqlGetWarningCount() + Returns the number of SQL warnings during the execution of the last statement +*/ +PHP_METHOD(PDOMySql, getWarningCount) +{ + pdo_dbh_t *dbh; + pdo_mysql_db_handle *H; + + dbh = Z_PDO_DBH_P(ZEND_THIS); + PDO_CONSTRUCT_CHECK; + + H = (pdo_mysql_db_handle *)dbh->driver_data; + RETURN_LONG(mysql_warning_count(H->server)); +} +/* }}} */ diff --git a/ext/pdo_mysql/tests/mysql_pdo_test.inc b/ext/pdo_mysql/tests/mysql_pdo_test.inc index 880f8dbf758f5..48d6b91d2f7f7 100644 --- a/ext/pdo_mysql/tests/mysql_pdo_test.inc +++ b/ext/pdo_mysql/tests/mysql_pdo_test.inc @@ -32,6 +32,35 @@ class MySQLPDOTest extends PDOTest { return $db; } + static function connect($drop_test_tables = false, $myattr = null, $mydsn = null) { + + $dsn = self::getDSN($mydsn); + $user = PDO_MYSQL_TEST_USER; + $pass = PDO_MYSQL_TEST_PASS; + $attr = getenv('PDOTEST_ATTR'); + + if (is_string($attr) && strlen($attr)) { + $attr = unserialize($attr); + } else { + $attr = null; + } + if ($user === false) + $user = NULL; + if ($pass === false) + $pass = NULL; + + $db = PDO::connect($dsn, $user, $pass, $attr); + if (!$db) { + die("Could not create PDO object (DSN=$dsn, user=$user)\n"); + } + + $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING); + $db->setAttribute(PDO::ATTR_CASE, PDO::CASE_LOWER); + + return $db; + } + + static function createTestTable($db, $engine = null) { if (!$engine) $engine = PDO_MYSQL_TEST_ENGINE; diff --git a/ext/pdo_mysql/tests/subclassing/pdomysql_001.phpt b/ext/pdo_mysql/tests/subclassing/pdomysql_001.phpt new file mode 100644 index 0000000000000..431a0ff96191c --- /dev/null +++ b/ext/pdo_mysql/tests/subclassing/pdomysql_001.phpt @@ -0,0 +1,48 @@ +--TEST-- +PDO_mysql subclass basic +--EXTENSIONS-- +pdo_mysql +--FILE-- +query('CREATE TABLE IF NOT EXISTS foobar (id INT, name TEXT)'); + +$db->query('INSERT INTO foobar VALUES (NULL, "PHP")'); +$db->query('INSERT INTO foobar VALUES (NULL, "PHP6")'); + +foreach ($db->query('SELECT name FROM foobar') as $row) { + var_dump($row); +} + +$db->query('DROP TABLE foobar'); + +echo "Fin."; +?> +--EXPECT-- +PdoMySql class exists. +array(2) { + ["name"]=> + string(3) "PHP" + [0]=> + string(3) "PHP" +} +array(2) { + ["name"]=> + string(4) "PHP6" + [0]=> + string(4) "PHP6" +} +Fin. diff --git a/ext/pdo_mysql/tests/subclassing/pdomysql_002.phpt b/ext/pdo_mysql/tests/subclassing/pdomysql_002.phpt new file mode 100644 index 0000000000000..6131b1fde1383 --- /dev/null +++ b/ext/pdo_mysql/tests/subclassing/pdomysql_002.phpt @@ -0,0 +1,60 @@ +--TEST-- +PDO_mysql coonect through PDO::connect +--EXTENSIONS-- +pdo_mysql +--FILE-- +query('DROP TABLE IF EXISTS test'); +$db->exec('CREATE TABLE IF NOT EXISTS test(id int NOT NULL PRIMARY KEY, name VARCHAR(10))'); +$db->exec("INSERT INTO test VALUES(1, 'A')"); +$db->exec("INSERT INTO test VALUES(2, 'B')"); +$db->exec("INSERT INTO test VALUES(3, 'C')"); + +foreach ($db->query('SELECT name FROM test') as $row) { + var_dump($row); +} + +$db->query('DROP TABLE test'); + +echo "Fin."; +?> +--EXPECT-- +PdoMysql class exists. +array(2) { + ["name"]=> + string(1) "A" + [0]=> + string(1) "A" +} +array(2) { + ["name"]=> + string(1) "B" + [0]=> + string(1) "B" +} +array(2) { + ["name"]=> + string(1) "C" + [0]=> + string(1) "C" +} +Fin. diff --git a/ext/pdo_mysql/tests/subclassing/pdomysql_003.phpt b/ext/pdo_mysql/tests/subclassing/pdomysql_003.phpt new file mode 100644 index 0000000000000..29f4e6dddf584 --- /dev/null +++ b/ext/pdo_mysql/tests/subclassing/pdomysql_003.phpt @@ -0,0 +1,32 @@ +--TEST-- +PDO_mysql getWarningCount +--EXTENSIONS-- +pdo_mysql +--FILE-- +query($q); + printf("Query %s produced %d warnings\n", $q, $db->getWarningCount()); +}; +$assertWarnings($db, 'SELECT 1 = 1', 0); +$assertWarnings($db, 'SELECT 1 = "A"', 1); + +--EXPECT-- +Query SELECT 1 = 1 produced 0 warnings +Query SELECT 1 = "A" produced 1 warnings diff --git a/ext/pdo_sqlite/tests/subclasses/pdosqlite_002.phpt b/ext/pdo_sqlite/tests/subclasses/pdosqlite_002.phpt index 3bc95149b2570..bb229ad5490f5 100644 --- a/ext/pdo_sqlite/tests/subclasses/pdosqlite_002.phpt +++ b/ext/pdo_sqlite/tests/subclasses/pdosqlite_002.phpt @@ -1,5 +1,5 @@ --TEST-- -PDOSqlite create through PDO::connect +PDOSqlite create through PDO::connect and function define. --EXTENSIONS-- pdo --FILE-- @@ -15,7 +15,7 @@ echo "PdoSqlite class exists.\n"; $db = Pdo::connect('sqlite::memory:'); if (!$db instanceof PdoSqlite) { - echo "Wrong class type. Should be PdoSqlite but is [" .get_class($db) . "\n"; + echo "Wrong class type. Should be PdoSqlite but is [" . get_class($db) . "\n"; } $db->query('CREATE TABLE IF NOT EXISTS foobar (id INT AUTO INCREMENT, name TEXT)'); From 6cbe69ea4ff00f10628ae145d02518e741eefcfd Mon Sep 17 00:00:00 2001 From: Danack Date: Fri, 5 May 2023 20:08:20 +0100 Subject: [PATCH 10/35] Initial version of PDOPgSql sub-class --- ext/pdo_pgsql/config.m4 | 2 +- ext/pdo_pgsql/pdo_pgsql.c | 11 ++ ext/pdo_pgsql/pdo_pgsql.stub.php | 38 +++++ ext/pdo_pgsql/pdo_pgsql_arginfo.h | 26 ++++ ext/pdo_pgsql/pdo_pgsql_class.c | 137 ++++++++++++++++++ .../tests/subclassing/pdopgsql_001.phpt | 47 ++++++ .../tests/subclassing/pdopgsql_002.phpt | 59 ++++++++ .../tests/subclassing/pdopgsql_003.phpt | 30 ++++ 8 files changed, 349 insertions(+), 1 deletion(-) create mode 100644 ext/pdo_pgsql/pdo_pgsql.stub.php create mode 100644 ext/pdo_pgsql/pdo_pgsql_arginfo.h create mode 100644 ext/pdo_pgsql/pdo_pgsql_class.c create mode 100644 ext/pdo_pgsql/tests/subclassing/pdopgsql_001.phpt create mode 100644 ext/pdo_pgsql/tests/subclassing/pdopgsql_002.phpt create mode 100644 ext/pdo_pgsql/tests/subclassing/pdopgsql_003.phpt diff --git a/ext/pdo_pgsql/config.m4 b/ext/pdo_pgsql/config.m4 index 80ffd97ac2ece..624b561a9410d 100644 --- a/ext/pdo_pgsql/config.m4 +++ b/ext/pdo_pgsql/config.m4 @@ -78,6 +78,6 @@ if test "$PHP_PDO_PGSQL" != "no"; then PHP_CHECK_PDO_INCLUDES - PHP_NEW_EXTENSION(pdo_pgsql, pdo_pgsql.c pgsql_driver.c pgsql_statement.c, $ext_shared,,-I$pdo_cv_inc_path) + PHP_NEW_EXTENSION(pdo_pgsql, pdo_pgsql.c pdo_pgsql_class.c pgsql_driver.c pgsql_statement.c, $ext_shared,,-I$pdo_cv_inc_path) PHP_ADD_EXTENSION_DEP(pdo_pgsql, pdo) fi diff --git a/ext/pdo_pgsql/pdo_pgsql.c b/ext/pdo_pgsql/pdo_pgsql.c index 582915a5a34f3..6db815897f7b1 100644 --- a/ext/pdo_pgsql/pdo_pgsql.c +++ b/ext/pdo_pgsql/pdo_pgsql.c @@ -25,6 +25,10 @@ #include "pdo/php_pdo_driver.h" #include "php_pdo_pgsql.h" #include "php_pdo_pgsql_int.h" +#include "pdo_pgsql_arginfo.h" + +zend_class_entry *pdopgsql_ce; +static pdo_driver_class_entry pdopgsql_pdo_driver_class_entry; /* {{{ pdo_sqlite_deps */ static const zend_module_dep pdo_pgsql_deps[] = { @@ -65,6 +69,13 @@ PHP_MINIT_FUNCTION(pdo_pgsql) REGISTER_PDO_CLASS_CONST_LONG("PGSQL_TRANSACTION_INERROR", (zend_long)PGSQL_TRANSACTION_INERROR); REGISTER_PDO_CLASS_CONST_LONG("PGSQL_TRANSACTION_UNKNOWN", (zend_long)PGSQL_TRANSACTION_UNKNOWN); + pdopgsql_ce = register_class_PDOPgSql(pdo_dbh_ce); + pdopgsql_ce->create_object = pdo_dbh_new; + + pdopgsql_pdo_driver_class_entry.driver_name = "pgsql"; + pdopgsql_pdo_driver_class_entry.driver_ce = pdopgsql_ce; + pdo_register_driver_specific_class(&pdopgsql_pdo_driver_class_entry); + return php_pdo_register_driver(&pdo_pgsql_driver); } /* }}} */ diff --git a/ext/pdo_pgsql/pdo_pgsql.stub.php b/ext/pdo_pgsql/pdo_pgsql.stub.php new file mode 100644 index 0000000000000..85302d2df7225 --- /dev/null +++ b/ext/pdo_pgsql/pdo_pgsql.stub.php @@ -0,0 +1,38 @@ +ce_flags |= ZEND_ACC_NOT_SERIALIZABLE; + + return class_entry; +} diff --git a/ext/pdo_pgsql/pdo_pgsql_class.c b/ext/pdo_pgsql/pdo_pgsql_class.c new file mode 100644 index 0000000000000..1c6fccca3f710 --- /dev/null +++ b/ext/pdo_pgsql/pdo_pgsql_class.c @@ -0,0 +1,137 @@ + +/* + +----------------------------------------------------------------------+ + | Copyright (c) The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | https://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Danack + +----------------------------------------------------------------------+ +*/ + +/* The PDO Database Handle Class */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php.h" +#include "php_ini.h" +#include "ext/standard/info.h" +#include "../pdo/php_pdo.h" +#include "../pdo/php_pdo_driver.h" +#include "../pdo/php_pdo_int.h" +#include "php_pdo_pgsql.h" +#include "php_pdo_pgsql_int.h" + +///* {{{ proto string PDO::mysqlGetWarningCount() +// Returns the number of SQL warnings during the execution of the last statement +//*/ +//PHP_METHOD(PDOMySql, getWarningCount) +//{ +// pdo_dbh_t *dbh; +// pdo_mysql_db_handle *H; +// +// dbh = Z_PDO_DBH_P(ZEND_THIS); +// PDO_CONSTRUCT_CHECK; +// +// H = (pdo_mysql_db_handle *)dbh->driver_data; +// RETURN_LONG(mysql_warning_count(H->server)); +//} +///* }}} */ + + + +// +//static void php_pgsql_escape_internal(INTERNAL_FUNCTION_PARAMETERS, int escape_literal) /* {{{ */ { +// zend_string *from = NULL; +// zval *pgsql_link = NULL; +// PGconn *pgsql; +// char *tmp; +// pgsql_link_handle *link; +// +// switch (ZEND_NUM_ARGS()) { +// case 1: +// if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &from) == FAILURE) { +// RETURN_THROWS(); +// } +// link = FETCH_DEFAULT_LINK(); +// CHECK_DEFAULT_LINK(link); +// break; +// +// default: +// if (zend_parse_parameters(ZEND_NUM_ARGS(), "OS", &pgsql_link, pgsql_link_ce, &from) == FAILURE) { +// RETURN_THROWS(); +// } +// link = Z_PGSQL_LINK_P(pgsql_link); +// CHECK_PGSQL_LINK(link); +// break; +// } +// +// pgsql = link->conn; +// +// if (escape_literal) { +// tmp = PQescapeLiteral(pgsql, ZSTR_VAL(from), ZSTR_LEN(from)); +// } else { +// tmp = PQescapeIdentifier(pgsql, ZSTR_VAL(from), ZSTR_LEN(from)); +// } +// if (!tmp) { +// php_error_docref(NULL, E_WARNING,"Failed to escape"); +// RETURN_FALSE; +// } +// +// RETVAL_STRING(tmp); +// PQfreemem(tmp); +//} +///* }}} */ + +///* {{{ Escape parameter as string literal (i.e. parameter) */ +//PHP_FUNCTION(pg_escape_literal) +//{ +// php_pgsql_escape_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); +//} +///* }}} */ + +/* {{{ Escape a identifier for insertion into a text field */ +PHP_METHOD(PDOPgSql, escapeIdentifier) +{ + zend_string *from = NULL; + char *tmp; + pdo_dbh_t *dbh; + pdo_pgsql_db_handle *H; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &from) == FAILURE) { + RETURN_THROWS(); + } + + dbh = Z_PDO_DBH_P(ZEND_THIS); + PDO_CONSTRUCT_CHECK; + PDO_DBH_CLEAR_ERR(); + + /* Obtain db Handle */ + H = (pdo_pgsql_db_handle *)dbh->driver_data; + + tmp = PQescapeIdentifier(H->server, ZSTR_VAL(from), ZSTR_LEN(from)); + + if (!tmp) { + // TODO - exception + php_error_docref(NULL, E_WARNING,"Failed to escape identifier"); + RETURN_FALSE; + } + + RETVAL_STRING(tmp); + PQfreemem(tmp); +} +/* }}} */ + + + + + + diff --git a/ext/pdo_pgsql/tests/subclassing/pdopgsql_001.phpt b/ext/pdo_pgsql/tests/subclassing/pdopgsql_001.phpt new file mode 100644 index 0000000000000..745eccde60d38 --- /dev/null +++ b/ext/pdo_pgsql/tests/subclassing/pdopgsql_001.phpt @@ -0,0 +1,47 @@ +--TEST-- +PdoPgSql subclass basic +--EXTENSIONS-- +pdo_mysql +--FILE-- +query('CREATE TABLE IF NOT EXISTS foobar (id INT, name TEXT)'); + +$db->query("INSERT INTO foobar VALUES (NULL, 'PHP')"); +$db->query("INSERT INTO foobar VALUES (NULL, 'PHP6')"); + +foreach ($db->query('SELECT name FROM foobar') as $row) { + var_dump($row); +} + +$db->query('DROP TABLE foobar'); + +echo "Fin."; +?> +--EXPECT-- +PdoPgSql class exists. +array(2) { + ["name"]=> + string(3) "PHP" + [0]=> + string(3) "PHP" +} +array(2) { + ["name"]=> + string(4) "PHP6" + [0]=> + string(4) "PHP6" +} +Fin. diff --git a/ext/pdo_pgsql/tests/subclassing/pdopgsql_002.phpt b/ext/pdo_pgsql/tests/subclassing/pdopgsql_002.phpt new file mode 100644 index 0000000000000..326a8f41728ec --- /dev/null +++ b/ext/pdo_pgsql/tests/subclassing/pdopgsql_002.phpt @@ -0,0 +1,59 @@ +--TEST-- +PdoPgSql coonect through PDO::connect +--EXTENSIONS-- +pdo_mysql +--FILE-- +query('DROP TABLE IF EXISTS test'); +$db->exec('CREATE TABLE IF NOT EXISTS test(id int NOT NULL PRIMARY KEY, name VARCHAR(10))'); +$db->exec("INSERT INTO test VALUES(1, 'A')"); +$db->exec("INSERT INTO test VALUES(2, 'B')"); +$db->exec("INSERT INTO test VALUES(3, 'C')"); + +foreach ($db->query('SELECT name FROM test') as $row) { + var_dump($row); +} + +$db->query('DROP TABLE test'); + +echo "Fin."; +?> +--EXPECT-- +PdoPgSql class exists. +array(2) { + ["name"]=> + string(1) "A" + [0]=> + string(1) "A" +} +array(2) { + ["name"]=> + string(1) "B" + [0]=> + string(1) "B" +} +array(2) { + ["name"]=> + string(1) "C" + [0]=> + string(1) "C" +} +Fin. diff --git a/ext/pdo_pgsql/tests/subclassing/pdopgsql_003.phpt b/ext/pdo_pgsql/tests/subclassing/pdopgsql_003.phpt new file mode 100644 index 0000000000000..8123808603678 --- /dev/null +++ b/ext/pdo_pgsql/tests/subclassing/pdopgsql_003.phpt @@ -0,0 +1,30 @@ +--TEST-- +PdoPgSql getWarningCount +--EXTENSIONS-- +pdo_mysql +--FILE-- +escapeIdentifier("This is a quote\""); + +// TODO - ask someone who knows about postgresql if this is correct: +echo "Result is [$result]\n"; + +--EXPECT-- +Result is ["This is a quote"""] + From df94bbfb793395ab9557a5fa04ae0b44cff39bdf Mon Sep 17 00:00:00 2001 From: Danack Date: Fri, 5 May 2023 20:13:42 +0100 Subject: [PATCH 11/35] Added missed file. --- ext/pdo_dblib/pdo_dblib_arginfo.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 ext/pdo_dblib/pdo_dblib_arginfo.h diff --git a/ext/pdo_dblib/pdo_dblib_arginfo.h b/ext/pdo_dblib/pdo_dblib_arginfo.h new file mode 100644 index 0000000000000..9919f0be3200a --- /dev/null +++ b/ext/pdo_dblib/pdo_dblib_arginfo.h @@ -0,0 +1,20 @@ +/* This is a generated file, edit the .stub.php file instead. + * Stub hash: 06c2f52a638c1ca9c56bcbebdc00367bb3eb9b26 */ + + + + +static const zend_function_entry class_PDODBLIB_methods[] = { + ZEND_FE_END +}; + +static zend_class_entry *register_class_PDODBLIB(zend_class_entry *class_entry_PDO) +{ + zend_class_entry ce, *class_entry; + + INIT_CLASS_ENTRY(ce, "PDODBLIB", class_PDODBLIB_methods); + class_entry = zend_register_internal_class_ex(&ce, class_entry_PDO); + class_entry->ce_flags |= ZEND_ACC_NOT_SERIALIZABLE; + + return class_entry; +} From a1b050e8d150ccd5a8df9c7089ad1379fc5b61ab Mon Sep 17 00:00:00 2001 From: Danack Date: Fri, 5 May 2023 22:25:38 +0100 Subject: [PATCH 12/35] Copied methods across from PDO class. --- ext/pdo_sqlite/pdo_sqlite.stub.php | 11 + ext/pdo_sqlite/pdo_sqlite_arginfo.h | 18 +- ext/pdo_sqlite/pdo_sqlite_class.c | 335 ++++++++++++++++-- ext/pdo_sqlite/sqlite_driver.c | 3 +- ext/pdo_sqlite/tests/subclasses/gc.phpt | 28 ++ .../pdo_sqlite_createaggregate.phpt | 32 ++ .../pdo_sqlite_createaggregate_002.phpt | 25 ++ .../pdo_sqlite_createcollation.phpt | 39 ++ .../pdo_sqlite_createfunction_with_flags.phpt | 38 ++ 9 files changed, 502 insertions(+), 27 deletions(-) create mode 100644 ext/pdo_sqlite/tests/subclasses/gc.phpt create mode 100644 ext/pdo_sqlite/tests/subclasses/pdo_sqlite_createaggregate.phpt create mode 100644 ext/pdo_sqlite/tests/subclasses/pdo_sqlite_createaggregate_002.phpt create mode 100644 ext/pdo_sqlite/tests/subclasses/pdo_sqlite_createcollation.phpt create mode 100644 ext/pdo_sqlite/tests/subclasses/pdo_sqlite_createfunction_with_flags.phpt diff --git a/ext/pdo_sqlite/pdo_sqlite.stub.php b/ext/pdo_sqlite/pdo_sqlite.stub.php index ee9abf9502b02..4d52e41e39a90 100644 --- a/ext/pdo_sqlite/pdo_sqlite.stub.php +++ b/ext/pdo_sqlite/pdo_sqlite.stub.php @@ -31,4 +31,15 @@ public function openBlob( //SQLITE_OPEN_CREATE + // Registers an aggregating User Defined Function for use in SQL statements + public function createAggregate( + string $name, + callable $step, + callable $finalize, + int $numArgs = -1 + ): bool {} + + // Registers a User Defined Function for use as a collating function in SQL statements + public function createCollation(string $name, callable $callback): bool {} + } diff --git a/ext/pdo_sqlite/pdo_sqlite_arginfo.h b/ext/pdo_sqlite/pdo_sqlite_arginfo.h index dee9c3f0937d5..8a4db0a45a071 100644 --- a/ext/pdo_sqlite/pdo_sqlite_arginfo.h +++ b/ext/pdo_sqlite/pdo_sqlite_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 67ac1b8b7e4ff45e18f8bfcd4d458ab0961b0d4c */ + * Stub hash: 949c01f6e018c7abeb29f2ed699e98ed2c0553a9 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PDOSqlite_createFunction, 0, 2, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, function_name, IS_STRING, 0) @@ -22,12 +22,26 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PDOSqlite_openBlob, 0, 3, ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, flags, IS_LONG, 0, "PDO::SQLITE_OPEN_READONLY") ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PDOSqlite_createAggregate, 0, 3, _IS_BOOL, 0) + ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, step, IS_CALLABLE, 0) + ZEND_ARG_TYPE_INFO(0, finalize, IS_CALLABLE, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, numArgs, IS_LONG, 0, "-1") +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PDOSqlite_createCollation, 0, 2, _IS_BOOL, 0) + ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, callback, IS_CALLABLE, 0) +ZEND_END_ARG_INFO() + ZEND_METHOD(PDOSqlite, createFunction); #if !defined(SQLITE_OMIT_LOAD_EXTENSION) ZEND_METHOD(PDOSqlite, loadExtension); #endif ZEND_METHOD(PDOSqlite, openBlob); +ZEND_METHOD(PDOSqlite, createAggregate); +ZEND_METHOD(PDOSqlite, createCollation); static const zend_function_entry class_PDOSqlite_methods[] = { @@ -36,6 +50,8 @@ static const zend_function_entry class_PDOSqlite_methods[] = { ZEND_ME(PDOSqlite, loadExtension, arginfo_class_PDOSqlite_loadExtension, ZEND_ACC_PUBLIC) #endif ZEND_ME(PDOSqlite, openBlob, arginfo_class_PDOSqlite_openBlob, ZEND_ACC_PUBLIC) + ZEND_ME(PDOSqlite, createAggregate, arginfo_class_PDOSqlite_createAggregate, ZEND_ACC_PUBLIC) + ZEND_ME(PDOSqlite, createCollation, arginfo_class_PDOSqlite_createCollation, ZEND_ACC_PUBLIC) ZEND_FE_END }; diff --git a/ext/pdo_sqlite/pdo_sqlite_class.c b/ext/pdo_sqlite/pdo_sqlite_class.c index 2e34215a639c6..a9a764aa67c01 100644 --- a/ext/pdo_sqlite/pdo_sqlite_class.c +++ b/ext/pdo_sqlite/pdo_sqlite_class.c @@ -35,11 +35,180 @@ #include "../pdo_sqlite/php_pdo_sqlite_int.h" // TODO - define this in appropriate header, not here. -extern void php_sqlite3_func_callback(sqlite3_context *context, int argc, - sqlite3_value **argv); + +typedef struct { + zval val; + zend_long row; +} pdopgsql_aggregate_context; + + + +static int do_callback(struct pdo_sqlite_fci *fc, zval *cb, + int argc, sqlite3_value **argv, sqlite3_context *context, + int is_agg) +{ + zval *zargs = NULL; + zval retval; + int i; + int ret; + int fake_argc; + pdopgsql_aggregate_context *agg_context = NULL; + + if (is_agg) { + is_agg = 2; + } + + fake_argc = argc + is_agg; + + fc->fci.size = sizeof(fc->fci); + ZVAL_COPY_VALUE(&fc->fci.function_name, cb); + fc->fci.object = NULL; + fc->fci.retval = &retval; + fc->fci.param_count = fake_argc; + + /* build up the params */ + + if (fake_argc) { + zargs = safe_emalloc(fake_argc, sizeof(zval), 0); + } + + if (is_agg) { + agg_context = sqlite3_aggregate_context(context, sizeof(pdopgsql_aggregate_context)); + if (!agg_context) { + efree(zargs); + return FAILURE; + } + if (Z_ISUNDEF(agg_context->val)) { + ZVAL_NEW_REF(&agg_context->val, &EG(uninitialized_zval)); + } + ZVAL_COPY_VALUE(&zargs[0], &agg_context->val); + ZVAL_LONG(&zargs[1], ++agg_context->row); + } + + for (i = 0; i < argc; i++) { + /* get the value */ + switch (sqlite3_value_type(argv[i])) { + case SQLITE_INTEGER: + ZVAL_LONG(&zargs[i + is_agg], sqlite3_value_int(argv[i])); + break; + + case SQLITE_FLOAT: + ZVAL_DOUBLE(&zargs[i + is_agg], sqlite3_value_double(argv[i])); + break; + + case SQLITE_NULL: + ZVAL_NULL(&zargs[i + is_agg]); + break; + + case SQLITE_BLOB: + case SQLITE3_TEXT: + default: + ZVAL_STRINGL(&zargs[i + is_agg], (char*)sqlite3_value_text(argv[i]), sqlite3_value_bytes(argv[i])); + break; + } + } + + fc->fci.params = zargs; + + if ((ret = zend_call_function(&fc->fci, &fc->fcc)) == FAILURE) { + php_error_docref(NULL, E_WARNING, "An error occurred while invoking the callback"); + } + + /* clean up the params */ + if (zargs) { + for (i = is_agg; i < fake_argc; i++) { + zval_ptr_dtor(&zargs[i]); + } + if (is_agg) { + zval_ptr_dtor(&zargs[1]); + } + efree(zargs); + } + + if (!is_agg || !argv) { + /* only set the sqlite return value if we are a scalar function, + * or if we are finalizing an aggregate */ + if (!Z_ISUNDEF(retval)) { + switch (Z_TYPE(retval)) { + case IS_LONG: + sqlite3_result_int(context, Z_LVAL(retval)); + break; + + case IS_NULL: + sqlite3_result_null(context); + break; + + case IS_DOUBLE: + sqlite3_result_double(context, Z_DVAL(retval)); + break; + + default: + if (!try_convert_to_string(&retval)) { + ret = FAILURE; + break; + } + sqlite3_result_text(context, Z_STRVAL(retval), Z_STRLEN(retval), SQLITE_TRANSIENT); + break; + } + } else { + sqlite3_result_error(context, "failed to invoke callback", 0); + } + + if (agg_context) { + zval_ptr_dtor(&agg_context->val); + } + } else { + /* we're stepping in an aggregate; the return value goes into + * the context */ + if (agg_context) { + if (Z_ISUNDEF(retval)) { + zval_ptr_dtor(&agg_context->val); + return FAILURE; + } + zval_ptr_dtor(Z_REFVAL(agg_context->val)); + ZVAL_COPY_VALUE(Z_REFVAL(agg_context->val), &retval); + ZVAL_UNDEF(&retval); + } + } + + if (!Z_ISUNDEF(retval)) { + zval_ptr_dtor(&retval); + } + + return ret; +} + + +void php_pgsql_func_callback(sqlite3_context *context, int argc, + sqlite3_value **argv) +{ + struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context); + + do_callback(&func->afunc, &func->func, argc, argv, context, 0); +} + +static void php_pgsql_func_step_callback(sqlite3_context *context, int argc, + sqlite3_value **argv) +{ + struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context); + + do_callback(&func->astep, &func->step, argc, argv, context, 1); +} + +static void php_pgsql_func_final_callback(sqlite3_context *context) +{ + struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context); + + do_callback(&func->afini, &func->fini, 0, NULL, context, 1); +} + + + + + /* {{{ proto bool PDOSqlite::createFunction(string $function_name, callable $callback, int $num_args = -1, int $flags = 0) - Creates a function that can be used + Creates a function that can be used in a query */ PHP_METHOD(PDOSqlite, createFunction) { @@ -68,11 +237,10 @@ PHP_METHOD(PDOSqlite, createFunction) PDO_CONSTRUCT_CHECK; H = (pdo_sqlite_db_handle *)dbh->driver_data; - func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func)); ret = sqlite3_create_function(H->db, func_name, argc, flags | SQLITE_UTF8, - func, php_sqlite3_func_callback, NULL, NULL); + func, php_pgsql_func_callback, NULL, NULL); if (ret == SQLITE_OK) { func->funcname = estrdup(func_name); @@ -95,13 +263,9 @@ PHP_METHOD(PDOSqlite, createFunction) /* {{{ Attempts to load an SQLite extension library. */ PHP_METHOD(PDOSqlite, loadExtension) { -// php_sqlite3_db_object *db_obj; -// zval *object = ZEND_THIS; char *extension, *lib_path, *errtext = NULL; - // char *extension_dir; char fullpath[MAXPATHLEN]; size_t extension_len;// , extension_dir_len; -// db_obj = Z_SQLITE3_DB_P(object); pdo_dbh_t *dbh; pdo_sqlite_db_handle *db_handle; @@ -348,12 +512,9 @@ static const php_stream_ops php_stream_pdosqlite3_ops = { }; - /* {{{ Open a blob as a stream which we can read / write to. */ PHP_METHOD(PDOSqlite, openBlob) { -// php_sqlite3_db_object *db_obj; -// zval *object = ZEND_THIS; char *table, *column, *dbname = "main", *mode = "rb"; size_t table_len, column_len, dbname_len; zend_long rowid, flags = SQLITE_OPEN_READONLY, sqlite_flags = 0; @@ -364,30 +525,20 @@ PHP_METHOD(PDOSqlite, openBlob) pdo_dbh_t *dbh; pdo_sqlite_db_handle *db_handle; -// if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "s", &extension, &extension_len)) { -// RETURN_THROWS(); -// } - dbh = Z_PDO_DBH_P(ZEND_THIS); PDO_CONSTRUCT_CHECK; - -// db_obj = Z_SQLITE3_DB_P(object); + db_handle = (pdo_sqlite_db_handle *)dbh->driver_data; if (zend_parse_parameters(ZEND_NUM_ARGS(), "ssl|pl", &table, &table_len, &column, &column_len, &rowid, &dbname, &dbname_len, &flags) == FAILURE) { RETURN_THROWS(); } - db_handle = (pdo_sqlite_db_handle *)dbh->driver_data; - sqlite3 *sqlite_handle; - sqlite_handle = db_handle->db; - -// SQLITE3_CHECK_INITIALIZED(db_obj, db_obj->initialised, SQLite3) - sqlite_flags = (flags & SQLITE_OPEN_READWRITE) ? 1 : 0; if (sqlite3_blob_open(sqlite_handle, dbname, table, column, rowid, sqlite_flags, &blob) != SQLITE_OK) { + // TODO - exception needed here. // php_sqlite3_error(db_obj, "Unable to open blob: %s", sqlite3_errmsg(db_obj->db)); // and converting to exception zend_throw_exception_ex(php_pdo_get_exception(), 0, errtext); RETURN_FALSE; @@ -412,3 +563,139 @@ PHP_METHOD(PDOSqlite, openBlob) } } /* }}} */ + +static int php_pgsql_collation_callback(void *context, + int string1_len, const void *string1, + int string2_len, const void *string2) +{ + int ret; + zval zargs[2]; + zval retval; + struct pdo_sqlite_collation *collation = (struct pdo_sqlite_collation*) context; + + collation->fc.fci.size = sizeof(collation->fc.fci); + ZVAL_COPY_VALUE(&collation->fc.fci.function_name, &collation->callback); + collation->fc.fci.object = NULL; + collation->fc.fci.retval = &retval; + + // Prepare the arguments. + ZVAL_STRINGL(&zargs[0], (char *) string1, string1_len); + ZVAL_STRINGL(&zargs[1], (char *) string2, string2_len); + collation->fc.fci.param_count = 2; + collation->fc.fci.params = zargs; + + if ((ret = zend_call_function(&collation->fc.fci, &collation->fc.fcc)) == FAILURE) { + php_error_docref(NULL, E_WARNING, "An error occurred while invoking the callback"); + } else if (!Z_ISUNDEF(retval)) { + if (Z_TYPE(retval) != IS_LONG) { + convert_to_long(&retval); + } + ret = 0; + if (Z_LVAL(retval) > 0) { + ret = 1; + } else if (Z_LVAL(retval) < 0) { + ret = -1; + } + zval_ptr_dtor(&retval); + } + + zval_ptr_dtor(&zargs[0]); + zval_ptr_dtor(&zargs[1]); + + return ret; +} + + +PHP_METHOD(PDOSqlite, createAggregate) +{ + struct pdo_sqlite_func *func; + zend_fcall_info step_fci, fini_fci; + zend_fcall_info_cache step_fcc, fini_fcc; + char *func_name; + size_t func_name_len; + zend_long argc = -1; + pdo_dbh_t *dbh; + pdo_sqlite_db_handle *H; + int ret; + +// pdo_dbh_t *dbh; +// pdo_sqlite_db_handle *db_handle; + + dbh = Z_PDO_DBH_P(ZEND_THIS); + PDO_CONSTRUCT_CHECK; + H = (pdo_sqlite_db_handle *)dbh->driver_data; + + ZEND_PARSE_PARAMETERS_START(3, 4) + Z_PARAM_STRING(func_name, func_name_len) + Z_PARAM_FUNC(step_fci, step_fcc) + Z_PARAM_FUNC(fini_fci, fini_fcc) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(argc) + ZEND_PARSE_PARAMETERS_END(); + + func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func)); + + ret = sqlite3_create_function(H->db, func_name, argc, SQLITE_UTF8, + func, NULL, php_pgsql_func_step_callback, php_pgsql_func_final_callback); + if (ret == SQLITE_OK) { + func->funcname = estrdup(func_name); + + ZVAL_COPY(&func->step, &step_fci.function_name); + + ZVAL_COPY(&func->fini, &fini_fci.function_name); + + func->argc = argc; + + func->next = H->funcs; + H->funcs = func; + + RETURN_TRUE; + } + + efree(func); + RETURN_FALSE; +} +/* }}} */ + +/* {{{ bool SQLite::createCollation(string name, callable callback) + Registers a collation with the sqlite db handle */ +PHP_METHOD(PDOSqlite, createCollation) +{ + struct pdo_sqlite_collation *collation; + zend_fcall_info fci; + zend_fcall_info_cache fcc; + char *collation_name; + size_t collation_name_len; + pdo_dbh_t *dbh; + pdo_sqlite_db_handle *H; +// pdo_dbh_t *dbh; +// pdo_sqlite_db_handle *db_handle; + int ret; + + ZEND_PARSE_PARAMETERS_START(2, 2) + Z_PARAM_STRING(collation_name, collation_name_len) + Z_PARAM_FUNC(fci, fcc) + ZEND_PARSE_PARAMETERS_END(); + + dbh = Z_PDO_DBH_P(ZEND_THIS); + PDO_CONSTRUCT_CHECK; + H = (pdo_sqlite_db_handle *)dbh->driver_data; + + collation = (struct pdo_sqlite_collation*)ecalloc(1, sizeof(*collation)); + + ret = sqlite3_create_collation(H->db, collation_name, SQLITE_UTF8, collation, php_pgsql_collation_callback); + if (ret == SQLITE_OK) { + collation->name = estrdup(collation_name); + + ZVAL_COPY(&collation->callback, &fci.function_name); + + collation->next = H->collations; + H->collations = collation; + + RETURN_TRUE; + } + + efree(collation); + RETURN_FALSE; +} +/* }}} */ diff --git a/ext/pdo_sqlite/sqlite_driver.c b/ext/pdo_sqlite/sqlite_driver.c index f74b69234c6c6..bdad23a581d56 100644 --- a/ext/pdo_sqlite/sqlite_driver.c +++ b/ext/pdo_sqlite/sqlite_driver.c @@ -453,8 +453,7 @@ static int do_callback(struct pdo_sqlite_fci *fc, zval *cb, return ret; } -// TODO - make static again static -void php_sqlite3_func_callback(sqlite3_context *context, int argc, +static void php_sqlite3_func_callback(sqlite3_context *context, int argc, sqlite3_value **argv) { struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context); diff --git a/ext/pdo_sqlite/tests/subclasses/gc.phpt b/ext/pdo_sqlite/tests/subclasses/gc.phpt new file mode 100644 index 0000000000000..e09b7dd48889f --- /dev/null +++ b/ext/pdo_sqlite/tests/subclasses/gc.phpt @@ -0,0 +1,28 @@ +--TEST-- +GC support for PDO Sqlite driver data +--EXTENSIONS-- +pdo_sqlite +--FILE-- +a = Pdo::connect('sqlite::memory:'); + +if (!$obj->a instanceof PdoSqlite) { + echo "Wrong class type. Should be PdoSqlite but is [" . get_class($obj->a) . "]\n"; +} + +$obj->a->createFunction('func1', function() use ($obj) {}, 1); +$obj->a->createAggregate('func2', function() use ($obj) {}, function() use($obj) {}); +$obj->a->createCollation('col', function() use ($obj) {}); + +?> +===DONE=== +--EXPECT-- +===DONE=== diff --git a/ext/pdo_sqlite/tests/subclasses/pdo_sqlite_createaggregate.phpt b/ext/pdo_sqlite/tests/subclasses/pdo_sqlite_createaggregate.phpt new file mode 100644 index 0000000000000..cc4763e4dbd91 --- /dev/null +++ b/ext/pdo_sqlite/tests/subclasses/pdo_sqlite_createaggregate.phpt @@ -0,0 +1,32 @@ +--TEST-- +PDO_sqlite: Testing createAggregate() +--EXTENSIONS-- +pdo_sqlite +--FILE-- +query('CREATE TABLE IF NOT EXISTS foobar (id INT AUTO INCREMENT, name TEXT)'); + +$db->query('INSERT INTO foobar VALUES (NULL, "PHP")'); +$db->query('INSERT INTO foobar VALUES (NULL, "PHP6")'); + +$db->createAggregate('testing', function(&$a, $b) { $a .= $b; return $a; }, function(&$v) { return $v; }); + + +foreach ($db->query('SELECT testing(name) FROM foobar') as $row) { + var_dump($row); +} + +$db->query('DROP TABLE foobar'); + +?> +--EXPECT-- +array(2) { + ["testing(name)"]=> + string(2) "12" + [0]=> + string(2) "12" +} diff --git a/ext/pdo_sqlite/tests/subclasses/pdo_sqlite_createaggregate_002.phpt b/ext/pdo_sqlite/tests/subclasses/pdo_sqlite_createaggregate_002.phpt new file mode 100644 index 0000000000000..9515b859efc81 --- /dev/null +++ b/ext/pdo_sqlite/tests/subclasses/pdo_sqlite_createaggregate_002.phpt @@ -0,0 +1,25 @@ +--TEST-- +PDO_sqlite: Testing invalid callback for createAggregate() +--EXTENSIONS-- +pdo_sqlite +--FILE-- +createAggregate('foo', 'a', ''); +} catch (\TypeError $e) { + echo $e->getMessage() . \PHP_EOL; +} +try { + $pdo->createAggregate('foo', 'strlen', ''); +} catch (\TypeError $e) { + echo $e->getMessage() . \PHP_EOL; +} + +?> +--EXPECT-- +PDOSqlite::createAggregate(): Argument #2 ($step) must be a valid callback, function "a" not found or invalid function name +PDOSqlite::createAggregate(): Argument #3 ($finalize) must be a valid callback, function "" not found or invalid function name diff --git a/ext/pdo_sqlite/tests/subclasses/pdo_sqlite_createcollation.phpt b/ext/pdo_sqlite/tests/subclasses/pdo_sqlite_createcollation.phpt new file mode 100644 index 0000000000000..80344de0a59f2 --- /dev/null +++ b/ext/pdo_sqlite/tests/subclasses/pdo_sqlite_createcollation.phpt @@ -0,0 +1,39 @@ +--TEST-- +PDO_sqlite: Testing sqliteCreateCollation() +--EXTENSIONS-- +pdo_sqlite +--FILE-- +setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + +$db->query('CREATE TABLE IF NOT EXISTS foobar (id INT AUTO INCREMENT, name TEXT)'); + +$db->query('INSERT INTO foobar VALUES (NULL, "1")'); +$db->query('INSERT INTO foobar VALUES (NULL, "2")'); +$db->query('INSERT INTO foobar VALUES (NULL, "10")'); + +$db->createCollation('MYCOLLATE', function($a, $b) { return strnatcmp($a, $b); }); + +$result = $db->query('SELECT name FROM foobar ORDER BY name COLLATE MYCOLLATE'); +foreach ($result as $row) { + echo $row['name'] . "\n"; +} + +$result = $db->query('SELECT name FROM foobar ORDER BY name'); +foreach ($result as $row) { + echo $row['name'] . "\n"; +} + +$db->query('DROP TABLE foobar'); + +?> +--EXPECT-- +1 +2 +10 +1 +10 +2 diff --git a/ext/pdo_sqlite/tests/subclasses/pdo_sqlite_createfunction_with_flags.phpt b/ext/pdo_sqlite/tests/subclasses/pdo_sqlite_createfunction_with_flags.phpt new file mode 100644 index 0000000000000..bedb8c6c3a724 --- /dev/null +++ b/ext/pdo_sqlite/tests/subclasses/pdo_sqlite_createfunction_with_flags.phpt @@ -0,0 +1,38 @@ +--TEST-- +PDO_sqlite: Testing createFunction() with flags +--EXTENSIONS-- +pdo_sqlite +--SKIPIF-- + +--FILE-- +query('CREATE TABLE IF NOT EXISTS foobar (id INT AUTO INCREMENT, name TEXT)'); +$db->query('INSERT INTO foobar VALUES (NULL, "PHP")'); +$db->query('INSERT INTO foobar VALUES (NULL, "PHP6")'); + +$db->createFunction('testing', function($v) { return strtolower($v); }, 1, PDO::SQLITE_DETERMINISTIC); + +foreach ($db->query('SELECT testing(name) FROM foobar') as $row) { + var_dump($row); +} + +$db->query('DROP TABLE foobar'); + +?> +--EXPECT-- +array(2) { + ["testing(name)"]=> + string(3) "php" + [0]=> + string(3) "php" +} +array(2) { + ["testing(name)"]=> + string(4) "php6" + [0]=> + string(4) "php6" +} From fd96e22829bf4ebb45f0d76358bde74a9610079e Mon Sep 17 00:00:00 2001 From: Danack Date: Sat, 6 May 2023 14:45:42 +0100 Subject: [PATCH 13/35] PDO_DBLIB tests are passing. --- .../tests/subclassing/pdodblib_001.phpt | 25 +++++++------- .../tests/subclassing/pdodblib_002.phpt | 34 ++++++++++--------- 2 files changed, 31 insertions(+), 28 deletions(-) diff --git a/ext/pdo_dblib/tests/subclassing/pdodblib_001.phpt b/ext/pdo_dblib/tests/subclassing/pdodblib_001.phpt index f12abd05e77ec..906013bfd2397 100644 --- a/ext/pdo_dblib/tests/subclassing/pdodblib_001.phpt +++ b/ext/pdo_dblib/tests/subclassing/pdodblib_001.phpt @@ -18,31 +18,32 @@ echo "PdoDblib class exists.\n"; $db = new PdoDblib($dsn, $user, $pass); -$db->query('CREATE TABLE IF NOT EXISTS foobar (id INT AUTO INCREMENT, name TEXT)'); +$db->query('drop table if exists #foobar;'); -$db->query('INSERT INTO foobar VALUES (NULL, "PHP")'); -$db->query('INSERT INTO foobar VALUES (NULL, "PHP6")'); +$db->query("create table #foobar(name varchar(32)); "); +$db->query("insert into #foobar values('PHP');"); +$db->query("insert into #foobar values('PHP6');"); -foreach ($db->query('SELECT testing(name) FROM foobar') as $row) { +foreach ($db->query('SELECT name FROM #foobar') as $row) { var_dump($row); } -$db->query('DROP TABLE foobar'); +$db->query('drop table #foobar;'); echo "Fin."; ?> --EXPECT-- -PdoSqlite class exists. +PdoDblib class exists. array(2) { - ["testing(name)"]=> - string(3) "php" + ["name"]=> + string(3) "PHP" [0]=> - string(3) "php" + string(3) "PHP" } array(2) { - ["testing(name)"]=> - string(4) "php6" + ["name"]=> + string(4) "PHP6" [0]=> - string(4) "php6" + string(4) "PHP6" } Fin. diff --git a/ext/pdo_dblib/tests/subclassing/pdodblib_002.phpt b/ext/pdo_dblib/tests/subclassing/pdodblib_002.phpt index bac3aacce8858..ee4777f70c90f 100644 --- a/ext/pdo_dblib/tests/subclassing/pdodblib_002.phpt +++ b/ext/pdo_dblib/tests/subclassing/pdodblib_002.phpt @@ -5,6 +5,8 @@ pdo --FILE-- exec('CREATE TABLE test(id int NOT NULL PRIMARY KEY, val VARCHAR(10))'); -$db->exec("INSERT INTO test VALUES(1, 'A')"); -$db->exec("INSERT INTO test VALUES(2, 'B')"); -$db->exec("INSERT INTO test VALUES(3, 'C')"); - -$stmt = $db->prepare('SELECT * from test'); -$stmt->execute(); +$db->query('drop table if exists #test;'); -var_dump($stmt->fetchAll(PDO::FETCH_OBJ)); +$db->query("create table #test(name varchar(32)); "); +$db->query("insert into #test values('PHP');"); +$db->query("insert into #test values('PHP6');"); +foreach ($db->query('SELECT name FROM #test') as $row) { + var_dump($row); +} -$db->query('DROP TABLE foobar'); +$db->query('drop table #test;'); echo "Fin."; ?> --EXPECT-- PdoDblib class exists. array(2) { - ["testing(name)"]=> - string(3) "php" + ["name"]=> + string(3) "PHP" [0]=> - string(3) "php" + string(3) "PHP" } array(2) { - ["testing(name)"]=> - string(4) "php6" + ["name"]=> + string(4) "PHP6" [0]=> - string(4) "php6" + string(4) "PHP6" } Fin. From 835c38b2ebf91c43d0856b644b2dce9f5d6ef729 Mon Sep 17 00:00:00 2001 From: Danack Date: Sat, 6 May 2023 19:12:50 +0100 Subject: [PATCH 14/35] All subclasses created, ODBC works. --- ext/pdo_firebird/pdo_firebird.c | 8 +++ ext/pdo_firebird/pdo_firebird.stub.php | 9 +++ ext/pdo_oci/pdo_oci.c | 12 ++++ ext/pdo_oci/pdo_oci.stub.php | 10 ++++ ext/pdo_oci/pdo_oci_arginfo.h | 20 +++++++ ext/pdo_oci/tests/subclassing/pdooci_001.phpt | 52 ++++++++++++++++ ext/pdo_oci/tests/subclassing/pdooci_002.phpt | 59 +++++++++++++++++++ ext/pdo_odbc/pdo_odbc.c | 11 ++++ ext/pdo_odbc/pdo_odbc.stub.php | 9 +++ ext/pdo_odbc/pdo_odbc_arginfo.h | 20 +++++++ .../tests/subclassing/pdoodbc_001.phpt | 48 +++++++++++++++ .../tests/subclassing/pdoodbc_002.phpt | 59 +++++++++++++++++++ 12 files changed, 317 insertions(+) create mode 100644 ext/pdo_firebird/pdo_firebird.stub.php create mode 100644 ext/pdo_oci/pdo_oci.stub.php create mode 100644 ext/pdo_oci/pdo_oci_arginfo.h create mode 100644 ext/pdo_oci/tests/subclassing/pdooci_001.phpt create mode 100644 ext/pdo_oci/tests/subclassing/pdooci_002.phpt create mode 100644 ext/pdo_odbc/pdo_odbc.stub.php create mode 100644 ext/pdo_odbc/pdo_odbc_arginfo.h create mode 100644 ext/pdo_odbc/tests/subclassing/pdoodbc_001.phpt create mode 100644 ext/pdo_odbc/tests/subclassing/pdoodbc_002.phpt diff --git a/ext/pdo_firebird/pdo_firebird.c b/ext/pdo_firebird/pdo_firebird.c index 9b8ca1394bee1..b424619ac4f89 100644 --- a/ext/pdo_firebird/pdo_firebird.c +++ b/ext/pdo_firebird/pdo_firebird.c @@ -25,6 +25,10 @@ #include "pdo/php_pdo_driver.h" #include "php_pdo_firebird.h" #include "php_pdo_firebird_int.h" +#include "pdo_firebird_arginfo.h" + +zend_class_entry *pdofirebird_ce; +static pdo_driver_class_entry pdofirebird_pdo_driver_class_entry; /* {{{ pdo_firebird_deps */ static const zend_module_dep pdo_firebird_deps[] = { @@ -62,6 +66,10 @@ PHP_MINIT_FUNCTION(pdo_firebird) /* {{{ */ return FAILURE; } + pdofirebird_pdo_driver_class_entry.driver_name = "firebird"; + pdofirebird_pdo_driver_class_entry.driver_ce = pdofirebird_ce; + pdo_register_driver_specific_class(&pdofirebird_pdo_driver_class_entry); + #ifdef ZEND_SIGNALS /* firebird replaces some signals at runtime, suppress warnings. */ SIGG(check) = 0; diff --git a/ext/pdo_firebird/pdo_firebird.stub.php b/ext/pdo_firebird/pdo_firebird.stub.php new file mode 100644 index 0000000000000..3f1605c90fb02 --- /dev/null +++ b/ext/pdo_firebird/pdo_firebird.stub.php @@ -0,0 +1,9 @@ + #endif +#include "pdo_oci_arginfo.h" + +zend_class_entry *pdooci_ce; + +static pdo_driver_class_entry pdooci_pdo_driver_class_entry; /* {{{ pdo_oci_module_entry */ @@ -94,6 +99,13 @@ PHP_MINIT_FUNCTION(pdo_oci) // Defer OCI init to PHP_RINIT_FUNCTION because with php-fpm, // NLS_LANG is not yet available here. + pdooci_ce = register_class_PDOOci(pdo_dbh_ce); + pdooci_ce->create_object = pdo_dbh_new; + + pdooci_pdo_driver_class_entry.driver_name = "oci"; + pdooci_pdo_driver_class_entry.driver_ce = pdooci_ce; + pdo_register_driver_specific_class(&pdooci_pdo_driver_class_entry); + #ifdef ZTS pdo_oci_env_mutex = tsrm_mutex_alloc(); #endif diff --git a/ext/pdo_oci/pdo_oci.stub.php b/ext/pdo_oci/pdo_oci.stub.php new file mode 100644 index 0000000000000..b33d464016577 --- /dev/null +++ b/ext/pdo_oci/pdo_oci.stub.php @@ -0,0 +1,10 @@ +ce_flags |= ZEND_ACC_NOT_SERIALIZABLE; + + return class_entry; +} diff --git a/ext/pdo_oci/tests/subclassing/pdooci_001.phpt b/ext/pdo_oci/tests/subclassing/pdooci_001.phpt new file mode 100644 index 0000000000000..b152ae44d9e24 --- /dev/null +++ b/ext/pdo_oci/tests/subclassing/pdooci_001.phpt @@ -0,0 +1,52 @@ +--TEST-- +PDO_oci subclass basic +--EXTENSIONS-- +pdo_oci +--FILE-- +query('CREATE TABLE IF NOT EXISTS foobar (id INT, name TEXT)'); + +$db->query('INSERT INTO foobar VALUES (NULL, "PHP")'); +$db->query('INSERT INTO foobar VALUES (NULL, "PHP6")'); + +foreach ($db->query('SELECT name FROM foobar') as $row) { + var_dump($row); +} + +$db->query('DROP TABLE foobar'); + +echo "Fin."; +?> +--EXPECT-- +PdoMySql class exists. +array(2) { + ["name"]=> + string(3) "PHP" + [0]=> + string(3) "PHP" +} +array(2) { + ["name"]=> + string(4) "PHP6" + [0]=> + string(4) "PHP6" +} +Fin. diff --git a/ext/pdo_oci/tests/subclassing/pdooci_002.phpt b/ext/pdo_oci/tests/subclassing/pdooci_002.phpt new file mode 100644 index 0000000000000..7a0bdd4740838 --- /dev/null +++ b/ext/pdo_oci/tests/subclassing/pdooci_002.phpt @@ -0,0 +1,59 @@ +--TEST-- +PDO_oci coonect through PDO::connect +--EXTENSIONS-- +pdo_oci +--FILE-- +query('DROP TABLE IF EXISTS test'); +$db->exec('CREATE TABLE IF NOT EXISTS test(id int NOT NULL PRIMARY KEY, name VARCHAR(10))'); +$db->exec("INSERT INTO test VALUES(1, 'A')"); +$db->exec("INSERT INTO test VALUES(2, 'B')"); +$db->exec("INSERT INTO test VALUES(3, 'C')"); + +foreach ($db->query('SELECT name FROM test') as $row) { + var_dump($row); +} + +$db->query('DROP TABLE test'); + +echo "Fin."; +?> +--EXPECT-- +PdoMysql class exists. +array(2) { + ["name"]=> + string(1) "A" + [0]=> + string(1) "A" +} +array(2) { + ["name"]=> + string(1) "B" + [0]=> + string(1) "B" +} +array(2) { + ["name"]=> + string(1) "C" + [0]=> + string(1) "C" +} +Fin. diff --git a/ext/pdo_odbc/pdo_odbc.c b/ext/pdo_odbc/pdo_odbc.c index 12874c8bd8747..9f36bd20dc694 100644 --- a/ext/pdo_odbc/pdo_odbc.c +++ b/ext/pdo_odbc/pdo_odbc.c @@ -25,6 +25,10 @@ #include "pdo/php_pdo_driver.h" #include "php_pdo_odbc.h" #include "php_pdo_odbc_int.h" +#include "pdo_odbc_arginfo.h" + +zend_class_entry *pdoodbc_ce; +static pdo_driver_class_entry pdoodbc_pdo_driver_class_entry; /* {{{ pdo_odbc_deps[] */ static const zend_module_dep pdo_odbc_deps[] = { @@ -102,6 +106,13 @@ PHP_MINIT_FUNCTION(pdo_odbc) REGISTER_PDO_CLASS_CONST_LONG("ODBC_SQL_USE_DRIVER", SQL_CUR_USE_DRIVER); REGISTER_PDO_CLASS_CONST_LONG("ODBC_SQL_USE_ODBC", SQL_CUR_USE_ODBC); + pdoodbc_ce = register_class_PDOOdbc(pdo_dbh_ce); + pdoodbc_ce->create_object = pdo_dbh_new; + + pdoodbc_pdo_driver_class_entry.driver_name = "odbc"; + pdoodbc_pdo_driver_class_entry.driver_ce = pdoodbc_ce; + pdo_register_driver_specific_class(&pdoodbc_pdo_driver_class_entry); + return SUCCESS; } /* }}} */ diff --git a/ext/pdo_odbc/pdo_odbc.stub.php b/ext/pdo_odbc/pdo_odbc.stub.php new file mode 100644 index 0000000000000..865820fdc6cd4 --- /dev/null +++ b/ext/pdo_odbc/pdo_odbc.stub.php @@ -0,0 +1,9 @@ +ce_flags |= ZEND_ACC_NOT_SERIALIZABLE; + + return class_entry; +} diff --git a/ext/pdo_odbc/tests/subclassing/pdoodbc_001.phpt b/ext/pdo_odbc/tests/subclassing/pdoodbc_001.phpt new file mode 100644 index 0000000000000..d4f3a481e4986 --- /dev/null +++ b/ext/pdo_odbc/tests/subclassing/pdoodbc_001.phpt @@ -0,0 +1,48 @@ +--TEST-- +PDO_odbc subclass basic +--EXTENSIONS-- +pdo_odbc +--FILE-- +query('CREATE TABLE IF NOT EXISTS foobar (id INT, name TEXT)'); + +$db->query('INSERT INTO foobar VALUES (NULL, "PHP")'); +$db->query('INSERT INTO foobar VALUES (NULL, "PHP6")'); + +foreach ($db->query('SELECT name FROM foobar') as $row) { + var_dump($row); +} + +$db->query('DROP TABLE foobar'); + +echo "Fin."; +?> +--EXPECT-- +PdoOdbc class exists. +array(2) { + ["name"]=> + string(3) "PHP" + [0]=> + string(3) "PHP" +} +array(2) { + ["name"]=> + string(4) "PHP6" + [0]=> + string(4) "PHP6" +} +Fin. diff --git a/ext/pdo_odbc/tests/subclassing/pdoodbc_002.phpt b/ext/pdo_odbc/tests/subclassing/pdoodbc_002.phpt new file mode 100644 index 0000000000000..59b7825a385d9 --- /dev/null +++ b/ext/pdo_odbc/tests/subclassing/pdoodbc_002.phpt @@ -0,0 +1,59 @@ +--TEST-- +PDO_mysql coonect through PDO::connect +--EXTENSIONS-- +PDO_odbc +--FILE-- +query('DROP TABLE IF EXISTS test'); +$db->exec('CREATE TABLE IF NOT EXISTS test(id int NOT NULL PRIMARY KEY, name VARCHAR(10))'); +$db->exec("INSERT INTO test VALUES(1, 'A')"); +$db->exec("INSERT INTO test VALUES(2, 'B')"); +$db->exec("INSERT INTO test VALUES(3, 'C')"); + +foreach ($db->query('SELECT name FROM test') as $row) { + var_dump($row); +} + +$db->query('DROP TABLE test'); + +echo "Fin."; +?> +--EXPECT-- +PdoOdbc class exists. +array(2) { + ["name"]=> + string(1) "A" + [0]=> + string(1) "A" +} +array(2) { + ["name"]=> + string(1) "B" + [0]=> + string(1) "B" +} +array(2) { + ["name"]=> + string(1) "C" + [0]=> + string(1) "C" +} +Fin. From a4b3fcf81fa45af7416d72a12fa3284b450b0bb0 Mon Sep 17 00:00:00 2001 From: Danack Date: Sat, 6 May 2023 19:42:01 +0100 Subject: [PATCH 15/35] pdo_firebird subclass is working. --- ext/pdo_firebird/pdo_firebird.c | 3 + ext/pdo_firebird/pdo_firebird.stub.php | 2 +- ext/pdo_firebird/pdo_firebird_arginfo.h | 20 ++++++ .../tests/subclassing/pdoodbc_001.phpt | 53 +++++++++++++++ .../tests/subclassing/pdoodbc_002.phpt | 65 +++++++++++++++++++ 5 files changed, 142 insertions(+), 1 deletion(-) create mode 100644 ext/pdo_firebird/pdo_firebird_arginfo.h create mode 100644 ext/pdo_firebird/tests/subclassing/pdoodbc_001.phpt create mode 100644 ext/pdo_firebird/tests/subclassing/pdoodbc_002.phpt diff --git a/ext/pdo_firebird/pdo_firebird.c b/ext/pdo_firebird/pdo_firebird.c index b424619ac4f89..9b99cf2cbf84b 100644 --- a/ext/pdo_firebird/pdo_firebird.c +++ b/ext/pdo_firebird/pdo_firebird.c @@ -66,6 +66,9 @@ PHP_MINIT_FUNCTION(pdo_firebird) /* {{{ */ return FAILURE; } + pdofirebird_ce = register_class_PDOFirebird(pdo_dbh_ce); + pdofirebird_ce->create_object = pdo_dbh_new; + pdofirebird_pdo_driver_class_entry.driver_name = "firebird"; pdofirebird_pdo_driver_class_entry.driver_ce = pdofirebird_ce; pdo_register_driver_specific_class(&pdofirebird_pdo_driver_class_entry); diff --git a/ext/pdo_firebird/pdo_firebird.stub.php b/ext/pdo_firebird/pdo_firebird.stub.php index 3f1605c90fb02..0b350de84b073 100644 --- a/ext/pdo_firebird/pdo_firebird.stub.php +++ b/ext/pdo_firebird/pdo_firebird.stub.php @@ -5,5 +5,5 @@ /** @not-serializable */ class PDOFirebird extends PDO { - + // not methods asdad } diff --git a/ext/pdo_firebird/pdo_firebird_arginfo.h b/ext/pdo_firebird/pdo_firebird_arginfo.h new file mode 100644 index 0000000000000..a451b69a1ab94 --- /dev/null +++ b/ext/pdo_firebird/pdo_firebird_arginfo.h @@ -0,0 +1,20 @@ +/* This is a generated file, edit the .stub.php file instead. + * Stub hash: 8183c1fc28fe958e997673b93c498812e2a3bef2 */ + + + + +static const zend_function_entry class_PDOFirebird_methods[] = { + ZEND_FE_END +}; + +static zend_class_entry *register_class_PDOFirebird(zend_class_entry *class_entry_PDO) +{ + zend_class_entry ce, *class_entry; + + INIT_CLASS_ENTRY(ce, "PDOFirebird", class_PDOFirebird_methods); + class_entry = zend_register_internal_class_ex(&ce, class_entry_PDO); + class_entry->ce_flags |= ZEND_ACC_NOT_SERIALIZABLE; + + return class_entry; +} diff --git a/ext/pdo_firebird/tests/subclassing/pdoodbc_001.phpt b/ext/pdo_firebird/tests/subclassing/pdoodbc_001.phpt new file mode 100644 index 0000000000000..f39cfb5e96286 --- /dev/null +++ b/ext/pdo_firebird/tests/subclassing/pdoodbc_001.phpt @@ -0,0 +1,53 @@ +--TEST-- +PDO_firebird subclass basic +--EXTENSIONS-- +pdo_firebird +--FILE-- +query('DROP TABLE foobar'); +} catch (\Exception $e) { + // TODO - find the 'not exists' syntax. +} + +$db->query('CREATE TABLE foobar (idx int NOT NULL PRIMARY KEY, name VARCHAR(20))'); +$db->query("INSERT INTO foobar VALUES (1, 'PHP')"); +$db->query("INSERT INTO foobar VALUES (2, 'PHP6')"); + +foreach ($db->query('SELECT name FROM foobar') as $row) { + var_dump($row); +} + +$db->query('DROP TABLE foobar'); + +echo "Fin."; +?> +--EXPECT-- +PDOFirebird class exists. +array(2) { + ["NAME"]=> + string(3) "PHP" + [0]=> + string(3) "PHP" +} +array(2) { + ["NAME"]=> + string(4) "PHP6" + [0]=> + string(4) "PHP6" +} +Fin. diff --git a/ext/pdo_firebird/tests/subclassing/pdoodbc_002.phpt b/ext/pdo_firebird/tests/subclassing/pdoodbc_002.phpt new file mode 100644 index 0000000000000..d3bebd053a0a5 --- /dev/null +++ b/ext/pdo_firebird/tests/subclassing/pdoodbc_002.phpt @@ -0,0 +1,65 @@ +--TEST-- +PDO_firebird coonect through PDO::connect +--EXTENSIONS-- +PDO_odbc +--FILE-- +query('DROP TABLE test'); +} catch (\Exception $e) { + // TODO - find the 'not exists' syntax. +} + +$db->query('CREATE TABLE test (idx int NOT NULL PRIMARY KEY, name VARCHAR(20))'); + +$db->exec("INSERT INTO test VALUES(1, 'A')"); +$db->exec("INSERT INTO test VALUES(2, 'B')"); +$db->exec("INSERT INTO test VALUES(3, 'C')"); + +foreach ($db->query('SELECT name FROM test') as $row) { + var_dump($row); +} + +$db->query('DROP TABLE test'); + +echo "Fin."; +?> +--EXPECT-- +PDOFirebird class exists. +array(2) { + ["NAME"]=> + string(1) "A" + [0]=> + string(1) "A" +} +array(2) { + ["NAME"]=> + string(1) "B" + [0]=> + string(1) "B" +} +array(2) { + ["NAME"]=> + string(1) "C" + [0]=> + string(1) "C" +} +Fin. From a987f0cd2dc9e315001122e669f927d64e3e2ef3 Mon Sep 17 00:00:00 2001 From: Danack Date: Sat, 6 May 2023 20:46:12 +0100 Subject: [PATCH 16/35] Changed config files name to be not ignored. --- ext/pdo_dblib/tests/config_functions.inc | 24 +++++++++++++++++ .../tests/subclassing/pdodblib_001.phpt | 2 +- .../tests/subclassing/pdodblib_002.phpt | 2 +- ext/pdo_firebird/tests/config_functions.inc | 23 ++++++++++++++++ .../tests/subclassing/pdoodbc_001.phpt | 2 +- .../tests/subclassing/pdoodbc_002.phpt | 2 +- .../tests/subclassing/pdomysql_001.phpt | 2 +- .../tests/subclassing/pdomysql_002.phpt | 2 +- .../tests/subclassing/pdomysql_003.phpt | 2 +- ext/pdo_oci/tests/config_functions.inc | 23 ++++++++++++++++ ext/pdo_oci/tests/subclassing/pdooci_001.phpt | 2 +- ext/pdo_oci/tests/subclassing/pdooci_002.phpt | 2 +- ext/pdo_odbc/tests/config_functions.inc | 27 +++++++++++++++++++ .../tests/subclassing/pdoodbc_001.phpt | 2 +- .../tests/subclassing/pdoodbc_002.phpt | 2 +- ext/pdo_pgsql/tests/config_functions.inc | 25 +++++++++++++++++ .../tests/subclassing/pdopgsql_001.phpt | 2 +- .../tests/subclassing/pdopgsql_002.phpt | 2 +- .../tests/subclassing/pdopgsql_003.phpt | 2 +- 19 files changed, 136 insertions(+), 14 deletions(-) create mode 100644 ext/pdo_dblib/tests/config_functions.inc create mode 100644 ext/pdo_firebird/tests/config_functions.inc create mode 100644 ext/pdo_oci/tests/config_functions.inc create mode 100644 ext/pdo_odbc/tests/config_functions.inc create mode 100644 ext/pdo_pgsql/tests/config_functions.inc diff --git a/ext/pdo_dblib/tests/config_functions.inc b/ext/pdo_dblib/tests/config_functions.inc new file mode 100644 index 0000000000000..cee246c9a7ff6 --- /dev/null +++ b/ext/pdo_dblib/tests/config_functions.inc @@ -0,0 +1,24 @@ + Date: Sat, 6 May 2023 23:49:54 +0300 Subject: [PATCH 17/35] Fix PDOOci tests --- ext/pdo_oci/tests/subclassing/pdooci_001.phpt | 17 ++++++----------- ext/pdo_oci/tests/subclassing/pdooci_002.phpt | 10 +++++----- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/ext/pdo_oci/tests/subclassing/pdooci_001.phpt b/ext/pdo_oci/tests/subclassing/pdooci_001.phpt index c7202b209f347..c0bf24c365add 100644 --- a/ext/pdo_oci/tests/subclassing/pdooci_001.phpt +++ b/ext/pdo_oci/tests/subclassing/pdooci_001.phpt @@ -15,17 +15,12 @@ echo "PdoOci class exists.\n"; [$dsn, $user, $pass] = getDsnUserAndPassword(); -var_dump([$dsn, $user, $pass]); -exit(0); - - - $db = new PdoOci($dsn, $user, $pass); -$db->query('CREATE TABLE IF NOT EXISTS foobar (id INT, name TEXT)'); +$db->query('CREATE TABLE IF NOT EXISTS foobar(id NUMBER, name VARCHAR2(6))'); -$db->query('INSERT INTO foobar VALUES (NULL, "PHP")'); -$db->query('INSERT INTO foobar VALUES (NULL, "PHP6")'); +$db->query("INSERT INTO foobar VALUES (NULL, 'PHP')"); +$db->query("INSERT INTO foobar VALUES (NULL, 'PHP6')"); foreach ($db->query('SELECT name FROM foobar') as $row) { var_dump($row); @@ -36,15 +31,15 @@ $db->query('DROP TABLE foobar'); echo "Fin."; ?> --EXPECT-- -PdoMySql class exists. +PdoOci class exists. array(2) { - ["name"]=> + ["NAME"]=> string(3) "PHP" [0]=> string(3) "PHP" } array(2) { - ["name"]=> + ["NAME"]=> string(4) "PHP6" [0]=> string(4) "PHP6" diff --git a/ext/pdo_oci/tests/subclassing/pdooci_002.phpt b/ext/pdo_oci/tests/subclassing/pdooci_002.phpt index a2dfb509ada99..27730bd954b49 100644 --- a/ext/pdo_oci/tests/subclassing/pdooci_002.phpt +++ b/ext/pdo_oci/tests/subclassing/pdooci_002.phpt @@ -23,7 +23,7 @@ if (!$db instanceof PdoOci) { } $db->query('DROP TABLE IF EXISTS test'); -$db->exec('CREATE TABLE IF NOT EXISTS test(id int NOT NULL PRIMARY KEY, name VARCHAR(10))'); +$db->exec('CREATE TABLE IF NOT EXISTS test(id NUMBER NOT NULL PRIMARY KEY, name VARCHAR2(10))'); $db->exec("INSERT INTO test VALUES(1, 'A')"); $db->exec("INSERT INTO test VALUES(2, 'B')"); $db->exec("INSERT INTO test VALUES(3, 'C')"); @@ -37,21 +37,21 @@ $db->query('DROP TABLE test'); echo "Fin."; ?> --EXPECT-- -PdoMysql class exists. +PdoOci class exists. array(2) { - ["name"]=> + ["NAME"]=> string(1) "A" [0]=> string(1) "A" } array(2) { - ["name"]=> + ["NAME"]=> string(1) "B" [0]=> string(1) "B" } array(2) { - ["name"]=> + ["NAME"]=> string(1) "C" [0]=> string(1) "C" From 4454698dac2a6ca739d08fbe8c5d9963e6dd8dd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C5=BEuris?= Date: Sun, 7 May 2023 00:23:11 +0300 Subject: [PATCH 18/35] Fix PDOFirebird test names --- .../tests/subclassing/{pdoodbc_001.phpt => pdofirebird_001.phpt} | 0 .../tests/subclassing/{pdoodbc_002.phpt => pdofirebird_002.phpt} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename ext/pdo_firebird/tests/subclassing/{pdoodbc_001.phpt => pdofirebird_001.phpt} (100%) rename ext/pdo_firebird/tests/subclassing/{pdoodbc_002.phpt => pdofirebird_002.phpt} (100%) diff --git a/ext/pdo_firebird/tests/subclassing/pdoodbc_001.phpt b/ext/pdo_firebird/tests/subclassing/pdofirebird_001.phpt similarity index 100% rename from ext/pdo_firebird/tests/subclassing/pdoodbc_001.phpt rename to ext/pdo_firebird/tests/subclassing/pdofirebird_001.phpt diff --git a/ext/pdo_firebird/tests/subclassing/pdoodbc_002.phpt b/ext/pdo_firebird/tests/subclassing/pdofirebird_002.phpt similarity index 100% rename from ext/pdo_firebird/tests/subclassing/pdoodbc_002.phpt rename to ext/pdo_firebird/tests/subclassing/pdofirebird_002.phpt From cd97c9d338e6996997a4e6f14b6117487c41ec5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C5=BEuris?= Date: Sun, 7 May 2023 00:27:10 +0300 Subject: [PATCH 19/35] Use RECREATE for PDOFirebird tests RECREATE will drop (if needed) before creating --- ext/pdo_firebird/tests/subclassing/pdofirebird_001.phpt | 8 +------- ext/pdo_firebird/tests/subclassing/pdofirebird_002.phpt | 8 +------- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/ext/pdo_firebird/tests/subclassing/pdofirebird_001.phpt b/ext/pdo_firebird/tests/subclassing/pdofirebird_001.phpt index 43c03b0ceea08..4cd63aec1c808 100644 --- a/ext/pdo_firebird/tests/subclassing/pdofirebird_001.phpt +++ b/ext/pdo_firebird/tests/subclassing/pdofirebird_001.phpt @@ -18,13 +18,7 @@ echo "PDOFirebird class exists.\n"; $db = new PDOFirebird($dsn, $user, $pass); -try { - $db->query('DROP TABLE foobar'); -} catch (\Exception $e) { - // TODO - find the 'not exists' syntax. -} - -$db->query('CREATE TABLE foobar (idx int NOT NULL PRIMARY KEY, name VARCHAR(20))'); +$db->query('RECREATE TABLE foobar (idx int NOT NULL PRIMARY KEY, name VARCHAR(20))'); $db->query("INSERT INTO foobar VALUES (1, 'PHP')"); $db->query("INSERT INTO foobar VALUES (2, 'PHP6')"); diff --git a/ext/pdo_firebird/tests/subclassing/pdofirebird_002.phpt b/ext/pdo_firebird/tests/subclassing/pdofirebird_002.phpt index c90b45e96e642..64e0ea201cea5 100644 --- a/ext/pdo_firebird/tests/subclassing/pdofirebird_002.phpt +++ b/ext/pdo_firebird/tests/subclassing/pdofirebird_002.phpt @@ -22,13 +22,7 @@ if (!$db instanceof PDOFirebird) { echo "Wrong class type. Should be PdoOdbc but is [" . get_class($db) . "\n"; } -try { - $db->query('DROP TABLE test'); -} catch (\Exception $e) { - // TODO - find the 'not exists' syntax. -} - -$db->query('CREATE TABLE test (idx int NOT NULL PRIMARY KEY, name VARCHAR(20))'); +$db->query('RECREATE TABLE test (idx int NOT NULL PRIMARY KEY, name VARCHAR(20))'); $db->exec("INSERT INTO test VALUES(1, 'A')"); $db->exec("INSERT INTO test VALUES(2, 'B')"); From 524c8933307204582f728da271bb6a12a84460c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C5=BEuris?= Date: Sun, 7 May 2023 00:35:25 +0300 Subject: [PATCH 20/35] Add PDOMysql testing setup helper --- ext/pdo_mysql/tests/config_functions.inc | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 ext/pdo_mysql/tests/config_functions.inc diff --git a/ext/pdo_mysql/tests/config_functions.inc b/ext/pdo_mysql/tests/config_functions.inc new file mode 100644 index 0000000000000..0f6019e0b7b7c --- /dev/null +++ b/ext/pdo_mysql/tests/config_functions.inc @@ -0,0 +1,24 @@ + Date: Sun, 7 May 2023 14:49:08 +0100 Subject: [PATCH 21/35] Copy methods from being the magic implementations, to being declared on the PdoPgsql class. --- ext/pdo_pgsql/pdo_pgsql.c | 6 ++ ext/pdo_pgsql/pdo_pgsql.stub.php | 82 ++++++++++++++++-------- ext/pdo_pgsql/pdo_pgsql_arginfo.h | 101 +++++++++++++++++++++++++++++- ext/pdo_pgsql/pdo_pgsql_class.c | 79 +++++++++++++++++------ ext/pdo_pgsql/pgsql_driver.c | 84 +++++++++++++++++++------ ext/pdo_pgsql/php_pdo_pgsql_int.h | 10 +++ 6 files changed, 295 insertions(+), 67 deletions(-) diff --git a/ext/pdo_pgsql/pdo_pgsql.c b/ext/pdo_pgsql/pdo_pgsql.c index 6db815897f7b1..e81157c7f9db8 100644 --- a/ext/pdo_pgsql/pdo_pgsql.c +++ b/ext/pdo_pgsql/pdo_pgsql.c @@ -27,6 +27,12 @@ #include "php_pdo_pgsql_int.h" #include "pdo_pgsql_arginfo.h" +#define REGISTER_PDOPGSQL_CLASS_CONST_LONG(const_name, value) \ + zend_declare_class_constant_long(php_pdo_get_dbh_ce(), const_name, sizeof(const_name)-1, (zend_long)value); + +#define REGISTER_PDOPGSQL_CLASS_CONST_STRING(const_name, value) \ + zend_declare_class_constant_stringl(php_pdo_get_dbh_ce(), const_name, sizeof(const_name)-1, value, sizeof(value)-1); + zend_class_entry *pdopgsql_ce; static pdo_driver_class_entry pdopgsql_pdo_driver_class_entry; diff --git a/ext/pdo_pgsql/pdo_pgsql.stub.php b/ext/pdo_pgsql/pdo_pgsql.stub.php index 85302d2df7225..26088ed10beb1 100644 --- a/ext/pdo_pgsql/pdo_pgsql.stub.php +++ b/ext/pdo_pgsql/pdo_pgsql.stub.php @@ -6,33 +6,61 @@ class PDOPgSql extends PDO { + /** + * @var int + * @cname PDO_PGSQL_ATTR_DISABLE_PREPARES + */ + public const ATTR_DISABLE_PREPARES = UNKNOWN; + + /** + * @var int + * @cname PGSQL_TRANSACTION_IDLE + */ + public const TRANSACTION_IDLE = UNKNOWN; + + /** + * @var int + * @cname PGSQL_TRANSACTION_ACTIVE + */ + public const TRANSACTION_ACTIVE = UNKNOWN; + + /** + * @var int + * @cname PGSQL_TRANSACTION_INTRANS + */ + public const TRANSACTION_INTRANS = UNKNOWN; + + /** + * @var int + * @cname PGSQL_TRANSACTION_INERROR + */ + public const TRANSACTION_INERROR = UNKNOWN; + + /** + * @var int + * @cname PGSQL_TRANSACTION_UNKNOWN + */ + public const TRANSACTION_UNKNOWN = UNKNOWN; + public function escapeIdentifier(string $input): string {} - // This is a comment -// /** @tentative-return-type */ -// public function pgsqlCopyFromArray(string $tableName, array $rows, string $separator = "\t", string $nullAs = "\\\\N", ?string $fields = null): bool {} -// -// /** @tentative-return-type */ -// public function pgsqlCopyFromFile(string $tableName, string $filename, string $separator = "\t", string $nullAs = "\\\\N", ?string $fields = null): bool {} -// -// /** @tentative-return-type */ -// public function pgsqlCopyToArray(string $tableName, string $separator = "\t", string $nullAs = "\\\\N", ?string $fields = null): array|false {} -// -// /** @tentative-return-type */ -// public function pgsqlCopyToFile(string $tableName, string $filename, string $separator = "\t", string $nullAs = "\\\\N", ?string $fields = null): bool {} -// -// /** @tentative-return-type */ -// public function pgsqlLOBCreate(): string|false {} -// -// /** @return resource|false */ -// public function pgsqlLOBOpen(string $oid, string $mode = "rb") {} -// -// /** @tentative-return-type */ -// public function pgsqlLOBUnlink(string $oid): bool {} -// -// /** @tentative-return-type */ -// public function pgsqlGetNotify(int $fetchMode = PDO::FETCH_USE_DEFAULT, int $timeoutMilliseconds = 0): array|false {} -// -// /** @tentative-return-type */ -// public function pgsqlGetPid(): int {} + public function copyFromArray(string $tableName, array $rows, 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 {} + + public function copyToArray(string $tableName, string $separator = "\t", string $nullAs = "\\\\N", ?string $fields = null): array|false {} + + public function copyToFile(string $tableName, string $filename, string $separator = "\t", string $nullAs = "\\\\N", ?string $fields = null): bool {} + + public function lobCreate(): string|false {} + + // Opens an existing large object stream. Must be called inside a transaction. + /** @return resource|false */ + public function lobOpen(string $oid, string $mode = "rb"){} + + public function lobUnlink(string $oid): bool {} + + public function getNotify(int $fetchMode = PDO::FETCH_USE_DEFAULT, int $timeoutMilliseconds = 0): array|false {} + + public function getPid(): int {} } diff --git a/ext/pdo_pgsql/pdo_pgsql_arginfo.h b/ext/pdo_pgsql/pdo_pgsql_arginfo.h index 23fa27825710f..9ec54b40312dd 100644 --- a/ext/pdo_pgsql/pdo_pgsql_arginfo.h +++ b/ext/pdo_pgsql/pdo_pgsql_arginfo.h @@ -1,16 +1,79 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 7aa8f420e9fb24633be2f72a061b32f4d9207620 */ + * Stub hash: 72f5729365dc3f7ae888e96b612ef9b236da2135 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PDOPgSql_escapeIdentifier, 0, 1, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, input, IS_STRING, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PDOPgSql_copyFromArray, 0, 2, _IS_BOOL, 0) + ZEND_ARG_TYPE_INFO(0, tableName, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, rows, IS_ARRAY, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, separator, IS_STRING, 0, "\"\\t\"") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, nullAs, IS_STRING, 0, "\"\\\\\\\\N\"") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, fields, IS_STRING, 1, "null") +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PDOPgSql_copyFromFile, 0, 2, _IS_BOOL, 0) + ZEND_ARG_TYPE_INFO(0, tableName, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, filename, IS_STRING, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, separator, IS_STRING, 0, "\"\\t\"") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, nullAs, IS_STRING, 0, "\"\\\\\\\\N\"") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, fields, IS_STRING, 1, "null") +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_PDOPgSql_copyToArray, 0, 1, MAY_BE_ARRAY|MAY_BE_FALSE) + ZEND_ARG_TYPE_INFO(0, tableName, IS_STRING, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, separator, IS_STRING, 0, "\"\\t\"") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, nullAs, IS_STRING, 0, "\"\\\\\\\\N\"") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, fields, IS_STRING, 1, "null") +ZEND_END_ARG_INFO() + +#define arginfo_class_PDOPgSql_copyToFile arginfo_class_PDOPgSql_copyFromFile + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_PDOPgSql_lobCreate, 0, 0, MAY_BE_STRING|MAY_BE_FALSE) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_class_PDOPgSql_lobOpen, 0, 0, 1) + ZEND_ARG_TYPE_INFO(0, oid, IS_STRING, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, mode, IS_STRING, 0, "\"rb\"") +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PDOPgSql_lobUnlink, 0, 1, _IS_BOOL, 0) + ZEND_ARG_TYPE_INFO(0, oid, IS_STRING, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_PDOPgSql_getNotify, 0, 0, MAY_BE_ARRAY|MAY_BE_FALSE) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, fetchMode, IS_LONG, 0, "PDO::FETCH_USE_DEFAULT") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, timeoutMilliseconds, IS_LONG, 0, "0") +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PDOPgSql_getPid, 0, 0, IS_LONG, 0) +ZEND_END_ARG_INFO() + ZEND_METHOD(PDOPgSql, escapeIdentifier); +ZEND_METHOD(PDOPgSql, copyFromArray); +ZEND_METHOD(PDOPgSql, copyFromFile); +ZEND_METHOD(PDOPgSql, copyToArray); +ZEND_METHOD(PDOPgSql, copyToFile); +ZEND_METHOD(PDOPgSql, lobCreate); +ZEND_METHOD(PDOPgSql, lobOpen); +ZEND_METHOD(PDOPgSql, lobUnlink); +ZEND_METHOD(PDOPgSql, getNotify); +ZEND_METHOD(PDOPgSql, getPid); static const zend_function_entry class_PDOPgSql_methods[] = { ZEND_ME(PDOPgSql, escapeIdentifier, arginfo_class_PDOPgSql_escapeIdentifier, ZEND_ACC_PUBLIC) + ZEND_ME(PDOPgSql, copyFromArray, arginfo_class_PDOPgSql_copyFromArray, ZEND_ACC_PUBLIC) + ZEND_ME(PDOPgSql, copyFromFile, arginfo_class_PDOPgSql_copyFromFile, ZEND_ACC_PUBLIC) + ZEND_ME(PDOPgSql, copyToArray, arginfo_class_PDOPgSql_copyToArray, ZEND_ACC_PUBLIC) + ZEND_ME(PDOPgSql, copyToFile, arginfo_class_PDOPgSql_copyToFile, ZEND_ACC_PUBLIC) + ZEND_ME(PDOPgSql, lobCreate, arginfo_class_PDOPgSql_lobCreate, ZEND_ACC_PUBLIC) + ZEND_ME(PDOPgSql, lobOpen, arginfo_class_PDOPgSql_lobOpen, ZEND_ACC_PUBLIC) + ZEND_ME(PDOPgSql, lobUnlink, arginfo_class_PDOPgSql_lobUnlink, ZEND_ACC_PUBLIC) + ZEND_ME(PDOPgSql, getNotify, arginfo_class_PDOPgSql_getNotify, ZEND_ACC_PUBLIC) + ZEND_ME(PDOPgSql, getPid, arginfo_class_PDOPgSql_getPid, ZEND_ACC_PUBLIC) ZEND_FE_END }; @@ -22,5 +85,41 @@ static zend_class_entry *register_class_PDOPgSql(zend_class_entry *class_entry_P class_entry = zend_register_internal_class_ex(&ce, class_entry_PDO); class_entry->ce_flags |= ZEND_ACC_NOT_SERIALIZABLE; + zval const_ATTR_DISABLE_PREPARES_value; + ZVAL_LONG(&const_ATTR_DISABLE_PREPARES_value, PDO_PGSQL_ATTR_DISABLE_PREPARES); + zend_string *const_ATTR_DISABLE_PREPARES_name = zend_string_init_interned("ATTR_DISABLE_PREPARES", sizeof("ATTR_DISABLE_PREPARES") - 1, 1); + zend_declare_class_constant_ex(class_entry, const_ATTR_DISABLE_PREPARES_name, &const_ATTR_DISABLE_PREPARES_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_ATTR_DISABLE_PREPARES_name); + + zval const_TRANSACTION_IDLE_value; + ZVAL_LONG(&const_TRANSACTION_IDLE_value, PGSQL_TRANSACTION_IDLE); + zend_string *const_TRANSACTION_IDLE_name = zend_string_init_interned("TRANSACTION_IDLE", sizeof("TRANSACTION_IDLE") - 1, 1); + zend_declare_class_constant_ex(class_entry, const_TRANSACTION_IDLE_name, &const_TRANSACTION_IDLE_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_TRANSACTION_IDLE_name); + + zval const_TRANSACTION_ACTIVE_value; + ZVAL_LONG(&const_TRANSACTION_ACTIVE_value, PGSQL_TRANSACTION_ACTIVE); + zend_string *const_TRANSACTION_ACTIVE_name = zend_string_init_interned("TRANSACTION_ACTIVE", sizeof("TRANSACTION_ACTIVE") - 1, 1); + zend_declare_class_constant_ex(class_entry, const_TRANSACTION_ACTIVE_name, &const_TRANSACTION_ACTIVE_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_TRANSACTION_ACTIVE_name); + + zval const_TRANSACTION_INTRANS_value; + ZVAL_LONG(&const_TRANSACTION_INTRANS_value, PGSQL_TRANSACTION_INTRANS); + zend_string *const_TRANSACTION_INTRANS_name = zend_string_init_interned("TRANSACTION_INTRANS", sizeof("TRANSACTION_INTRANS") - 1, 1); + zend_declare_class_constant_ex(class_entry, const_TRANSACTION_INTRANS_name, &const_TRANSACTION_INTRANS_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_TRANSACTION_INTRANS_name); + + zval const_TRANSACTION_INERROR_value; + ZVAL_LONG(&const_TRANSACTION_INERROR_value, PGSQL_TRANSACTION_INERROR); + zend_string *const_TRANSACTION_INERROR_name = zend_string_init_interned("TRANSACTION_INERROR", sizeof("TRANSACTION_INERROR") - 1, 1); + zend_declare_class_constant_ex(class_entry, const_TRANSACTION_INERROR_name, &const_TRANSACTION_INERROR_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_TRANSACTION_INERROR_name); + + zval const_TRANSACTION_UNKNOWN_value; + ZVAL_LONG(&const_TRANSACTION_UNKNOWN_value, PGSQL_TRANSACTION_UNKNOWN); + zend_string *const_TRANSACTION_UNKNOWN_name = zend_string_init_interned("TRANSACTION_UNKNOWN", sizeof("TRANSACTION_UNKNOWN") - 1, 1); + zend_declare_class_constant_ex(class_entry, const_TRANSACTION_UNKNOWN_name, &const_TRANSACTION_UNKNOWN_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_TRANSACTION_UNKNOWN_name); + return class_entry; } diff --git a/ext/pdo_pgsql/pdo_pgsql_class.c b/ext/pdo_pgsql/pdo_pgsql_class.c index 1c6fccca3f710..03d739aa8449f 100644 --- a/ext/pdo_pgsql/pdo_pgsql_class.c +++ b/ext/pdo_pgsql/pdo_pgsql_class.c @@ -30,25 +30,6 @@ #include "php_pdo_pgsql.h" #include "php_pdo_pgsql_int.h" -///* {{{ proto string PDO::mysqlGetWarningCount() -// Returns the number of SQL warnings during the execution of the last statement -//*/ -//PHP_METHOD(PDOMySql, getWarningCount) -//{ -// pdo_dbh_t *dbh; -// pdo_mysql_db_handle *H; -// -// dbh = Z_PDO_DBH_P(ZEND_THIS); -// PDO_CONSTRUCT_CHECK; -// -// H = (pdo_mysql_db_handle *)dbh->driver_data; -// RETURN_LONG(mysql_warning_count(H->server)); -//} -///* }}} */ - - - -// //static void php_pgsql_escape_internal(INTERNAL_FUNCTION_PARAMETERS, int escape_literal) /* {{{ */ { // zend_string *from = NULL; // zval *pgsql_link = NULL; @@ -131,7 +112,67 @@ PHP_METHOD(PDOPgSql, escapeIdentifier) /* }}} */ +/* {{{ Returns true if the copy worked fine or false if error */ +PHP_METHOD(PDOPgSql, copyFromArray) +{ + pgsqlCopyFromArray_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} +/* }}} */ + + +/* {{{ Returns true if the copy worked fine or false if error */ +PHP_METHOD(PDOPgSql, copyFromFile) +{ + pgsqlCopyFromFile_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} +/* }}} */ + +/* {{{ Returns true if the copy worked fine or false if error */ +PHP_METHOD(PDOPgSql, copyToFile) +{ + pgsqlCopyToFile_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU); + +} +/* }}} */ + +/* {{{ Returns true if the copy worked fine or false if error */ +PHP_METHOD(PDOPgSql, copyToArray) +{ + pgsqlCopyToArray_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} +/* }}} */ + +/* {{{ Creates a new large object, returning its identifier. Must be called inside a transaction. */ +PHP_METHOD(PDOPgSql, lobCreate) +{ + pgsqlLOBCreate_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} +/* }}} */ +/* {{{ Opens an existing large object stream. Must be called inside a transaction. */ +PHP_METHOD(PDOPgSql, lobOpen) +{ + pgsqlLOBOpen_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} +/* }}} */ +/* {{{ Deletes the large object identified by oid. Must be called inside a transaction. */ +PHP_METHOD(PDOPgSql, lobUnlink) +{ + pgsqlLOBUnlink_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} +/* }}} */ +/* {{{ Get asynchronous notification */ +PHP_METHOD(PDOPgSql, getNotify) +{ + pgsqlGetNotify_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} +/* }}} */ +/* {{{ Get backend(server) pid */ +PHP_METHOD(PDOPgSql, getPid) +{ + pgsqlGetPid_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} +/* }}} */ diff --git a/ext/pdo_pgsql/pgsql_driver.c b/ext/pdo_pgsql/pgsql_driver.c index 54bf7ede6bfaa..41d99ad81ab14 100644 --- a/ext/pdo_pgsql/pgsql_driver.c +++ b/ext/pdo_pgsql/pgsql_driver.c @@ -550,8 +550,7 @@ static bool pgsql_handle_rollback(pdo_dbh_t *dbh) return pdo_pgsql_transaction_cmd("ROLLBACK", dbh); } -/* {{{ Returns true if the copy worked fine or false if error */ -PHP_METHOD(PDO_PGSql_Ext, pgsqlCopyFromArray) +void pgsqlCopyFromArray_internal(INTERNAL_FUNCTION_PARAMETERS) { pdo_dbh_t *dbh; pdo_pgsql_db_handle *H; @@ -661,10 +660,15 @@ PHP_METHOD(PDO_PGSql_Ext, pgsqlCopyFromArray) RETURN_FALSE; } } -/* }}} */ /* {{{ Returns true if the copy worked fine or false if error */ -PHP_METHOD(PDO_PGSql_Ext, pgsqlCopyFromFile) +PHP_METHOD(PDO_PGSql_Ext, pgsqlCopyFromArray) +{ + pgsqlCopyFromArray_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} +/* }}} */ + +void pgsqlCopyFromFile_internal(INTERNAL_FUNCTION_PARAMETERS) { pdo_dbh_t *dbh; pdo_pgsql_db_handle *H; @@ -758,11 +762,15 @@ PHP_METHOD(PDO_PGSql_Ext, pgsqlCopyFromFile) RETURN_FALSE; } } -/* }}} */ - /* {{{ Returns true if the copy worked fine or false if error */ -PHP_METHOD(PDO_PGSql_Ext, pgsqlCopyToFile) +PHP_METHOD(PDO_PGSql_Ext, pgsqlCopyFromFile) +{ + pgsqlCopyFromFile_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} +/* }}} */ + +void pgsqlCopyToFile_internal(INTERNAL_FUNCTION_PARAMETERS) { pdo_dbh_t *dbh; pdo_pgsql_db_handle *H; @@ -853,10 +861,16 @@ PHP_METHOD(PDO_PGSql_Ext, pgsqlCopyToFile) RETURN_FALSE; } } -/* }}} */ /* {{{ Returns true if the copy worked fine or false if error */ -PHP_METHOD(PDO_PGSql_Ext, pgsqlCopyToArray) +PHP_METHOD(PDO_PGSql_Ext, pgsqlCopyToFile) +{ + pgsqlCopyToFile_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU); + +} +/* }}} */ + +void pgsqlCopyToArray_internal(INTERNAL_FUNCTION_PARAMETERS) { pdo_dbh_t *dbh; pdo_pgsql_db_handle *H; @@ -928,11 +942,15 @@ PHP_METHOD(PDO_PGSql_Ext, pgsqlCopyToArray) RETURN_FALSE; } } -/* }}} */ +/* {{{ Returns true if the copy worked fine or false if error */ +PHP_METHOD(PDO_PGSql_Ext, pgsqlCopyToArray) +{ + pgsqlCopyToArray_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} +/* }}} */ -/* {{{ Creates a new large object, returning its identifier. Must be called inside a transaction. */ -PHP_METHOD(PDO_PGSql_Ext, pgsqlLOBCreate) +void pgsqlLOBCreate_internal(INTERNAL_FUNCTION_PARAMETERS) { pdo_dbh_t *dbh; pdo_pgsql_db_handle *H; @@ -957,10 +975,15 @@ PHP_METHOD(PDO_PGSql_Ext, pgsqlLOBCreate) PDO_HANDLE_DBH_ERR(); RETURN_FALSE; } + +/* {{{ Creates a new large object, returning its identifier. Must be called inside a transaction. */ +PHP_METHOD(PDO_PGSql_Ext, pgsqlLOBCreate) +{ + pgsqlLOBCreate_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} /* }}} */ -/* {{{ Opens an existing large object stream. Must be called inside a transaction. */ -PHP_METHOD(PDO_PGSql_Ext, pgsqlLOBOpen) +void pgsqlLOBOpen_internal(INTERNAL_FUNCTION_PARAMETERS) { pdo_dbh_t *dbh; pdo_pgsql_db_handle *H; @@ -1008,10 +1031,15 @@ PHP_METHOD(PDO_PGSql_Ext, pgsqlLOBOpen) PDO_HANDLE_DBH_ERR(); RETURN_FALSE; } + +/* {{{ Opens an existing large object stream. Must be called inside a transaction. */ +PHP_METHOD(PDO_PGSql_Ext, pgsqlLOBOpen) +{ + pgsqlLOBOpen_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} /* }}} */ -/* {{{ Deletes the large object identified by oid. Must be called inside a transaction. */ -PHP_METHOD(PDO_PGSql_Ext, pgsqlLOBUnlink) +void pgsqlLOBUnlink_internal(INTERNAL_FUNCTION_PARAMETERS) { pdo_dbh_t *dbh; pdo_pgsql_db_handle *H; @@ -1043,10 +1071,15 @@ PHP_METHOD(PDO_PGSql_Ext, pgsqlLOBUnlink) PDO_HANDLE_DBH_ERR(); RETURN_FALSE; } + +/* {{{ Deletes the large object identified by oid. Must be called inside a transaction. */ +PHP_METHOD(PDO_PGSql_Ext, pgsqlLOBUnlink) +{ + pgsqlLOBUnlink_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} /* }}} */ -/* {{{ Get asynchronous notification */ -PHP_METHOD(PDO_PGSql_Ext, pgsqlGetNotify) +void pgsqlGetNotify_internal(INTERNAL_FUNCTION_PARAMETERS) { pdo_dbh_t *dbh; pdo_pgsql_db_handle *H; @@ -1123,10 +1156,15 @@ PHP_METHOD(PDO_PGSql_Ext, pgsqlGetNotify) PQfreemem(pgsql_notify); } + +/* {{{ Get asynchronous notification */ +PHP_METHOD(PDO_PGSql_Ext, pgsqlGetNotify) +{ + pgsqlGetNotify_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} /* }}} */ -/* {{{ Get backend(server) pid */ -PHP_METHOD(PDO_PGSql_Ext, pgsqlGetPid) +void pgsqlGetPid_internal(INTERNAL_FUNCTION_PARAMETERS) { pdo_dbh_t *dbh; pdo_pgsql_db_handle *H; @@ -1140,6 +1178,12 @@ PHP_METHOD(PDO_PGSql_Ext, pgsqlGetPid) RETURN_LONG(PQbackendPID(H->server)); } + +/* {{{ Get backend(server) pid */ +PHP_METHOD(PDO_PGSql_Ext, pgsqlGetPid) +{ + pgsqlGetPid_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} /* }}} */ static const zend_function_entry *pdo_pgsql_get_driver_methods(pdo_dbh_t *dbh, int kind) diff --git a/ext/pdo_pgsql/php_pdo_pgsql_int.h b/ext/pdo_pgsql/php_pdo_pgsql_int.h index 8ef8b68138489..5e40c44596edd 100644 --- a/ext/pdo_pgsql/php_pdo_pgsql_int.h +++ b/ext/pdo_pgsql/php_pdo_pgsql_int.h @@ -107,4 +107,14 @@ extern const php_stream_ops pdo_pgsql_lob_stream_ops; void pdo_libpq_version(char *buf, size_t len); +void pgsqlCopyFromArray_internal(INTERNAL_FUNCTION_PARAMETERS); +void pgsqlCopyFromFile_internal(INTERNAL_FUNCTION_PARAMETERS); +void pgsqlCopyToArray_internal(INTERNAL_FUNCTION_PARAMETERS); +void pgsqlCopyToFile_internal(INTERNAL_FUNCTION_PARAMETERS); +void pgsqlLOBCreate_internal(INTERNAL_FUNCTION_PARAMETERS); +void pgsqlLOBOpen_internal(INTERNAL_FUNCTION_PARAMETERS); +void pgsqlLOBUnlink_internal(INTERNAL_FUNCTION_PARAMETERS); +void pgsqlGetNotify_internal(INTERNAL_FUNCTION_PARAMETERS); +void pgsqlGetPid_internal(INTERNAL_FUNCTION_PARAMETERS); + #endif /* PHP_PDO_PGSQL_INT_H */ From 8803312105282709d3ee6a1d1bc9d3c5afd70edb Mon Sep 17 00:00:00 2001 From: Danack Date: Mon, 3 Jul 2023 12:15:14 +0100 Subject: [PATCH 22/35] Standardized class names. --- ext/pdo_dblib/pdo_dblib.c | 14 ++-- ext/pdo_dblib/pdo_dblib.stub.php | 2 +- ext/pdo_dblib/pdo_dblib_arginfo.h | 6 +- ext/pdo_firebird/pdo_firebird.c | 14 ++-- ext/pdo_firebird/pdo_firebird.stub.php | 4 +- ext/pdo_firebird/pdo_firebird_arginfo.h | 6 +- .../tests/subclassing/pdofirebird_001.phpt | 10 +-- .../tests/subclassing/pdofirebird_002.phpt | 10 +-- ext/pdo_mysql/pdo_mysql.c | 2 +- ext/pdo_mysql/pdo_mysql.stub.php | 2 +- ext/pdo_mysql/pdo_mysql_arginfo.h | 12 +-- ext/pdo_mysql/pdo_mysql_class.c | 2 +- ext/pdo_oci/pdo_oci.c | 2 +- ext/pdo_oci/pdo_oci.stub.php | 5 +- ext/pdo_oci/pdo_oci_arginfo.h | 6 +- ext/pdo_odbc/pdo_odbc.c | 2 +- ext/pdo_odbc/pdo_odbc.stub.php | 4 +- ext/pdo_odbc/pdo_odbc_arginfo.h | 6 +- ext/pdo_pgsql/pdo_pgsql.c | 18 ++--- ext/pdo_pgsql/pdo_pgsql.stub.php | 3 +- ext/pdo_pgsql/pdo_pgsql_arginfo.h | 70 +++++++++--------- ext/pdo_pgsql/pdo_pgsql_class.c | 20 ++--- .../tests/subclassing/pdopgsql_001.phpt | 12 +-- .../tests/subclassing/pdopgsql_002.phpt | 14 ++-- .../tests/subclassing/pdopgsql_003.phpt | 10 +-- ext/pdo_sqlite/pdo_sqlite.c | 2 +- ext/pdo_sqlite/pdo_sqlite.stub.php | 74 ++++++++++++++----- ext/pdo_sqlite/pdo_sqlite_arginfo.h | 36 ++++----- ext/pdo_sqlite/pdo_sqlite_class.c | 27 +++---- .../pdo_sqlite_createaggregate_002.phpt | 4 +- .../tests/subclasses/pdosqlite_001.phpt | 2 +- .../tests/subclasses/pdosqlite_002.phpt | 2 +- .../tests/subclasses/pdosqlite_003.phpt | 2 +- .../subclasses/pdosqlite_004_blobopen.phpt | 2 +- 34 files changed, 219 insertions(+), 188 deletions(-) diff --git a/ext/pdo_dblib/pdo_dblib.c b/ext/pdo_dblib/pdo_dblib.c index 27a1c5eef520a..7b1f7b5d63477 100644 --- a/ext/pdo_dblib/pdo_dblib.c +++ b/ext/pdo_dblib/pdo_dblib.c @@ -32,8 +32,8 @@ ZEND_DECLARE_MODULE_GLOBALS(dblib) static PHP_GINIT_FUNCTION(dblib); -zend_class_entry *pdodblib_ce; -static pdo_driver_class_entry pdodblib_pdo_driver_class_entry; +zend_class_entry *PdoDblib_ce; +static pdo_driver_class_entry PdoDblib_pdo_driver_class_entry; static const zend_module_dep pdo_dblib_deps[] = { ZEND_MOD_REQUIRED("pdo") @@ -205,12 +205,12 @@ PHP_MINIT_FUNCTION(pdo_dblib) return FAILURE; } - pdodblib_ce = register_class_PDODBLIB(pdo_dbh_ce); - pdodblib_ce->create_object = pdo_dbh_new; + PdoDblib_ce = register_class_PdoDblib(pdo_dbh_ce); + PdoDblib_ce->create_object = pdo_dbh_new; - pdodblib_pdo_driver_class_entry.driver_name = "dblib"; - pdodblib_pdo_driver_class_entry.driver_ce = pdodblib_ce; - pdo_register_driver_specific_class(&pdodblib_pdo_driver_class_entry); + PdoDblib_pdo_driver_class_entry.driver_name = "dblib"; + PdoDblib_pdo_driver_class_entry.driver_ce = PdoDblib_ce; + pdo_register_driver_specific_class(&PdoDblib_pdo_driver_class_entry); if (FAILURE == php_pdo_register_driver(&pdo_dblib_driver)) { return FAILURE; diff --git a/ext/pdo_dblib/pdo_dblib.stub.php b/ext/pdo_dblib/pdo_dblib.stub.php index 1804e5bd3b9b2..2556fb639cfa1 100644 --- a/ext/pdo_dblib/pdo_dblib.stub.php +++ b/ext/pdo_dblib/pdo_dblib.stub.php @@ -3,7 +3,7 @@ /** @generate-class-entries */ /** @not-serializable */ -class PDODBLIB extends PDO +class PdoDblib extends PDO { } diff --git a/ext/pdo_dblib/pdo_dblib_arginfo.h b/ext/pdo_dblib/pdo_dblib_arginfo.h index 9919f0be3200a..f6a6b3660df51 100644 --- a/ext/pdo_dblib/pdo_dblib_arginfo.h +++ b/ext/pdo_dblib/pdo_dblib_arginfo.h @@ -4,15 +4,15 @@ -static const zend_function_entry class_PDODBLIB_methods[] = { +static const zend_function_entry class_PdoDblib_methods[] = { ZEND_FE_END }; -static zend_class_entry *register_class_PDODBLIB(zend_class_entry *class_entry_PDO) +static zend_class_entry *register_class_PdoDblib(zend_class_entry *class_entry_PDO) { zend_class_entry ce, *class_entry; - INIT_CLASS_ENTRY(ce, "PDODBLIB", class_PDODBLIB_methods); + INIT_CLASS_ENTRY(ce, "PdoDblib", class_PdoDblib_methods); class_entry = zend_register_internal_class_ex(&ce, class_entry_PDO); class_entry->ce_flags |= ZEND_ACC_NOT_SERIALIZABLE; diff --git a/ext/pdo_firebird/pdo_firebird.c b/ext/pdo_firebird/pdo_firebird.c index 9b99cf2cbf84b..4494617a441a8 100644 --- a/ext/pdo_firebird/pdo_firebird.c +++ b/ext/pdo_firebird/pdo_firebird.c @@ -27,8 +27,8 @@ #include "php_pdo_firebird_int.h" #include "pdo_firebird_arginfo.h" -zend_class_entry *pdofirebird_ce; -static pdo_driver_class_entry pdofirebird_pdo_driver_class_entry; +zend_class_entry *PdoFirebird_ce; +static pdo_driver_class_entry PdoFirebird_pdo_driver_class_entry; /* {{{ pdo_firebird_deps */ static const zend_module_dep pdo_firebird_deps[] = { @@ -66,12 +66,12 @@ PHP_MINIT_FUNCTION(pdo_firebird) /* {{{ */ return FAILURE; } - pdofirebird_ce = register_class_PDOFirebird(pdo_dbh_ce); - pdofirebird_ce->create_object = pdo_dbh_new; + PdoFirebird_ce = register_class_PdoFirebird(pdo_dbh_ce); + PdoFirebird_ce->create_object = pdo_dbh_new; - pdofirebird_pdo_driver_class_entry.driver_name = "firebird"; - pdofirebird_pdo_driver_class_entry.driver_ce = pdofirebird_ce; - pdo_register_driver_specific_class(&pdofirebird_pdo_driver_class_entry); + PdoFirebird_pdo_driver_class_entry.driver_name = "firebird"; + PdoFirebird_pdo_driver_class_entry.driver_ce = PdoFirebird_ce; + pdo_register_driver_specific_class(&PdoFirebird_pdo_driver_class_entry); #ifdef ZEND_SIGNALS /* firebird replaces some signals at runtime, suppress warnings. */ diff --git a/ext/pdo_firebird/pdo_firebird.stub.php b/ext/pdo_firebird/pdo_firebird.stub.php index 0b350de84b073..9b1501b58ed5e 100644 --- a/ext/pdo_firebird/pdo_firebird.stub.php +++ b/ext/pdo_firebird/pdo_firebird.stub.php @@ -3,7 +3,7 @@ /** @generate-class-entries */ /** @not-serializable */ -class PDOFirebird extends PDO +class PdoFirebird extends PDO { - // not methods asdad + } diff --git a/ext/pdo_firebird/pdo_firebird_arginfo.h b/ext/pdo_firebird/pdo_firebird_arginfo.h index a451b69a1ab94..73f6f5fa172ea 100644 --- a/ext/pdo_firebird/pdo_firebird_arginfo.h +++ b/ext/pdo_firebird/pdo_firebird_arginfo.h @@ -4,15 +4,15 @@ -static const zend_function_entry class_PDOFirebird_methods[] = { +static const zend_function_entry class_PdoFirebird_methods[] = { ZEND_FE_END }; -static zend_class_entry *register_class_PDOFirebird(zend_class_entry *class_entry_PDO) +static zend_class_entry *register_class_PdoFirebird(zend_class_entry *class_entry_PDO) { zend_class_entry ce, *class_entry; - INIT_CLASS_ENTRY(ce, "PDOFirebird", class_PDOFirebird_methods); + INIT_CLASS_ENTRY(ce, "PdoFirebird", class_PdoFirebird_methods); class_entry = zend_register_internal_class_ex(&ce, class_entry_PDO); class_entry->ce_flags |= ZEND_ACC_NOT_SERIALIZABLE; diff --git a/ext/pdo_firebird/tests/subclassing/pdofirebird_001.phpt b/ext/pdo_firebird/tests/subclassing/pdofirebird_001.phpt index 4cd63aec1c808..6adafff9c1ddd 100644 --- a/ext/pdo_firebird/tests/subclassing/pdofirebird_001.phpt +++ b/ext/pdo_firebird/tests/subclassing/pdofirebird_001.phpt @@ -7,16 +7,16 @@ pdo_firebird require_once __DIR__ . "/../config_functions.inc"; -if (class_exists(PDOFirebird::class) === false) { - echo "PDOFirebird class does not exist.\n"; +if (class_exists(PdoFirebird::class) === false) { + echo "PdoFirebird class does not exist.\n"; exit(-1); } -echo "PDOFirebird class exists.\n"; +echo "PdoFirebird class exists.\n"; [$dsn, $user, $pass] = getDsnUserAndPassword(); -$db = new PDOFirebird($dsn, $user, $pass); +$db = new PdoFirebird($dsn, $user, $pass); $db->query('RECREATE TABLE foobar (idx int NOT NULL PRIMARY KEY, name VARCHAR(20))'); $db->query("INSERT INTO foobar VALUES (1, 'PHP')"); @@ -31,7 +31,7 @@ $db->query('DROP TABLE foobar'); echo "Fin."; ?> --EXPECT-- -PDOFirebird class exists. +PdoFirebird class exists. array(2) { ["NAME"]=> string(3) "PHP" diff --git a/ext/pdo_firebird/tests/subclassing/pdofirebird_002.phpt b/ext/pdo_firebird/tests/subclassing/pdofirebird_002.phpt index 64e0ea201cea5..e425975038eb9 100644 --- a/ext/pdo_firebird/tests/subclassing/pdofirebird_002.phpt +++ b/ext/pdo_firebird/tests/subclassing/pdofirebird_002.phpt @@ -7,18 +7,18 @@ PDO_odbc require_once __DIR__ . "/../config_functions.inc"; -if (class_exists(PDOFirebird::class) === false) { - echo "PDOFirebird class does not exist.\n"; +if (class_exists(PdoFirebird::class) === false) { + echo "PdoFirebird class does not exist.\n"; exit(-1); } -echo "PDOFirebird class exists.\n"; +echo "PdoFirebird class exists.\n"; [$dsn, $user, $pass] = getDsnUserAndPassword(); $db = Pdo::connect($dsn, $user, $pass); -if (!$db instanceof PDOFirebird) { +if (!$db instanceof PdoFirebird) { echo "Wrong class type. Should be PdoOdbc but is [" . get_class($db) . "\n"; } @@ -37,7 +37,7 @@ $db->query('DROP TABLE test'); echo "Fin."; ?> --EXPECT-- -PDOFirebird class exists. +PdoFirebird class exists. array(2) { ["NAME"]=> string(1) "A" diff --git a/ext/pdo_mysql/pdo_mysql.c b/ext/pdo_mysql/pdo_mysql.c index 4f3720ad2a569..83d2e9db5652a 100644 --- a/ext/pdo_mysql/pdo_mysql.c +++ b/ext/pdo_mysql/pdo_mysql.c @@ -136,7 +136,7 @@ static PHP_MINIT_FUNCTION(pdo_mysql) mysqlnd_reverse_api_register_api(&pdo_mysql_reverse_api); #endif - pdomysql_ce = register_class_PDOMySql(pdo_dbh_ce); + pdomysql_ce = register_class_PdoMysql(pdo_dbh_ce); pdomysql_ce->create_object = pdo_dbh_new; pdomysql_pdo_driver_class_entry.driver_name = "mysql"; diff --git a/ext/pdo_mysql/pdo_mysql.stub.php b/ext/pdo_mysql/pdo_mysql.stub.php index 82d95a83f8420..8759d98ba1aa4 100644 --- a/ext/pdo_mysql/pdo_mysql.stub.php +++ b/ext/pdo_mysql/pdo_mysql.stub.php @@ -3,7 +3,7 @@ /** @generate-class-entries */ /** @not-serializable */ -class PDOMySql extends PDO +class PdoMysql extends PDO { public function getWarningCount(): int {} } diff --git a/ext/pdo_mysql/pdo_mysql_arginfo.h b/ext/pdo_mysql/pdo_mysql_arginfo.h index 7e347c88078af..d8ef744c019ea 100644 --- a/ext/pdo_mysql/pdo_mysql_arginfo.h +++ b/ext/pdo_mysql/pdo_mysql_arginfo.h @@ -1,23 +1,23 @@ /* This is a generated file, edit the .stub.php file instead. * Stub hash: 0b4ccc19bba532b56c7b6936a01bfccc4a7bea79 */ -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PDOMySql_getWarningCount, 0, 0, IS_LONG, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PdoMysql_getWarningCount, 0, 0, IS_LONG, 0) ZEND_END_ARG_INFO() -ZEND_METHOD(PDOMySql, getWarningCount); +ZEND_METHOD(PdoMysql, getWarningCount); -static const zend_function_entry class_PDOMySql_methods[] = { - ZEND_ME(PDOMySql, getWarningCount, arginfo_class_PDOMySql_getWarningCount, ZEND_ACC_PUBLIC) +static const zend_function_entry class_PdoMysql_methods[] = { + ZEND_ME(PdoMysql, getWarningCount, arginfo_class_PdoMysql_getWarningCount, ZEND_ACC_PUBLIC) ZEND_FE_END }; -static zend_class_entry *register_class_PDOMySql(zend_class_entry *class_entry_PDO) +static zend_class_entry *register_class_PdoMysql(zend_class_entry *class_entry_PDO) { zend_class_entry ce, *class_entry; - INIT_CLASS_ENTRY(ce, "PDOMySql", class_PDOMySql_methods); + INIT_CLASS_ENTRY(ce, "PdoMysql", class_PdoMysql_methods); class_entry = zend_register_internal_class_ex(&ce, class_entry_PDO); class_entry->ce_flags |= ZEND_ACC_NOT_SERIALIZABLE; diff --git a/ext/pdo_mysql/pdo_mysql_class.c b/ext/pdo_mysql/pdo_mysql_class.c index 9be995a9c5eeb..083dcb8b3a845 100644 --- a/ext/pdo_mysql/pdo_mysql_class.c +++ b/ext/pdo_mysql/pdo_mysql_class.c @@ -33,7 +33,7 @@ /* {{{ proto string PDO::mysqlGetWarningCount() Returns the number of SQL warnings during the execution of the last statement */ -PHP_METHOD(PDOMySql, getWarningCount) +PHP_METHOD(PdoMysql, getWarningCount) { pdo_dbh_t *dbh; pdo_mysql_db_handle *H; diff --git a/ext/pdo_oci/pdo_oci.c b/ext/pdo_oci/pdo_oci.c index 4d9f9b4562c8c..7bb4da0a556c3 100644 --- a/ext/pdo_oci/pdo_oci.c +++ b/ext/pdo_oci/pdo_oci.c @@ -99,7 +99,7 @@ PHP_MINIT_FUNCTION(pdo_oci) // Defer OCI init to PHP_RINIT_FUNCTION because with php-fpm, // NLS_LANG is not yet available here. - pdooci_ce = register_class_PDOOci(pdo_dbh_ce); + pdooci_ce = register_class_PdoOci(pdo_dbh_ce); pdooci_ce->create_object = pdo_dbh_new; pdooci_pdo_driver_class_entry.driver_name = "oci"; diff --git a/ext/pdo_oci/pdo_oci.stub.php b/ext/pdo_oci/pdo_oci.stub.php index b33d464016577..b1db5d64c4075 100644 --- a/ext/pdo_oci/pdo_oci.stub.php +++ b/ext/pdo_oci/pdo_oci.stub.php @@ -3,8 +3,7 @@ /** @generate-class-entries */ /** @not-serializable */ -class PDOOci extends PDO +class PdoOci extends PDO { - // no methods -// public function foo(): int {} + } diff --git a/ext/pdo_oci/pdo_oci_arginfo.h b/ext/pdo_oci/pdo_oci_arginfo.h index 90abcaf1966a0..90920d257fa3a 100644 --- a/ext/pdo_oci/pdo_oci_arginfo.h +++ b/ext/pdo_oci/pdo_oci_arginfo.h @@ -4,15 +4,15 @@ -static const zend_function_entry class_PDOOci_methods[] = { +static const zend_function_entry class_PdoOci_methods[] = { ZEND_FE_END }; -static zend_class_entry *register_class_PDOOci(zend_class_entry *class_entry_PDO) +static zend_class_entry *register_class_PdoOci(zend_class_entry *class_entry_PDO) { zend_class_entry ce, *class_entry; - INIT_CLASS_ENTRY(ce, "PDOOci", class_PDOOci_methods); + INIT_CLASS_ENTRY(ce, "PdoOci", class_PdoOci_methods); class_entry = zend_register_internal_class_ex(&ce, class_entry_PDO); class_entry->ce_flags |= ZEND_ACC_NOT_SERIALIZABLE; diff --git a/ext/pdo_odbc/pdo_odbc.c b/ext/pdo_odbc/pdo_odbc.c index 9f36bd20dc694..f015b00f8fb2c 100644 --- a/ext/pdo_odbc/pdo_odbc.c +++ b/ext/pdo_odbc/pdo_odbc.c @@ -106,7 +106,7 @@ PHP_MINIT_FUNCTION(pdo_odbc) REGISTER_PDO_CLASS_CONST_LONG("ODBC_SQL_USE_DRIVER", SQL_CUR_USE_DRIVER); REGISTER_PDO_CLASS_CONST_LONG("ODBC_SQL_USE_ODBC", SQL_CUR_USE_ODBC); - pdoodbc_ce = register_class_PDOOdbc(pdo_dbh_ce); + pdoodbc_ce = register_class_PdoOdbc(pdo_dbh_ce); pdoodbc_ce->create_object = pdo_dbh_new; pdoodbc_pdo_driver_class_entry.driver_name = "odbc"; diff --git a/ext/pdo_odbc/pdo_odbc.stub.php b/ext/pdo_odbc/pdo_odbc.stub.php index 865820fdc6cd4..81f4e793e350a 100644 --- a/ext/pdo_odbc/pdo_odbc.stub.php +++ b/ext/pdo_odbc/pdo_odbc.stub.php @@ -3,7 +3,7 @@ /** @generate-class-entries */ /** @not-serializable */ -class PDOOdbc extends PDO +class PdoOdbc extends PDO { - // no methods + } diff --git a/ext/pdo_odbc/pdo_odbc_arginfo.h b/ext/pdo_odbc/pdo_odbc_arginfo.h index f6d64f05c49b6..f275ae72f2830 100644 --- a/ext/pdo_odbc/pdo_odbc_arginfo.h +++ b/ext/pdo_odbc/pdo_odbc_arginfo.h @@ -4,15 +4,15 @@ -static const zend_function_entry class_PDOOdbc_methods[] = { +static const zend_function_entry class_PdoOdbc_methods[] = { ZEND_FE_END }; -static zend_class_entry *register_class_PDOOdbc(zend_class_entry *class_entry_PDO) +static zend_class_entry *register_class_PdoOdbc(zend_class_entry *class_entry_PDO) { zend_class_entry ce, *class_entry; - INIT_CLASS_ENTRY(ce, "PDOOdbc", class_PDOOdbc_methods); + INIT_CLASS_ENTRY(ce, "PdoOdbc", class_PdoOdbc_methods); class_entry = zend_register_internal_class_ex(&ce, class_entry_PDO); class_entry->ce_flags |= ZEND_ACC_NOT_SERIALIZABLE; diff --git a/ext/pdo_pgsql/pdo_pgsql.c b/ext/pdo_pgsql/pdo_pgsql.c index e81157c7f9db8..db76df24078ca 100644 --- a/ext/pdo_pgsql/pdo_pgsql.c +++ b/ext/pdo_pgsql/pdo_pgsql.c @@ -27,14 +27,14 @@ #include "php_pdo_pgsql_int.h" #include "pdo_pgsql_arginfo.h" -#define REGISTER_PDOPGSQL_CLASS_CONST_LONG(const_name, value) \ +#define REGISTER_PdoPgsql_CLASS_CONST_LONG(const_name, value) \ zend_declare_class_constant_long(php_pdo_get_dbh_ce(), const_name, sizeof(const_name)-1, (zend_long)value); -#define REGISTER_PDOPGSQL_CLASS_CONST_STRING(const_name, value) \ +#define REGISTER_PdoPgsql_CLASS_CONST_STRING(const_name, value) \ zend_declare_class_constant_stringl(php_pdo_get_dbh_ce(), const_name, sizeof(const_name)-1, value, sizeof(value)-1); -zend_class_entry *pdopgsql_ce; -static pdo_driver_class_entry pdopgsql_pdo_driver_class_entry; +zend_class_entry *PdoPgsql_ce; +static pdo_driver_class_entry PdoPgsql_pdo_driver_class_entry; /* {{{ pdo_sqlite_deps */ static const zend_module_dep pdo_pgsql_deps[] = { @@ -75,12 +75,12 @@ PHP_MINIT_FUNCTION(pdo_pgsql) REGISTER_PDO_CLASS_CONST_LONG("PGSQL_TRANSACTION_INERROR", (zend_long)PGSQL_TRANSACTION_INERROR); REGISTER_PDO_CLASS_CONST_LONG("PGSQL_TRANSACTION_UNKNOWN", (zend_long)PGSQL_TRANSACTION_UNKNOWN); - pdopgsql_ce = register_class_PDOPgSql(pdo_dbh_ce); - pdopgsql_ce->create_object = pdo_dbh_new; + PdoPgsql_ce = register_class_PdoPgsql(pdo_dbh_ce); + PdoPgsql_ce->create_object = pdo_dbh_new; - pdopgsql_pdo_driver_class_entry.driver_name = "pgsql"; - pdopgsql_pdo_driver_class_entry.driver_ce = pdopgsql_ce; - pdo_register_driver_specific_class(&pdopgsql_pdo_driver_class_entry); + PdoPgsql_pdo_driver_class_entry.driver_name = "pgsql"; + PdoPgsql_pdo_driver_class_entry.driver_ce = PdoPgsql_ce; + pdo_register_driver_specific_class(&PdoPgsql_pdo_driver_class_entry); return php_pdo_register_driver(&pdo_pgsql_driver); } diff --git a/ext/pdo_pgsql/pdo_pgsql.stub.php b/ext/pdo_pgsql/pdo_pgsql.stub.php index 26088ed10beb1..af67a7638d720 100644 --- a/ext/pdo_pgsql/pdo_pgsql.stub.php +++ b/ext/pdo_pgsql/pdo_pgsql.stub.php @@ -3,9 +3,8 @@ /** @generate-class-entries */ /** @not-serializable */ -class PDOPgSql extends PDO +class PdoPgsql extends PDO { - /** * @var int * @cname PDO_PGSQL_ATTR_DISABLE_PREPARES diff --git a/ext/pdo_pgsql/pdo_pgsql_arginfo.h b/ext/pdo_pgsql/pdo_pgsql_arginfo.h index 9ec54b40312dd..85159ecc8064b 100644 --- a/ext/pdo_pgsql/pdo_pgsql_arginfo.h +++ b/ext/pdo_pgsql/pdo_pgsql_arginfo.h @@ -1,11 +1,11 @@ /* This is a generated file, edit the .stub.php file instead. * Stub hash: 72f5729365dc3f7ae888e96b612ef9b236da2135 */ -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PDOPgSql_escapeIdentifier, 0, 1, IS_STRING, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PdoPgsql_escapeIdentifier, 0, 1, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, input, IS_STRING, 0) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PDOPgSql_copyFromArray, 0, 2, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PdoPgsql_copyFromArray, 0, 2, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, tableName, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, rows, IS_ARRAY, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, separator, IS_STRING, 0, "\"\\t\"") @@ -13,7 +13,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PDOPgSql_copyFromArray, 0, ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, fields, IS_STRING, 1, "null") ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PDOPgSql_copyFromFile, 0, 2, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PdoPgsql_copyFromFile, 0, 2, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, tableName, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, filename, IS_STRING, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, separator, IS_STRING, 0, "\"\\t\"") @@ -21,67 +21,67 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PDOPgSql_copyFromFile, 0, ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, fields, IS_STRING, 1, "null") ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_PDOPgSql_copyToArray, 0, 1, MAY_BE_ARRAY|MAY_BE_FALSE) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_PdoPgsql_copyToArray, 0, 1, MAY_BE_ARRAY|MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, tableName, IS_STRING, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, separator, IS_STRING, 0, "\"\\t\"") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, nullAs, IS_STRING, 0, "\"\\\\\\\\N\"") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, fields, IS_STRING, 1, "null") ZEND_END_ARG_INFO() -#define arginfo_class_PDOPgSql_copyToFile arginfo_class_PDOPgSql_copyFromFile +#define arginfo_class_PdoPgsql_copyToFile arginfo_class_PdoPgsql_copyFromFile -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_PDOPgSql_lobCreate, 0, 0, MAY_BE_STRING|MAY_BE_FALSE) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_PdoPgsql_lobCreate, 0, 0, MAY_BE_STRING|MAY_BE_FALSE) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_class_PDOPgSql_lobOpen, 0, 0, 1) +ZEND_BEGIN_ARG_INFO_EX(arginfo_class_PdoPgsql_lobOpen, 0, 0, 1) ZEND_ARG_TYPE_INFO(0, oid, IS_STRING, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, mode, IS_STRING, 0, "\"rb\"") ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PDOPgSql_lobUnlink, 0, 1, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PdoPgsql_lobUnlink, 0, 1, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, oid, IS_STRING, 0) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_PDOPgSql_getNotify, 0, 0, MAY_BE_ARRAY|MAY_BE_FALSE) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_PdoPgsql_getNotify, 0, 0, MAY_BE_ARRAY|MAY_BE_FALSE) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, fetchMode, IS_LONG, 0, "PDO::FETCH_USE_DEFAULT") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, timeoutMilliseconds, IS_LONG, 0, "0") ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PDOPgSql_getPid, 0, 0, IS_LONG, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PdoPgsql_getPid, 0, 0, IS_LONG, 0) ZEND_END_ARG_INFO() -ZEND_METHOD(PDOPgSql, escapeIdentifier); -ZEND_METHOD(PDOPgSql, copyFromArray); -ZEND_METHOD(PDOPgSql, copyFromFile); -ZEND_METHOD(PDOPgSql, copyToArray); -ZEND_METHOD(PDOPgSql, copyToFile); -ZEND_METHOD(PDOPgSql, lobCreate); -ZEND_METHOD(PDOPgSql, lobOpen); -ZEND_METHOD(PDOPgSql, lobUnlink); -ZEND_METHOD(PDOPgSql, getNotify); -ZEND_METHOD(PDOPgSql, getPid); - - -static const zend_function_entry class_PDOPgSql_methods[] = { - ZEND_ME(PDOPgSql, escapeIdentifier, arginfo_class_PDOPgSql_escapeIdentifier, ZEND_ACC_PUBLIC) - ZEND_ME(PDOPgSql, copyFromArray, arginfo_class_PDOPgSql_copyFromArray, ZEND_ACC_PUBLIC) - ZEND_ME(PDOPgSql, copyFromFile, arginfo_class_PDOPgSql_copyFromFile, ZEND_ACC_PUBLIC) - ZEND_ME(PDOPgSql, copyToArray, arginfo_class_PDOPgSql_copyToArray, ZEND_ACC_PUBLIC) - ZEND_ME(PDOPgSql, copyToFile, arginfo_class_PDOPgSql_copyToFile, ZEND_ACC_PUBLIC) - ZEND_ME(PDOPgSql, lobCreate, arginfo_class_PDOPgSql_lobCreate, ZEND_ACC_PUBLIC) - ZEND_ME(PDOPgSql, lobOpen, arginfo_class_PDOPgSql_lobOpen, ZEND_ACC_PUBLIC) - ZEND_ME(PDOPgSql, lobUnlink, arginfo_class_PDOPgSql_lobUnlink, ZEND_ACC_PUBLIC) - ZEND_ME(PDOPgSql, getNotify, arginfo_class_PDOPgSql_getNotify, ZEND_ACC_PUBLIC) - ZEND_ME(PDOPgSql, getPid, arginfo_class_PDOPgSql_getPid, ZEND_ACC_PUBLIC) +ZEND_METHOD(PdoPgsql, escapeIdentifier); +ZEND_METHOD(PdoPgsql, copyFromArray); +ZEND_METHOD(PdoPgsql, copyFromFile); +ZEND_METHOD(PdoPgsql, copyToArray); +ZEND_METHOD(PdoPgsql, copyToFile); +ZEND_METHOD(PdoPgsql, lobCreate); +ZEND_METHOD(PdoPgsql, lobOpen); +ZEND_METHOD(PdoPgsql, lobUnlink); +ZEND_METHOD(PdoPgsql, getNotify); +ZEND_METHOD(PdoPgsql, getPid); + + +static const zend_function_entry class_PdoPgsql_methods[] = { + ZEND_ME(PdoPgsql, escapeIdentifier, arginfo_class_PdoPgsql_escapeIdentifier, ZEND_ACC_PUBLIC) + ZEND_ME(PdoPgsql, copyFromArray, arginfo_class_PdoPgsql_copyFromArray, ZEND_ACC_PUBLIC) + ZEND_ME(PdoPgsql, copyFromFile, arginfo_class_PdoPgsql_copyFromFile, ZEND_ACC_PUBLIC) + ZEND_ME(PdoPgsql, copyToArray, arginfo_class_PdoPgsql_copyToArray, ZEND_ACC_PUBLIC) + ZEND_ME(PdoPgsql, copyToFile, arginfo_class_PdoPgsql_copyToFile, ZEND_ACC_PUBLIC) + ZEND_ME(PdoPgsql, lobCreate, arginfo_class_PdoPgsql_lobCreate, ZEND_ACC_PUBLIC) + ZEND_ME(PdoPgsql, lobOpen, arginfo_class_PdoPgsql_lobOpen, ZEND_ACC_PUBLIC) + ZEND_ME(PdoPgsql, lobUnlink, arginfo_class_PdoPgsql_lobUnlink, ZEND_ACC_PUBLIC) + ZEND_ME(PdoPgsql, getNotify, arginfo_class_PdoPgsql_getNotify, ZEND_ACC_PUBLIC) + ZEND_ME(PdoPgsql, getPid, arginfo_class_PdoPgsql_getPid, ZEND_ACC_PUBLIC) ZEND_FE_END }; -static zend_class_entry *register_class_PDOPgSql(zend_class_entry *class_entry_PDO) +static zend_class_entry *register_class_PdoPgsql(zend_class_entry *class_entry_PDO) { zend_class_entry ce, *class_entry; - INIT_CLASS_ENTRY(ce, "PDOPgSql", class_PDOPgSql_methods); + INIT_CLASS_ENTRY(ce, "PdoPgsql", class_PdoPgsql_methods); class_entry = zend_register_internal_class_ex(&ce, class_entry_PDO); class_entry->ce_flags |= ZEND_ACC_NOT_SERIALIZABLE; diff --git a/ext/pdo_pgsql/pdo_pgsql_class.c b/ext/pdo_pgsql/pdo_pgsql_class.c index 03d739aa8449f..6db5e3668cfa5 100644 --- a/ext/pdo_pgsql/pdo_pgsql_class.c +++ b/ext/pdo_pgsql/pdo_pgsql_class.c @@ -80,7 +80,7 @@ ///* }}} */ /* {{{ Escape a identifier for insertion into a text field */ -PHP_METHOD(PDOPgSql, escapeIdentifier) +PHP_METHOD(PdoPgsql, escapeIdentifier) { zend_string *from = NULL; char *tmp; @@ -113,7 +113,7 @@ PHP_METHOD(PDOPgSql, escapeIdentifier) /* {{{ Returns true if the copy worked fine or false if error */ -PHP_METHOD(PDOPgSql, copyFromArray) +PHP_METHOD(PdoPgsql, copyFromArray) { pgsqlCopyFromArray_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU); } @@ -121,14 +121,14 @@ PHP_METHOD(PDOPgSql, copyFromArray) /* {{{ Returns true if the copy worked fine or false if error */ -PHP_METHOD(PDOPgSql, copyFromFile) +PHP_METHOD(PdoPgsql, copyFromFile) { pgsqlCopyFromFile_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU); } /* }}} */ /* {{{ Returns true if the copy worked fine or false if error */ -PHP_METHOD(PDOPgSql, copyToFile) +PHP_METHOD(PdoPgsql, copyToFile) { pgsqlCopyToFile_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU); @@ -136,42 +136,42 @@ PHP_METHOD(PDOPgSql, copyToFile) /* }}} */ /* {{{ Returns true if the copy worked fine or false if error */ -PHP_METHOD(PDOPgSql, copyToArray) +PHP_METHOD(PdoPgsql, copyToArray) { pgsqlCopyToArray_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU); } /* }}} */ /* {{{ Creates a new large object, returning its identifier. Must be called inside a transaction. */ -PHP_METHOD(PDOPgSql, lobCreate) +PHP_METHOD(PdoPgsql, lobCreate) { pgsqlLOBCreate_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU); } /* }}} */ /* {{{ Opens an existing large object stream. Must be called inside a transaction. */ -PHP_METHOD(PDOPgSql, lobOpen) +PHP_METHOD(PdoPgsql, lobOpen) { pgsqlLOBOpen_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU); } /* }}} */ /* {{{ Deletes the large object identified by oid. Must be called inside a transaction. */ -PHP_METHOD(PDOPgSql, lobUnlink) +PHP_METHOD(PdoPgsql, lobUnlink) { pgsqlLOBUnlink_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU); } /* }}} */ /* {{{ Get asynchronous notification */ -PHP_METHOD(PDOPgSql, getNotify) +PHP_METHOD(PdoPgsql, getNotify) { pgsqlGetNotify_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU); } /* }}} */ /* {{{ Get backend(server) pid */ -PHP_METHOD(PDOPgSql, getPid) +PHP_METHOD(PdoPgsql, getPid) { pgsqlGetPid_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU); } diff --git a/ext/pdo_pgsql/tests/subclassing/pdopgsql_001.phpt b/ext/pdo_pgsql/tests/subclassing/pdopgsql_001.phpt index 7fddd0141a28b..91ddb4a6f9fc0 100644 --- a/ext/pdo_pgsql/tests/subclassing/pdopgsql_001.phpt +++ b/ext/pdo_pgsql/tests/subclassing/pdopgsql_001.phpt @@ -1,5 +1,5 @@ --TEST-- -PdoPgSql subclass basic +PdoPgsql subclass basic --EXTENSIONS-- pdo_mysql --FILE-- @@ -7,15 +7,15 @@ pdo_mysql require_once __DIR__ . "/../config_functions.inc"; -if (class_exists(PdoPgSql::class) === false) { - echo "PdoPgSql class does not exist.\n"; +if (class_exists(PdoPgsql::class) === false) { + echo "PdoPgsql class does not exist.\n"; exit(-1); } -echo "PdoPgSql class exists.\n"; +echo "PdoPgsql class exists.\n"; $dsn = getDsn(); -$db = new PdoPgSql($dsn); +$db = new PdoPgsql($dsn); $db->query('CREATE TABLE IF NOT EXISTS foobar (id INT, name TEXT)'); @@ -31,7 +31,7 @@ $db->query('DROP TABLE foobar'); echo "Fin."; ?> --EXPECT-- -PdoPgSql class exists. +PdoPgsql class exists. array(2) { ["name"]=> string(3) "PHP" diff --git a/ext/pdo_pgsql/tests/subclassing/pdopgsql_002.phpt b/ext/pdo_pgsql/tests/subclassing/pdopgsql_002.phpt index 344e678445d52..5fec78741401e 100644 --- a/ext/pdo_pgsql/tests/subclassing/pdopgsql_002.phpt +++ b/ext/pdo_pgsql/tests/subclassing/pdopgsql_002.phpt @@ -1,5 +1,5 @@ --TEST-- -PdoPgSql coonect through PDO::connect +PdoPgsql coonect through PDO::connect --EXTENSIONS-- pdo_mysql --FILE-- @@ -7,19 +7,19 @@ pdo_mysql require_once __DIR__ . "/../config_functions.inc"; -if (class_exists(PdoPgSql::class) === false) { - echo "PdoPgSql class does not exist.\n"; +if (class_exists(PdoPgsql::class) === false) { + echo "PdoPgsql class does not exist.\n"; exit(-1); } -echo "PdoPgSql class exists.\n"; +echo "PdoPgsql class exists.\n"; $dsn = getDsn(); $db = Pdo::connect($dsn); -if (!$db instanceof PdoPgSql) { - echo "Wrong class type. Should be PdoPgSql but is [" . get_class($db) . "\n"; +if (!$db instanceof PdoPgsql) { + echo "Wrong class type. Should be PdoPgsql but is [" . get_class($db) . "\n"; } $db->query('DROP TABLE IF EXISTS test'); @@ -37,7 +37,7 @@ $db->query('DROP TABLE test'); echo "Fin."; ?> --EXPECT-- -PdoPgSql class exists. +PdoPgsql class exists. array(2) { ["name"]=> string(1) "A" diff --git a/ext/pdo_pgsql/tests/subclassing/pdopgsql_003.phpt b/ext/pdo_pgsql/tests/subclassing/pdopgsql_003.phpt index 38124a39bbab9..babef145460d6 100644 --- a/ext/pdo_pgsql/tests/subclassing/pdopgsql_003.phpt +++ b/ext/pdo_pgsql/tests/subclassing/pdopgsql_003.phpt @@ -1,5 +1,5 @@ --TEST-- -PdoPgSql getWarningCount +PdoPgsql getWarningCount --EXTENSIONS-- pdo_mysql --FILE-- @@ -7,8 +7,8 @@ pdo_mysql require_once __DIR__ . "/../config_functions.inc"; -if (class_exists(PdoPgSql::class) === false) { - echo "PdoPgSql class does not exist.\n"; +if (class_exists(PdoPgsql::class) === false) { + echo "PdoPgsql class does not exist.\n"; exit(-1); } @@ -16,8 +16,8 @@ $dsn = getDsn(); $db = Pdo::connect($dsn); -if (!$db instanceof PdoPgSql) { - echo "Wrong class type. Should be PdoPgSql but is [" . get_class($db) . "\n"; +if (!$db instanceof PdoPgsql) { + echo "Wrong class type. Should be PdoPgsql but is [" . get_class($db) . "\n"; } $result = $db->escapeIdentifier("This is a quote\""); diff --git a/ext/pdo_sqlite/pdo_sqlite.c b/ext/pdo_sqlite/pdo_sqlite.c index 47d1b86d9de44..974eaa7bdc10e 100644 --- a/ext/pdo_sqlite/pdo_sqlite.c +++ b/ext/pdo_sqlite/pdo_sqlite.c @@ -73,7 +73,7 @@ PHP_MINIT_FUNCTION(pdo_sqlite) REGISTER_PDO_CLASS_CONST_LONG("SQLITE_ATTR_READONLY_STATEMENT", (zend_long)PDO_SQLITE_ATTR_READONLY_STATEMENT); REGISTER_PDO_CLASS_CONST_LONG("SQLITE_ATTR_EXTENDED_RESULT_CODES", (zend_long)PDO_SQLITE_ATTR_EXTENDED_RESULT_CODES); - pdosqlite_ce = register_class_PDOSqlite(pdo_dbh_ce); + pdosqlite_ce = register_class_PdoSqlite(pdo_dbh_ce); pdosqlite_ce->create_object = pdo_dbh_new; pdosqlite_pdo_driver_class_entry.driver_name = "sqlite"; diff --git a/ext/pdo_sqlite/pdo_sqlite.stub.php b/ext/pdo_sqlite/pdo_sqlite.stub.php index 4d52e41e39a90..ec197ad945705 100644 --- a/ext/pdo_sqlite/pdo_sqlite.stub.php +++ b/ext/pdo_sqlite/pdo_sqlite.stub.php @@ -3,8 +3,61 @@ /** @generate-class-entries */ /** @not-serializable */ -class PDOSqlite extends PDO +class PdoSqlite extends PDO { + /** + * @var int + * @cname SQLITE_DETERMINISTIC + */ + public const SQLITE_DETERMINISTIC = UNKNOWN; + + /** + * @var int + * @cname SQLITE_ATTR_OPEN_FLAGS + */ + public const SQLITE_ATTR_OPEN_FLAGS = UNKNOWN; + + /** + * @var int + * @cname SQLITE_OPEN_READONLY + */ + public const SQLITE_OPEN_READONLY = UNKNOWN; + + /** + * @var int + * @cname SQLITE_OPEN_READWRITE + */ + public const SQLITE_OPEN_READWRITE = UNKNOWN; + + /** + * @var int + * @cname SQLITE_OPEN_CREATE + */ + public const SQLITE_OPEN_CREATE = UNKNOWN; + + /** + * @var int + * @cname SQLITE_ATTR_READONLY_STATEMENT + */ + public const SQLITE_ATTR_READONLY_STATEMENT = UNKNOWN; + + /** + * @var int + * @cname + */ + public const SQLITE_ATTR_EXTENDED_RESULT_CODES = UNKNOWN; + + // Registers an aggregating User Defined Function for use in SQL statements + public function createAggregate( + string $name, + callable $step, + callable $finalize, + int $numArgs = -1 + ): bool {} + + // Registers a User Defined Function for use as a collating function in SQL statements + public function createCollation(string $name, callable $callback): bool {} + public function createFunction( string $function_name, callable $callback, @@ -23,23 +76,6 @@ public function openBlob( string $column, int $rowid, ?string $dbname = "main", //null, - int $flags = PDO::SQLITE_OPEN_READONLY + int $flags = PdoSqlite::SQLITE_OPEN_READONLY ): mixed /* resource|false */ {} - -//SQLITE_OPEN_READONLY -//SQLITE_OPEN_READWRITE -//SQLITE_OPEN_CREATE - - - // Registers an aggregating User Defined Function for use in SQL statements - public function createAggregate( - string $name, - callable $step, - callable $finalize, - int $numArgs = -1 - ): bool {} - - // Registers a User Defined Function for use as a collating function in SQL statements - public function createCollation(string $name, callable $callback): bool {} - } diff --git a/ext/pdo_sqlite/pdo_sqlite_arginfo.h b/ext/pdo_sqlite/pdo_sqlite_arginfo.h index 8a4db0a45a071..7b80a7ff135ba 100644 --- a/ext/pdo_sqlite/pdo_sqlite_arginfo.h +++ b/ext/pdo_sqlite/pdo_sqlite_arginfo.h @@ -1,7 +1,7 @@ /* This is a generated file, edit the .stub.php file instead. * Stub hash: 949c01f6e018c7abeb29f2ed699e98ed2c0553a9 */ -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PDOSqlite_createFunction, 0, 2, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PdoSqlite_createFunction, 0, 2, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, function_name, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, callback, IS_CALLABLE, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, num_args, IS_LONG, 0, "-1") @@ -9,12 +9,12 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PDOSqlite_createFunction, ZEND_END_ARG_INFO() #if !defined(SQLITE_OMIT_LOAD_EXTENSION) -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PDOSqlite_loadExtension, 0, 1, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PdoSqlite_loadExtension, 0, 1, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 0) ZEND_END_ARG_INFO() #endif -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PDOSqlite_openBlob, 0, 3, IS_MIXED, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PdoSqlite_openBlob, 0, 3, IS_MIXED, 0) ZEND_ARG_TYPE_INFO(0, table, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, column, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, rowid, IS_LONG, 0) @@ -22,44 +22,44 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PDOSqlite_openBlob, 0, 3, ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, flags, IS_LONG, 0, "PDO::SQLITE_OPEN_READONLY") ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PDOSqlite_createAggregate, 0, 3, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PdoSqlite_createAggregate, 0, 3, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, step, IS_CALLABLE, 0) ZEND_ARG_TYPE_INFO(0, finalize, IS_CALLABLE, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, numArgs, IS_LONG, 0, "-1") ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PDOSqlite_createCollation, 0, 2, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PdoSqlite_createCollation, 0, 2, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, callback, IS_CALLABLE, 0) ZEND_END_ARG_INFO() -ZEND_METHOD(PDOSqlite, createFunction); +ZEND_METHOD(PdoSqlite, createFunction); #if !defined(SQLITE_OMIT_LOAD_EXTENSION) -ZEND_METHOD(PDOSqlite, loadExtension); +ZEND_METHOD(PdoSqlite, loadExtension); #endif -ZEND_METHOD(PDOSqlite, openBlob); -ZEND_METHOD(PDOSqlite, createAggregate); -ZEND_METHOD(PDOSqlite, createCollation); +ZEND_METHOD(PdoSqlite, openBlob); +ZEND_METHOD(PdoSqlite, createAggregate); +ZEND_METHOD(PdoSqlite, createCollation); -static const zend_function_entry class_PDOSqlite_methods[] = { - ZEND_ME(PDOSqlite, createFunction, arginfo_class_PDOSqlite_createFunction, ZEND_ACC_PUBLIC) +static const zend_function_entry class_PdoSqlite_methods[] = { + ZEND_ME(PdoSqlite, createFunction, arginfo_class_PdoSqlite_createFunction, ZEND_ACC_PUBLIC) #if !defined(SQLITE_OMIT_LOAD_EXTENSION) - ZEND_ME(PDOSqlite, loadExtension, arginfo_class_PDOSqlite_loadExtension, ZEND_ACC_PUBLIC) + ZEND_ME(PdoSqlite, loadExtension, arginfo_class_PdoSqlite_loadExtension, ZEND_ACC_PUBLIC) #endif - ZEND_ME(PDOSqlite, openBlob, arginfo_class_PDOSqlite_openBlob, ZEND_ACC_PUBLIC) - ZEND_ME(PDOSqlite, createAggregate, arginfo_class_PDOSqlite_createAggregate, ZEND_ACC_PUBLIC) - ZEND_ME(PDOSqlite, createCollation, arginfo_class_PDOSqlite_createCollation, ZEND_ACC_PUBLIC) + ZEND_ME(PdoSqlite, openBlob, arginfo_class_PdoSqlite_openBlob, ZEND_ACC_PUBLIC) + ZEND_ME(PdoSqlite, createAggregate, arginfo_class_PdoSqlite_createAggregate, ZEND_ACC_PUBLIC) + ZEND_ME(PdoSqlite, createCollation, arginfo_class_PdoSqlite_createCollation, ZEND_ACC_PUBLIC) ZEND_FE_END }; -static zend_class_entry *register_class_PDOSqlite(zend_class_entry *class_entry_PDO) +static zend_class_entry *register_class_PdoSqlite(zend_class_entry *class_entry_PDO) { zend_class_entry ce, *class_entry; - INIT_CLASS_ENTRY(ce, "PDOSqlite", class_PDOSqlite_methods); + INIT_CLASS_ENTRY(ce, "PdoSqlite", class_PdoSqlite_methods); class_entry = zend_register_internal_class_ex(&ce, class_entry_PDO); class_entry->ce_flags |= ZEND_ACC_NOT_SERIALIZABLE; diff --git a/ext/pdo_sqlite/pdo_sqlite_class.c b/ext/pdo_sqlite/pdo_sqlite_class.c index a9a764aa67c01..e47e2da49227c 100644 --- a/ext/pdo_sqlite/pdo_sqlite_class.c +++ b/ext/pdo_sqlite/pdo_sqlite_class.c @@ -207,10 +207,10 @@ static void php_pgsql_func_final_callback(sqlite3_context *context) -/* {{{ proto bool PDOSqlite::createFunction(string $function_name, callable $callback, int $num_args = -1, int $flags = 0) +/* {{{ proto bool PdoSqlite::createFunction(string $function_name, callable $callback, int $num_args = -1, int $flags = 0) Creates a function that can be used in a query */ -PHP_METHOD(PDOSqlite, createFunction) +PHP_METHOD(PdoSqlite, createFunction) { //copied from sqlite_driver.c @@ -261,7 +261,7 @@ PHP_METHOD(PDOSqlite, createFunction) #ifndef SQLITE_OMIT_LOAD_EXTENSION /* {{{ Attempts to load an SQLite extension library. */ -PHP_METHOD(PDOSqlite, loadExtension) +PHP_METHOD(PdoSqlite, loadExtension) { char *extension, *lib_path, *errtext = NULL; char fullpath[MAXPATHLEN]; @@ -330,21 +330,20 @@ PHP_METHOD(PDOSqlite, loadExtension) // RETURN_FALSE; // } -// note: expected 'sqlite3 *' but argument is of type 'pdo_sqlite_db_handle *' sqlite3 *sqlite_handle; sqlite_handle = db_handle->db; - /* Extension loading should only be enabled for when we attempt to load */ - sqlite3_enable_load_extension(sqlite_handle, 1); + // This only enables extension loading for the C api, not for SQL + sqlite3_db_config(db, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 1); + if (sqlite3_load_extension(sqlite_handle, fullpath, 0, &errtext) != SQLITE_OK) { - //php_sqlite3_error(db_obj, "%s", errtext); + // TODO - check exception message is acceptable zend_throw_exception_ex(php_pdo_get_exception(), 0, errtext); - sqlite3_free(errtext); - sqlite3_enable_load_extension(sqlite_handle, 0); + sqlite3_db_config(db, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 1); RETURN_FALSE; } - sqlite3_enable_load_extension(sqlite_handle, 0); + sqlite3_db_config(db, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 1); RETURN_TRUE; } @@ -513,7 +512,7 @@ static const php_stream_ops php_stream_pdosqlite3_ops = { /* {{{ Open a blob as a stream which we can read / write to. */ -PHP_METHOD(PDOSqlite, openBlob) +PHP_METHOD(PdoSqlite, openBlob) { char *table, *column, *dbname = "main", *mode = "rb"; size_t table_len, column_len, dbname_len; @@ -606,7 +605,7 @@ static int php_pgsql_collation_callback(void *context, } -PHP_METHOD(PDOSqlite, createAggregate) +PHP_METHOD(PdoSqlite, createAggregate) { struct pdo_sqlite_func *func; zend_fcall_info step_fci, fini_fci; @@ -659,7 +658,7 @@ PHP_METHOD(PDOSqlite, createAggregate) /* {{{ bool SQLite::createCollation(string name, callable callback) Registers a collation with the sqlite db handle */ -PHP_METHOD(PDOSqlite, createCollation) +PHP_METHOD(PdoSqlite, createCollation) { struct pdo_sqlite_collation *collation; zend_fcall_info fci; @@ -668,8 +667,6 @@ PHP_METHOD(PDOSqlite, createCollation) size_t collation_name_len; pdo_dbh_t *dbh; pdo_sqlite_db_handle *H; -// pdo_dbh_t *dbh; -// pdo_sqlite_db_handle *db_handle; int ret; ZEND_PARSE_PARAMETERS_START(2, 2) diff --git a/ext/pdo_sqlite/tests/subclasses/pdo_sqlite_createaggregate_002.phpt b/ext/pdo_sqlite/tests/subclasses/pdo_sqlite_createaggregate_002.phpt index 9515b859efc81..e4152c06e81e8 100644 --- a/ext/pdo_sqlite/tests/subclasses/pdo_sqlite_createaggregate_002.phpt +++ b/ext/pdo_sqlite/tests/subclasses/pdo_sqlite_createaggregate_002.phpt @@ -21,5 +21,5 @@ try { ?> --EXPECT-- -PDOSqlite::createAggregate(): Argument #2 ($step) must be a valid callback, function "a" not found or invalid function name -PDOSqlite::createAggregate(): Argument #3 ($finalize) must be a valid callback, function "" not found or invalid function name +PdoSqlite::createAggregate(): Argument #2 ($step) must be a valid callback, function "a" not found or invalid function name +PdoSqlite::createAggregate(): Argument #3 ($finalize) must be a valid callback, function "" not found or invalid function name diff --git a/ext/pdo_sqlite/tests/subclasses/pdosqlite_001.phpt b/ext/pdo_sqlite/tests/subclasses/pdosqlite_001.phpt index 0ee9cd51ac077..b10a871ab8910 100644 --- a/ext/pdo_sqlite/tests/subclasses/pdosqlite_001.phpt +++ b/ext/pdo_sqlite/tests/subclasses/pdosqlite_001.phpt @@ -1,5 +1,5 @@ --TEST-- -PDOSqlite basic +PdoSqlite basic --EXTENSIONS-- pdo --FILE-- diff --git a/ext/pdo_sqlite/tests/subclasses/pdosqlite_002.phpt b/ext/pdo_sqlite/tests/subclasses/pdosqlite_002.phpt index bb229ad5490f5..4991f26168323 100644 --- a/ext/pdo_sqlite/tests/subclasses/pdosqlite_002.phpt +++ b/ext/pdo_sqlite/tests/subclasses/pdosqlite_002.phpt @@ -1,5 +1,5 @@ --TEST-- -PDOSqlite create through PDO::connect and function define. +PdoSqlite create through PDO::connect and function define. --EXTENSIONS-- pdo --FILE-- diff --git a/ext/pdo_sqlite/tests/subclasses/pdosqlite_003.phpt b/ext/pdo_sqlite/tests/subclasses/pdosqlite_003.phpt index 931c32c34a83e..0befb1511fa0b 100644 --- a/ext/pdo_sqlite/tests/subclasses/pdosqlite_003.phpt +++ b/ext/pdo_sqlite/tests/subclasses/pdosqlite_003.phpt @@ -1,5 +1,5 @@ --TEST-- -PDOSqlite load extension +PdoSqlite load extension --EXTENSIONS-- pdo --FILE-- diff --git a/ext/pdo_sqlite/tests/subclasses/pdosqlite_004_blobopen.phpt b/ext/pdo_sqlite/tests/subclasses/pdosqlite_004_blobopen.phpt index 5976f41a31c6a..de1a1935e98a5 100644 --- a/ext/pdo_sqlite/tests/subclasses/pdosqlite_004_blobopen.phpt +++ b/ext/pdo_sqlite/tests/subclasses/pdosqlite_004_blobopen.phpt @@ -1,5 +1,5 @@ --TEST-- -PDOSqlite::blobOpen stream test +PdoSqlite::blobOpen stream test --EXTENSIONS-- pdo --FILE-- From 08abcf48d378e429a38249d530228fbdd1d85d66 Mon Sep 17 00:00:00 2001 From: Danack Date: Mon, 3 Jul 2023 13:53:05 +0100 Subject: [PATCH 23/35] Corrected constants to not have prefix. Made extension loading work and implemented exceptions. --- ext/pdo_mysql/pdo_mysql_arginfo.h | 2 +- ext/pdo_sqlite/pdo_sqlite.stub.php | 28 +++---- ext/pdo_sqlite/pdo_sqlite_arginfo.h | 78 ++++++++++++++----- ext/pdo_sqlite/pdo_sqlite_class.c | 55 +++---------- ext/pdo_sqlite/php_pdo_sqlite_int.h | 3 + .../subclasses/pdo_sqlite_constants.phpt | 26 +++++++ .../pdo_sqlite_createfunction_with_flags.phpt | 2 +- .../tests/subclasses/pdosqlite_001.phpt | 2 +- .../tests/subclasses/pdosqlite_002.phpt | 2 +- .../subclasses/pdosqlite_004_blobopen.phpt | 2 +- .../pdosqlite_load_extension_failure.phpt | 43 ++++++++++ 11 files changed, 161 insertions(+), 82 deletions(-) create mode 100644 ext/pdo_sqlite/tests/subclasses/pdo_sqlite_constants.phpt create mode 100644 ext/pdo_sqlite/tests/subclasses/pdosqlite_load_extension_failure.phpt diff --git a/ext/pdo_mysql/pdo_mysql_arginfo.h b/ext/pdo_mysql/pdo_mysql_arginfo.h index d8ef744c019ea..d0795b664fa98 100644 --- a/ext/pdo_mysql/pdo_mysql_arginfo.h +++ b/ext/pdo_mysql/pdo_mysql_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 0b4ccc19bba532b56c7b6936a01bfccc4a7bea79 */ + * Stub hash: 151e8bf9fb5870f4b2793c8f1549815ca036c64e */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PdoMysql_getWarningCount, 0, 0, IS_LONG, 0) ZEND_END_ARG_INFO() diff --git a/ext/pdo_sqlite/pdo_sqlite.stub.php b/ext/pdo_sqlite/pdo_sqlite.stub.php index ec197ad945705..a9a74966e23ee 100644 --- a/ext/pdo_sqlite/pdo_sqlite.stub.php +++ b/ext/pdo_sqlite/pdo_sqlite.stub.php @@ -9,43 +9,43 @@ class PdoSqlite extends PDO * @var int * @cname SQLITE_DETERMINISTIC */ - public const SQLITE_DETERMINISTIC = UNKNOWN; + public const DETERMINISTIC = UNKNOWN; /** * @var int - * @cname SQLITE_ATTR_OPEN_FLAGS + * @cname SQLITE_OPEN_READONLY */ - public const SQLITE_ATTR_OPEN_FLAGS = UNKNOWN; + public const OPEN_READONLY = UNKNOWN; /** * @var int - * @cname SQLITE_OPEN_READONLY + * @cname SQLITE_OPEN_READWRITE */ - public const SQLITE_OPEN_READONLY = UNKNOWN; + public const OPEN_READWRITE = UNKNOWN; /** * @var int - * @cname SQLITE_OPEN_READWRITE + * @cname SQLITE_OPEN_CREATE */ - public const SQLITE_OPEN_READWRITE = UNKNOWN; + public const OPEN_CREATE = UNKNOWN; /** * @var int - * @cname SQLITE_OPEN_CREATE + * @cname PDO_SQLITE_ATTR_OPEN_FLAGS */ - public const SQLITE_OPEN_CREATE = UNKNOWN; + public const ATTR_OPEN_FLAGS = UNKNOWN; /** * @var int - * @cname SQLITE_ATTR_READONLY_STATEMENT + * @cname PDO_SQLITE_ATTR_READONLY_STATEMENT */ - public const SQLITE_ATTR_READONLY_STATEMENT = UNKNOWN; + public const ATTR_READONLY_STATEMENT = UNKNOWN; /** * @var int - * @cname + * @cname PDO_SQLITE_ATTR_EXTENDED_RESULT_CODES */ - public const SQLITE_ATTR_EXTENDED_RESULT_CODES = UNKNOWN; + public const ATTR_EXTENDED_RESULT_CODES = UNKNOWN; // Registers an aggregating User Defined Function for use in SQL statements public function createAggregate( @@ -76,6 +76,6 @@ public function openBlob( string $column, int $rowid, ?string $dbname = "main", //null, - int $flags = PdoSqlite::SQLITE_OPEN_READONLY + int $flags = PdoSqlite::OPEN_READONLY ): mixed /* resource|false */ {} } diff --git a/ext/pdo_sqlite/pdo_sqlite_arginfo.h b/ext/pdo_sqlite/pdo_sqlite_arginfo.h index 7b80a7ff135ba..c9ae2c976d150 100644 --- a/ext/pdo_sqlite/pdo_sqlite_arginfo.h +++ b/ext/pdo_sqlite/pdo_sqlite_arginfo.h @@ -1,5 +1,17 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 949c01f6e018c7abeb29f2ed699e98ed2c0553a9 */ + * Stub hash: 90e72918989ba39299db8af818e17d17a610eba3 */ + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PdoSqlite_createAggregate, 0, 3, _IS_BOOL, 0) + ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, step, IS_CALLABLE, 0) + ZEND_ARG_TYPE_INFO(0, finalize, IS_CALLABLE, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, numArgs, IS_LONG, 0, "-1") +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PdoSqlite_createCollation, 0, 2, _IS_BOOL, 0) + ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, callback, IS_CALLABLE, 0) +ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PdoSqlite_createFunction, 0, 2, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, function_name, IS_STRING, 0) @@ -19,39 +31,27 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PdoSqlite_openBlob, 0, 3, ZEND_ARG_TYPE_INFO(0, column, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, rowid, IS_LONG, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, dbname, IS_STRING, 1, "\"main\"") - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, flags, IS_LONG, 0, "PDO::SQLITE_OPEN_READONLY") -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PdoSqlite_createAggregate, 0, 3, _IS_BOOL, 0) - ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 0) - ZEND_ARG_TYPE_INFO(0, step, IS_CALLABLE, 0) - ZEND_ARG_TYPE_INFO(0, finalize, IS_CALLABLE, 0) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, numArgs, IS_LONG, 0, "-1") -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PdoSqlite_createCollation, 0, 2, _IS_BOOL, 0) - ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 0) - ZEND_ARG_TYPE_INFO(0, callback, IS_CALLABLE, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, flags, IS_LONG, 0, "PdoSqlite::OPEN_READONLY") ZEND_END_ARG_INFO() +ZEND_METHOD(PdoSqlite, createAggregate); +ZEND_METHOD(PdoSqlite, createCollation); ZEND_METHOD(PdoSqlite, createFunction); #if !defined(SQLITE_OMIT_LOAD_EXTENSION) ZEND_METHOD(PdoSqlite, loadExtension); #endif ZEND_METHOD(PdoSqlite, openBlob); -ZEND_METHOD(PdoSqlite, createAggregate); -ZEND_METHOD(PdoSqlite, createCollation); static const zend_function_entry class_PdoSqlite_methods[] = { + ZEND_ME(PdoSqlite, createAggregate, arginfo_class_PdoSqlite_createAggregate, ZEND_ACC_PUBLIC) + ZEND_ME(PdoSqlite, createCollation, arginfo_class_PdoSqlite_createCollation, ZEND_ACC_PUBLIC) ZEND_ME(PdoSqlite, createFunction, arginfo_class_PdoSqlite_createFunction, ZEND_ACC_PUBLIC) #if !defined(SQLITE_OMIT_LOAD_EXTENSION) ZEND_ME(PdoSqlite, loadExtension, arginfo_class_PdoSqlite_loadExtension, ZEND_ACC_PUBLIC) #endif ZEND_ME(PdoSqlite, openBlob, arginfo_class_PdoSqlite_openBlob, ZEND_ACC_PUBLIC) - ZEND_ME(PdoSqlite, createAggregate, arginfo_class_PdoSqlite_createAggregate, ZEND_ACC_PUBLIC) - ZEND_ME(PdoSqlite, createCollation, arginfo_class_PdoSqlite_createCollation, ZEND_ACC_PUBLIC) ZEND_FE_END }; @@ -63,5 +63,47 @@ static zend_class_entry *register_class_PdoSqlite(zend_class_entry *class_entry_ class_entry = zend_register_internal_class_ex(&ce, class_entry_PDO); class_entry->ce_flags |= ZEND_ACC_NOT_SERIALIZABLE; + zval const_DETERMINISTIC_value; + ZVAL_LONG(&const_DETERMINISTIC_value, SQLITE_DETERMINISTIC); + zend_string *const_DETERMINISTIC_name = zend_string_init_interned("DETERMINISTIC", sizeof("DETERMINISTIC") - 1, 1); + zend_declare_class_constant_ex(class_entry, const_DETERMINISTIC_name, &const_DETERMINISTIC_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_DETERMINISTIC_name); + + zval const_OPEN_READONLY_value; + ZVAL_LONG(&const_OPEN_READONLY_value, SQLITE_OPEN_READONLY); + zend_string *const_OPEN_READONLY_name = zend_string_init_interned("OPEN_READONLY", sizeof("OPEN_READONLY") - 1, 1); + zend_declare_class_constant_ex(class_entry, const_OPEN_READONLY_name, &const_OPEN_READONLY_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_OPEN_READONLY_name); + + zval const_OPEN_READWRITE_value; + ZVAL_LONG(&const_OPEN_READWRITE_value, SQLITE_OPEN_READWRITE); + zend_string *const_OPEN_READWRITE_name = zend_string_init_interned("OPEN_READWRITE", sizeof("OPEN_READWRITE") - 1, 1); + zend_declare_class_constant_ex(class_entry, const_OPEN_READWRITE_name, &const_OPEN_READWRITE_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_OPEN_READWRITE_name); + + zval const_OPEN_CREATE_value; + ZVAL_LONG(&const_OPEN_CREATE_value, SQLITE_OPEN_CREATE); + zend_string *const_OPEN_CREATE_name = zend_string_init_interned("OPEN_CREATE", sizeof("OPEN_CREATE") - 1, 1); + zend_declare_class_constant_ex(class_entry, const_OPEN_CREATE_name, &const_OPEN_CREATE_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_OPEN_CREATE_name); + + zval const_ATTR_OPEN_FLAGS_value; + ZVAL_LONG(&const_ATTR_OPEN_FLAGS_value, PDO_SQLITE_ATTR_OPEN_FLAGS); + zend_string *const_ATTR_OPEN_FLAGS_name = zend_string_init_interned("ATTR_OPEN_FLAGS", sizeof("ATTR_OPEN_FLAGS") - 1, 1); + zend_declare_class_constant_ex(class_entry, const_ATTR_OPEN_FLAGS_name, &const_ATTR_OPEN_FLAGS_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_ATTR_OPEN_FLAGS_name); + + zval const_ATTR_READONLY_STATEMENT_value; + ZVAL_LONG(&const_ATTR_READONLY_STATEMENT_value, PDO_SQLITE_ATTR_READONLY_STATEMENT); + zend_string *const_ATTR_READONLY_STATEMENT_name = zend_string_init_interned("ATTR_READONLY_STATEMENT", sizeof("ATTR_READONLY_STATEMENT") - 1, 1); + zend_declare_class_constant_ex(class_entry, const_ATTR_READONLY_STATEMENT_name, &const_ATTR_READONLY_STATEMENT_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_ATTR_READONLY_STATEMENT_name); + + zval const_ATTR_EXTENDED_RESULT_CODES_value; + ZVAL_LONG(&const_ATTR_EXTENDED_RESULT_CODES_value, PDO_SQLITE_ATTR_EXTENDED_RESULT_CODES); + zend_string *const_ATTR_EXTENDED_RESULT_CODES_name = zend_string_init_interned("ATTR_EXTENDED_RESULT_CODES", sizeof("ATTR_EXTENDED_RESULT_CODES") - 1, 1); + zend_declare_class_constant_ex(class_entry, const_ATTR_EXTENDED_RESULT_CODES_name, &const_ATTR_EXTENDED_RESULT_CODES_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_ATTR_EXTENDED_RESULT_CODES_name); + return class_entry; } diff --git a/ext/pdo_sqlite/pdo_sqlite_class.c b/ext/pdo_sqlite/pdo_sqlite_class.c index e47e2da49227c..0012e6c0bb602 100644 --- a/ext/pdo_sqlite/pdo_sqlite_class.c +++ b/ext/pdo_sqlite/pdo_sqlite_class.c @@ -263,7 +263,7 @@ PHP_METHOD(PdoSqlite, createFunction) /* {{{ Attempts to load an SQLite extension library. */ PHP_METHOD(PdoSqlite, loadExtension) { - char *extension, *lib_path, *errtext = NULL; + char *extension, *errtext = NULL; char fullpath[MAXPATHLEN]; size_t extension_len;// , extension_dir_len; @@ -279,71 +279,36 @@ PHP_METHOD(PdoSqlite, loadExtension) db_handle = (pdo_sqlite_db_handle *)dbh->driver_data; - // SQLITE3_CHECK_INITIALIZED(db_obj, db_obj->initialised, SQLite3) - #ifdef ZTS if ((strncmp(sapi_module.name, "cgi", 3) != 0) && (strcmp(sapi_module.name, "cli") != 0) && (strncmp(sapi_module.name, "embed", 5) != 0) ) { // TODO - needs test. - php_sqlite3_error(db_obj, "Not supported in multithreaded Web servers"); - // and converting to exception zend_throw_exception_ex(php_pdo_get_exception(), 0, errtext); - + zend_throw_exception_ex(php_pdo_get_exception(), 0, "Not supported in multithreaded Web servers"); RETURN_FALSE; } #endif -// if (!SQLITE3G(extension_dir)) { -// php_sqlite3_error(db_obj, "SQLite Extension are disabled"); -// RETURN_FALSE; -// } -// -// if (extension_len == 0) { -// php_sqlite3_error(db_obj, "Empty string as an extension"); -// RETURN_FALSE; -// } - -// extension_dir = SQLITE3G(extension_dir); -// extension_dir_len = strlen(SQLITE3G(extension_dir)); - -// if (IS_SLASH(extension_dir[extension_dir_len-1])) { -// spprintf(&lib_path, 0, "%s%s", extension_dir, extension); -// } else { -// spprintf(&lib_path, 0, "%s%c%s", extension_dir, DEFAULT_SLASH, extension); -// } - - spprintf(&lib_path, 0, "%s",extension); - - if (!VCWD_REALPATH(lib_path, fullpath)) { -// php_sqlite3_error(db_obj, "Unable to load extension at '%s'", lib_path); - // TODO - enable this error -// zend_throw_exception_ex(php_pdo_get_exception(), 0, "There is no active transaction"); - efree(lib_path); + + if (!VCWD_REALPATH(extension, fullpath)) { + zend_throw_exception_ex(php_pdo_get_exception(), 0, "Unable to load extension '%s'", extension); RETURN_FALSE; } - efree(lib_path); - -// if (strncmp(fullpath, extension_dir, extension_dir_len) != 0) { -// php_sqlite3_error(db_obj, "Unable to open extensions outside the defined directory"); -// RETURN_FALSE; -// } - sqlite3 *sqlite_handle; - sqlite_handle = db_handle->db; // This only enables extension loading for the C api, not for SQL - sqlite3_db_config(db, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 1); + sqlite3_db_config(sqlite_handle, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 1, NULL); if (sqlite3_load_extension(sqlite_handle, fullpath, 0, &errtext) != SQLITE_OK) { - // TODO - check exception message is acceptable - zend_throw_exception_ex(php_pdo_get_exception(), 0, errtext); - sqlite3_db_config(db, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 1); + + zend_throw_exception_ex(php_pdo_get_exception(), 0, "Unable to load extension '%s'", errtext); + sqlite3_db_config(sqlite_handle, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 0, NULL); RETURN_FALSE; } - sqlite3_db_config(db, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 1); + sqlite3_db_config(sqlite_handle, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 0, NULL); RETURN_TRUE; } diff --git a/ext/pdo_sqlite/php_pdo_sqlite_int.h b/ext/pdo_sqlite/php_pdo_sqlite_int.h index c9aeee08a3a59..08d37af9e5e58 100644 --- a/ext/pdo_sqlite/php_pdo_sqlite_int.h +++ b/ext/pdo_sqlite/php_pdo_sqlite_int.h @@ -78,4 +78,7 @@ enum { PDO_SQLITE_ATTR_EXTENDED_RESULT_CODES }; +#define REGISTER_PDO_SQLITE_CLASS_CONST_LONG(const_name, value) \ + zend_declare_class_constant_long(pdosqlite_ce, const_name, sizeof(const_name)-1, (zend_long)value); + #endif diff --git a/ext/pdo_sqlite/tests/subclasses/pdo_sqlite_constants.phpt b/ext/pdo_sqlite/tests/subclasses/pdo_sqlite_constants.phpt new file mode 100644 index 0000000000000..da48a02c7cfe8 --- /dev/null +++ b/ext/pdo_sqlite/tests/subclasses/pdo_sqlite_constants.phpt @@ -0,0 +1,26 @@ +--TEST-- +PDO_sqlite: Testing constants exist +--EXTENSIONS-- +pdo_sqlite +--FILE-- + +--EXPECTF-- +Hello +int(%d) +int(%d) +int(%d) +int(%d) +int(%d) +int(%d) +int(%d) diff --git a/ext/pdo_sqlite/tests/subclasses/pdo_sqlite_createfunction_with_flags.phpt b/ext/pdo_sqlite/tests/subclasses/pdo_sqlite_createfunction_with_flags.phpt index bedb8c6c3a724..d29e79fc903df 100644 --- a/ext/pdo_sqlite/tests/subclasses/pdo_sqlite_createfunction_with_flags.phpt +++ b/ext/pdo_sqlite/tests/subclasses/pdo_sqlite_createfunction_with_flags.phpt @@ -14,7 +14,7 @@ $db->query('CREATE TABLE IF NOT EXISTS foobar (id INT AUTO INCREMENT, name TEXT) $db->query('INSERT INTO foobar VALUES (NULL, "PHP")'); $db->query('INSERT INTO foobar VALUES (NULL, "PHP6")'); -$db->createFunction('testing', function($v) { return strtolower($v); }, 1, PDO::SQLITE_DETERMINISTIC); +$db->createFunction('testing', function($v) { return strtolower($v); }, 1, PdoSqlite::DETERMINISTIC); foreach ($db->query('SELECT testing(name) FROM foobar') as $row) { var_dump($row); diff --git a/ext/pdo_sqlite/tests/subclasses/pdosqlite_001.phpt b/ext/pdo_sqlite/tests/subclasses/pdosqlite_001.phpt index b10a871ab8910..0fe00b15e4ef4 100644 --- a/ext/pdo_sqlite/tests/subclasses/pdosqlite_001.phpt +++ b/ext/pdo_sqlite/tests/subclasses/pdosqlite_001.phpt @@ -19,7 +19,7 @@ $db->query('INSERT INTO foobar VALUES (NULL, "PHP")'); $db->query('INSERT INTO foobar VALUES (NULL, "PHP6")'); -$db->createFunction('testing', function($v) { return strtolower($v); }, 1, PDO::SQLITE_DETERMINISTIC); +$db->createFunction('testing', function($v) { return strtolower($v); }, 1, PdoSqlite::DETERMINISTIC); foreach ($db->query('SELECT testing(name) FROM foobar') as $row) { diff --git a/ext/pdo_sqlite/tests/subclasses/pdosqlite_002.phpt b/ext/pdo_sqlite/tests/subclasses/pdosqlite_002.phpt index 4991f26168323..606b2bb0ab726 100644 --- a/ext/pdo_sqlite/tests/subclasses/pdosqlite_002.phpt +++ b/ext/pdo_sqlite/tests/subclasses/pdosqlite_002.phpt @@ -23,7 +23,7 @@ $db->query('INSERT INTO foobar VALUES (NULL, "PHP")'); $db->query('INSERT INTO foobar VALUES (NULL, "PHP6")'); -$db->createFunction('testing', function($v) { return strtolower($v); }, 1, PDO::SQLITE_DETERMINISTIC); +$db->createFunction('testing', function($v) { return strtolower($v); }, 1, PdoSqlite::DETERMINISTIC); foreach ($db->query('SELECT testing(name) FROM foobar') as $row) { diff --git a/ext/pdo_sqlite/tests/subclasses/pdosqlite_004_blobopen.phpt b/ext/pdo_sqlite/tests/subclasses/pdosqlite_004_blobopen.phpt index de1a1935e98a5..256cea80ca812 100644 --- a/ext/pdo_sqlite/tests/subclasses/pdosqlite_004_blobopen.phpt +++ b/ext/pdo_sqlite/tests/subclasses/pdosqlite_004_blobopen.phpt @@ -33,7 +33,7 @@ var_dump(fwrite($stream, 'ABCD')); echo "Closing Stream\n"; var_dump(fclose($stream)); echo "Opening stream in write mode\n"; -$stream = $db->openBlob('test', 'data', 1, 'main', PDO::SQLITE_OPEN_READWRITE); +$stream = $db->openBlob('test', 'data', 1, 'main', PdoSqlite::OPEN_READWRITE); var_dump($stream); echo "Writing to blob\n"; var_dump(fwrite($stream, 'ABCD')); diff --git a/ext/pdo_sqlite/tests/subclasses/pdosqlite_load_extension_failure.phpt b/ext/pdo_sqlite/tests/subclasses/pdosqlite_load_extension_failure.phpt new file mode 100644 index 0000000000000..2f550dce9d5b5 --- /dev/null +++ b/ext/pdo_sqlite/tests/subclasses/pdosqlite_load_extension_failure.phpt @@ -0,0 +1,43 @@ +--TEST-- +PdoSqlite load extension +--EXTENSIONS-- +pdo +--FILE-- +loadExtension("/this/does/not_exist"); + echo "Failed to throw exception"; +} +catch (PDOException $pdoException) { + echo $pdoException->getMessage() . "\n"; +} + + + +try { + echo "Loading invalid file.\n"; + $result = $db->loadExtension(__FILE__); + echo "Failed to throw exception"; +} +catch (PDOException $pdoException) { + echo $pdoException->getMessage() . "\n"; +} + + +echo "Fin."; +?> +--EXPECTF-- +Loading non-existent file. +Unable to load extension '/this/does/not_exist' +Loading invalid file. +Unable to load extension '%s: cannot open shared object file: No such file or directory' +Fin. From 9f95d8b1161186cd174c693fe185c40a039aeb06 Mon Sep 17 00:00:00 2001 From: Danack Date: Mon, 3 Jul 2023 13:55:32 +0100 Subject: [PATCH 24/35] Added note on safety. --- ext/pdo_sqlite/pdo_sqlite_class.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ext/pdo_sqlite/pdo_sqlite_class.c b/ext/pdo_sqlite/pdo_sqlite_class.c index 0012e6c0bb602..43401693260e3 100644 --- a/ext/pdo_sqlite/pdo_sqlite_class.c +++ b/ext/pdo_sqlite/pdo_sqlite_class.c @@ -308,6 +308,10 @@ PHP_METHOD(PdoSqlite, loadExtension) sqlite3_db_config(sqlite_handle, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 0, NULL); RETURN_FALSE; } + + // We disable extension loading for a vague feeling of safety. This is probably not necessary + // as extensions can only be loaded through C code, not through SQL, and if someone can get + // some C code to run on the server, they can do anything. sqlite3_db_config(sqlite_handle, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 0, NULL); RETURN_TRUE; From 51487c2b3bb0dec301a04e9e4b41028e2398364f Mon Sep 17 00:00:00 2001 From: Danack Date: Mon, 3 Jul 2023 14:04:43 +0100 Subject: [PATCH 25/35] WS. --- ext/pdo_sqlite/pdo_sqlite_class.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ext/pdo_sqlite/pdo_sqlite_class.c b/ext/pdo_sqlite/pdo_sqlite_class.c index 43401693260e3..4de44934a5fd2 100644 --- a/ext/pdo_sqlite/pdo_sqlite_class.c +++ b/ext/pdo_sqlite/pdo_sqlite_class.c @@ -265,7 +265,7 @@ PHP_METHOD(PdoSqlite, loadExtension) { char *extension, *errtext = NULL; char fullpath[MAXPATHLEN]; - size_t extension_len;// , extension_dir_len; + size_t extension_len; pdo_dbh_t *dbh; pdo_sqlite_db_handle *db_handle; @@ -303,7 +303,6 @@ PHP_METHOD(PdoSqlite, loadExtension) sqlite3_db_config(sqlite_handle, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 1, NULL); if (sqlite3_load_extension(sqlite_handle, fullpath, 0, &errtext) != SQLITE_OK) { - zend_throw_exception_ex(php_pdo_get_exception(), 0, "Unable to load extension '%s'", errtext); sqlite3_db_config(sqlite_handle, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 0, NULL); RETURN_FALSE; From 4572b8d855d064ae4f9acb1bae1a0a7a740e6c8d Mon Sep 17 00:00:00 2001 From: Danack Date: Mon, 3 Jul 2023 14:27:39 +0100 Subject: [PATCH 26/35] Tidying up. --- ext/pdo/pdo_dbh.c | 22 ++++++-------- ext/pdo/php_pdo_driver.h | 4 ++- ext/pdo_pgsql/pdo_pgsql_class.c | 49 ------------------------------- ext/pdo_sqlite/pdo_sqlite_class.c | 3 -- 4 files changed, 12 insertions(+), 66 deletions(-) diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index 3c860367fab21..abf6eb2b3e06f 100644 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -219,13 +219,18 @@ static char *dsn_from_uri(char *uri, char *buf, size_t buflen) /* {{{ */ /* }}} */ - +#define MAX_PDO_SUB_CLASSES 64 static int number_of_pdo_driver_class_entries = 0; -static pdo_driver_class_entry *pdo_driver_class_entries[64]; +static pdo_driver_class_entry *pdo_driver_class_entries[MAX_PDO_SUB_CLASSES]; -// TODO - remove this and roll it into the standard driver class entries +// It would be possible remove this and roll it into the standard driver class entries +// I chose not to do it at this time, as that would break existing PDO extensions void pdo_register_driver_specific_class(pdo_driver_class_entry *driver_class_entry) { + if (number_of_pdo_driver_class_entries >= MAX_PDO_SUB_CLASSES) { + + } + pdo_driver_class_entries[number_of_pdo_driver_class_entries] = driver_class_entry; number_of_pdo_driver_class_entries += 1; } @@ -315,9 +320,8 @@ void internal_construct(INTERNAL_FUNCTION_PARAMETERS, zval *object, zval *new_zv RETURN_THROWS(); } - // TODO - turn into a function? if (object == NULL) { - // could this every happen? + // could this ever happen? if (driver->driver_name == NULL) { zend_throw_exception_ex(php_pdo_get_exception(), 0, "Driver name is NULL"); RETURN_THROWS(); @@ -488,15 +492,7 @@ PHP_METHOD(PDO, __construct) /* {{{ */ PHP_METHOD(PDO, connect) { -// zval *new_object = NULL; -// return_value = NULL; internal_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, NULL, return_value); - - if (return_value == NULL) { - // Fix stuff up here? - printf("Retval is still null.\n"); - exit(-1); - } } /* }}} */ diff --git a/ext/pdo/php_pdo_driver.h b/ext/pdo/php_pdo_driver.h index 25327fbc6e378..ce17ead86cc62 100644 --- a/ext/pdo/php_pdo_driver.h +++ b/ext/pdo/php_pdo_driver.h @@ -215,7 +215,9 @@ typedef struct { } pdo_driver_t; -// TODO - remove this separate struct, and roll it into pdo_driver_t +// NOTE - This separate struct, could be rolled it into pdo_driver_t +// I chose not to, as that would cause BC break and require a lot of +// downstream work. typedef struct { char *driver_name; zend_class_entry *driver_ce; diff --git a/ext/pdo_pgsql/pdo_pgsql_class.c b/ext/pdo_pgsql/pdo_pgsql_class.c index 6db5e3668cfa5..b55e03081b791 100644 --- a/ext/pdo_pgsql/pdo_pgsql_class.c +++ b/ext/pdo_pgsql/pdo_pgsql_class.c @@ -30,55 +30,6 @@ #include "php_pdo_pgsql.h" #include "php_pdo_pgsql_int.h" -//static void php_pgsql_escape_internal(INTERNAL_FUNCTION_PARAMETERS, int escape_literal) /* {{{ */ { -// zend_string *from = NULL; -// zval *pgsql_link = NULL; -// PGconn *pgsql; -// char *tmp; -// pgsql_link_handle *link; -// -// switch (ZEND_NUM_ARGS()) { -// case 1: -// if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &from) == FAILURE) { -// RETURN_THROWS(); -// } -// link = FETCH_DEFAULT_LINK(); -// CHECK_DEFAULT_LINK(link); -// break; -// -// default: -// if (zend_parse_parameters(ZEND_NUM_ARGS(), "OS", &pgsql_link, pgsql_link_ce, &from) == FAILURE) { -// RETURN_THROWS(); -// } -// link = Z_PGSQL_LINK_P(pgsql_link); -// CHECK_PGSQL_LINK(link); -// break; -// } -// -// pgsql = link->conn; -// -// if (escape_literal) { -// tmp = PQescapeLiteral(pgsql, ZSTR_VAL(from), ZSTR_LEN(from)); -// } else { -// tmp = PQescapeIdentifier(pgsql, ZSTR_VAL(from), ZSTR_LEN(from)); -// } -// if (!tmp) { -// php_error_docref(NULL, E_WARNING,"Failed to escape"); -// RETURN_FALSE; -// } -// -// RETVAL_STRING(tmp); -// PQfreemem(tmp); -//} -///* }}} */ - -///* {{{ Escape parameter as string literal (i.e. parameter) */ -//PHP_FUNCTION(pg_escape_literal) -//{ -// php_pgsql_escape_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); -//} -///* }}} */ - /* {{{ Escape a identifier for insertion into a text field */ PHP_METHOD(PdoPgsql, escapeIdentifier) { diff --git a/ext/pdo_sqlite/pdo_sqlite_class.c b/ext/pdo_sqlite/pdo_sqlite_class.c index 4de44934a5fd2..71f5639316a9d 100644 --- a/ext/pdo_sqlite/pdo_sqlite_class.c +++ b/ext/pdo_sqlite/pdo_sqlite_class.c @@ -585,9 +585,6 @@ PHP_METHOD(PdoSqlite, createAggregate) pdo_sqlite_db_handle *H; int ret; -// pdo_dbh_t *dbh; -// pdo_sqlite_db_handle *db_handle; - dbh = Z_PDO_DBH_P(ZEND_THIS); PDO_CONSTRUCT_CHECK; H = (pdo_sqlite_db_handle *)dbh->driver_data; From 4439f57e9d4d117087b86c48b13a0a1b25603701 Mon Sep 17 00:00:00 2001 From: Danack Date: Mon, 3 Jul 2023 14:32:08 +0100 Subject: [PATCH 27/35] Standardised directory name. --- ext/pdo_dblib/tests/{subclassing => subclasses}/pdodblib_001.phpt | 0 ext/pdo_dblib/tests/{subclassing => subclasses}/pdodblib_002.phpt | 0 .../tests/{subclassing => subclasses}/pdofirebird_001.phpt | 0 .../tests/{subclassing => subclasses}/pdofirebird_002.phpt | 0 ext/pdo_mysql/tests/{subclassing => subclasses}/pdomysql_001.phpt | 0 ext/pdo_mysql/tests/{subclassing => subclasses}/pdomysql_002.phpt | 0 ext/pdo_mysql/tests/{subclassing => subclasses}/pdomysql_003.phpt | 0 ext/pdo_oci/tests/{subclassing => subclasses}/pdooci_001.phpt | 0 ext/pdo_oci/tests/{subclassing => subclasses}/pdooci_002.phpt | 0 ext/pdo_odbc/tests/{subclassing => subclasses}/pdoodbc_001.phpt | 0 ext/pdo_odbc/tests/{subclassing => subclasses}/pdoodbc_002.phpt | 0 ext/pdo_pgsql/tests/{subclassing => subclasses}/pdopgsql_001.phpt | 0 ext/pdo_pgsql/tests/{subclassing => subclasses}/pdopgsql_002.phpt | 0 ext/pdo_pgsql/tests/{subclassing => subclasses}/pdopgsql_003.phpt | 0 14 files changed, 0 insertions(+), 0 deletions(-) rename ext/pdo_dblib/tests/{subclassing => subclasses}/pdodblib_001.phpt (100%) rename ext/pdo_dblib/tests/{subclassing => subclasses}/pdodblib_002.phpt (100%) rename ext/pdo_firebird/tests/{subclassing => subclasses}/pdofirebird_001.phpt (100%) rename ext/pdo_firebird/tests/{subclassing => subclasses}/pdofirebird_002.phpt (100%) rename ext/pdo_mysql/tests/{subclassing => subclasses}/pdomysql_001.phpt (100%) rename ext/pdo_mysql/tests/{subclassing => subclasses}/pdomysql_002.phpt (100%) rename ext/pdo_mysql/tests/{subclassing => subclasses}/pdomysql_003.phpt (100%) rename ext/pdo_oci/tests/{subclassing => subclasses}/pdooci_001.phpt (100%) rename ext/pdo_oci/tests/{subclassing => subclasses}/pdooci_002.phpt (100%) rename ext/pdo_odbc/tests/{subclassing => subclasses}/pdoodbc_001.phpt (100%) rename ext/pdo_odbc/tests/{subclassing => subclasses}/pdoodbc_002.phpt (100%) rename ext/pdo_pgsql/tests/{subclassing => subclasses}/pdopgsql_001.phpt (100%) rename ext/pdo_pgsql/tests/{subclassing => subclasses}/pdopgsql_002.phpt (100%) rename ext/pdo_pgsql/tests/{subclassing => subclasses}/pdopgsql_003.phpt (100%) diff --git a/ext/pdo_dblib/tests/subclassing/pdodblib_001.phpt b/ext/pdo_dblib/tests/subclasses/pdodblib_001.phpt similarity index 100% rename from ext/pdo_dblib/tests/subclassing/pdodblib_001.phpt rename to ext/pdo_dblib/tests/subclasses/pdodblib_001.phpt diff --git a/ext/pdo_dblib/tests/subclassing/pdodblib_002.phpt b/ext/pdo_dblib/tests/subclasses/pdodblib_002.phpt similarity index 100% rename from ext/pdo_dblib/tests/subclassing/pdodblib_002.phpt rename to ext/pdo_dblib/tests/subclasses/pdodblib_002.phpt diff --git a/ext/pdo_firebird/tests/subclassing/pdofirebird_001.phpt b/ext/pdo_firebird/tests/subclasses/pdofirebird_001.phpt similarity index 100% rename from ext/pdo_firebird/tests/subclassing/pdofirebird_001.phpt rename to ext/pdo_firebird/tests/subclasses/pdofirebird_001.phpt diff --git a/ext/pdo_firebird/tests/subclassing/pdofirebird_002.phpt b/ext/pdo_firebird/tests/subclasses/pdofirebird_002.phpt similarity index 100% rename from ext/pdo_firebird/tests/subclassing/pdofirebird_002.phpt rename to ext/pdo_firebird/tests/subclasses/pdofirebird_002.phpt diff --git a/ext/pdo_mysql/tests/subclassing/pdomysql_001.phpt b/ext/pdo_mysql/tests/subclasses/pdomysql_001.phpt similarity index 100% rename from ext/pdo_mysql/tests/subclassing/pdomysql_001.phpt rename to ext/pdo_mysql/tests/subclasses/pdomysql_001.phpt diff --git a/ext/pdo_mysql/tests/subclassing/pdomysql_002.phpt b/ext/pdo_mysql/tests/subclasses/pdomysql_002.phpt similarity index 100% rename from ext/pdo_mysql/tests/subclassing/pdomysql_002.phpt rename to ext/pdo_mysql/tests/subclasses/pdomysql_002.phpt diff --git a/ext/pdo_mysql/tests/subclassing/pdomysql_003.phpt b/ext/pdo_mysql/tests/subclasses/pdomysql_003.phpt similarity index 100% rename from ext/pdo_mysql/tests/subclassing/pdomysql_003.phpt rename to ext/pdo_mysql/tests/subclasses/pdomysql_003.phpt diff --git a/ext/pdo_oci/tests/subclassing/pdooci_001.phpt b/ext/pdo_oci/tests/subclasses/pdooci_001.phpt similarity index 100% rename from ext/pdo_oci/tests/subclassing/pdooci_001.phpt rename to ext/pdo_oci/tests/subclasses/pdooci_001.phpt diff --git a/ext/pdo_oci/tests/subclassing/pdooci_002.phpt b/ext/pdo_oci/tests/subclasses/pdooci_002.phpt similarity index 100% rename from ext/pdo_oci/tests/subclassing/pdooci_002.phpt rename to ext/pdo_oci/tests/subclasses/pdooci_002.phpt diff --git a/ext/pdo_odbc/tests/subclassing/pdoodbc_001.phpt b/ext/pdo_odbc/tests/subclasses/pdoodbc_001.phpt similarity index 100% rename from ext/pdo_odbc/tests/subclassing/pdoodbc_001.phpt rename to ext/pdo_odbc/tests/subclasses/pdoodbc_001.phpt diff --git a/ext/pdo_odbc/tests/subclassing/pdoodbc_002.phpt b/ext/pdo_odbc/tests/subclasses/pdoodbc_002.phpt similarity index 100% rename from ext/pdo_odbc/tests/subclassing/pdoodbc_002.phpt rename to ext/pdo_odbc/tests/subclasses/pdoodbc_002.phpt diff --git a/ext/pdo_pgsql/tests/subclassing/pdopgsql_001.phpt b/ext/pdo_pgsql/tests/subclasses/pdopgsql_001.phpt similarity index 100% rename from ext/pdo_pgsql/tests/subclassing/pdopgsql_001.phpt rename to ext/pdo_pgsql/tests/subclasses/pdopgsql_001.phpt diff --git a/ext/pdo_pgsql/tests/subclassing/pdopgsql_002.phpt b/ext/pdo_pgsql/tests/subclasses/pdopgsql_002.phpt similarity index 100% rename from ext/pdo_pgsql/tests/subclassing/pdopgsql_002.phpt rename to ext/pdo_pgsql/tests/subclasses/pdopgsql_002.phpt diff --git a/ext/pdo_pgsql/tests/subclassing/pdopgsql_003.phpt b/ext/pdo_pgsql/tests/subclasses/pdopgsql_003.phpt similarity index 100% rename from ext/pdo_pgsql/tests/subclassing/pdopgsql_003.phpt rename to ext/pdo_pgsql/tests/subclasses/pdopgsql_003.phpt From 6aafba0c6608b3faf49887c3d0f38ec7bb5c97b0 Mon Sep 17 00:00:00 2001 From: Danack Date: Mon, 3 Jul 2023 14:41:55 +0100 Subject: [PATCH 28/35] Fix tpyo. --- ext/pdo_firebird/tests/subclasses/pdofirebird_002.phpt | 2 +- ext/pdo_mysql/tests/subclasses/pdomysql_002.phpt | 2 +- ext/pdo_oci/tests/subclasses/pdooci_002.phpt | 2 +- ext/pdo_odbc/tests/subclasses/pdoodbc_002.phpt | 2 +- ext/pdo_pgsql/tests/subclasses/pdopgsql_002.phpt | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ext/pdo_firebird/tests/subclasses/pdofirebird_002.phpt b/ext/pdo_firebird/tests/subclasses/pdofirebird_002.phpt index e425975038eb9..632783aee1f6c 100644 --- a/ext/pdo_firebird/tests/subclasses/pdofirebird_002.phpt +++ b/ext/pdo_firebird/tests/subclasses/pdofirebird_002.phpt @@ -1,5 +1,5 @@ --TEST-- -PDO_firebird coonect through PDO::connect +PDO_firebird connect through PDO::connect --EXTENSIONS-- PDO_odbc --FILE-- diff --git a/ext/pdo_mysql/tests/subclasses/pdomysql_002.phpt b/ext/pdo_mysql/tests/subclasses/pdomysql_002.phpt index bd0f0f8430a46..081c9329aafe7 100644 --- a/ext/pdo_mysql/tests/subclasses/pdomysql_002.phpt +++ b/ext/pdo_mysql/tests/subclasses/pdomysql_002.phpt @@ -1,5 +1,5 @@ --TEST-- -PDO_mysql coonect through PDO::connect +PDO_mysql connect through PDO::connect --EXTENSIONS-- pdo_mysql --FILE-- diff --git a/ext/pdo_oci/tests/subclasses/pdooci_002.phpt b/ext/pdo_oci/tests/subclasses/pdooci_002.phpt index 27730bd954b49..6b1e0141bf393 100644 --- a/ext/pdo_oci/tests/subclasses/pdooci_002.phpt +++ b/ext/pdo_oci/tests/subclasses/pdooci_002.phpt @@ -1,5 +1,5 @@ --TEST-- -PDO_oci coonect through PDO::connect +PDO_oci connect through PDO::connect --EXTENSIONS-- pdo_oci --FILE-- diff --git a/ext/pdo_odbc/tests/subclasses/pdoodbc_002.phpt b/ext/pdo_odbc/tests/subclasses/pdoodbc_002.phpt index 767ae06ccd6cb..cf362dac70791 100644 --- a/ext/pdo_odbc/tests/subclasses/pdoodbc_002.phpt +++ b/ext/pdo_odbc/tests/subclasses/pdoodbc_002.phpt @@ -1,5 +1,5 @@ --TEST-- -PDO_mysql coonect through PDO::connect +PDO_mysql connect through PDO::connect --EXTENSIONS-- PDO_odbc --FILE-- diff --git a/ext/pdo_pgsql/tests/subclasses/pdopgsql_002.phpt b/ext/pdo_pgsql/tests/subclasses/pdopgsql_002.phpt index 5fec78741401e..8e25c8c3beaef 100644 --- a/ext/pdo_pgsql/tests/subclasses/pdopgsql_002.phpt +++ b/ext/pdo_pgsql/tests/subclasses/pdopgsql_002.phpt @@ -1,5 +1,5 @@ --TEST-- -PdoPgsql coonect through PDO::connect +PdoPgsql connect through PDO::connect --EXTENSIONS-- pdo_mysql --FILE-- From 43acd48724377c84accd61a49f6577a9e8446015 Mon Sep 17 00:00:00 2001 From: Danack Date: Tue, 4 Jul 2023 15:17:16 +0100 Subject: [PATCH 29/35] Copy function detection in m4 file across from sqlite3, and separate define name. --- ext/pdo_sqlite/config.m4 | 6 ++++++ ext/pdo_sqlite/pdo_sqlite.stub.php | 7 ++++--- ext/pdo_sqlite/pdo_sqlite_class.c | 2 +- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/ext/pdo_sqlite/config.m4 b/ext/pdo_sqlite/config.m4 index 382958114f497..51b50c1de7ee0 100644 --- a/ext/pdo_sqlite/config.m4 +++ b/ext/pdo_sqlite/config.m4 @@ -26,6 +26,12 @@ if test "$PHP_PDO_SQLITE" != "no"; then AC_DEFINE(HAVE_SQLITE3_COLUMN_TABLE_NAME, 1, [have sqlite3_column_table_name]) ], [], [$PDO_SQLITE_SHARED_LIBADD]) + PHP_CHECK_LIBRARY(sqlite3, sqlite3_load_extension, + [], + [AC_DEFINE(PDO_SQLITE_OMIT_LOAD_EXTENSION, 1, [have sqlite3 with extension support])], + [$PDO_SQLITE_SHARED_LIBADD] + ) + PHP_SUBST(PDO_SQLITE_SHARED_LIBADD) PHP_NEW_EXTENSION(pdo_sqlite, pdo_sqlite.c pdo_sqlite_class.c sqlite_driver.c sqlite_statement.c, $ext_shared,,-I$pdo_cv_inc_path) diff --git a/ext/pdo_sqlite/pdo_sqlite.stub.php b/ext/pdo_sqlite/pdo_sqlite.stub.php index a9a74966e23ee..f50d70fc4b60f 100644 --- a/ext/pdo_sqlite/pdo_sqlite.stub.php +++ b/ext/pdo_sqlite/pdo_sqlite.stub.php @@ -65,9 +65,10 @@ public function createFunction( int $flags = 0 ): bool {} -// Whether SQLITE_OMIT_LOAD_EXTENSION is defined or not depends on how -// SQLite was compiled: https://www.sqlite.org/compile.html -#ifndef SQLITE_OMIT_LOAD_EXTENSION +// PDO_SQLITE_OMIT_LOAD_EXTENSION might be defined by ext/pdo_sqlite/config.m4 +// if Sqlite3 did not have the sqlite3_load_extension function present +// which can deepend on how SQLite was compiled: https://www.sqlite.org/compile.html +#ifndef PDO_SQLITE_OMIT_LOAD_EXTENSION public function loadExtension(string $name): bool {} #endif diff --git a/ext/pdo_sqlite/pdo_sqlite_class.c b/ext/pdo_sqlite/pdo_sqlite_class.c index 71f5639316a9d..f0721670e743f 100644 --- a/ext/pdo_sqlite/pdo_sqlite_class.c +++ b/ext/pdo_sqlite/pdo_sqlite_class.c @@ -259,7 +259,7 @@ PHP_METHOD(PdoSqlite, createFunction) } /* }}} */ -#ifndef SQLITE_OMIT_LOAD_EXTENSION +#ifndef PDO_SQLITE_OMIT_LOAD_EXTENSION /* {{{ Attempts to load an SQLite extension library. */ PHP_METHOD(PdoSqlite, loadExtension) { From 23aab3c2ddcffb5dd8fc7bb1bf9b91e564670964 Mon Sep 17 00:00:00 2001 From: Danack Date: Tue, 11 Jul 2023 12:39:16 +0100 Subject: [PATCH 30/35] Standardized case. --- ext/pdo_mysql/tests/subclasses/pdomysql_001.phpt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ext/pdo_mysql/tests/subclasses/pdomysql_001.phpt b/ext/pdo_mysql/tests/subclasses/pdomysql_001.phpt index 7b6f883d7b569..b4c08497882f7 100644 --- a/ext/pdo_mysql/tests/subclasses/pdomysql_001.phpt +++ b/ext/pdo_mysql/tests/subclasses/pdomysql_001.phpt @@ -7,11 +7,11 @@ pdo_mysql require_once __DIR__ . "/../config_functions.inc"; -if (class_exists(PdoMySql::class) === false) { - echo "PdoMySql class does not exist.\n"; +if (class_exists(PdoMysql::class) === false) { + echo "PdoMysql class does not exist.\n"; exit(-1); } -echo "PdoMySql class exists.\n"; +echo "PdoMysql class exists.\n"; [$dsn, $user, $pass] = getDsnUserAndPassword(); @@ -32,7 +32,7 @@ $db->query('DROP TABLE foobar'); echo "Fin."; ?> --EXPECT-- -PdoMySql class exists. +PdoMysql class exists. array(2) { ["name"]=> string(3) "PHP" From 61d8ae24e84b38b250e883181022dd67cb52a824 Mon Sep 17 00:00:00 2001 From: Danack Date: Tue, 18 Jul 2023 12:24:54 +0100 Subject: [PATCH 31/35] Remove trailing ?> --- ext/pdo_sqlite/tests/subclasses/stream_test.inc | 2 -- 1 file changed, 2 deletions(-) diff --git a/ext/pdo_sqlite/tests/subclasses/stream_test.inc b/ext/pdo_sqlite/tests/subclasses/stream_test.inc index e982173e94614..d4bee82fbc492 100644 --- a/ext/pdo_sqlite/tests/subclasses/stream_test.inc +++ b/ext/pdo_sqlite/tests/subclasses/stream_test.inc @@ -44,5 +44,3 @@ class PDOSQLite_Test_Stream } stream_wrapper_register('pdosqliteBlobTest', PDOSQLite_Test_Stream::class) or die("Unable to register pdosqliteBlobTest stream"); - -?> From bb3a6341d5313ce92fceaa8a941290b0917f72a8 Mon Sep 17 00:00:00 2001 From: Danack Date: Tue, 18 Jul 2023 12:36:15 +0100 Subject: [PATCH 32/35] Removed un-needed includes. --- ext/pdo_pgsql/pdo_pgsql_class.c | 2 -- ext/pdo_sqlite/pdo_sqlite_arginfo.h | 8 ++++---- ext/pdo_sqlite/pdo_sqlite_class.c | 2 -- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/ext/pdo_pgsql/pdo_pgsql_class.c b/ext/pdo_pgsql/pdo_pgsql_class.c index b55e03081b791..d78f94c5af27f 100644 --- a/ext/pdo_pgsql/pdo_pgsql_class.c +++ b/ext/pdo_pgsql/pdo_pgsql_class.c @@ -22,8 +22,6 @@ #endif #include "php.h" -#include "php_ini.h" -#include "ext/standard/info.h" #include "../pdo/php_pdo.h" #include "../pdo/php_pdo_driver.h" #include "../pdo/php_pdo_int.h" diff --git a/ext/pdo_sqlite/pdo_sqlite_arginfo.h b/ext/pdo_sqlite/pdo_sqlite_arginfo.h index c9ae2c976d150..6503dcfef9c0c 100644 --- a/ext/pdo_sqlite/pdo_sqlite_arginfo.h +++ b/ext/pdo_sqlite/pdo_sqlite_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 90e72918989ba39299db8af818e17d17a610eba3 */ + * Stub hash: 7702f8a3d098844742a87bcea211c6f23eb5b270 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PdoSqlite_createAggregate, 0, 3, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 0) @@ -20,7 +20,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PdoSqlite_createFunction, ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, flags, IS_LONG, 0, "0") ZEND_END_ARG_INFO() -#if !defined(SQLITE_OMIT_LOAD_EXTENSION) +#if !defined(PDO_SQLITE_OMIT_LOAD_EXTENSION) ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PdoSqlite_loadExtension, 0, 1, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 0) ZEND_END_ARG_INFO() @@ -38,7 +38,7 @@ ZEND_END_ARG_INFO() ZEND_METHOD(PdoSqlite, createAggregate); ZEND_METHOD(PdoSqlite, createCollation); ZEND_METHOD(PdoSqlite, createFunction); -#if !defined(SQLITE_OMIT_LOAD_EXTENSION) +#if !defined(PDO_SQLITE_OMIT_LOAD_EXTENSION) ZEND_METHOD(PdoSqlite, loadExtension); #endif ZEND_METHOD(PdoSqlite, openBlob); @@ -48,7 +48,7 @@ static const zend_function_entry class_PdoSqlite_methods[] = { ZEND_ME(PdoSqlite, createAggregate, arginfo_class_PdoSqlite_createAggregate, ZEND_ACC_PUBLIC) ZEND_ME(PdoSqlite, createCollation, arginfo_class_PdoSqlite_createCollation, ZEND_ACC_PUBLIC) ZEND_ME(PdoSqlite, createFunction, arginfo_class_PdoSqlite_createFunction, ZEND_ACC_PUBLIC) -#if !defined(SQLITE_OMIT_LOAD_EXTENSION) +#if !defined(PDO_SQLITE_OMIT_LOAD_EXTENSION) ZEND_ME(PdoSqlite, loadExtension, arginfo_class_PdoSqlite_loadExtension, ZEND_ACC_PUBLIC) #endif ZEND_ME(PdoSqlite, openBlob, arginfo_class_PdoSqlite_openBlob, ZEND_ACC_PUBLIC) diff --git a/ext/pdo_sqlite/pdo_sqlite_class.c b/ext/pdo_sqlite/pdo_sqlite_class.c index f0721670e743f..dcd8f34411d00 100644 --- a/ext/pdo_sqlite/pdo_sqlite_class.c +++ b/ext/pdo_sqlite/pdo_sqlite_class.c @@ -22,8 +22,6 @@ #endif #include "php.h" -#include "php_ini.h" -#include "ext/standard/info.h" #include "../pdo/php_pdo.h" #include "../pdo/php_pdo_driver.h" #include "../pdo/php_pdo_int.h" From 589c950b270d07ae791dc2c59664957c95b08c71 Mon Sep 17 00:00:00 2001 From: Danack Date: Tue, 18 Jul 2023 12:40:33 +0100 Subject: [PATCH 33/35] CS --- ext/pdo/pdo_dbh.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index abf6eb2b3e06f..c463b4fa84c8c 100644 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -335,8 +335,7 @@ void internal_construct(INTERNAL_FUNCTION_PARAMETERS, zval *object, zval *new_zv } dbh = Z_PDO_DBH_P(new_zval_object); - } - else { + } else { dbh = Z_PDO_DBH_P(object); } From 48e458bc29eea105e9541476df4a56ce7bf0f57c Mon Sep 17 00:00:00 2001 From: Danack Date: Tue, 18 Jul 2023 12:43:55 +0100 Subject: [PATCH 34/35] Change to ZEND_ASSERT --- ext/pdo/pdo_dbh.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index c463b4fa84c8c..e3c647bd3edec 100644 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -321,12 +321,7 @@ void internal_construct(INTERNAL_FUNCTION_PARAMETERS, zval *object, zval *new_zv } if (object == NULL) { - // could this ever happen? - if (driver->driver_name == NULL) { - zend_throw_exception_ex(php_pdo_get_exception(), 0, "Driver name is NULL"); - RETURN_THROWS(); - } - + ZEND_ASSERT((driver->driver_name != NULL) && "PDO driver name is null"); create_specific_pdo_object(new_zval_object, driver->driver_name); if (new_zval_object == NULL) { From b51d423cd9856663ea4dd9dd0d56014709783aa3 Mon Sep 17 00:00:00 2001 From: Danack Date: Tue, 18 Jul 2023 12:48:11 +0100 Subject: [PATCH 35/35] Change to unsigned int. remove setting something to null. --- ext/pdo/pdo_dbh.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index e3c647bd3edec..f7a8d85eb0f4f 100644 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -220,7 +220,7 @@ static char *dsn_from_uri(char *uri, char *buf, size_t buflen) /* {{{ */ #define MAX_PDO_SUB_CLASSES 64 -static int number_of_pdo_driver_class_entries = 0; +static unsigned int number_of_pdo_driver_class_entries = 0; static pdo_driver_class_entry *pdo_driver_class_entries[MAX_PDO_SUB_CLASSES]; // It would be possible remove this and roll it into the standard driver class entries @@ -228,7 +228,7 @@ static pdo_driver_class_entry *pdo_driver_class_entries[MAX_PDO_SUB_CLASSES]; void pdo_register_driver_specific_class(pdo_driver_class_entry *driver_class_entry) { if (number_of_pdo_driver_class_entries >= MAX_PDO_SUB_CLASSES) { - + // TODO - return false } pdo_driver_class_entries[number_of_pdo_driver_class_entries] = driver_class_entry; @@ -1490,7 +1490,6 @@ void pdo_dbh_init(void) memcpy(&pdosqlite_dbh_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); pdosqlite_dbh_object_handlers.offset = XtOffsetOf(pdo_dbh_object_t, std); pdosqlite_dbh_object_handlers.free_obj = pdo_dbh_free_storage; - pdosqlite_dbh_object_handlers.clone_obj = NULL; pdosqlite_dbh_object_handlers.get_method = dbh_method_get; pdosqlite_dbh_object_handlers.compare = zend_objects_not_comparable; pdosqlite_dbh_object_handlers.get_gc = dbh_get_gc;