mirror of
https://github.com/php/php-src.git
synced 2026-04-18 13:31:27 +02:00
Use zpp for PDO fetch mode
Also changing the function signatures to accept variadic args for the fetch params. If we're already breaking Doctrine anyway, we may as well do it properly.
This commit is contained in:
@@ -1025,17 +1025,13 @@ PHP_METHOD(PDO, query)
|
||||
pdo_stmt_t *stmt;
|
||||
char *statement;
|
||||
size_t statement_len;
|
||||
zend_long fetch_mode;
|
||||
zval *args = NULL;
|
||||
uint32_t num_args = 0;
|
||||
pdo_dbh_object_t *dbh_obj = Z_PDO_OBJECT_P(ZEND_THIS);
|
||||
pdo_dbh_t *dbh = dbh_obj->inner;
|
||||
|
||||
/* Return a meaningful error when no parameters were passed */
|
||||
if (!ZEND_NUM_ARGS()) {
|
||||
zend_parse_parameters(0, "z|z", NULL, NULL);
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
if (FAILURE == zend_parse_parameters(1, "s", &statement,
|
||||
&statement_len)) {
|
||||
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "s|l*", &statement, &statement_len, &fetch_mode, &args, &num_args)) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
@@ -1065,7 +1061,7 @@ PHP_METHOD(PDO, query)
|
||||
|
||||
if (dbh->methods->preparer(dbh, statement, statement_len, stmt, NULL)) {
|
||||
PDO_STMT_CLEAR_ERR();
|
||||
if (ZEND_NUM_ARGS() == 1 || SUCCESS == pdo_stmt_setup_fetch_mode(INTERNAL_FUNCTION_PARAM_PASSTHRU, stmt, 1)) {
|
||||
if (ZEND_NUM_ARGS() == 1 || SUCCESS == pdo_stmt_setup_fetch_mode(stmt, fetch_mode, args, num_args)) {
|
||||
|
||||
/* now execute the statement */
|
||||
PDO_STMT_CLEAR_ERR();
|
||||
|
||||
@@ -37,7 +37,7 @@ class PDO
|
||||
public function prepare(string $statement, array $driver_options = []) {}
|
||||
|
||||
/** @return PDOStatement|false */
|
||||
public function query(string $statement) {}
|
||||
public function query(string $statement, int $fetch_mode = UNKNOWN, ...$fetch_mode_args) {}
|
||||
|
||||
/** @return string|false */
|
||||
public function quote(string $string, int $parameter_type = PDO::PARAM_STR) {}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* This is a generated file, edit the .stub.php file instead.
|
||||
* Stub hash: 38748c44d78c0173218bcb771b466d2a04bc87ad */
|
||||
* Stub hash: c329bfda55244467a2cd62f9d5c5120ec3f24eef */
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_PDO___construct, 0, 0, 1)
|
||||
ZEND_ARG_TYPE_INFO(0, dsn, IS_STRING, 0)
|
||||
@@ -38,7 +38,11 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_PDO_prepare, 0, 0, 1)
|
||||
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, driver_options, IS_ARRAY, 0, "[]")
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
#define arginfo_class_PDO_query arginfo_class_PDO_exec
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_PDO_query, 0, 0, 1)
|
||||
ZEND_ARG_TYPE_INFO(0, statement, IS_STRING, 0)
|
||||
ZEND_ARG_TYPE_INFO(0, fetch_mode, IS_LONG, 0)
|
||||
ZEND_ARG_VARIADIC_INFO(0, fetch_mode_args)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_PDO_quote, 0, 0, 1)
|
||||
ZEND_ARG_TYPE_INFO(0, string, IS_STRING, 0)
|
||||
|
||||
@@ -1725,11 +1725,9 @@ PHP_METHOD(PDOStatement, getColumnMeta)
|
||||
|
||||
/* {{{ Changes the default fetch mode for subsequent fetches (params have different meaning for different fetch modes) */
|
||||
|
||||
int pdo_stmt_setup_fetch_mode(INTERNAL_FUNCTION_PARAMETERS, pdo_stmt_t *stmt, int skip)
|
||||
int pdo_stmt_setup_fetch_mode(pdo_stmt_t *stmt, zend_long mode, zval *args, uint32_t num_args)
|
||||
{
|
||||
zend_long mode = PDO_FETCH_BOTH;
|
||||
int flags = 0, argc = ZEND_NUM_ARGS() - skip;
|
||||
zval *args;
|
||||
int flags = 0;
|
||||
zend_class_entry *cep;
|
||||
int retval;
|
||||
|
||||
@@ -1748,29 +1746,11 @@ int pdo_stmt_setup_fetch_mode(INTERNAL_FUNCTION_PARAMETERS, pdo_stmt_t *stmt, in
|
||||
|
||||
stmt->default_fetch_type = PDO_FETCH_BOTH;
|
||||
|
||||
if (argc == 0) {
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
args = safe_emalloc(ZEND_NUM_ARGS(), sizeof(zval), 0);
|
||||
|
||||
retval = zend_get_parameters_array_ex(ZEND_NUM_ARGS(), args);
|
||||
|
||||
if (SUCCESS == retval) {
|
||||
if (Z_TYPE(args[skip]) != IS_LONG) {
|
||||
pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "mode must be an integer");
|
||||
retval = FAILURE;
|
||||
} else {
|
||||
mode = Z_LVAL(args[skip]);
|
||||
flags = mode & PDO_FETCH_FLAGS;
|
||||
|
||||
retval = pdo_stmt_verify_mode(stmt, mode, 0);
|
||||
}
|
||||
}
|
||||
flags = mode & PDO_FETCH_FLAGS;
|
||||
retval = pdo_stmt_verify_mode(stmt, mode, 0);
|
||||
|
||||
if (FAILURE == retval) {
|
||||
PDO_STMT_CLEAR_ERR();
|
||||
efree(args);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
@@ -1785,7 +1765,7 @@ int pdo_stmt_setup_fetch_mode(INTERNAL_FUNCTION_PARAMETERS, pdo_stmt_t *stmt, in
|
||||
case PDO_FETCH_BOUND:
|
||||
case PDO_FETCH_NAMED:
|
||||
case PDO_FETCH_KEY_PAIR:
|
||||
if (argc != 1) {
|
||||
if (num_args != 0) {
|
||||
pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "fetch mode doesn't allow any extra arguments");
|
||||
} else {
|
||||
retval = SUCCESS;
|
||||
@@ -1793,12 +1773,12 @@ int pdo_stmt_setup_fetch_mode(INTERNAL_FUNCTION_PARAMETERS, pdo_stmt_t *stmt, in
|
||||
break;
|
||||
|
||||
case PDO_FETCH_COLUMN:
|
||||
if (argc != 2) {
|
||||
if (num_args != 1) {
|
||||
pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "fetch mode requires the colno argument");
|
||||
} else if (Z_TYPE(args[skip+1]) != IS_LONG) {
|
||||
} else if (Z_TYPE(args[0]) != IS_LONG) {
|
||||
pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "colno must be an integer");
|
||||
} else {
|
||||
stmt->fetch.column = Z_LVAL(args[skip+1]);
|
||||
stmt->fetch.column = Z_LVAL(args[0]);
|
||||
retval = SUCCESS;
|
||||
}
|
||||
break;
|
||||
@@ -1806,21 +1786,21 @@ int pdo_stmt_setup_fetch_mode(INTERNAL_FUNCTION_PARAMETERS, pdo_stmt_t *stmt, in
|
||||
case PDO_FETCH_CLASS:
|
||||
/* Gets its class name from 1st column */
|
||||
if ((flags & PDO_FETCH_CLASSTYPE) == PDO_FETCH_CLASSTYPE) {
|
||||
if (argc != 1) {
|
||||
if (num_args != 0) {
|
||||
pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "fetch mode doesn't allow any extra arguments");
|
||||
} else {
|
||||
stmt->fetch.cls.ce = NULL;
|
||||
retval = SUCCESS;
|
||||
}
|
||||
} else {
|
||||
if (argc < 2) {
|
||||
if (num_args < 1) {
|
||||
pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "fetch mode requires the classname argument");
|
||||
} else if (argc > 3) {
|
||||
} else if (num_args > 2) {
|
||||
pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "too many arguments");
|
||||
} else if (Z_TYPE(args[skip+1]) != IS_STRING) {
|
||||
} else if (Z_TYPE(args[0]) != IS_STRING) {
|
||||
pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "classname must be a string");
|
||||
} else {
|
||||
cep = zend_lookup_class(Z_STR(args[skip+1]));
|
||||
cep = zend_lookup_class(Z_STR(args[0]));
|
||||
if (cep) {
|
||||
retval = SUCCESS;
|
||||
stmt->fetch.cls.ce = cep;
|
||||
@@ -1835,12 +1815,12 @@ int pdo_stmt_setup_fetch_mode(INTERNAL_FUNCTION_PARAMETERS, pdo_stmt_t *stmt, in
|
||||
php_error_docref(NULL, E_WARNING, "PHP might crash if you don't call $stmt->setFetchMode() to reset to defaults on this persistent statement. This will be fixed in a later release");
|
||||
}
|
||||
#endif
|
||||
if (argc == 3) {
|
||||
if (Z_TYPE(args[skip+2]) != IS_NULL && Z_TYPE(args[skip+2]) != IS_ARRAY) {
|
||||
if (num_args == 2) {
|
||||
if (Z_TYPE(args[1]) != IS_NULL && Z_TYPE(args[1]) != IS_ARRAY) {
|
||||
pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "ctor_args must be either NULL or an array");
|
||||
retval = FAILURE;
|
||||
} else if (Z_TYPE(args[skip+2]) == IS_ARRAY && zend_hash_num_elements(Z_ARRVAL(args[skip+2]))) {
|
||||
ZVAL_ARR(&stmt->fetch.cls.ctor_args, zend_array_dup(Z_ARRVAL(args[skip+2])));
|
||||
} else if (Z_TYPE(args[1]) == IS_ARRAY && zend_hash_num_elements(Z_ARRVAL(args[1]))) {
|
||||
ZVAL_ARR(&stmt->fetch.cls.ctor_args, zend_array_dup(Z_ARRVAL(args[1])));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1852,9 +1832,9 @@ int pdo_stmt_setup_fetch_mode(INTERNAL_FUNCTION_PARAMETERS, pdo_stmt_t *stmt, in
|
||||
break;
|
||||
|
||||
case PDO_FETCH_INTO:
|
||||
if (argc != 2) {
|
||||
if (num_args != 1) {
|
||||
pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "fetch mode requires the object parameter");
|
||||
} else if (Z_TYPE(args[skip+1]) != IS_OBJECT) {
|
||||
} else if (Z_TYPE(args[0]) != IS_OBJECT) {
|
||||
pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "object must be an object");
|
||||
} else {
|
||||
retval = SUCCESS;
|
||||
@@ -1866,7 +1846,7 @@ int pdo_stmt_setup_fetch_mode(INTERNAL_FUNCTION_PARAMETERS, pdo_stmt_t *stmt, in
|
||||
php_error_docref(NULL, E_WARNING, "PHP might crash if you don't call $stmt->setFetchMode() to reset to defaults on this persistent statement. This will be fixed in a later release");
|
||||
}
|
||||
#endif
|
||||
ZVAL_COPY(&stmt->fetch.into, &args[skip+1]);
|
||||
ZVAL_COPY(&stmt->fetch.into, &args[0]);
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -1888,19 +1868,21 @@ int pdo_stmt_setup_fetch_mode(INTERNAL_FUNCTION_PARAMETERS, pdo_stmt_t *stmt, in
|
||||
*/
|
||||
PDO_STMT_CLEAR_ERR();
|
||||
|
||||
efree(args);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
PHP_METHOD(PDOStatement, setFetchMode)
|
||||
{
|
||||
zend_long fetch_mode;
|
||||
zval *args = NULL;
|
||||
uint32_t num_args = 0;
|
||||
PHP_STMT_GET_OBJ;
|
||||
|
||||
RETVAL_BOOL(
|
||||
pdo_stmt_setup_fetch_mode(INTERNAL_FUNCTION_PARAM_PASSTHRU,
|
||||
stmt, 0) == SUCCESS
|
||||
);
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "l*", &fetch_mode, &args, &num_args) == FAILURE) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
RETVAL_BOOL(pdo_stmt_setup_fetch_mode(stmt, fetch_mode, args, num_args) == SUCCESS);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ class PDOStatement implements IteratorAggregate
|
||||
public function setAttribute(int $attribute, $value) {}
|
||||
|
||||
/** @return bool */
|
||||
public function setFetchMode(int $mode, $param1 = UNKNOWN, $param2 = UNKNOWN) {}
|
||||
public function setFetchMode(int $mode, ...$params) {}
|
||||
|
||||
public function getIterator(): Iterator {}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* This is a generated file, edit the .stub.php file instead.
|
||||
* Stub hash: 77e61065025ff7394466ef6d683d37b4a1c793e7 */
|
||||
* Stub hash: 590a642abbc8d54be143a1c595e9e704888e9b5f */
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_PDOStatement_bindColumn, 0, 0, 2)
|
||||
ZEND_ARG_TYPE_MASK(0, column, MAY_BE_LONG|MAY_BE_STRING, NULL)
|
||||
@@ -78,8 +78,7 @@ ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_PDOStatement_setFetchMode, 0, 0, 1)
|
||||
ZEND_ARG_TYPE_INFO(0, mode, IS_LONG, 0)
|
||||
ZEND_ARG_INFO(0, param1)
|
||||
ZEND_ARG_INFO(0, param2)
|
||||
ZEND_ARG_VARIADIC_INFO(0, params)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_PDOStatement_getIterator, 0, 0, Iterator, 0)
|
||||
|
||||
@@ -41,7 +41,7 @@ void pdo_dbstmt_free_storage(zend_object *std);
|
||||
zend_object_iterator *pdo_stmt_iter_get(zend_class_entry *ce, zval *object, int by_ref);
|
||||
extern zend_object_handlers pdo_dbstmt_object_handlers;
|
||||
int pdo_stmt_describe_columns(pdo_stmt_t *stmt);
|
||||
int pdo_stmt_setup_fetch_mode(INTERNAL_FUNCTION_PARAMETERS, pdo_stmt_t *stmt, int skip_first_arg);
|
||||
int pdo_stmt_setup_fetch_mode(pdo_stmt_t *stmt, zend_long fetch_mode, zval *args, uint32_t num_args);
|
||||
|
||||
extern zend_object *pdo_row_new(zend_class_entry *ce);
|
||||
extern const zend_function_entry pdo_row_functions[];
|
||||
|
||||
@@ -24,9 +24,11 @@ var_dump($stmt);
|
||||
|
||||
|
||||
// Bug entry [3]
|
||||
$stmt = $db->query("SELECT * FROM test", 'abc');
|
||||
var_dump($stmt);
|
||||
|
||||
try {
|
||||
$stmt = $db->query("SELECT * FROM test", 'abc');
|
||||
} catch (TypeError $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
|
||||
// Bug entry [4]
|
||||
$stmt = $db->query("SELECT * FROM test", PDO::FETCH_CLASS, 0, 0, 0);
|
||||
@@ -52,9 +54,7 @@ var_dump($stmt);
|
||||
--EXPECTF--
|
||||
Warning: PDO::query(): SQLSTATE[HY000]: General error: fetch mode doesn't allow any extra arguments in %s
|
||||
bool(false)
|
||||
|
||||
Warning: PDO::query(): SQLSTATE[HY000]: General error: mode must be an integer in %s
|
||||
bool(false)
|
||||
PDO::query(): Argument #2 ($fetch_mode) must be of type int, string given
|
||||
|
||||
Warning: PDO::query(): SQLSTATE[HY000]: General error: too many arguments in %s
|
||||
bool(false)
|
||||
|
||||
@@ -47,7 +47,7 @@ class PDODatabaseX extends PDO
|
||||
$this->test2 = 22;
|
||||
}
|
||||
|
||||
function query($sql)
|
||||
function query($sql, ...$rest)
|
||||
{
|
||||
echo __METHOD__ . "()\n";
|
||||
$stmt = parent::prepare($sql, array(PDO::ATTR_STATEMENT_CLASS=>array('PDOStatementx')));
|
||||
|
||||
@@ -42,7 +42,7 @@ class PDODatabase extends PDO
|
||||
echo __METHOD__ . "()\n";
|
||||
}
|
||||
|
||||
function query($sql)
|
||||
function query($sql, ...$rest)
|
||||
{
|
||||
echo __METHOD__ . "()\n";
|
||||
$stmt = $this->prepare($sql, array(PDO::ATTR_STATEMENT_CLASS=>array('PDOStatementx', array($this))));
|
||||
|
||||
@@ -48,7 +48,7 @@ class PDODatabase extends PDO
|
||||
echo __METHOD__ . "()\n";
|
||||
}
|
||||
|
||||
function query($sql)
|
||||
function query($sql, ...$rest)
|
||||
{
|
||||
echo __METHOD__ . "()\n";
|
||||
$stmt = $this->prepare($sql, array(PDO::ATTR_STATEMENT_CLASS=>array('PDOStatementx', array($this))));
|
||||
|
||||
@@ -49,7 +49,7 @@ class PDODatabase extends PDO
|
||||
echo __METHOD__ . "()\n";
|
||||
}
|
||||
|
||||
function query($sql)
|
||||
function query($sql, ...$rest)
|
||||
{
|
||||
echo __METHOD__ . "()\n";
|
||||
return parent::query($sql);
|
||||
|
||||
Reference in New Issue
Block a user