summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext/pdo/pdo_dbh.c150
-rw-r--r--ext/pdo/pdo_stmt.c562
-rw-r--r--ext/pdo/pdo_stmt.stub.php14
-rw-r--r--ext/pdo/pdo_stmt_arginfo.h6
-rw-r--r--ext/pdo/php_pdo.h10
-rw-r--r--ext/pdo/php_pdo_int.h3
-rw-r--r--ext/pdo/tests/bug_44159.phpt63
-rw-r--r--ext/pdo/tests/bug_44173.phpt61
-rw-r--r--ext/pdo/tests/pdo_038.phpt21
-rw-r--r--ext/pdo/tests/pdo_quote_empty_string.phpt31
-rw-r--r--ext/pdo_mysql/tests/pdo_mysql_attr_errmode.phpt48
-rw-r--r--ext/pdo_mysql/tests/pdo_mysql_attr_oracle_nulls.phpt30
-rw-r--r--ext/pdo_mysql/tests/pdo_mysql_attr_statement_class.phpt57
-rw-r--r--ext/pdo_mysql/tests/pdo_mysql_prepare_emulated.phpt9
-rw-r--r--ext/pdo_mysql/tests/pdo_mysql_prepare_native.phpt9
-rw-r--r--ext/pdo_mysql/tests/pdo_mysql_stmt_getcolumnmeta.phpt8
-rw-r--r--ext/pdo_sqlite/tests/bug_44159_sqlite_version.phpt22
-rw-r--r--ext/pdo_sqlite/tests/pdo_fetch_func_001.phpt112
18 files changed, 674 insertions, 542 deletions
diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c
index 780de94707..0f5eaab2e6 100644
--- a/ext/pdo/pdo_dbh.c
+++ b/ext/pdo/pdo_dbh.c
@@ -425,12 +425,10 @@ options:
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)) {
- if (Z_TYPE_P(ctor_args) != IS_ARRAY) {
- pdo_raise_impl_error(dbh, NULL, "HY000", "constructor arguments must be passed as an array");
- return NULL;
- }
+ /* This implies an error within PDO if this does not hold */
+ ZEND_ASSERT(Z_TYPE_P(ctor_args) == IS_ARRAY);
if (!dbstmt_ce->constructor) {
- pdo_raise_impl_error(dbh, NULL, "HY000", "user-supplied statement does not accept constructor arguments");
+ zend_throw_error(NULL, "User-supplied statement does not accept constructor arguments");
return NULL;
}
}
@@ -487,7 +485,7 @@ PHP_METHOD(PDO, prepare)
pdo_stmt_t *stmt;
char *statement;
size_t statement_len;
- zval *options = NULL, *opt, *item, ctor_args;
+ zval *options = NULL, *value, *item, ctor_args;
zend_class_entry *dbstmt_ce, *pce;
pdo_dbh_object_t *dbh_obj = Z_PDO_OBJECT_P(ZEND_THIS);
pdo_dbh_t *dbh = dbh_obj->inner;
@@ -498,42 +496,44 @@ PHP_METHOD(PDO, prepare)
Z_PARAM_ARRAY(options)
ZEND_PARSE_PARAMETERS_END();
- PDO_DBH_CLEAR_ERR();
PDO_CONSTRUCT_CHECK;
- if (ZEND_NUM_ARGS() > 1 && (opt = zend_hash_index_find(Z_ARRVAL_P(options), PDO_ATTR_STATEMENT_CLASS)) != NULL) {
- if (Z_TYPE_P(opt) != IS_ARRAY || (item = zend_hash_index_find(Z_ARRVAL_P(opt), 0)) == NULL
- || Z_TYPE_P(item) != IS_STRING
- || (pce = zend_lookup_class(Z_STR_P(item))) == NULL
- ) {
- pdo_raise_impl_error(dbh, NULL, "HY000",
- "PDO::ATTR_STATEMENT_CLASS requires format array(classname, array(ctor_args)); "
- "the classname must be a string specifying an existing class"
- );
- PDO_HANDLE_DBH_ERR();
- RETURN_FALSE;
+ if (statement_len == 0) {
+ zend_argument_value_error(1, "cannot be empty");
+ RETURN_THROWS();
+ }
+
+ PDO_DBH_CLEAR_ERR();
+
+ if (options && (value = zend_hash_index_find(Z_ARRVAL_P(options), PDO_ATTR_STATEMENT_CLASS)) != NULL) {
+ if (Z_TYPE_P(value) != IS_ARRAY) {
+ zend_type_error("PDO::ATTR_STATEMENT_CLASS value must be of type array, %s given",
+ zend_zval_type_name(value));
+ RETURN_THROWS();
+ }
+ 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 "
+ "array(classname, array(ctor_args))");
+ RETURN_THROWS();
+ }
+ 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");
+ RETURN_THROWS();
}
dbstmt_ce = pce;
if (!instanceof_function(dbstmt_ce, pdo_dbstmt_ce)) {
- pdo_raise_impl_error(dbh, NULL, "HY000",
- "user-supplied statement class must be derived from PDOStatement");
- PDO_HANDLE_DBH_ERR();
- RETURN_FALSE;
+ zend_type_error("PDO::ATTR_STATEMENT_CLASS class must be derived from PDOStatement");
+ RETURN_THROWS();
}
if (dbstmt_ce->constructor && !(dbstmt_ce->constructor->common.fn_flags & (ZEND_ACC_PRIVATE|ZEND_ACC_PROTECTED))) {
- pdo_raise_impl_error(dbh, NULL, "HY000",
- "user-supplied statement class cannot have a public constructor");
- PDO_HANDLE_DBH_ERR();
- RETURN_FALSE;
+ zend_type_error("User-supplied statement class cannot have a public constructor");
+ RETURN_THROWS();
}
- if ((item = zend_hash_index_find(Z_ARRVAL_P(opt), 1)) != NULL) {
+ if ((item = zend_hash_index_find(Z_ARRVAL_P(value), 1)) != NULL) {
if (Z_TYPE_P(item) != IS_ARRAY) {
- pdo_raise_impl_error(dbh, NULL, "HY000",
- "PDO::ATTR_STATEMENT_CLASS requires format array(classname, ctor_args); "
- "ctor_args must be an array"
- );
- PDO_HANDLE_DBH_ERR();
- RETURN_FALSE;
+ zend_type_error("PDO::ATTR_STATEMENT_CLASS ctor_args must be of type ?array, %s given",
+ zend_zval_type_name(value));
+ RETURN_THROWS();
}
ZVAL_COPY_VALUE(&ctor_args, item);
} else {
@@ -544,11 +544,10 @@ PHP_METHOD(PDO, prepare)
ZVAL_COPY_VALUE(&ctor_args, &dbh->def_stmt_ctor_args);
}
+ /* Need to check if pdo_stmt_instantiate() throws an exception unconditionally to see if can change the RETURN_FALSE; */
if (!pdo_stmt_instantiate(dbh, return_value, dbstmt_ce, &ctor_args)) {
if (EXPECTED(!EG(exception))) {
- pdo_raise_impl_error(dbh, NULL, "HY000",
- "failed to instantiate user-supplied statement class"
- );
+ zend_throw_error(NULL, "Cannot instantiate user-supplied statement class");
}
PDO_HANDLE_DBH_ERR();
RETURN_FALSE;
@@ -679,10 +678,10 @@ static int pdo_dbh_attribute_set(pdo_dbh_t *dbh, zend_long attr, zval *value) /*
{
zend_long lval;
+/* TODO: Make distinction between numeric and non-numeric strings */
#define PDO_LONG_PARAM_CHECK \
if (Z_TYPE_P(value) != IS_LONG && Z_TYPE_P(value) != IS_STRING && Z_TYPE_P(value) != IS_FALSE && Z_TYPE_P(value) != IS_TRUE) { \
- pdo_raise_impl_error(dbh, NULL, "HY000", "attribute value must be an integer"); \
- PDO_HANDLE_DBH_ERR(); \
+ zend_type_error("Attribute value must be of type int for selected attribute, %s given", zend_zval_type_name(value)); \
return FAILURE; \
} \
@@ -697,8 +696,7 @@ static int pdo_dbh_attribute_set(pdo_dbh_t *dbh, zend_long attr, zval *value) /*
dbh->error_mode = lval;
return SUCCESS;
default:
- pdo_raise_impl_error(dbh, NULL, "HY000", "invalid error mode");
- PDO_HANDLE_DBH_ERR();
+ zend_value_error("Error mode must be one of the PDO::ERRMODE_* constants");
return FAILURE;
}
return FAILURE;
@@ -713,8 +711,7 @@ static int pdo_dbh_attribute_set(pdo_dbh_t *dbh, zend_long attr, zval *value) /*
dbh->desired_case = lval;
return SUCCESS;
default:
- pdo_raise_impl_error(dbh, NULL, "HY000", "invalid case folding mode");
- PDO_HANDLE_DBH_ERR();
+ zend_value_error("Case folding mode must be one of the PDO::CASE_* constants");
return FAILURE;
}
return FAILURE;
@@ -729,7 +726,7 @@ static int pdo_dbh_attribute_set(pdo_dbh_t *dbh, zend_long attr, zval *value) /*
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) {
- pdo_raise_impl_error(dbh, NULL, "HY000", "FETCH_INTO and FETCH_CLASS are not yet supported as default fetch modes");
+ zend_value_error("PDO::FETCH_INTO and PDO::FETCH_CLASS cannot be set as the default fetch mode");
return FAILURE;
}
}
@@ -738,7 +735,7 @@ static int pdo_dbh_attribute_set(pdo_dbh_t *dbh, zend_long attr, zval *value) /*
}
lval = zval_get_long(value);
if (lval == PDO_FETCH_USE_DEFAULT) {
- pdo_raise_impl_error(dbh, NULL, "HY000", "invalid fetch mode type");
+ zend_value_error("Fetch mode must be a bitmask of PDO::FETCH_* constants");
return FAILURE;
}
dbh->default_fetch_type = lval;
@@ -761,28 +758,26 @@ static int pdo_dbh_attribute_set(pdo_dbh_t *dbh, zend_long attr, zval *value) /*
PDO_HANDLE_DBH_ERR();
return FAILURE;
}
- if (Z_TYPE_P(value) != IS_ARRAY
- || (item = zend_hash_index_find(Z_ARRVAL_P(value), 0)) == NULL
- || Z_TYPE_P(item) != IS_STRING
- || (pce = zend_lookup_class(Z_STR_P(item))) == NULL
- ) {
- pdo_raise_impl_error(dbh, NULL, "HY000",
- "PDO::ATTR_STATEMENT_CLASS requires format array(classname, array(ctor_args)); "
- "the classname must be a string specifying an existing class"
- );
- PDO_HANDLE_DBH_ERR();
+ if (Z_TYPE_P(value) != IS_ARRAY) {
+ zend_type_error("PDO::ATTR_STATEMENT_CLASS value must be of type array, %s given",
+ zend_zval_type_name(value));
+ return FAILURE;
+ }
+ 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 "
+ "array(classname, array(ctor_args))");
+ return FAILURE;
+ }
+ 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");
return FAILURE;
}
if (!instanceof_function(pce, pdo_dbstmt_ce)) {
- pdo_raise_impl_error(dbh, NULL, "HY000",
- "user-supplied statement class must be derived from PDOStatement");
- PDO_HANDLE_DBH_ERR();
+ zend_type_error("PDO::ATTR_STATEMENT_CLASS class must be derived from PDOStatement");
return FAILURE;
}
if (pce->constructor && !(pce->constructor->common.fn_flags & (ZEND_ACC_PRIVATE|ZEND_ACC_PROTECTED))) {
- pdo_raise_impl_error(dbh, NULL, "HY000",
- "user-supplied statement class cannot have a public constructor");
- PDO_HANDLE_DBH_ERR();
+ zend_type_error("User-supplied statement class cannot have a public constructor");
return FAILURE;
}
dbh->def_stmt_ce = pce;
@@ -792,11 +787,8 @@ static int 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) {
- pdo_raise_impl_error(dbh, NULL, "HY000",
- "PDO::ATTR_STATEMENT_CLASS requires format array(classname, array(ctor_args)); "
- "ctor_args must be an array"
- );
- PDO_HANDLE_DBH_ERR();
+ zend_type_error("PDO::ATTR_STATEMENT_CLASS ctor_args must be of type ?array, %s given",
+ zend_zval_type_name(value));
return FAILURE;
}
ZVAL_COPY(&dbh->def_stmt_ctor_args, item);
@@ -927,10 +919,11 @@ PHP_METHOD(PDO, exec)
Z_PARAM_STRING(statement, statement_len)
ZEND_PARSE_PARAMETERS_END();
- if (!statement_len) {
- pdo_raise_impl_error(dbh, NULL, "HY000", "trying to execute an empty query");
- RETURN_FALSE;
+ if (statement_len == 0) {
+ zend_argument_value_error(1, "cannot be empty");
+ RETURN_THROWS();
}
+
PDO_DBH_CLEAR_ERR();
PDO_CONSTRUCT_CHECK;
ret = dbh->methods->doer(dbh, statement, statement_len);
@@ -955,8 +948,10 @@ PHP_METHOD(PDO, lastInsertId)
Z_PARAM_STRING_OR_NULL(name, namelen)
ZEND_PARSE_PARAMETERS_END();
- PDO_DBH_CLEAR_ERR();
PDO_CONSTRUCT_CHECK;
+
+ PDO_DBH_CLEAR_ERR();
+
if (!dbh->methods->last_id) {
pdo_raise_impl_error(dbh, NULL, "IM001", "driver does not support lastInsertId()");
RETURN_FALSE;
@@ -1060,13 +1055,20 @@ PHP_METHOD(PDO, query)
pdo_dbh_object_t *dbh_obj = Z_PDO_OBJECT_P(ZEND_THIS);
pdo_dbh_t *dbh = dbh_obj->inner;
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "s|l!*", &statement, &statement_len, &fetch_mode, &fetch_mode_is_null, &args, &num_args)) {
+ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "s|l!*", &statement, &statement_len,
+ &fetch_mode, &fetch_mode_is_null, &args, &num_args)) {
RETURN_THROWS();
}
- PDO_DBH_CLEAR_ERR();
PDO_CONSTRUCT_CHECK;
+ if (statement_len == 0) {
+ zend_argument_value_error(1, "cannot be empty");
+ RETURN_THROWS();
+ }
+
+ PDO_DBH_CLEAR_ERR();
+
if (!pdo_stmt_instantiate(dbh, return_value, dbh->def_stmt_ce, &dbh->def_stmt_ctor_args)) {
if (EXPECTED(!EG(exception))) {
pdo_raise_impl_error(dbh, NULL, "HY000", "failed to instantiate user supplied statement class");
@@ -1090,8 +1092,7 @@ PHP_METHOD(PDO, query)
if (dbh->methods->preparer(dbh, statement, statement_len, stmt, NULL)) {
PDO_STMT_CLEAR_ERR();
- if (fetch_mode_is_null || SUCCESS == pdo_stmt_setup_fetch_mode(stmt, fetch_mode, args, num_args)) {
-
+ if (fetch_mode_is_null || pdo_stmt_setup_fetch_mode(stmt, fetch_mode, 2, args, num_args)) {
/* now execute the statement */
PDO_STMT_CLEAR_ERR();
if (stmt->methods->executer(stmt)) {
@@ -1139,8 +1140,9 @@ PHP_METHOD(PDO, quote)
Z_PARAM_LONG(paramtype)
ZEND_PARSE_PARAMETERS_END();
- PDO_DBH_CLEAR_ERR();
PDO_CONSTRUCT_CHECK;
+
+ PDO_DBH_CLEAR_ERR();
if (!dbh->methods->quoter) {
pdo_raise_impl_error(dbh, NULL, "IM001", "driver does not support quoting");
RETURN_FALSE;
diff --git a/ext/pdo/pdo_stmt.c b/ext/pdo/pdo_stmt.c
index 8ed0a77636..0cec5d9955 100644
--- a/ext/pdo/pdo_stmt.c
+++ b/ext/pdo/pdo_stmt.c
@@ -34,11 +34,12 @@
#include "php_memory_streams.h"
#include "pdo_stmt_arginfo.h"
-#define PHP_STMT_GET_OBJ \
- pdo_stmt_t *stmt = Z_PDO_STMT_P(ZEND_THIS); \
- if (!stmt->dbh) { \
- RETURN_FALSE; \
- } \
+#define PHP_STMT_GET_OBJ \
+ pdo_stmt_t *stmt = Z_PDO_STMT_P(ZEND_THIS); \
+ if (!stmt->dbh) { \
+ zend_throw_error(NULL, "PDO object is uninitialized"); \
+ RETURN_THROWS(); \
+ } \
static inline int rewrite_name_to_position(pdo_stmt_t *stmt, struct pdo_bound_param_data *param) /* {{{ */
{
@@ -62,6 +63,7 @@ static inline int rewrite_name_to_position(pdo_stmt_t *stmt, struct pdo_bound_pa
param->name = zend_string_init(name, strlen(name), 0);
return 1;
}
+ /* TODO Error? */
pdo_raise_impl_error(stmt->dbh, stmt, "HY093", "parameter was not defined");
return 0;
}
@@ -72,12 +74,14 @@ static inline int rewrite_name_to_position(pdo_stmt_t *stmt, struct pdo_bound_pa
continue;
}
if (param->paramno >= 0) {
+ /* TODO Error? */
pdo_raise_impl_error(stmt->dbh, stmt, "IM001", "PDO refuses to handle repeating the same :named parameter for multiple positions with this driver, as it might be unsafe to do so. Consider using a separate name for each parameter instead");
return -1;
}
param->paramno = position;
return 1;
} ZEND_HASH_FOREACH_END();
+ /* TODO Error? */
pdo_raise_impl_error(stmt->dbh, stmt, "HY093", "parameter was not defined");
return 0;
}
@@ -256,7 +260,7 @@ static int really_register_bound_param(struct pdo_bound_param_data *param, pdo_s
for (i = 0; i < stmt->column_count; i++) {
if (ZSTR_LEN(stmt->columns[i].name) == ZSTR_LEN(param->name) &&
- strncmp(ZSTR_VAL(stmt->columns[i].name), ZSTR_VAL(param->name), ZSTR_LEN(param->name) + 1) == 0) {
+ strncmp(ZSTR_VAL(stmt->columns[i].name), ZSTR_VAL(param->name), ZSTR_LEN(param->name) + 1) == 0) {
param->paramno = i;
break;
}
@@ -265,7 +269,9 @@ static int really_register_bound_param(struct pdo_bound_param_data *param, pdo_s
/* if you prepare and then execute passing an array of params keyed by names,
* then this will trigger, and we don't want that */
if (param->paramno == -1) {
+ /* Should this always be an Error? */
char *tmp;
+ /* TODO Error? */
spprintf(&tmp, 0, "Did not find column name '%s' in the defined columns; it will not be bound", ZSTR_VAL(param->name));
pdo_raise_impl_error(stmt->dbh, stmt, "HY000", tmp);
efree(tmp);
@@ -398,9 +404,9 @@ PHP_METHOD(PDOStatement, execute)
if (PDO_PLACEHOLDER_NONE == stmt->supports_placeholders) {
/* handle the emulated parameter binding,
- * stmt->active_query_string holds the query with binds expanded and
+ * stmt->active_query_string holds the query with binds expanded and
* quoted.
- */
+ */
/* string is leftover from previous calls so PDOStatement::debugDumpParams() can access */
if (stmt->active_query_string && stmt->active_query_string != stmt->query_string) {
@@ -457,10 +463,15 @@ static inline void fetch_value(pdo_stmt_t *stmt, zval *dest, int colno, int *typ
int caller_frees = 0;
int type, new_type;
- if (colno < 0 || colno >= stmt->column_count) {
- pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "Invalid column index");
- ZVAL_FALSE(dest);
+ if (colno < 0) {
+ zend_value_error("Column index must be greater than or equal to 0");
+ ZVAL_NULL(dest);
+ return;
+ }
+ if (colno >= stmt->column_count) {
+ zend_value_error("Invalid column index");
+ ZVAL_NULL(dest);
return;
}
@@ -666,6 +677,7 @@ static int do_fetch_class_prepare(pdo_stmt_t *stmt) /* {{{ */
fcc->called_scope = ce;
return 1;
} else if (!Z_ISUNDEF(stmt->fetch.cls.ctor_args)) {
+ /* TODO Error? */
pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "user-supplied class does not have a constructor, use NULL for the ctor_params parameter, or simply omit it");
return 0;
} else {
@@ -680,12 +692,12 @@ static int make_callable_ex(pdo_stmt_t *stmt, zval *callable, zend_fcall_info *
if (zend_fcall_info_init(callable, 0, fci, fcc, NULL, &is_callable_error) == FAILURE) {
if (is_callable_error) {
- pdo_raise_impl_error(stmt->dbh, stmt, "HY000", is_callable_error);
+ zend_type_error("%s", is_callable_error);
efree(is_callable_error);
} else {
- pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "user-supplied function must be a valid callback");
+ zend_type_error("User-supplied function must be a valid callback");
}
- return 0;
+ return false;
}
if (is_callable_error) {
/* Possible error message */
@@ -695,20 +707,20 @@ static int make_callable_ex(pdo_stmt_t *stmt, zval *callable, zend_fcall_info *
fci->param_count = num_args; /* probably less */
fci->params = safe_emalloc(sizeof(zval), num_args, 0);
- return 1;
+ return true;
}
/* }}} */
-static int do_fetch_func_prepare(pdo_stmt_t *stmt) /* {{{ */
+static bool do_fetch_func_prepare(pdo_stmt_t *stmt) /* {{{ */
{
zend_fcall_info *fci = &stmt->fetch.cls.fci;
zend_fcall_info_cache *fcc = &stmt->fetch.cls.fcc;
if (!make_callable_ex(stmt, &stmt->fetch.func.function, fci, fcc, stmt->column_count)) {
- return 0;
+ return false;
} else {
stmt->fetch.func.values = safe_emalloc(sizeof(zval), stmt->column_count, 0);
- return 1;
+ return true;
}
}
/* }}} */
@@ -718,7 +730,7 @@ static void do_fetch_opt_finish(pdo_stmt_t *stmt, int free_ctor_agrs) /* {{{ */
/* fci.size is used to check if it is valid */
if (stmt->fetch.cls.fci.size && stmt->fetch.cls.fci.params) {
if (!Z_ISUNDEF(stmt->fetch.cls.ctor_args)) {
- /* Added to free constructor arguments */
+ /* Added to free constructor arguments */
zend_fcall_info_args_clear(&stmt->fetch.cls.fci, 1);
} else {
efree(stmt->fetch.cls.fci.params);
@@ -806,23 +818,27 @@ static bool do_fetch(pdo_stmt_t *stmt, zval *return_value, enum pdo_fetch_type h
break;
case PDO_FETCH_COLUMN:
- if (colno >= 0 && colno < stmt->column_count) {
- if (flags == PDO_FETCH_GROUP && stmt->fetch.column == -1) {
- fetch_value(stmt, return_value, 1, NULL);
- } else if (flags == PDO_FETCH_GROUP && colno) {
- fetch_value(stmt, return_value, 0, NULL);
- } else {
- fetch_value(stmt, return_value, colno, NULL);
- }
- if (!return_all) {
- return 1;
- } else {
- break;
- }
+ if (colno < 0 ) {
+ zend_value_error("Column index must be greater than or equal to 0");
+ return false;
+ }
+
+ if (colno >= stmt->column_count) {
+ zend_value_error("Invalid column index");
+ return false;
+ }
+
+ if (flags == PDO_FETCH_GROUP && stmt->fetch.column == -1) {
+ fetch_value(stmt, return_value, 1, NULL);
+ } else if (flags == PDO_FETCH_GROUP && colno) {
+ fetch_value(stmt, return_value, 0, NULL);
} else {
- pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "Invalid column index");
+ fetch_value(stmt, return_value, colno, NULL);
}
- return 0;
+ if (!return_all) {
+ return 1;
+ }
+ break;
case PDO_FETCH_OBJ:
object_init_ex(return_value, ZEND_STANDARD_CLASS_DEF_PTR);
@@ -854,7 +870,9 @@ static bool do_fetch(pdo_stmt_t *stmt, zval *return_value, enum pdo_fetch_type h
zval_ptr_dtor_str(&val);
}
ce = stmt->fetch.cls.ce;
+ /* TODO: Make this an assertion and ensure this is true higher up? */
if (!ce) {
+ /* TODO Error? */
pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "No fetch class specified");
return 0;
}
@@ -872,6 +890,7 @@ static bool do_fetch(pdo_stmt_t *stmt, zval *return_value, enum pdo_fetch_type h
stmt->fetch.cls.fci.object = Z_OBJ_P(return_value);
stmt->fetch.cls.fcc.object = Z_OBJ_P(return_value);
if (zend_call_function(&stmt->fetch.cls.fci, &stmt->fetch.cls.fcc) == FAILURE) {
+ /* TODO Error? */
pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "could not call class constructor");
return 0;
} else {
@@ -886,6 +905,7 @@ static bool do_fetch(pdo_stmt_t *stmt, zval *return_value, enum pdo_fetch_type h
case PDO_FETCH_INTO:
if (Z_ISUNDEF(stmt->fetch.into)) {
+ /* TODO ArgumentCountError? */
pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "No fetch-into object specified.");
return 0;
break;
@@ -900,6 +920,7 @@ static bool do_fetch(pdo_stmt_t *stmt, zval *return_value, enum pdo_fetch_type h
case PDO_FETCH_FUNC:
if (Z_ISUNDEF(stmt->fetch.func.function)) {
+ /* TODO ArgumentCountError? */
pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "No fetch function specified");
return 0;
}
@@ -910,10 +931,7 @@ static bool do_fetch(pdo_stmt_t *stmt, zval *return_value, enum pdo_fetch_type h
}
}
break;
-
- default:
- /* shouldn't happen */
- return 0;
+ EMPTY_SWITCH_DEFAULT_CASE();
}
if (return_all && how != PDO_FETCH_KEY_PAIR) {
@@ -1039,9 +1057,8 @@ static bool do_fetch(pdo_stmt_t *stmt, zval *return_value, enum pdo_fetch_type h
default:
zval_ptr_dtor(&val);
- pdo_raise_impl_error(stmt->dbh, stmt, "22003", "mode is out of range");
+ zend_value_error("Fetch mode must be a bitmask of PDO::FETCH_* constants");
return 0;
- break;
}
}
@@ -1051,6 +1068,7 @@ static bool do_fetch(pdo_stmt_t *stmt, zval *return_value, enum pdo_fetch_type h
stmt->fetch.cls.fci.object = Z_OBJ_P(return_value);
stmt->fetch.cls.fcc.object = Z_OBJ_P(return_value);
if (zend_call_function(&stmt->fetch.cls.fci, &stmt->fetch.cls.fcc) == FAILURE) {
+ /* TODO Error? */
pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "could not call class constructor");
return 0;
} else {
@@ -1071,6 +1089,7 @@ static bool do_fetch(pdo_stmt_t *stmt, zval *return_value, enum pdo_fetch_type h
stmt->fetch.func.fci.param_count = idx;
stmt->fetch.func.fci.retval = &retval;
if (zend_call_function(&stmt->fetch.func.fci, &stmt->fetch.func.fcc) == FAILURE) {
+ /* TODO Error? */
pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "could not call user-supplied function");
return 0;
} else {
@@ -1110,14 +1129,14 @@ static bool do_fetch(pdo_stmt_t *stmt, zval *return_value, enum pdo_fetch_type h
}
/* }}} */
-static int pdo_stmt_verify_mode(pdo_stmt_t *stmt, zend_long mode, int fetch_all) /* {{{ */
+static bool pdo_stmt_verify_mode(pdo_stmt_t *stmt, zend_long mode, 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) {
- pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "invalid fetch mode");
+ zend_argument_value_error(mode_arg_num, "must be a bitmask of PDO::FETCH_* constants");
return 0;
}
@@ -1129,28 +1148,28 @@ static int pdo_stmt_verify_mode(pdo_stmt_t *stmt, zend_long mode, int fetch_all)
switch(mode) {
case PDO_FETCH_FUNC:
if (!fetch_all) {
- pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "PDO::FETCH_FUNC is only allowed in PDOStatement::fetchAll()");
+ zend_value_error("Can only use PDO::FETCH_FUNC in PDOStatement::fetchAll()");
return 0;
}
return 1;
case PDO_FETCH_LAZY:
if (fetch_all) {
- pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "PDO::FETCH_LAZY can't be used with PDOStatement::fetchAll()");
+ zend_argument_value_error(mode_arg_num, "cannot be PDO::FETCH_LAZY in PDOStatement::fetchAll()");
return 0;
}
/* fall through */
default:
if ((flags & PDO_FETCH_SERIALIZE) == PDO_FETCH_SERIALIZE) {
- pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "PDO::FETCH_SERIALIZE can only be used together with PDO::FETCH_CLASS");
+ zend_argument_value_error(mode_arg_num, "must use PDO::FETCH_SERIALIZE with PDO::FETCH_CLASS");
return 0;
}
if ((flags & PDO_FETCH_CLASSTYPE) == PDO_FETCH_CLASSTYPE) {
- pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "PDO::FETCH_CLASSTYPE can only be used together with PDO::FETCH_CLASS");
+ zend_argument_value_error(mode_arg_num, "must use PDO::FETCH_CLASSTYPE with PDO::FETCH_CLASS");
return 0;
}
if (mode >= PDO_FETCH__MAX) {
- pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "invalid fetch mode");
+ zend_argument_value_error(mode_arg_num, "must be a bitmask of PDO::FETCH_* constants");
return 0;
}
/* no break; */
@@ -1175,14 +1194,14 @@ PHP_METHOD(PDOStatement, fetch)
Z_PARAM_LONG(off)
ZEND_PARSE_PARAMETERS_END();
- PHP_STMT_GET_OBJ;
+ PHP_STMT_GET_OBJ;
PDO_STMT_CLEAR_ERR();
- if (!pdo_stmt_verify_mode(stmt, how, 0)) {
- RETURN_FALSE;
+ if (!pdo_stmt_verify_mode(stmt, how, 1, false)) {
+ RETURN_THROWS();
}
- if (!do_fetch(stmt, return_value, how, ori, off, 0)) {
+ if (!do_fetch(stmt, return_value, how, ori, off, NULL)) {
PDO_HANDLE_STMT_ERR();
RETURN_FALSE;
}
@@ -1192,9 +1211,6 @@ PHP_METHOD(PDOStatement, fetch)
/* {{{ Fetches the next row and returns it as an object. */
PHP_METHOD(PDOStatement, fetchObject)
{
- zend_long how = PDO_FETCH_CLASS;
- zend_long ori = PDO_FETCH_ORI_NEXT;
- zend_long off = 0;
zend_class_entry *ce = NULL;
zend_class_entry *old_ce;
zval old_ctor_args, *ctor_args = NULL;
@@ -1209,10 +1225,6 @@ PHP_METHOD(PDOStatement, fetchObject)
PHP_STMT_GET_OBJ;
PDO_STMT_CLEAR_ERR();
- if (!pdo_stmt_verify_mode(stmt, how, 0)) {
- RETURN_FALSE;
- }
-
old_ce = stmt->fetch.cls.ce;
ZVAL_COPY_VALUE(&old_ctor_args, &stmt->fetch.cls.ctor_args);
old_arg_count = stmt->fetch.cls.fci.param_count;
@@ -1232,7 +1244,7 @@ PHP_METHOD(PDOStatement, fetchObject)
stmt->fetch.cls.ce = zend_standard_class_def;
}
- if (!do_fetch(stmt, return_value, how, ori, off, 0)) {
+ if (!do_fetch(stmt, return_value, PDO_FETCH_CLASS, PDO_FETCH_ORI_NEXT, /* offset */ 0, NULL)) {
PDO_HANDLE_STMT_ERR();
RETVAL_FALSE;
}
@@ -1270,22 +1282,23 @@ PHP_METHOD(PDOStatement, fetchColumn)
PHP_METHOD(PDOStatement, fetchAll)
{
zend_long how = PDO_FETCH_USE_DEFAULT;
- zval data, *return_all;
+ zval data, *return_all = NULL;
zval *arg2 = NULL;
zend_class_entry *old_ce;
zval old_ctor_args, *ctor_args = NULL;
- int error = 0, flags, old_arg_count;
+ bool error = false;
+ int flags, old_arg_count;
ZEND_PARSE_PARAMETERS_START(0, 3)
Z_PARAM_OPTIONAL
Z_PARAM_LONG(how)
- Z_PARAM_ZVAL(arg2)
- Z_PARAM_ZVAL(ctor_args)
+ Z_PARAM_ZVAL_OR_NULL(arg2)
+ Z_PARAM_ARRAY_OR_NULL(ctor_args)
ZEND_PARSE_PARAMETERS_END();
PHP_STMT_GET_OBJ;
- if (!pdo_stmt_verify_mode(stmt, how, 1)) {
- RETURN_FALSE;
+ if (!pdo_stmt_verify_mode(stmt, how, 1, true)) {
+ RETURN_THROWS();
}
old_ce = stmt->fetch.cls.ce;
@@ -1294,85 +1307,88 @@ PHP_METHOD(PDOStatement, fetchAll)
do_fetch_opt_finish(stmt, 0);
- switch(how & ~PDO_FETCH_FLAGS) {
- case PDO_FETCH_CLASS:
- switch(ZEND_NUM_ARGS()) {
- case 0:
- case 1:
- stmt->fetch.cls.ce = zend_standard_class_def;
- break;
- case 3:
- if (Z_TYPE_P(ctor_args) != IS_NULL && Z_TYPE_P(ctor_args) != IS_ARRAY) {
- pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "ctor_args must be either NULL or an array");
- error = 1;
- break;
- }
- if (Z_TYPE_P(ctor_args) != IS_ARRAY || !zend_hash_num_elements(Z_ARRVAL_P(ctor_args))) {
- ctor_args = NULL;
+ /* TODO Would be good to reuse part of pdo_stmt_setup_fetch_mode() in some way */
+
+ switch (how & ~PDO_FETCH_FLAGS) {
+ case PDO_FETCH_CLASS:
+ /* Figure out correct class */
+ if (arg2) {
+ if (Z_TYPE_P(arg2) != IS_STRING) {
+ zend_argument_type_error(2, "must be of type string, %s given", zend_zval_type_name(arg2));
+ RETURN_THROWS();
+ }
+ stmt->fetch.cls.ce = zend_fetch_class(Z_STR_P(arg2), ZEND_FETCH_CLASS_AUTO);
+ if (!stmt->fetch.cls.ce) {
+ zend_argument_type_error(2, "must be a valid class");
+ RETURN_THROWS();
+ }
+ } else {
+ stmt->fetch.cls.ce = zend_standard_class_def;
}
- /* no break */
- case 2:
- if (ctor_args) {
+
+ if (ctor_args && zend_hash_num_elements(Z_ARRVAL_P(ctor_args)) > 0) {
ZVAL_COPY_VALUE(&stmt->fetch.cls.ctor_args, ctor_args); /* we're not going to free these */
} else {
ZVAL_UNDEF(&stmt->fetch.cls.ctor_args);
}
- if (Z_TYPE_P(arg2) != IS_STRING) {
- pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "Invalid class name (should be a string)");
- error = 1;
- break;
- } else {
- stmt->fetch.cls.ce = zend_fetch_class(Z_STR_P(arg2), ZEND_FETCH_CLASS_AUTO);
- if (!stmt->fetch.cls.ce) {
- pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "could not find user-specified class");
- error = 1;
- break;
- }
- }
- }
- if (!error) {
+
do_fetch_class_prepare(stmt);
- }
- break;
-
- case PDO_FETCH_FUNC:
- switch (ZEND_NUM_ARGS()) {
- case 0:
- case 1:
- pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "no fetch function specified");
- error = 1;
- break;
- case 3:
- case 2:
- ZVAL_COPY_VALUE(&stmt->fetch.func.function, arg2);
- if (do_fetch_func_prepare(stmt) == 0) {
- error = 1;
- }
- break;
- }
- break;
+ break;
- case PDO_FETCH_COLUMN:
- switch(ZEND_NUM_ARGS()) {
- case 0:
- case 1:
- stmt->fetch.column = how & PDO_FETCH_GROUP ? -1 : 0;
+ case PDO_FETCH_FUNC: /* Cannot be a default fetch mode */
+ if (ZEND_NUM_ARGS() != 2) {
+ zend_string *func = get_active_function_or_method_name();
+ zend_argument_count_error("%s() expects exactly 2 argument for PDO::FETCH_FUNC, %d given",
+ ZSTR_VAL(func), ZEND_NUM_ARGS());
+ zend_string_release(func);
+ RETURN_THROWS();
+ }
+ if (arg2 == NULL) {
+ /* TODO use "must be of type callable" format? */
+ zend_argument_type_error(2, "must be a callable, null given");
+ RETURN_THROWS();
+ }
+ /* TODO Check it is a callable? */
+ ZVAL_COPY_VALUE(&stmt->fetch.func.function, arg2);
+ if (do_fetch_func_prepare(stmt) == false) {
+ RETURN_THROWS();
+ }
break;
- case 2:
- convert_to_long(arg2);
- stmt->fetch.column = Z_LVAL_P(arg2);
+
+ case PDO_FETCH_COLUMN:
+ if (ZEND_NUM_ARGS() > 2) {
+ zend_string *func = get_active_function_or_method_name();
+ zend_argument_count_error("%s() expects at most 2 argument for the fetch mode provided, %d given",
+ ZSTR_VAL(func), ZEND_NUM_ARGS());
+ zend_string_release(func);
+ RETURN_THROWS();
+ }
+ /* Is column index passed? */
+ if (arg2) {
+ // Reuse convert_to_long(arg2); ?
+ if (Z_TYPE_P(arg2) != IS_LONG) {
+ zend_argument_type_error(2, "must be of type int, %s given", zend_zval_type_name(arg2));
+ RETURN_THROWS();
+ }
+ if (Z_LVAL_P(arg2) < 0) {
+ zend_argument_value_error(2, "must be greater than or equal to 0");
+ RETURN_THROWS();
+ }
+ stmt->fetch.column = Z_LVAL_P(arg2);
+ } else {
+ stmt->fetch.column = how & PDO_FETCH_GROUP ? -1 : 0;
+ }
break;
- case 3:
- pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "Third parameter not allowed for PDO::FETCH_COLUMN");
- error = 1;
- }
- break;
- default:
- if (ZEND_NUM_ARGS() > 1) {
- pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "Extraneous additional parameters");
- error = 1;
- }
+ default:
+ /* No support for PDO_FETCH_INTO which takes 2 args??? */
+ if (ZEND_NUM_ARGS() > 1) {
+ zend_string *func = get_active_function_or_method_name();
+ zend_argument_count_error("%s() expects exactly 1 argument for the fetch mode provided, %d given",
+ ZSTR_VAL(func), ZEND_NUM_ARGS());
+ zend_string_release(func);
+ RETURN_THROWS();
+ }
}
flags = how & PDO_FETCH_FLAGS;
@@ -1382,48 +1398,42 @@ PHP_METHOD(PDOStatement, fetchAll)
how |= stmt->default_fetch_type & ~PDO_FETCH_FLAGS;
}
- if (!error) {
- PDO_STMT_CLEAR_ERR();
- if ((how & PDO_FETCH_GROUP) || how == PDO_FETCH_KEY_PAIR ||
- (how == PDO_FETCH_USE_DEFAULT && stmt->default_fetch_type == PDO_FETCH_KEY_PAIR)
- ) {
- array_init(return_value);
- return_all = return_value;
- } else {
- return_all = 0;
- }
- if (!do_fetch(stmt, &data, how | flags, PDO_FETCH_ORI_NEXT, 0, return_all)) {
- error = 2;
- }
+ PDO_STMT_CLEAR_ERR();
+ if ((how & PDO_FETCH_GROUP) || how == PDO_FETCH_KEY_PAIR ||
+ (how == PDO_FETCH_USE_DEFAULT && stmt->default_fetch_type == PDO_FETCH_KEY_PAIR)
+ ) {
+ array_init(return_value);
+ return_all = return_value;
+ }
+ if (!do_fetch(stmt, &data, how | flags, PDO_FETCH_ORI_NEXT, /* offset */ 0, return_all)) {
+ error = true;
}
+
if (!error) {
if ((how & PDO_FETCH_GROUP)) {
- while (do_fetch(stmt, &data, how | flags, PDO_FETCH_ORI_NEXT, 0, return_all));
+ while (do_fetch(stmt, &data, how | flags, PDO_FETCH_ORI_NEXT, /* offset */ 0, return_all));
} else if (how == PDO_FETCH_KEY_PAIR || (how == PDO_FETCH_USE_DEFAULT && stmt->default_fetch_type == PDO_FETCH_KEY_PAIR)) {
- while (do_fetch(stmt, &data, how | flags, PDO_FETCH_ORI_NEXT, 0, return_all));
+ while (do_fetch(stmt, &data, how | flags, PDO_FETCH_ORI_NEXT, /* offset */ 0, return_all));
} else {
array_init(return_value);
do {
zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &data);
- } while (do_fetch(stmt, &data, how | flags, PDO_FETCH_ORI_NEXT, 0, 0));
+ } while (do_fetch(stmt, &data, how | flags, PDO_FETCH_ORI_NEXT, /* offset */ 0, NULL));
}
}
do_fetch_opt_finish(stmt, 0);
+ /* Restore defaults which were changed by PDO_FETCH_CLASS mode */
stmt->fetch.cls.ce = old_ce;
ZVAL_COPY_VALUE(&stmt->fetch.cls.ctor_args, &old_ctor_args);
stmt->fetch.cls.fci.param_count = old_arg_count;
+ /* on no results, return an empty array */
if (error) {
PDO_HANDLE_STMT_ERR();
- if (error != 2) {
- RETURN_FALSE;
- } else { /* on no results, return an empty array */
- if (Z_TYPE_P(return_value) != IS_ARRAY) {
- array_init(return_value);
- }
- return;
+ if (Z_TYPE_P(return_value) != IS_ARRAY) {
+ array_init(return_value);
}
}
}
@@ -1451,12 +1461,16 @@ static void register_bound_param(INTERNAL_FUNCTION_PARAMETERS, int is_param) /*
param.param_type = (int) param_type;
if (param.name) {
+ if (ZSTR_LEN(param.name) == 0) {
+ zend_argument_value_error(1, "cannot be empty");
+ RETURN_THROWS();
+ }
param.paramno = -1;
} else if (param.paramno > 0) {
--param.paramno; /* make it zero-based internally */
} else {
- pdo_raise_impl_error(stmt->dbh, stmt, "HY093", "Columns/Parameters are 1-based");
- RETURN_FALSE;
+ zend_argument_value_error(1, "must be greater than or equal to 1");
+ RETURN_THROWS();
}
if (driver_params) {
@@ -1495,12 +1509,16 @@ PHP_METHOD(PDOStatement, bindValue)
param.param_type = (int) param_type;
if (param.name) {
+ if (ZSTR_LEN(param.name) == 0) {
+ zend_argument_value_error(1, "cannot be empty");
+ RETURN_THROWS();
+ }
param.paramno = -1;
} else if (param.paramno > 0) {
--param.paramno; /* make it zero-based internally */
} else {
- pdo_raise_impl_error(stmt->dbh, stmt, "HY093", "Columns/Parameters are 1-based");
- RETURN_FALSE;
+ zend_argument_value_error(1, "must be greater than or equal to 1");
+ RETURN_THROWS();
}
ZVAL_COPY(&param.parameter, parameter);
@@ -1557,7 +1575,7 @@ PHP_METHOD(PDOStatement, errorCode)
PHP_METHOD(PDOStatement, errorInfo)
{
int error_count;
- int error_count_diff = 0;
+ int error_count_diff = 0;
int error_expected_count = 3;
ZEND_PARSE_PARAMETERS_NONE();
@@ -1595,8 +1613,11 @@ PHP_METHOD(PDOStatement, setAttribute)
ZEND_PARSE_PARAMETERS_END();
PHP_STMT_GET_OBJ;
+
+ /* Driver hasn't registered a function for setting attributes */
if (!stmt->methods->set_attribute) {
- goto fail;
+ pdo_raise_impl_error(stmt->dbh, stmt, "IM001", "This driver doesn't support setting attributes");
+ RETURN_FALSE;
}
PDO_STMT_CLEAR_ERR();
@@ -1604,12 +1625,8 @@ PHP_METHOD(PDOStatement, setAttribute)
RETURN_TRUE;
}
-fail:
- if (!stmt->methods->set_attribute) {
- pdo_raise_impl_error(stmt->dbh, stmt, "IM001", "This driver doesn't support setting attributes");
- } else {
- PDO_HANDLE_STMT_ERR();
- }
+ /* Error while setting attribute */
+ PDO_HANDLE_STMT_ERR();
RETURN_FALSE;
}
/* }}} */
@@ -1686,9 +1703,9 @@ PHP_METHOD(PDOStatement, getColumnMeta)
ZEND_PARSE_PARAMETERS_END();
PHP_STMT_GET_OBJ;
- if(colno < 0) {
- pdo_raise_impl_error(stmt->dbh, stmt, "42P10", "column number must be non-negative");
- RETURN_FALSE;
+ if (colno < 0) {
+ zend_argument_value_error(1, "must be greater than or equal to 0");
+ RETURN_THROWS();
}
if (!stmt->methods->get_column_meta) {
@@ -1716,13 +1733,13 @@ 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(pdo_stmt_t *stmt, zend_long mode, zval *args, uint32_t num_args)
+bool pdo_stmt_setup_fetch_mode(pdo_stmt_t *stmt, zend_long mode, uint32_t mode_arg_num,
+ zval *args, uint32_t variadic_num_args)
{
int flags = 0;
- zend_class_entry *cep;
- int retval;
-
- do_fetch_opt_finish(stmt, 1);
+ uint32_t arg1_arg_num = mode_arg_num + 1;
+ uint32_t constructor_arg_num = mode_arg_num + 2;
+ uint32_t total_num_args = mode_arg_num + variadic_num_args;
switch (stmt->default_fetch_type) {
case PDO_FETCH_INTO:
@@ -1739,12 +1756,10 @@ int pdo_stmt_setup_fetch_mode(pdo_stmt_t *stmt, zend_long mode, zval *args, uint
flags = mode & PDO_FETCH_FLAGS;
- if (!pdo_stmt_verify_mode(stmt, mode, 0)) {
- PDO_STMT_CLEAR_ERR();
- return FAILURE;
+ if (!pdo_stmt_verify_mode(stmt, mode, mode_arg_num, false)) {
+ return false;
}
- retval = FAILURE;
switch (mode & ~PDO_FETCH_FLAGS) {
case PDO_FETCH_USE_DEFAULT:
case PDO_FETCH_LAZY:
@@ -1755,100 +1770,120 @@ int pdo_stmt_setup_fetch_mode(pdo_stmt_t *stmt, zend_long mode, zval *args, uint
case PDO_FETCH_BOUND:
case PDO_FETCH_NAMED:
case PDO_FETCH_KEY_PAIR:
- if (num_args != 0) {
- pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "fetch mode doesn't allow any extra arguments");
- } else {
- retval = SUCCESS;
+ if (variadic_num_args != 0) {
+ zend_string *func = get_active_function_or_method_name();
+ zend_argument_count_error("%s() expects exactly %d arguments for the fetch mode provided, %d given",
+ ZSTR_VAL(func), mode_arg_num, total_num_args);
+ zend_string_release(func);
+ return false;
}
break;
case PDO_FETCH_COLUMN:
- if (num_args != 1) {
- pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "fetch mode requires the colno argument");
- } 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[0]);
- retval = SUCCESS;
- }
+ if (variadic_num_args != 1) {
+ zend_string *func = get_active_function_or_method_name();
+ zend_argument_count_error("%s() expects exactly %d arguments for the fetch mode provided, %d given",
+ ZSTR_VAL(func), arg1_arg_num, total_num_args);
+ zend_string_release(func);
+ return false;
+ }
+ if (Z_TYPE(args[0]) != IS_LONG) {
+ zend_argument_type_error(arg1_arg_num, "must be of type int, %s given", zend_zval_type_name(&args[0]));
+ return false;
+ }
+ if (Z_LVAL(args[0]) < 0) {
+ zend_argument_value_error(arg1_arg_num, "must be greater than or equal to 0");
+ return false;
+ }
+ stmt->fetch.column = Z_LVAL(args[0]);
break;
- case PDO_FETCH_CLASS:
+ case PDO_FETCH_CLASS: {
+ HashTable *constructor_args = NULL;
+ /* Undef constructor arguments */
+ ZVAL_UNDEF(&stmt->fetch.cls.ctor_args);
/* Gets its class name from 1st column */
if ((flags & PDO_FETCH_CLASSTYPE) == PDO_FETCH_CLASSTYPE) {
- 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;
+ if (variadic_num_args != 0) {
+ zend_string *func = get_active_function_or_method_name();
+ zend_argument_count_error("%s() expects exactly %d arguments for the fetch mode provided, %d given",
+ ZSTR_VAL(func), mode_arg_num, total_num_args);
+ zend_string_release(func);
+ return false;
}
+ stmt->fetch.cls.ce = NULL;
} else {
- if (num_args < 1) {
- pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "fetch mode requires the classname argument");
- } else if (num_args > 2) {
- pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "too many arguments");
- } 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[0]));
- if (cep) {
- retval = SUCCESS;
- stmt->fetch.cls.ce = cep;
- }
+ zend_class_entry *cep;
+ if (variadic_num_args == 0) {
+ zend_string *func = get_active_function_or_method_name();
+ zend_argument_count_error("%s() expects at least %d arguments for the fetch mode provided, %d given",
+ ZSTR_VAL(func), arg1_arg_num, total_num_args);
+ zend_string_release(func);
+ return false;
}
- }
-
- if (SUCCESS == retval) {
- ZVAL_UNDEF(&stmt->fetch.cls.ctor_args);
- if (num_args == 2) {
+ /* constructor_arguments can be null/not passed */
+ if (variadic_num_args > 2) {
+ zend_string *func = get_active_function_or_method_name();
+ zend_argument_count_error("%s() expects at most %d arguments for the fetch mode provided, %d given",
+ ZSTR_VAL(func), constructor_arg_num, total_num_args);
+ zend_string_release(func);
+ return false;
+ }
+ if (Z_TYPE(args[0]) != IS_STRING) {
+ zend_argument_type_error(arg1_arg_num, "must be of type string, %s given", zend_zval_type_name(&args[0]));
+ return false;
+ }
+ cep = zend_lookup_class(Z_STR(args[0]));
+ if (!cep) {
+ zend_argument_type_error(arg1_arg_num, "must be a valid class");
+ return false;
+ }
+ /* Verify constructor_args (args[1]) is ?array */
+ /* TODO: Improve logic? */
+ if (variadic_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[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])));
+ zend_argument_type_error(constructor_arg_num, "must be of type ?array, %s given",
+ zend_zval_type_name(&args[1]));
+ return false;
+ }
+ if (Z_TYPE(args[1]) == IS_ARRAY && zend_hash_num_elements(Z_ARRVAL(args[1]))) {
+ constructor_args = Z_ARRVAL(args[1]);
}
}
+ stmt->fetch.cls.ce = cep;
- if (SUCCESS == retval) {
- do_fetch_class_prepare(stmt);
+ /* If constructor arguments are present and not empty */
+ if (constructor_args) {
+ ZVAL_ARR(&stmt->fetch.cls.ctor_args, zend_array_dup(constructor_args));
}
}
+ do_fetch_class_prepare(stmt);
break;
-
+ }
case PDO_FETCH_INTO:
- if (num_args != 1) {
- pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "fetch mode requires the object parameter");
- } else if (Z_TYPE(args[0]) != IS_OBJECT) {
- pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "object must be an object");
- } else {
- retval = SUCCESS;
+ if (total_num_args != arg1_arg_num) {
+ zend_string *func = get_active_function_or_method_name();
+ zend_argument_count_error("%s() expects exactly %d arguments for the fetch mode provided, %d given",
+ ZSTR_VAL(func), arg1_arg_num, total_num_args);
+ zend_string_release(func);
+ return false;
}
-
- if (SUCCESS == retval) {
- ZVAL_COPY(&stmt->fetch.into, &args[0]);
+ if (Z_TYPE(args[0]) != IS_OBJECT) {
+ zend_argument_type_error(arg1_arg_num, "must be of type object, %s given", zend_zval_type_name(&args[0]));
+ return false;
}
+ ZVAL_COPY(&stmt->fetch.into, &args[0]);
break;
-
default:
- pdo_raise_impl_error(stmt->dbh, stmt, "22003", "Invalid fetch mode specified");
+ zend_argument_value_error(mode_arg_num, "must be one of the PDO::FETCH_* constants");
+ return false;
}
- if (SUCCESS == retval) {
- stmt->default_fetch_type = mode;
- }
-
- /*
- * PDO error (if any) has already been raised at this point.
- *
- * The error_code is cleared, otherwise the caller will read the
- * last error message from the driver.
- *
- */
- PDO_STMT_CLEAR_ERR();
+ stmt->default_fetch_type = mode;
- return retval;
+ return true;
}
PHP_METHOD(PDOStatement, setFetchMode)
@@ -1862,13 +1897,21 @@ PHP_METHOD(PDOStatement, setFetchMode)
}
PHP_STMT_GET_OBJ;
- RETVAL_BOOL(pdo_stmt_setup_fetch_mode(stmt, fetch_mode, args, num_args) == SUCCESS);
+
+ do_fetch_opt_finish(stmt, 1);
+
+ if (!pdo_stmt_setup_fetch_mode(stmt, fetch_mode, 1, args, num_args)) {
+ RETURN_THROWS();
+ }
+
+ // TODO Void return?
+ RETURN_TRUE;
}
/* }}} */
/* {{{ Advances to the next rowset in a multi-rowset statement handle. Returns true if it succeeded, false otherwise */
-static int pdo_stmt_do_next_rowset(pdo_stmt_t *stmt)
+static bool pdo_stmt_do_next_rowset(pdo_stmt_t *stmt)
{
/* un-describe */
if (stmt->columns) {
@@ -1963,6 +2006,7 @@ PHP_METHOD(PDOStatement, debugDumpParams)
ZEND_PARSE_PARAMETERS_NONE();
PHP_STMT_GET_OBJ;
+
if (out == NULL) {
RETURN_FALSE;
}
@@ -2024,10 +2068,8 @@ PHP_METHOD(PDOStatement, getIterator)
/* {{{ overloaded handlers for PDOStatement class */
static zval *dbstmt_prop_write(zend_object *object, zend_string *name, zval *value, void **cache_slot)
{
- pdo_stmt_t *stmt = php_pdo_stmt_fetch_object(object);
-
if (strcmp(ZSTR_VAL(name), "queryString") == 0) {
- pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "property queryString is read only");
+ zend_throw_error(NULL, "Property queryString is read only");
return value;
} else {
return zend_std_write_property(object, name, value, cache_slot);
@@ -2036,10 +2078,8 @@ static zval *dbstmt_prop_write(zend_object *object, zend_string *name, zval *val
static void dbstmt_prop_delete(zend_object *object, zend_string *name, void **cache_slot)
{
- pdo_stmt_t *stmt = php_pdo_stmt_fetch_object(object);
-
if (strcmp(ZSTR_VAL(name), "queryString") == 0) {
- pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "property queryString is read only");
+ zend_throw_error(NULL, "Property queryString is read only");
} else {
zend_std_unset_property(object, name, cache_slot);
}
@@ -2225,7 +2265,7 @@ static void pdo_stmt_iter_move_forwards(zend_object_iterator *iter)
}
if (!do_fetch(stmt, &I->fetch_ahead, PDO_FETCH_USE_DEFAULT,
- PDO_FETCH_ORI_NEXT, 0, 0)) {
+ PDO_FETCH_ORI_NEXT, /* offset */ 0, NULL)) {
PDO_HANDLE_STMT_ERR();
I->key = (zend_ulong)-1;
@@ -2265,7 +2305,7 @@ zend_object_iterator *pdo_stmt_iter_get(zend_class_entry *ce, zval *object, int
ZVAL_OBJ(&I->iter.data, Z_OBJ_P(object));
if (!do_fetch(stmt, &I->fetch_ahead, PDO_FETCH_USE_DEFAULT,
- PDO_FETCH_ORI_NEXT, 0, 0)) {
+ PDO_FETCH_ORI_NEXT, /* offset */ 0, NULL)) {
PDO_HANDLE_STMT_ERR();
I->key = (zend_ulong)-1;
ZVAL_UNDEF(&I->fetch_ahead);
@@ -2296,7 +2336,7 @@ static zval *row_prop_read(zend_object *object, zend_string *name, int type, voi
* numbers */
for (colno = 0; colno < stmt->column_count; colno++) {
if (ZSTR_LEN(stmt->columns[colno].name) == ZSTR_LEN(name) &&
- strncmp(ZSTR_VAL(stmt->columns[colno].name), ZSTR_VAL(name), ZSTR_LEN(name)) == 0) {
+ strncmp(ZSTR_VAL(stmt->columns[colno].name), ZSTR_VAL(name), ZSTR_LEN(name)) == 0) {
fetch_value(stmt, rv, colno, NULL);
return rv;
}
@@ -2338,7 +2378,7 @@ static zval *row_dim_read(zend_object *object, zval *member, int type, zval *rv)
* numbers */
for (colno = 0; colno < stmt->column_count; colno++) {
if (ZSTR_LEN(stmt->columns[colno].name) == Z_STRLEN_P(member) &&
- strncmp(ZSTR_VAL(stmt->columns[colno].name), Z_STRVAL_P(member), Z_STRLEN_P(member)) == 0) {
+ strncmp(ZSTR_VAL(stmt->columns[colno].name), Z_STRVAL_P(member), Z_STRLEN_P(member)) == 0) {
fetch_value(stmt, rv, colno, NULL);
return rv;
}
@@ -2380,7 +2420,7 @@ static int row_prop_exists(zend_object *object, zend_string *name, int check_emp
* numbers */
for (colno = 0; colno < stmt->column_count; colno++) {
if (ZSTR_LEN(stmt->columns[colno].name) == ZSTR_LEN(name) &&
- strncmp(ZSTR_VAL(stmt->columns[colno].name), ZSTR_VAL(name), ZSTR_LEN(name)) == 0) {
+ strncmp(ZSTR_VAL(stmt->columns[colno].name), ZSTR_VAL(name), ZSTR_LEN(name)) == 0) {
int res;
zval val;
@@ -2420,7 +2460,7 @@ static int row_dim_exists(zend_object *object, zval *member, int check_empty)
* numbers */
for (colno = 0; colno < stmt->column_count; colno++) {
if (ZSTR_LEN(stmt->columns[colno].name) == Z_STRLEN_P(member) &&
- strncmp(ZSTR_VAL(stmt->columns[colno].name), Z_STRVAL_P(member), Z_STRLEN_P(member)) == 0) {
+ strncmp(ZSTR_VAL(stmt->columns[colno].name), Z_STRVAL_P(member), Z_STRLEN_P(member)) == 0) {
int res;
zval val;
diff --git a/ext/pdo/pdo_stmt.stub.php b/ext/pdo/pdo_stmt.stub.php
index b280f73ffd..2732c8a71d 100644
--- a/ext/pdo/pdo_stmt.stub.php
+++ b/ext/pdo/pdo_stmt.stub.php
@@ -16,16 +16,16 @@ class PDOStatement implements IteratorAggregate
/** @return bool */
public function closeCursor() {}
- /** @return int|false */
+ /** @return int */
public function columnCount() {}
/** @return bool|null */
public function debugDumpParams() {}
- /** @return string|false|null */
+ /** @return string|null */
public function errorCode() {}
- /** @return array|false */
+ /** @return array */
public function errorInfo() {}
/** @return bool */
@@ -34,8 +34,8 @@ class PDOStatement implements IteratorAggregate
/** @return mixed */
public function fetch(int $fetch_style = PDO::FETCH_BOTH, int $cursor_orientation = PDO::FETCH_ORI_NEXT, int $cursor_offset = 0) {}
- /** @return array|false */
- public function fetchAll(int $fetch_style = PDO::FETCH_BOTH, mixed ...$fetch_args) {}
+ /** @return array */
+ public function fetchAll(int $fetch_style = PDO::FETCH_BOTH, mixed ...$fetch_mode_args) {}
/** @return mixed */
public function fetchColumn(int $column_number = 0) {}
@@ -52,14 +52,14 @@ class PDOStatement implements IteratorAggregate
/** @return bool */
public function nextRowset() {}
- /** @return int|false */
+ /** @return int */
public function rowCount() {}
/** @return bool */
public function setAttribute(int $attribute, mixed $value) {}
/** @return bool */
- public function setFetchMode(int $mode, mixed ...$params) {}
+ public function setFetchMode(int $mode, mixed ...$fetch_mode_args) {}
public function getIterator(): Iterator {}
}
diff --git a/ext/pdo/pdo_stmt_arginfo.h b/ext/pdo/pdo_stmt_arginfo.h
index 116449ad3a..157507a852 100644
--- a/ext/pdo/pdo_stmt_arginfo.h
+++ b/ext/pdo/pdo_stmt_arginfo.h
@@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
- * Stub hash: a35e66ccff5e569f07ae8372e661e005943dfbc7 */
+ * Stub hash: c12bc1c5d1e3dbd8cce67e50c974b20ec5564e67 */
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_PDOStatement_bindColumn, 0, 0, 2)
ZEND_ARG_TYPE_MASK(0, column, MAY_BE_STRING|MAY_BE_LONG, NULL)
@@ -46,7 +46,7 @@ ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_PDOStatement_fetchAll, 0, 0, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, fetch_style, IS_LONG, 0, "PDO::FETCH_BOTH")
- ZEND_ARG_VARIADIC_TYPE_INFO(0, fetch_args, IS_MIXED, 0)
+ ZEND_ARG_VARIADIC_TYPE_INFO(0, fetch_mode_args, IS_MIXED, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_PDOStatement_fetchColumn, 0, 0, 0)
@@ -77,7 +77,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_VARIADIC_TYPE_INFO(0, params, IS_MIXED, 0)
+ ZEND_ARG_VARIADIC_TYPE_INFO(0, fetch_mode_args, IS_MIXED, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_PDOStatement_getIterator, 0, 0, Iterator, 0)
diff --git a/ext/pdo/php_pdo.h b/ext/pdo/php_pdo.h
index 9d9e73915d..89cd22c8e8 100644
--- a/ext/pdo/php_pdo.h
+++ b/ext/pdo/php_pdo.h
@@ -53,11 +53,11 @@ PHP_MINFO_FUNCTION(pdo);
#define REGISTER_PDO_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);
-#define PDO_CONSTRUCT_CHECK \
- if (!dbh->driver) { \
- pdo_raise_impl_error(dbh, NULL, "00000", "PDO constructor was not called"); \
- return; \
- } \
+#define PDO_CONSTRUCT_CHECK \
+ if (!dbh->driver) { \
+ zend_throw_error(NULL, "PDO object is not initialized, constructor was not called"); \
+ RETURN_THROWS(); \
+ } \
#endif /* PHP_PDO_H */
diff --git a/ext/pdo/php_pdo_int.h b/ext/pdo/php_pdo_int.h
index 7fe3bfc850..7f992a5fd0 100644
--- a/ext/pdo/php_pdo_int.h
+++ b/ext/pdo/php_pdo_int.h
@@ -40,7 +40,8 @@ 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(pdo_stmt_t *stmt, zend_long fetch_mode, zval *args, uint32_t num_args);
+bool pdo_stmt_setup_fetch_mode(pdo_stmt_t *stmt, zend_long mode, uint32_t mode_arg_num,
+ zval *args, uint32_t variadic_num_args);
extern zend_object *pdo_row_new(zend_class_entry *ce);
extern const zend_function_entry pdo_row_functions[];
diff --git a/ext/pdo/tests/bug_44159.phpt b/ext/pdo/tests/bug_44159.phpt
index 0e1116d588..b5601eed41 100644
--- a/ext/pdo/tests/bug_44159.phpt
+++ b/ext/pdo/tests/bug_44159.phpt
@@ -2,51 +2,46 @@
PDO Common: Bug #44159 (Crash: $pdo->setAttribute(PDO::STATEMENT_ATTR_CLASS, NULL))
--SKIPIF--
<?php
-if (!extension_loaded('pdo')) die('skip PDO not available');
-try {
- $pdo = new PDO("sqlite:".__DIR__."/foo.db");
-} catch (Exception $e) {
- die("skip PDP_SQLITE not available");
-}
+if (!extension_loaded('pdo')) die('skip');
+$dir = getenv('REDIR_TEST_DIR');
+if (false == $dir) die('skip no driver');
+require_once $dir . 'pdo_test.inc';
+PDOTest::skip();
?>
--FILE--
<?php
-$pdo = new PDO("sqlite:".__DIR__."/foo.db");
+if (getenv('REDIR_TEST_DIR') === false) putenv('REDIR_TEST_DIR='.__DIR__ . '/../../pdo/tests/');
+require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc';
+$pdo = PDOTest::factory();
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
-$attrs = array(PDO::ATTR_STATEMENT_CLASS, PDO::ATTR_STRINGIFY_FETCHES, PDO::NULL_TO_STRING);
+$attrs = array(PDO::ATTR_STATEMENT_CLASS, PDO::ATTR_STRINGIFY_FETCHES);
foreach ($attrs as $attr) {
- var_dump($pdo->setAttribute($attr, NULL));
- var_dump($pdo->setAttribute($attr, 1));
- var_dump($pdo->setAttribute($attr, 'nonsense'));
+ try {
+ var_dump($pdo->setAttribute($attr, NULL));
+ } catch (\Error $e) {
+ echo get_class($e), ': ', $e->getMessage(), \PHP_EOL;
+ }
+ try {
+ var_dump($pdo->setAttribute($attr, 1));
+ } catch (\Error $e) {
+ echo get_class($e), ': ', $e->getMessage(), \PHP_EOL;
+ }
+ try {
+ var_dump($pdo->setAttribute($attr, 'nonsense'));
+ } catch (\Error $e) {
+ echo get_class($e), ': ', $e->getMessage(), \PHP_EOL;
+ }
}
@unlink(__DIR__."/foo.db");
?>
---EXPECTF--
-Warning: PDO::setAttribute(): SQLSTATE[HY000]: General error: PDO::ATTR_STATEMENT_CLASS requires format array(classname, array(ctor_args)); the classname must be a string specifying an existing class in %s on line %d
-
-Warning: PDO::setAttribute(): SQLSTATE[HY000]: General error in %s on line %d
-bool(false)
-
-Warning: PDO::setAttribute(): SQLSTATE[HY000]: General error: PDO::ATTR_STATEMENT_CLASS requires format array(classname, array(ctor_args)); the classname must be a string specifying an existing class in %s on line %d
-
-Warning: PDO::setAttribute(): SQLSTATE[HY000]: General error in %s on line %d
-bool(false)
-
-Warning: PDO::setAttribute(): SQLSTATE[HY000]: General error: PDO::ATTR_STATEMENT_CLASS requires format array(classname, array(ctor_args)); the classname must be a string specifying an existing class in %s on line %d
-
-Warning: PDO::setAttribute(): SQLSTATE[HY000]: General error in %s on line %d
-bool(false)
-
-Warning: PDO::setAttribute(): SQLSTATE[HY000]: General error: attribute value must be an integer in %s on line %d
-
-Warning: PDO::setAttribute(): SQLSTATE[HY000]: General error in %s on line %d
-bool(false)
-bool(true)
-bool(true)
-bool(true)
+--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: Attribute value must be of type int for selected attribute, null given
bool(true)
bool(true)
diff --git a/ext/pdo/tests/bug_44173.phpt b/ext/pdo/tests/bug_44173.phpt
index df98f332fe..0baa7973e5 100644
--- a/ext/pdo/tests/bug_44173.phpt
+++ b/ext/pdo/tests/bug_44173.phpt
@@ -19,8 +19,12 @@ $db->exec("INSERT INTO test VALUES (1)");
// Bug entry [2] -- 1 is PDO::FETCH_LAZY
-$stmt = $db->query("SELECT * FROM test", PDO::FETCH_LAZY, 0, 0);
-var_dump($stmt);
+try {
+ $stmt = $db->query("SELECT * FROM test", PDO::FETCH_LAZY, 0, []);
+ var_dump($stmt);
+} catch (\TypeError $e) {
+ echo $e->getMessage(), \PHP_EOL;
+}
// Bug entry [3]
@@ -31,39 +35,46 @@ try {
}
// Bug entry [4]
-$stmt = $db->query("SELECT * FROM test", PDO::FETCH_CLASS, 0, 0, 0);
-var_dump($stmt);
+try {
+ $stmt = $db->query("SELECT * FROM test", PDO::FETCH_CLASS, 0, 0, 0);
+ var_dump($stmt);
+} catch (\ArgumentCountError $e) {
+ echo $e->getMessage(), \PHP_EOL;
+}
// Bug entry [5]
-$stmt = $db->query("SELECT * FROM test", PDO::FETCH_INTO);
-var_dump($stmt);
+try {
+ $stmt = $db->query("SELECT * FROM test", PDO::FETCH_INTO);
+ var_dump($stmt);
+} catch (\ArgumentCountError $e) {
+ echo $e->getMessage(), \PHP_EOL;
+}
// Bug entry [6]
-$stmt = $db->query("SELECT * FROM test", PDO::FETCH_COLUMN);
-var_dump($stmt);
+try {
+ $stmt = $db->query("SELECT * FROM test", PDO::FETCH_COLUMN);
+ var_dump($stmt);
+} catch (\ArgumentCountError $e) {
+ echo $e->getMessage(), \PHP_EOL;
+}
// Bug entry [7]
-$stmt = $db->query("SELECT * FROM test", PDO::FETCH_CLASS);
-var_dump($stmt);
+try {
+ $stmt = $db->query("SELECT * FROM test", PDO::FETCH_CLASS);
+ var_dump($stmt);
+} catch (\ArgumentCountError $e) {
+ echo $e->getMessage(), \PHP_EOL;
+}
?>
---EXPECTF--
-Warning: PDO::query(): SQLSTATE[HY000]: General error: fetch mode doesn't allow any extra arguments in %s
-bool(false)
+--EXPECT--
+PDO::query() expects exactly 2 arguments for the fetch mode provided, 4 given
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)
-
-Warning: PDO::query(): SQLSTATE[HY000]: General error: fetch mode requires the object parameter in %s
-bool(false)
-
-Warning: PDO::query(): SQLSTATE[HY000]: General error: fetch mode requires the colno argument in %s
-bool(false)
-
-Warning: PDO::query(): SQLSTATE[HY000]: General error: fetch mode requires the classname argument in %s
-bool(false)
+PDO::query() expects at most 4 arguments for the fetch mode provided, 5 given
+PDO::query() expects exactly 3 arguments for the fetch mode provided, 2 given
+PDO::query() expects exactly 3 arguments for the fetch mode provided, 2 given
+PDO::query() expects at least 3 arguments for the fetch mode provided, 2 given
diff --git a/ext/pdo/tests/pdo_038.phpt b/ext/pdo/tests/pdo_038.phpt
index 3ff2d090a8..a2887f35db 100644
--- a/ext/pdo/tests/pdo_038.phpt
+++ b/ext/pdo/tests/pdo_038.phpt
@@ -32,14 +32,19 @@ switch ($conn->getAttribute(PDO::ATTR_DRIVER_NAME)) {
$stmt = $conn->prepare($query);
-var_dump(fetchColumn($stmt, -1));
+try {
+ var_dump(fetchColumn($stmt, -1));
+} catch (\ValueError $e) {
+ echo $e->getMessage(), \PHP_EOL;
+}
var_dump(fetchColumn($stmt, 0));
-var_dump(fetchColumn($stmt, 1));
+try {
+ var_dump(fetchColumn($stmt, 1));
+} catch (\ValueError $e) {
+ echo $e->getMessage(), \PHP_EOL;
+}
?>
---EXPECTF--
-Warning: PDOStatement::fetchColumn(): SQLSTATE[HY000]: General error: Invalid column index in %s
-bool(false)
+--EXPECT--
+Column index must be greater than or equal to 0
string(1) "1"
-
-Warning: PDOStatement::fetchColumn(): SQLSTATE[HY000]: General error: Invalid column index in %s
-bool(false)
+Invalid column index
diff --git a/ext/pdo/tests/pdo_quote_empty_string.phpt b/ext/pdo/tests/pdo_quote_empty_string.phpt
new file mode 100644
index 0000000000..214d1014b9
--- /dev/null
+++ b/ext/pdo/tests/pdo_quote_empty_string.phpt
@@ -0,0 +1,31 @@
+--TEST--
+PDO::quote() must accept empty string for drivers which support this feature
+--SKIPIF--
+<?php
+if (!extension_loaded('pdo')) die('skip');
+$dir = getenv('REDIR_TEST_DIR');
+if (false == $dir) die('skip no driver');
+require_once $dir . 'pdo_test.inc';
+PDOTest::skip();
+?>
+--FILE--
+<?php
+if (getenv('REDIR_TEST_DIR') === false) putenv('REDIR_TEST_DIR='.__DIR__ . '/../../pdo/tests/');
+require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc';
+
+$pdo = PDOTest::factory();
+$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+
+try {
+ $result = $pdo->quote('');
+ if (!is_string($result)) {
+ var_dump($result);
+ }
+} catch (\PDOException) {
+ // Do nothing as quoting is not supported with this driver
+}
+?>
+DONE
+
+--EXPECT--
+DONE
diff --git a/ext/pdo_mysql/tests/pdo_mysql_attr_errmode.phpt b/ext/pdo_mysql/tests/pdo_mysql_attr_errmode.phpt
index 0d6cee356e..d6ebd87f60 100644
--- a/ext/pdo_mysql/tests/pdo_mysql_attr_errmode.phpt
+++ b/ext/pdo_mysql/tests/pdo_mysql_attr_errmode.phpt
@@ -14,29 +14,27 @@ error_reporting=E_ALL
require_once(__DIR__ . DIRECTORY_SEPARATOR . 'mysql_pdo_test.inc');
$db = MySQLPDOTest::factory();
- $valid = array(PDO::ERRMODE_SILENT, PDO::ERRMODE_WARNING, PDO::ERRMODE_EXCEPTION);
- do {
- $invalid = mt_rand(-1000, 1000);
- } while (in_array($invalid, $valid));
-
-
- $tmp = array();
- if (false != @$db->setAttribute(PDO::ATTR_ERRMODE, $tmp))
- printf("[001] Maybe PDO could indicate that this is not a proper way of setting the ERRMODE...\n");
-
- $tmp = new stdClass();
- $ret = @$db->setAttribute(PDO::ATTR_ERRMODE, $tmp);
- if (false != $ret)
- printf("[002] Maybe PDO could indicate that this is not a proper way of setting the ERRMODE...%s\n",
- var_export($ret, true));
-
- $ret = @$db->setAttribute(PDO::ATTR_ERRMODE, 'pdo');
- if (false != $ret)
- printf("[003] Maybe PDO could indicate that this is not a proper way of setting the ERRMODE...%s\n",
- var_export($ret, true));
-
- if (false != @$db->setAttribute(PDO::ATTR_ERRMODE, $invalid))
- printf("[004] Invalid ERRMODE should be rejected\n");
+ try {
+ $db->setAttribute(PDO::ATTR_ERRMODE, []);
+ } catch (\Error $e) {
+ echo get_class($e), ': ', $e->getMessage(), \PHP_EOL;
+ }
+ try {
+ $db->setAttribute(PDO::ATTR_ERRMODE, new stdClass());
+ } catch (\Error $e) {
+ echo get_class($e), ': ', $e->getMessage(), \PHP_EOL;
+ }
+ try {
+ /* This currently passes */
+ $db->setAttribute(PDO::ATTR_ERRMODE, 'pdo');
+ } catch (\Error $e) {
+ echo get_class($e), ': ', $e->getMessage(), \PHP_EOL;
+ }
+ try {
+ $db->setAttribute(PDO::ATTR_ERRMODE, 1000);
+ } catch (\Error $e) {
+ echo get_class($e), ': ', $e->getMessage(), \PHP_EOL;
+ }
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
// no message for any PDO call but...
@@ -160,7 +158,9 @@ error_reporting=E_ALL
print "done!\n";
?>
--EXPECTF--
-[003] Maybe PDO could indicate that this is not a proper way of setting the ERRMODE...true
+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
+ValueError: 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_oracle_nulls.phpt b/ext/pdo_mysql/tests/pdo_mysql_attr_oracle_nulls.phpt
index 694a039441..6d922a037d 100644
--- a/ext/pdo_mysql/tests/pdo_mysql_attr_oracle_nulls.phpt
+++ b/ext/pdo_mysql/tests/pdo_mysql_attr_oracle_nulls.phpt
@@ -12,16 +12,22 @@ MySQLPDOTest::skip();
$db = MySQLPDOTest::factory();
MySQLPDOTest::createTestTable($db);
- $tmp = array();
- if (false !== @$db->setAttribute(PDO::ATTR_ORACLE_NULLS, $tmp))
- printf("[001] Maybe PDO could indicate that this is not a proper way of setting ATTR_ORACLE_NULLS...\n");
-
- $tmp = new stdClass();
- if (false !== @$db->setAttribute(PDO::ATTR_ORACLE_NULLS, $tmp));
- printf("[002] Maybe PDO could indicate that this is not a proper way of setting ATTR_ORACLE_NULLS...\n");
-
- if (false !== @$db->setAttribute(PDO::ATTR_ORACLE_NULLS, 'pdo'))
- printf("[003] Maybe PDO could indicate that this is not a proper way of setting ATTR_ORACLE_NULLS...\n");
+ try {
+ $db->setAttribute(PDO::ATTR_ORACLE_NULLS, []);
+ } catch (\TypeError $e) {
+ echo $e->getMessage(), \PHP_EOL;
+ }
+ try {
+ $db->setAttribute(PDO::ATTR_ORACLE_NULLS, new stdClass());
+ } catch (\TypeError $e) {
+ echo $e->getMessage(), \PHP_EOL;
+ }
+ try {
+ /* Currently passes... */
+ $db->setAttribute(PDO::ATTR_ORACLE_NULLS, 'pdo');
+ } catch (\TypeError $e) {
+ echo $e->getMessage(), \PHP_EOL;
+ }
$db->setAttribute(PDO::ATTR_ORACLE_NULLS, 1);
$stmt = $db->query("SELECT NULL AS z, '' AS a, ' ' AS b, TRIM(' ') as c, ' d' AS d, '" . chr(0) . " e' AS e");
@@ -82,8 +88,8 @@ MySQLPDOTest::skip();
print "done!";
?>
--EXPECTF--
-[002] Maybe PDO could indicate that this is not a proper way of setting ATTR_ORACLE_NULLS...
-[003] Maybe PDO could indicate that this is not a proper way of setting ATTR_ORACLE_NULLS...
+Attribute value must be of type int for selected attribute, array given
+Attribute value must be of type int for selected attribute, stdClass given
array(1) {
[0]=>
array(6) {
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 66df0cda45..6d536f9ded 100644
--- a/ext/pdo_mysql/tests/pdo_mysql_attr_statement_class.phpt
+++ b/ext/pdo_mysql/tests/pdo_mysql_attr_statement_class.phpt
@@ -16,15 +16,22 @@ $db = MySQLPDOTest::factory();
$default = $db->getAttribute(PDO::ATTR_STATEMENT_CLASS);
var_dump($default);
- if (false !== ($tmp = @$db->setAttribute(PDO::ATTR_STATEMENT_CLASS, 'foo')))
- printf("[002] Expecting boolean/false got %s\n", var_export($tmp, true));
-
- if (false !== ($tmp = @$db->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('classname'))))
- printf("[003] Expecting boolean/false got %s\n", var_export($tmp, true));
-
+ try {
+ $db->setAttribute(PDO::ATTR_STATEMENT_CLASS, 'foo');
+ } catch (\TypeError $e) {
+ echo $e->getMessage(), \PHP_EOL;
+ }
+ try {
+ $db->setAttribute(PDO::ATTR_STATEMENT_CLASS, ['classname']);
+ } catch (\TypeError $e) {
+ echo $e->getMessage(), \PHP_EOL;
+ }
// unknown class
- if (false !== ($tmp = $db->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('classname', array()))))
- printf("[004] Expecting boolean/false got %s\n", var_export($tmp, true));
+ try {
+ $db->setAttribute(PDO::ATTR_STATEMENT_CLASS, ['classname', []]);
+ } catch (\TypeError $e) {
+ echo $e->getMessage(), \PHP_EOL;
+ }
// class not derived from PDOStatement
class myclass {
@@ -32,8 +39,12 @@ $db = MySQLPDOTest::factory();
printf("myclass\n");
}
}
- if (false !== ($tmp = $db->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('myclass', array()))))
- printf("[005] Expecting boolean/false got %s\n", var_export($tmp, true));
+
+ try {
+ $db->setAttribute(PDO::ATTR_STATEMENT_CLASS, ['myclass', []]);
+ } catch (\TypeError $e) {
+ echo $e->getMessage(), \PHP_EOL;
+ }
// public constructor not allowed
class mystatement extends PDOStatement {
@@ -42,8 +53,13 @@ $db = MySQLPDOTest::factory();
}
}
- if (false !== ($tmp = $db->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('mystatement', array()))))
- printf("[006] Expecting boolean/false got %s\n", var_export($tmp, true));
+ try {
+ if (false !== ($tmp = $db->setAttribute(PDO::ATTR_STATEMENT_CLASS, ['mystatement', []])))
+ printf("[006] Expecting boolean/false got %s\n", var_export($tmp, true));
+ } catch (\Error $e) {
+ echo get_class($e), ': ', $e->getMessage(), \PHP_EOL;
+ }
+
// ... but a public destructor is allowed
class mystatement2 extends PDOStatement {
@@ -109,18 +125,11 @@ array(1) {
[0]=>
string(12) "PDOStatement"
}
-
-Warning: PDO::setAttribute(): SQLSTATE[HY000]: General error: PDO::ATTR_STATEMENT_CLASS requires format array(classname, array(ctor_args)); the classname must be a string specifying an existing class in %s on line %d
-
-Warning: PDO::setAttribute(): SQLSTATE[HY000]: General error in %s on line %d
-
-Warning: PDO::setAttribute(): SQLSTATE[HY000]: General error: user-supplied statement class must be derived from PDOStatement in %s on line %d
-
-Warning: PDO::setAttribute(): SQLSTATE[HY000]: General error in %s on line %d
-
-Warning: PDO::setAttribute(): SQLSTATE[HY000]: General error: user-supplied statement class cannot have a public constructor in %s on line %d
-
-Warning: PDO::setAttribute(): SQLSTATE[HY000]: General error in %s on line %d
+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
array(2) {
[0]=>
string(12) "mystatement4"
diff --git a/ext/pdo_mysql/tests/pdo_mysql_prepare_emulated.phpt b/ext/pdo_mysql/tests/pdo_mysql_prepare_emulated.phpt
index 6fe2ff20ba..6afd57420f 100644
--- a/ext/pdo_mysql/tests/pdo_mysql_prepare_emulated.phpt
+++ b/ext/pdo_mysql/tests/pdo_mysql_prepare_emulated.phpt
@@ -88,9 +88,11 @@ $db = MySQLPDOTest::factory();
if (1 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY))
printf("[002] Unable to switch to emulated prepared statements, test will fail\n");
- // TODO - that's PDO - you can prepare empty statements!
- prepex(3, $db, '',
- array(), array('execute' => array('sqlstate' => '42000')));
+ try {
+ prepex(3, $db, '', [], ['execute' => ['sqlstate' => '42000']]);
+ } catch (\ValueError $e) {
+ echo $e->getMessage(), \PHP_EOL;
+ }
// lets be fair and do the most simple SELECT first
$stmt = prepex(4, $db, 'SELECT 1 as "one"');
@@ -328,6 +330,7 @@ $db->exec('DROP TABLE IF EXISTS test');
PDO's PS parser has some problems with invalid SQL and crashes from time to time
(check with valgrind...)
--EXPECT--
+PDO::prepare(): Argument #1 ($statement) cannot be empty
array(1) {
["one"]=>
string(1) "1"
diff --git a/ext/pdo_mysql/tests/pdo_mysql_prepare_native.phpt b/ext/pdo_mysql/tests/pdo_mysql_prepare_native.phpt
index 5ea3e94c1e..839fc43c15 100644
--- a/ext/pdo_mysql/tests/pdo_mysql_prepare_native.phpt
+++ b/ext/pdo_mysql/tests/pdo_mysql_prepare_native.phpt
@@ -99,9 +99,11 @@ $db = MySQLPDOTest::factory();
if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY))
printf("[002] Unable to turn off emulated prepared statements\n");
- // TODO - that's PDO - you can prepare empty statements!
- prepex(3, $db, '',
- array(), array('prepare' => array('sqlstate' => '42000')));
+ try {
+ prepex(3, $db, '', [], ['prepare' => ['sqlstate' => '42000']]);
+ } catch (\ValueError $e) {
+ echo $e->getMessage(), \PHP_EOL;
+ }
// lets be fair and do the most simple SELECT first
$stmt = prepex(4, $db, 'SELECT 1 as "one"');
@@ -342,6 +344,7 @@ $db = MySQLPDOTest::factory();
$db->exec('DROP TABLE IF EXISTS test');
?>
--EXPECT--
+PDO::prepare(): Argument #1 ($statement) cannot be empty
array(1) {
[0]=>
array(1) {
diff --git a/ext/pdo_mysql/tests/pdo_mysql_stmt_getcolumnmeta.phpt b/ext/pdo_mysql/tests/pdo_mysql_stmt_getcolumnmeta.phpt
index 44f0a0ebb1..b5b0275f04 100644
--- a/ext/pdo_mysql/tests/pdo_mysql_stmt_getcolumnmeta.phpt
+++ b/ext/pdo_mysql/tests/pdo_mysql_stmt_getcolumnmeta.phpt
@@ -32,8 +32,11 @@ try {
$stmt->execute();
// invalid offset
- if (false !== ($tmp = @$stmt->getColumnMeta(-1)))
- printf("[004] Expecting false got %s\n", var_export($tmp, true));
+ try {
+ $stmt->getColumnMeta(-1);
+ } catch (\ValueError $e) {
+ echo $e->getMessage(), \PHP_EOL;
+ }
$emulated = $stmt->getColumnMeta(0);
@@ -299,5 +302,6 @@ $db->exec('DROP TABLE IF EXISTS test');
print "done!";
?>
--EXPECT--
+PDOStatement::getColumnMeta(): Argument #1 ($column) must be greater than or equal to 0
Testing native PS...
done!
diff --git a/ext/pdo_sqlite/tests/bug_44159_sqlite_version.phpt b/ext/pdo_sqlite/tests/bug_44159_sqlite_version.phpt
new file mode 100644
index 0000000000..fc30f1d21c
--- /dev/null
+++ b/ext/pdo_sqlite/tests/bug_44159_sqlite_version.phpt
@@ -0,0 +1,22 @@
+--TEST--
+PDO Common: Bug #44159: SQLite variant
+--SKIPIF--
+<?php
+if (!extension_loaded('pdo_sqlite')) die('skip PDO SQLite not available');
+?>
+--FILE--
+<?php
+$pdo = new PDO("sqlite:".__DIR__."/foo.db");
+$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
+
+var_dump($pdo->setAttribute(PDO::NULL_TO_STRING, NULL));
+var_dump($pdo->setAttribute(PDO::NULL_TO_STRING, 1));
+var_dump($pdo->setAttribute(PDO::NULL_TO_STRING, 'nonsense'));
+
+@unlink(__DIR__."/foo.db");
+
+?>
+--EXPECT--
+bool(true)
+bool(true)
+bool(true)
diff --git a/ext/pdo_sqlite/tests/pdo_fetch_func_001.phpt b/ext/pdo_sqlite/tests/pdo_fetch_func_001.phpt
index 4600b7935b..814a01a647 100644
--- a/ext/pdo_sqlite/tests/pdo_fetch_func_001.phpt
+++ b/ext/pdo_sqlite/tests/pdo_fetch_func_001.phpt
@@ -20,20 +20,40 @@ $st->fetchAll(PDO::FETCH_FUNC, function($x, $y) use ($st) { var_dump($st); print
$st = $db->query('SELECT name FROM testing');
var_dump($st->fetchAll(PDO::FETCH_FUNC, 'strtoupper'));
-$st = $db->query('SELECT * FROM testing');
-var_dump($st->fetchAll(PDO::FETCH_FUNC, 'nothing'));
+try {
+ $st = $db->query('SELECT * FROM testing');
+ var_dump($st->fetchAll(PDO::FETCH_FUNC, 'nothing'));
+} catch (\TypeError $e) {
+ echo $e->getMessage(), \PHP_EOL;
+}
-$st = $db->query('SELECT * FROM testing');
-var_dump($st->fetchAll(PDO::FETCH_FUNC, ''));
+try {
+ $st = $db->query('SELECT * FROM testing');
+ var_dump($st->fetchAll(PDO::FETCH_FUNC, ''));
+} catch (\TypeError $e) {
+ echo $e->getMessage(), \PHP_EOL;
+}
-$st = $db->query('SELECT * FROM testing');
-var_dump($st->fetchAll(PDO::FETCH_FUNC, NULL));
+try {
+ $st = $db->query('SELECT * FROM testing');
+ var_dump($st->fetchAll(PDO::FETCH_FUNC, NULL));
+} catch (\TypeError $e) {
+ echo $e->getMessage(), \PHP_EOL;
+}
-$st = $db->query('SELECT * FROM testing');
-var_dump($st->fetchAll(PDO::FETCH_FUNC, 1));
+try {
+ $st = $db->query('SELECT * FROM testing');
+ var_dump($st->fetchAll(PDO::FETCH_FUNC, 1));
+} catch (\TypeError $e) {
+ echo $e->getMessage(), \PHP_EOL;
+}
-$st = $db->query('SELECT * FROM testing');
-var_dump($st->fetchAll(PDO::FETCH_FUNC, array('self', 'foo')));
+try {
+ $st = $db->query('SELECT * FROM testing');
+ var_dump($st->fetchAll(PDO::FETCH_FUNC, array('self', 'foo')));
+} catch (\TypeError $e) {
+ echo $e->getMessage(), \PHP_EOL;
+}
class foo {
public function method($x) {
@@ -64,14 +84,26 @@ new bar($db);
$st = $db->query('SELECT * FROM testing');
var_dump($st->fetchAll(PDO::FETCH_FUNC, array('bar', 'test')));
-$st = $db->query('SELECT * FROM testing');
-var_dump($st->fetchAll(PDO::FETCH_FUNC, array('bar', 'test2')));
+try {
+ $st = $db->query('SELECT * FROM testing');
+ var_dump($st->fetchAll(PDO::FETCH_FUNC, array('bar', 'test2')));
+} catch (\TypeError $e) {
+ echo $e->getMessage(), \PHP_EOL;
+}
-$st = $db->query('SELECT * FROM testing');
-var_dump($st->fetchAll(PDO::FETCH_FUNC, array('bar', 'test3')));
+try {
+ $st = $db->query('SELECT * FROM testing');
+ var_dump($st->fetchAll(PDO::FETCH_FUNC, array('bar', 'test3')));
+} catch (\TypeError $e) {
+ echo $e->getMessage(), \PHP_EOL;
+}
-$st = $db->query('SELECT * FROM testing');
-var_dump($st->fetchAll(PDO::FETCH_FUNC, array('bar', 'inexistent')));
+try {
+ $st = $db->query('SELECT * FROM testing');
+ var_dump($st->fetchAll(PDO::FETCH_FUNC, array('bar', 'inexistent')));
+} catch (\TypeError $e) {
+ echo $e->getMessage(), \PHP_EOL;
+}
?>
--EXPECTF--
@@ -91,31 +123,11 @@ array(2) {
[1]=>
string(0) ""
}
-
-Warning: PDOStatement::fetchAll(): SQLSTATE[HY000]: General error: function "nothing" not found or invalid function name in %s on line %d
-
-Warning: PDOStatement::fetchAll(): SQLSTATE[HY000]: General error in %s on line %d
-bool(false)
-
-Warning: PDOStatement::fetchAll(): SQLSTATE[HY000]: General error: function "" not found or invalid function name in %s on line %d
-
-Warning: PDOStatement::fetchAll(): SQLSTATE[HY000]: General error in %s on line %d
-bool(false)
-
-Warning: PDOStatement::fetchAll(): SQLSTATE[HY000]: General error: no array or string given in %s on line %d
-
-Warning: PDOStatement::fetchAll(): SQLSTATE[HY000]: General error in %s on line %d
-bool(false)
-
-Warning: PDOStatement::fetchAll(): SQLSTATE[HY000]: General error: no array or string given in %s on line %d
-
-Warning: PDOStatement::fetchAll(): SQLSTATE[HY000]: General error in %s on line %d
-bool(false)
-
-Warning: PDOStatement::fetchAll(): SQLSTATE[HY000]: General error: cannot access "self" when no class scope is active in %s on line %d
-
-Warning: PDOStatement::fetchAll(): SQLSTATE[HY000]: General error in %s on line %d
-bool(false)
+function "nothing" not found or invalid function name
+function "" not found or invalid function name
+PDOStatement::fetchAll(): Argument #2 must be a callable, null given
+no array or string given
+cannot access "self" when no class scope is active
array(2) {
[0]=>
string(9) "--- 1 ---"
@@ -128,18 +140,6 @@ array(2) {
[1]=>
string(4) "2---"
}
-
-Warning: PDOStatement::fetchAll(): SQLSTATE[HY000]: General error: non-static method bar::test2() cannot be called statically in %s on line %d
-
-Warning: PDOStatement::fetchAll(): SQLSTATE[HY000]: General error in %s on line %d
-bool(false)
-
-Warning: PDOStatement::fetchAll(): SQLSTATE[HY000]: General error: non-static method bar::test3() cannot be called statically in %s on line %d
-
-Warning: PDOStatement::fetchAll(): SQLSTATE[HY000]: General error in %s on line %d
-bool(false)
-
-Warning: PDOStatement::fetchAll(): SQLSTATE[HY000]: General error: class bar does not have a method "inexistent" in %s on line %d
-
-Warning: PDOStatement::fetchAll(): SQLSTATE[HY000]: General error in %s on line %d
-bool(false)
+non-static method bar::test2() cannot be called statically
+non-static method bar::test3() cannot be called statically
+class bar does not have a method "inexistent"