diff --git a/UPGRADING b/UPGRADING index 9df115d1e735e..9457d157d4d1a 100644 --- a/UPGRADING +++ b/UPGRADING @@ -61,6 +61,9 @@ PHP 8.5 UPGRADE NOTES array value reference assignment: $ctor_args = [&$valByRef] . Attempting to modify a PDOStatement during a call to PDO::fetch(), PDO::fetchObject(), PDO::fetchAll() will now throw an Error. + . The value of the constants PDO::FETCH_GROUP, PDO::FETCH_UNIQUE, + PDO::FETCH_CLASSTYPE, PDO::FETCH_PROPS_LATE, and PDO::FETCH_SERIALIZE + has changed. - PDO_FIREBIRD: . A ValueError is now thrown when trying to set a cursor name that is too diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index 89db4a106e861..c8ac190d72080 100644 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -24,7 +24,6 @@ #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" @@ -36,7 +35,7 @@ #include "zend_observer.h" #include "zend_extensions.h" -static bool pdo_dbh_attribute_set(pdo_dbh_t *dbh, zend_long attr, zval *value); +static bool pdo_dbh_attribute_set(pdo_dbh_t *dbh, zend_long attr, zval *value, uint32_t value_arg_num); void pdo_throw_exception(unsigned int driver_errcode, char *driver_errmsg, pdo_error_type *pdo_error) { @@ -513,7 +512,7 @@ PDO_API void php_pdo_internal_construct_driver(INTERNAL_FUNCTION_PARAMETERS, zen ZVAL_DEREF(attr_value); /* TODO: Should the constructor fail when the attribute cannot be set? */ - pdo_dbh_attribute_set(dbh, long_key, attr_value); + pdo_dbh_attribute_set(dbh, long_key, attr_value, 3); } ZEND_HASH_FOREACH_END(); } @@ -777,7 +776,7 @@ PHP_METHOD(PDO, inTransaction) } /* }}} */ -PDO_API bool pdo_get_long_param(zend_long *lval, zval *value) +PDO_API bool pdo_get_long_param(zend_long *lval, const zval *value) { switch (Z_TYPE_P(value)) { case IS_LONG: @@ -795,7 +794,7 @@ PDO_API bool pdo_get_long_param(zend_long *lval, zval *value) return false; } } -PDO_API bool pdo_get_bool_param(bool *bval, zval *value) +PDO_API bool pdo_get_bool_param(bool *bval, const zval *value) { switch (Z_TYPE_P(value)) { case IS_TRUE: @@ -815,7 +814,7 @@ PDO_API bool pdo_get_bool_param(bool *bval, zval *value) } /* Return false on failure, true otherwise */ -static bool pdo_dbh_attribute_set(pdo_dbh_t *dbh, zend_long attr, zval *value) /* {{{ */ +static bool pdo_dbh_attribute_set(pdo_dbh_t *dbh, zend_long attr, zval *value, uint32_t value_arg_num) /* {{{ */ { zend_long lval; bool bval; @@ -832,7 +831,7 @@ static bool pdo_dbh_attribute_set(pdo_dbh_t *dbh, zend_long attr, zval *value) / dbh->error_mode = lval; return true; default: - zend_value_error("Error mode must be one of the PDO::ERRMODE_* constants"); + zend_argument_value_error(value_arg_num, "Error mode must be one of the PDO::ERRMODE_* constants"); return false; } return false; @@ -848,7 +847,7 @@ static bool pdo_dbh_attribute_set(pdo_dbh_t *dbh, zend_long attr, zval *value) / dbh->desired_case = lval; return true; default: - zend_value_error("Case folding mode must be one of the PDO::CASE_* constants"); + zend_argument_value_error(value_arg_num, "Case folding mode must be one of the PDO::CASE_* constants"); return false; } return false; @@ -862,22 +861,22 @@ static bool pdo_dbh_attribute_set(pdo_dbh_t *dbh, zend_long attr, zval *value) / return true; case PDO_ATTR_DEFAULT_FETCH_MODE: - if (Z_TYPE_P(value) == IS_ARRAY) { - zval *tmp; - if ((tmp = zend_hash_index_find(Z_ARRVAL_P(value), 0)) != NULL && Z_TYPE_P(tmp) == IS_LONG) { - if (Z_LVAL_P(tmp) == PDO_FETCH_INTO || Z_LVAL_P(tmp) == PDO_FETCH_CLASS) { - zend_value_error("PDO::FETCH_INTO and PDO::FETCH_CLASS cannot be set as the default fetch mode"); - return false; - } - } - lval = zval_get_long(value); - } else { - if (!pdo_get_long_param(&lval, value)) { - return false; - } + if (!pdo_get_long_param(&lval, value)) { + return false; + } + if (!pdo_verify_fetch_mode(PDO_FETCH_USE_DEFAULT, lval, value_arg_num, false)) { + return false; + } + if (UNEXPECTED( + lval == PDO_FETCH_USE_DEFAULT + || lval == PDO_FETCH_INTO + || lval == PDO_FETCH_FUNC + )) { + zend_argument_value_error(value_arg_num, "cannot set default fetch mode to PDO::FETCH_USE_DEFAULT, PDO::FETCH_INTO, PDO::FETCH_FUNC"); + return false; } - if (lval == PDO_FETCH_USE_DEFAULT) { - zend_value_error("Fetch mode must be a bitmask of PDO::FETCH_* constants"); + if (UNEXPECTED((lval & PDO_FETCH_CLASS) && (lval & PDO_FETCH_CLASSTYPE) == 0)) { + zend_argument_value_error(value_arg_num, "cannot set default fetch mode to PDO::FETCH_CLASS without PDO::FETCH_CLASSTYPE"); return false; } dbh->default_fetch_type = lval; @@ -907,25 +906,25 @@ static bool pdo_dbh_attribute_set(pdo_dbh_t *dbh, zend_long attr, zval *value) / return false; } if (Z_TYPE_P(value) != IS_ARRAY) { - zend_type_error("PDO::ATTR_STATEMENT_CLASS value must be of type array, %s given", + zend_argument_type_error(value_arg_num, "PDO::ATTR_STATEMENT_CLASS value must be of type array, %s given", zend_zval_value_name(value)); return false; } if ((item = zend_hash_index_find(Z_ARRVAL_P(value), 0)) == NULL) { - zend_value_error("PDO::ATTR_STATEMENT_CLASS value must be an array with the format " + zend_argument_value_error(value_arg_num, "PDO::ATTR_STATEMENT_CLASS value must be an array with the format " "array(classname, constructor_args)"); return false; } if (Z_TYPE_P(item) != IS_STRING || (pce = zend_lookup_class(Z_STR_P(item))) == NULL) { - zend_type_error("PDO::ATTR_STATEMENT_CLASS class must be a valid class"); + zend_argument_type_error(value_arg_num, "PDO::ATTR_STATEMENT_CLASS class must be a valid class"); return false; } if (!instanceof_function(pce, pdo_dbstmt_ce)) { - zend_type_error("PDO::ATTR_STATEMENT_CLASS class must be derived from PDOStatement"); + zend_argument_type_error(value_arg_num, "PDO::ATTR_STATEMENT_CLASS class must be derived from PDOStatement"); return false; } if (pce->constructor && !(pce->constructor->common.fn_flags & (ZEND_ACC_PRIVATE|ZEND_ACC_PROTECTED))) { - zend_type_error("User-supplied statement class cannot have a public constructor"); + zend_argument_type_error(value_arg_num, "User-supplied statement class cannot have a public constructor"); return false; } dbh->def_stmt_ce = pce; @@ -935,7 +934,7 @@ static bool pdo_dbh_attribute_set(pdo_dbh_t *dbh, zend_long attr, zval *value) / } if ((item = zend_hash_index_find(Z_ARRVAL_P(value), 1)) != NULL) { if (Z_TYPE_P(item) != IS_ARRAY) { - zend_type_error("PDO::ATTR_STATEMENT_CLASS constructor_args must be of type ?array, %s given", + zend_argument_type_error(value_arg_num, "PDO::ATTR_STATEMENT_CLASS constructor_args must be of type ?array, %s given", zend_zval_value_name(value)); return false; } @@ -981,7 +980,7 @@ PHP_METHOD(PDO, setAttribute) PDO_DBH_CLEAR_ERR(); PDO_CONSTRUCT_CHECK; - RETURN_BOOL(pdo_dbh_attribute_set(dbh, attr, value)); + RETURN_BOOL(pdo_dbh_attribute_set(dbh, attr, value, 2)); } /* }}} */ diff --git a/ext/pdo/pdo_stmt.c b/ext/pdo/pdo_stmt.c index b2b4984ef8177..38879e98901cc 100644 --- a/ext/pdo/pdo_stmt.c +++ b/ext/pdo/pdo_stmt.c @@ -693,7 +693,7 @@ static bool do_fetch(pdo_stmt_t *stmt, zval *return_value, enum pdo_fetch_type h if (how == PDO_FETCH_COLUMN) { int colno = stmt->fetch.column; - if ((flags & PDO_FETCH_GROUP) && stmt->fetch.column == -1) { + if ((flags & (PDO_FETCH_GROUP|PDO_FETCH_UNIQUE)) && stmt->fetch.column == -1) { colno = 1; } @@ -763,13 +763,6 @@ static bool do_fetch(pdo_stmt_t *stmt, zval *return_value, enum pdo_fetch_type h } zval_ptr_dtor(&ce_name_from_column); } else { - /* This can happen if the fetch flags are set via PDO::setAttribute() - * $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_CLASS); - * See ext/pdo/tests/bug_38253.phpt */ - if (UNEXPECTED(ce == NULL)) { - pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "No fetch class specified"); - goto in_fetch_error; - } ctor_arguments = stmt->fetch.cls.ctor_args; } ZEND_ASSERT(ce != NULL); @@ -794,14 +787,7 @@ static bool do_fetch(pdo_stmt_t *stmt, zval *return_value, enum pdo_fetch_type h break; case PDO_FETCH_INTO: - /* This can happen if the fetch flags are set via PDO::setAttribute() - * $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_INTO); - * See ext/pdo/tests/bug_38253.phpt */ - if (stmt->fetch.into == NULL) { - pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "No fetch-into object specified."); - goto in_fetch_error; - } - + ZEND_ASSERT(stmt->fetch.into != NULL); ZVAL_OBJ_COPY(return_value, stmt->fetch.into); /* We want the behaviour of fetching into an object to be called from the global scope rather @@ -810,13 +796,7 @@ static bool do_fetch(pdo_stmt_t *stmt, zval *return_value, enum pdo_fetch_type h break; case PDO_FETCH_FUNC: - /* This can happen if the fetch flags are set via PDO::setAttribute() - * $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_FUNC); - * See ext/pdo/tests/bug_38253.phpt */ - if (UNEXPECTED(!ZEND_FCC_INITIALIZED(stmt->fetch.func.fcc))) { - pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "No fetch function specified"); - goto in_fetch_error; - } + ZEND_ASSERT(ZEND_FCC_INITIALIZED(stmt->fetch.func.fcc)); /* There will be at most stmt->column_count parameters. * However, if we fetch a group key we will have over allocated. */ fetch_function_params = safe_emalloc(sizeof(zval), stmt->column_count, 0); @@ -946,59 +926,80 @@ static bool do_fetch(pdo_stmt_t *stmt, zval *return_value, enum pdo_fetch_type h // TODO Error on the following cases: -// Using any fetch flag with PDO_FETCH_KEY_PAIR // Combining PDO_FETCH_UNIQUE and PDO_FETCH_GROUP -// Using PDO_FETCH_UNIQUE or PDO_FETCH_GROUP outside of fetchAll() -// Combining PDO_FETCH_PROPS_LATE with a fetch mode different than PDO_FETCH_CLASS -// Improve error detection when combining PDO_FETCH_USE_DEFAULT with -// Reject PDO_FETCH_INTO mode with fetch_all as no support -// Reject $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, value); bypass -static bool pdo_stmt_verify_mode(pdo_stmt_t *stmt, zend_long mode, uint32_t mode_arg_num, bool fetch_all) /* {{{ */ +PDO_API bool pdo_verify_fetch_mode(uint32_t default_mode_and_flags, zend_long mode_and_flags, uint32_t mode_arg_num, bool fetch_all) /* {{{ */ { - int flags = mode & PDO_FETCH_FLAGS; - - mode = mode & ~PDO_FETCH_FLAGS; - - if (mode < 0 || mode >= PDO_FETCH__MAX) { + /* Mode must be a positive */ + if (mode_and_flags < 0 || mode_and_flags >= PDO_FIRST_INVALID_FLAG) { zend_argument_value_error(mode_arg_num, "must be a bitmask of PDO::FETCH_* constants"); - return 0; + return false; } + uint32_t flags = (zend_ulong)mode_and_flags & PDO_FETCH_FLAGS; + enum pdo_fetch_type mode = (zend_ulong)mode_and_flags & ~PDO_FETCH_FLAGS; + if (mode == PDO_FETCH_USE_DEFAULT) { - flags = stmt->default_fetch_type & PDO_FETCH_FLAGS; - mode = stmt->default_fetch_type & ~PDO_FETCH_FLAGS; + flags = default_mode_and_flags & PDO_FETCH_FLAGS; + mode = default_mode_and_flags & ~PDO_FETCH_FLAGS; + } + + /* Flags can only be used in limited circumstances */ + if (flags != 0) { + bool has_class_flags = (flags & (PDO_FETCH_CLASSTYPE|PDO_FETCH_PROPS_LATE|PDO_FETCH_SERIALIZE)) != 0; + if (has_class_flags && mode != PDO_FETCH_CLASS) { + zend_argument_value_error(mode_arg_num, "cannot use PDO::FETCH_CLASSTYPE, PDO::FETCH_PROPS_LATE, or PDO::FETCH_SERIALIZE fetch flags with a fetch mode different than PDO::FETCH_CLASS"); + return false; + } + // TODO Prevent setting those flags together or not? This would affect PDO::setFetchMode() + //bool has_grouping_flags = flags & (PDO_FETCH_GROUP|PDO_FETCH_UNIQUE); + //if (has_grouping_flags && !fetch_all) { + // zend_argument_value_error(mode_arg_num, "cannot use PDO::FETCH_GROUP, or PDO::FETCH_UNIQUE fetch flags outside of PDOStatemnt::fetchAll()"); + // return false; + //} + if (flags & PDO_FETCH_SERIALIZE) { + php_error_docref(NULL, E_DEPRECATED, "The PDO::FETCH_SERIALIZE mode is deprecated"); + if (UNEXPECTED(EG(exception))) { + return false; + } + } } - switch(mode) { + switch (mode) { case PDO_FETCH_FUNC: if (!fetch_all) { - zend_value_error("Can only use PDO::FETCH_FUNC in PDOStatement::fetchAll()"); - return 0; + zend_argument_value_error(mode_arg_num, "PDO::FETCH_FUNC can only be used with PDOStatement::fetchAll()"); + return false; } - return 1; + return true; case PDO_FETCH_LAZY: if (fetch_all) { - zend_argument_value_error(mode_arg_num, "cannot be PDO::FETCH_LAZY in PDOStatement::fetchAll()"); - return 0; - } - ZEND_FALLTHROUGH; - default: - if ((flags & PDO_FETCH_SERIALIZE) == PDO_FETCH_SERIALIZE) { - zend_argument_value_error(mode_arg_num, "must use PDO::FETCH_SERIALIZE with PDO::FETCH_CLASS"); - return 0; + zend_argument_value_error(mode_arg_num, "PDO::FETCH_LAZY cannot be used with PDOStatement::fetchAll()"); + return false; } - if ((flags & PDO_FETCH_CLASSTYPE) == PDO_FETCH_CLASSTYPE) { - zend_argument_value_error(mode_arg_num, "must use PDO::FETCH_CLASSTYPE with PDO::FETCH_CLASS"); - return 0; + return true; + + case PDO_FETCH_INTO: + if (fetch_all) { + zend_argument_value_error(mode_arg_num, "PDO::FETCH_INTO cannot be used with PDOStatement::fetchAll()"); + return false; } - ZEND_FALLTHROUGH; + return true; + case PDO_FETCH_ASSOC: + case PDO_FETCH_NUM: + case PDO_FETCH_BOTH: + case PDO_FETCH_OBJ: + case PDO_FETCH_BOUND: + case PDO_FETCH_COLUMN: case PDO_FETCH_CLASS: - if (flags & PDO_FETCH_SERIALIZE) { - php_error_docref(NULL, E_DEPRECATED, "The PDO::FETCH_SERIALIZE mode is deprecated"); - } - return 1; + case PDO_FETCH_NAMED: + case PDO_FETCH_KEY_PAIR: + return true; + + default: + zend_argument_value_error(mode_arg_num, "must be a bitmask of PDO::FETCH_* constants"); + return false; } } /* }}} */ @@ -1020,7 +1021,7 @@ PHP_METHOD(PDOStatement, fetch) PHP_STMT_GET_OBJ; PDO_STMT_CLEAR_ERR(); - if (!pdo_stmt_verify_mode(stmt, how, 1, false)) { + if (!pdo_verify_fetch_mode(stmt->default_fetch_type, how, 1, false)) { RETURN_THROWS(); } @@ -1140,7 +1141,7 @@ PHP_METHOD(PDOStatement, fetchAll) ZEND_PARSE_PARAMETERS_END(); PHP_STMT_GET_OBJ; - if (!pdo_stmt_verify_mode(stmt, how, 1, true)) { + if (!pdo_verify_fetch_mode(stmt->default_fetch_type, how, 1, true)) { RETURN_THROWS(); } @@ -1215,7 +1216,7 @@ PHP_METHOD(PDOStatement, fetchAll) } stmt->fetch.column = Z_LVAL_P(arg2); } else { - stmt->fetch.column = flags & PDO_FETCH_GROUP ? -1 : 0; + stmt->fetch.column = flags & (PDO_FETCH_GROUP|PDO_FETCH_UNIQUE) ? -1 : 0; } break; @@ -1576,12 +1577,8 @@ void pdo_stmt_free_default_fetch_mode(pdo_stmt_t *stmt) { enum pdo_fetch_type default_fetch_mode = stmt->default_fetch_type & ~PDO_FETCH_FLAGS; if (default_fetch_mode == PDO_FETCH_INTO) { - /* This can happen if the fetch flags are set via PDO::setAttribute() - * $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_INTO); - * See ext/pdo/tests/bug_38253.phpt */ - if (EXPECTED(stmt->fetch.into != NULL)) { - OBJ_RELEASE(stmt->fetch.into); - } + ZEND_ASSERT(stmt->fetch.into != NULL); + OBJ_RELEASE(stmt->fetch.into); } else if (default_fetch_mode == PDO_FETCH_CLASS) { if (stmt->fetch.cls.ctor_args != NULL) { zend_array_release(stmt->fetch.cls.ctor_args); @@ -1606,7 +1603,7 @@ bool pdo_stmt_setup_fetch_mode(pdo_stmt_t *stmt, zend_long mode, uint32_t mode_a flags = mode & PDO_FETCH_FLAGS; - if (!pdo_stmt_verify_mode(stmt, mode, mode_arg_num, false)) { + if (!pdo_verify_fetch_mode(stmt->default_fetch_type, mode, mode_arg_num, false)) { return false; } diff --git a/ext/pdo/php_pdo_driver.h b/ext/pdo/php_pdo_driver.h index afaae4023d3ea..af749cc128ea3 100644 --- a/ext/pdo/php_pdo_driver.h +++ b/ext/pdo/php_pdo_driver.h @@ -63,6 +63,7 @@ enum pdo_param_type { #define PDO_PARAM_TYPE(x) ((x) & ~PDO_PARAM_FLAGS) +/* Fetch mode is a bitmask of the fetch type (first 4 bits) with the fetch flags (bit 5 to 9)*/ enum pdo_fetch_type { PDO_FETCH_USE_DEFAULT, PDO_FETCH_LAZY, @@ -77,15 +78,17 @@ enum pdo_fetch_type { PDO_FETCH_FUNC, /* fetch into function and return its result */ PDO_FETCH_NAMED, /* like PDO_FETCH_ASSOC, but can handle duplicate names */ PDO_FETCH_KEY_PAIR, /* fetch into an array where the 1st column is a key and all subsequent columns are values */ - PDO_FETCH__MAX /* must be last */ }; -#define PDO_FETCH_FLAGS 0xFFFF0000 /* fetchAll() modes or'd to PDO_FETCH_XYZ */ -#define PDO_FETCH_GROUP 0x00010000 /* fetch into groups */ -#define PDO_FETCH_UNIQUE 0x00030000 /* fetch into groups assuming first col is unique */ -#define PDO_FETCH_CLASSTYPE 0x00040000 /* fetch class gets its class name from 1st column */ -#define PDO_FETCH_SERIALIZE 0x00080000 /* fetch class instances by calling serialize */ -#define PDO_FETCH_PROPS_LATE 0x00100000 /* fetch props after calling ctor */ +#define PDO_FETCH_FLAGS 0xFFFFFFF0 /* fetch flags mask */ +#define PDO_FETCH_GROUP (1u << 5u) /* fetch into groups */ +#define PDO_FETCH_UNIQUE (1u << 6u) /* fetch into groups assuming first col is unique */ +/* PDO_FETCH_CLASS only flags */ +#define PDO_FETCH_CLASSTYPE (1u << 7u) /* fetch class gets its class name from 1st column */ +#define PDO_FETCH_PROPS_LATE (1u << 8u) /* fetch props after calling ctor */ +#define PDO_FETCH_SERIALIZE (1u << 9u) /* DEPRECATED: fetch class instances by calling serialize */ +#define PDO_FIRST_INVALID_FLAG (1u << 10u) + /* fetch orientation for scrollable cursors */ enum pdo_fetch_orientation { @@ -465,9 +468,12 @@ struct _pdo_dbh_t { /* bitmap for pdo_param_event(s) to skip in dispatch_param_event */ unsigned skip_param_evt:7; + /* defaults for fetches */ + unsigned default_fetch_type:9; + /* the sum of the number of bits here and the bit fields preceding should * equal 32 */ - unsigned _reserved_flags:14; + unsigned _reserved_flags:5; /* data source string used to open this handle */ const char *data_source; @@ -500,9 +506,6 @@ struct _pdo_dbh_t { * when PDO::query() fails */ pdo_stmt_t *query_stmt; zval query_stmt_zval; - - /* defaults for fetches */ - enum pdo_fetch_type default_fetch_type; }; /* represents a connection to a database */ @@ -574,7 +577,10 @@ struct _pdo_stmt_t { * bindParam() for its prepared statements, if false, PDO should * emulate prepare and bind on its behalf */ uint16_t supports_placeholders:2; - uint16_t reserved: 12; + + /* defaults for fetches */ + uint16_t default_fetch_type:9; + uint16_t reserved:3; /* keep track of bound input parameters. Some drivers support * input/output parameters, but you can't rely on that working */ @@ -592,9 +598,6 @@ struct _pdo_stmt_t { * */ int32_t column_count; - /* defaults for fetches */ - enum pdo_fetch_type default_fetch_type; - union { int column; struct { @@ -698,8 +701,10 @@ PDO_API void php_pdo_stmt_set_column_count(pdo_stmt_t *stmt, int new_count); PDO_API void php_pdo_internal_construct_driver(INTERNAL_FUNCTION_PARAMETERS, zend_object *current_object, zend_class_entry *called_scope, zval *new_zval_object); /* Normalization for fetching long param for driver attributes */ -PDO_API bool pdo_get_long_param(zend_long *lval, zval *value); -PDO_API bool pdo_get_bool_param(bool *bval, zval *value); +PDO_API bool pdo_get_long_param(zend_long *lval, const zval *value); +PDO_API bool pdo_get_bool_param(bool *bval, const zval *value); + +PDO_API bool pdo_verify_fetch_mode(uint32_t default_mode_and_flags, zend_long mode_and_flags, uint32_t mode_arg_num, bool fetch_all); PDO_API void pdo_throw_exception(unsigned int driver_errcode, char *driver_errmsg, pdo_error_type *pdo_error); diff --git a/ext/pdo/tests/bug_38253.phpt b/ext/pdo/tests/bug_38253.phpt index 91d94d31aeef8..a58b2ec8d95c8 100644 --- a/ext/pdo/tests/bug_38253.phpt +++ b/ext/pdo/tests/bug_38253.phpt @@ -18,20 +18,32 @@ $pdo = PDOTest::factory(); $pdo->exec ("create table test38253 (id integer primary key, n varchar(255))"); $pdo->exec ("INSERT INTO test38253 (id, n) VALUES (1, 'hi')"); -$pdo->setAttribute (PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_CLASS); -$stmt = $pdo->prepare ("SELECT * FROM test38253"); -$stmt->execute(); -var_dump($stmt->fetchAll()); +try { + $pdo->setAttribute (PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_CLASS); + $stmt = $pdo->prepare ("SELECT * FROM test38253"); + $stmt->execute(); + var_dump($stmt->fetchAll()); +} catch (\Throwable $e) { + echo $e::class, ': ', $e->getMessage(), \PHP_EOL; +} -$pdo->setAttribute (PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_FUNC); -$stmt = $pdo->prepare ("SELECT * FROM test38253"); -$stmt->execute(); -var_dump($stmt->fetchAll()); +try { + $pdo->setAttribute (PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_FUNC); + $stmt = $pdo->prepare ("SELECT * FROM test38253"); + $stmt->execute(); + var_dump($stmt->fetchAll()); +} catch (\Throwable $e) { + echo $e::class, ': ', $e->getMessage(), \PHP_EOL; +} -$pdo->setAttribute (PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_INTO); -$stmt = $pdo->prepare ("SELECT * FROM test38253"); -$stmt->execute(); -var_dump($stmt->fetchAll()); +try { + $pdo->setAttribute (PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_INTO); + $stmt = $pdo->prepare ("SELECT * FROM test38253"); + $stmt->execute(); + var_dump($stmt->fetch()); +} catch (\Throwable $e) { + echo $e::class, ': ', $e->getMessage(), \PHP_EOL; +} ?> --CLEAN-- @@ -40,21 +52,7 @@ require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc'; $db = PDOTest::factory(); PDOTest::dropTableIfExists($db, "test38253"); ?> ---EXPECTF-- -Warning: PDOStatement::fetchAll(): SQLSTATE[HY000]: General error: No fetch class specified in %s on line %d - -Warning: PDOStatement::fetchAll(): SQLSTATE[HY000]: General error in %s on line %d -array(0) { -} - -Warning: PDOStatement::fetchAll(): SQLSTATE[HY000]: General error: No fetch function specified in %s on line %d - -Warning: PDOStatement::fetchAll(): SQLSTATE[HY000]: General error in %s on line %d -array(0) { -} - -Warning: PDOStatement::fetchAll(): SQLSTATE[HY000]: General error: No fetch-into object specified. in %s on line %d - -Warning: PDOStatement::fetchAll(): SQLSTATE[HY000]: General error in %s on line %d -array(0) { -} +--EXPECT-- +ValueError: PDO::setAttribute(): Argument #2 ($value) cannot set default fetch mode to PDO::FETCH_CLASS without PDO::FETCH_CLASSTYPE +ValueError: PDO::setAttribute(): Argument #2 ($value) PDO::FETCH_FUNC can only be used with PDOStatement::fetchAll() +ValueError: PDO::setAttribute(): Argument #2 ($value) cannot set default fetch mode to PDO::FETCH_USE_DEFAULT, PDO::FETCH_INTO, PDO::FETCH_FUNC diff --git a/ext/pdo/tests/bug_44159.phpt b/ext/pdo/tests/bug_44159.phpt index 9d6b2876a15ef..1784324875edc 100644 --- a/ext/pdo/tests/bug_44159.phpt +++ b/ext/pdo/tests/bug_44159.phpt @@ -40,9 +40,9 @@ foreach ($attrs as $attr) { ?> --EXPECT-- -TypeError: PDO::ATTR_STATEMENT_CLASS value must be of type array, null given -TypeError: PDO::ATTR_STATEMENT_CLASS value must be of type array, int given -TypeError: PDO::ATTR_STATEMENT_CLASS value must be of type array, string given +TypeError: PDO::setAttribute(): Argument #2 ($value) PDO::ATTR_STATEMENT_CLASS value must be of type array, null given +TypeError: PDO::setAttribute(): Argument #2 ($value) PDO::ATTR_STATEMENT_CLASS value must be of type array, int given +TypeError: PDO::setAttribute(): Argument #2 ($value) PDO::ATTR_STATEMENT_CLASS value must be of type array, string given TypeError: Attribute value must be of type bool for selected attribute, null given bool(true) TypeError: Attribute value must be of type bool for selected attribute, string given diff --git a/ext/pdo_mysql/tests/pdo_mysql_attr_errmode.phpt b/ext/pdo_mysql/tests/pdo_mysql_attr_errmode.phpt index df5f6c99d3483..95fcb16824c0f 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_attr_errmode.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_attr_errmode.phpt @@ -158,7 +158,7 @@ error_reporting=E_ALL TypeError: Attribute value must be of type int for selected attribute, array given TypeError: Attribute value must be of type int for selected attribute, stdClass given TypeError: Attribute value must be of type int for selected attribute, string given -ValueError: Error mode must be one of the PDO::ERRMODE_* constants +ValueError: PDO::setAttribute(): Argument #2 ($value) Error mode must be one of the PDO::ERRMODE_* constants Warning: PDO::query(): SQLSTATE[42000]: Syntax error or access violation: %d You have an error in your SQL syntax; check the manual that corresponds to your %s server version for the right syntax to use near '%s' at line %d in %s on line %d diff --git a/ext/pdo_mysql/tests/pdo_mysql_attr_statement_class.phpt b/ext/pdo_mysql/tests/pdo_mysql_attr_statement_class.phpt index a22af1cbdefb1..c932d14288d15 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_attr_statement_class.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_attr_statement_class.phpt @@ -136,11 +136,11 @@ array(1) { [0]=> string(12) "PDOStatement" } -PDO::ATTR_STATEMENT_CLASS value must be of type array, string given -PDO::ATTR_STATEMENT_CLASS class must be a valid class -PDO::ATTR_STATEMENT_CLASS class must be a valid class -PDO::ATTR_STATEMENT_CLASS class must be derived from PDOStatement -TypeError: User-supplied statement class cannot have a public constructor +PDO::setAttribute(): Argument #2 ($value) PDO::ATTR_STATEMENT_CLASS value must be of type array, string given +PDO::setAttribute(): Argument #2 ($value) PDO::ATTR_STATEMENT_CLASS class must be a valid class +PDO::setAttribute(): Argument #2 ($value) PDO::ATTR_STATEMENT_CLASS class must be a valid class +PDO::setAttribute(): Argument #2 ($value) PDO::ATTR_STATEMENT_CLASS class must be derived from PDOStatement +TypeError: PDO::setAttribute(): Argument #2 ($value) User-supplied statement class cannot have a public constructor array(2) { [0]=> string(12) "mystatement4"