#endif
PHP_FE(mysqli_errno, arginfo_mysqli_only_link)
PHP_FE(mysqli_error, arginfo_mysqli_only_link)
+ PHP_FE(mysqli_error_list, arginfo_mysqli_only_link)
PHP_FE(mysqli_stmt_execute, arginfo_mysqli_only_statement)
PHP_FALIAS(mysqli_execute, mysqli_stmt_execute, arginfo_mysqli_only_statement)
PHP_FE(mysqli_fetch_field, arginfo_mysqli_only_result)
PHP_FE(mysqli_stmt_data_seek, arginfo_mysqli_stmt_data_seek)
PHP_FE(mysqli_stmt_errno, arginfo_mysqli_only_statement)
PHP_FE(mysqli_stmt_error, arginfo_mysqli_only_statement)
+ PHP_FE(mysqli_stmt_error_list, arginfo_mysqli_only_statement)
PHP_FE(mysqli_stmt_fetch, arginfo_mysqli_only_statement)
PHP_FE(mysqli_stmt_field_count, arginfo_mysqli_only_statement)
PHP_FE(mysqli_stmt_free_result, arginfo_mysqli_only_statement)
PHP_FUNCTION(mysqli_dump_debug_info);
PHP_FUNCTION(mysqli_errno);
PHP_FUNCTION(mysqli_error);
+PHP_FUNCTION(mysqli_error_list);
PHP_FUNCTION(mysqli_fetch_all);
PHP_FUNCTION(mysqli_fetch_array);
PHP_FUNCTION(mysqli_fetch_assoc);
PHP_FUNCTION(mysqli_stmt_data_seek);
PHP_FUNCTION(mysqli_stmt_errno);
PHP_FUNCTION(mysqli_stmt_error);
+PHP_FUNCTION(mysqli_stmt_error_list);
PHP_FUNCTION(mysqli_stmt_free_result);
PHP_FUNCTION(mysqli_stmt_get_result);
PHP_FUNCTION(mysqli_stmt_get_warnings);
/* }}} */
+
/* {{{ proto array mysqli_get_client_stats(void)
Returns statistics about the zval cache */
PHP_FUNCTION(mysqli_get_client_stats)
#endif
/* }}} */
+/* {{{ proto mixed mysqli_error_list (object connection)
+ Fetches all client errors */
+PHP_FUNCTION(mysqli_error_list)
+{
+ MY_MYSQL *mysql;
+ zval *mysql_link;
+
+ if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
+ return;
+ }
+ MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
+ array_init(return_value);
+#if defined(MYSQLI_USE_MYSQLND)
+ if (mysql->mysql->error_info.error_list) {
+ MYSQLND_ERROR_LIST_ELEMENT * message;
+ zend_llist_position pos;
+ for (message = (MYSQLND_ERROR_LIST_ELEMENT *) zend_llist_get_first_ex(mysql->mysql->error_info.error_list, &pos);
+ message;
+ message = (MYSQLND_ERROR_LIST_ELEMENT *) zend_llist_get_next_ex(mysql->mysql->error_info.error_list, &pos))
+ {
+ zval * single_error;
+ MAKE_STD_ZVAL(single_error);
+ array_init(single_error);
+ add_assoc_long_ex(single_error, "errno", sizeof("errno"), message->error_no);
+ add_assoc_string_ex(single_error, "sqlstate", sizeof("sqlstate"), message->sqlstate, 1);
+ add_assoc_string_ex(single_error, "error", sizeof("error"), message->error, 1);
+ add_next_index_zval(return_value, single_error);
+ }
+ }
+#else
+ if (mysql_errno(mysql->mysql)) {
+ zval * single_error;
+ MAKE_STD_ZVAL(single_error);
+ array_init(single_error);
+ add_assoc_long_ex(single_error, "errno", sizeof("errno"), mysql_errno(mysql->mysql));
+ add_assoc_string_ex(single_error, "sqlstate", sizeof("sqlstate"), mysql_sqlstate(mysql->mysql), 1);
+ add_assoc_string_ex(single_error, "error", sizeof("error"), mysql_error(mysql->mysql), 1);
+ add_next_index_zval(return_value, single_error);
+ }
+#endif
+}
+/* }}} */
+
+
+/* {{{ proto string mysqli_stmt_error_list(object stmt)
+*/
+PHP_FUNCTION(mysqli_stmt_error_list)
+{
+ MY_STMT *stmt;
+ zval *mysql_stmt;
+
+ if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
+ return;
+ }
+ MYSQLI_FETCH_RESOURCE_STMT(stmt, &mysql_stmt, MYSQLI_STATUS_INITIALIZED);
+ array_init(return_value);
+#if defined(MYSQLI_USE_MYSQLND)
+ if (stmt->stmt && stmt->stmt->data && stmt->stmt->data->error_info.error_list) {
+ MYSQLND_ERROR_LIST_ELEMENT * message;
+ zend_llist_position pos;
+ for (message = (MYSQLND_ERROR_LIST_ELEMENT *) zend_llist_get_first_ex(stmt->stmt->data->error_info.error_list, &pos);
+ message;
+ message = (MYSQLND_ERROR_LIST_ELEMENT *) zend_llist_get_next_ex(stmt->stmt->data->error_info.error_list, &pos))
+ {
+ zval * single_error;
+ MAKE_STD_ZVAL(single_error);
+ array_init(single_error);
+ add_assoc_long_ex(single_error, "errno", sizeof("errno"), message->error_no);
+ add_assoc_string_ex(single_error, "sqlstate", sizeof("sqlstate"), message->sqlstate, 1);
+ add_assoc_string_ex(single_error, "error", sizeof("error"), message->error, 1);
+ add_next_index_zval(return_value, single_error);
+ }
+ }
+#else
+ if (mysql_stmt_errno(stmt->stmt)) {
+ zval * single_error;
+ MAKE_STD_ZVAL(single_error);
+ array_init(single_error);
+ add_assoc_long_ex(single_error, "errno", sizeof("errno"), mysql_stmt_errno(stmt->stmt));
+ add_assoc_string_ex(single_error, "sqlstate", sizeof("sqlstate"), mysql_stmt_sqlstate(stmt->stmt), 1);
+ add_assoc_string_ex(single_error, "error", sizeof("error"), mysql_stmt_error(stmt->stmt), 1);
+ add_next_index_zval(return_value, single_error);
+ }
+#endif
+}
+/* }}} */
+
/* {{{ proto mixed mysqli_fetch_object (object result [, string class_name [, NULL|array ctor_params]])
Fetch a result row as an object */
}
/* }}} */
+
+/* {{{ property link_error_list_read */
+static int link_error_list_read(mysqli_object *obj, zval **retval TSRMLS_DC)
+{
+ MY_MYSQL *mysql;
+
+ MAKE_STD_ZVAL(*retval);
+
+ CHECK_STATUS(MYSQLI_STATUS_VALID);
+
+ mysql = (MY_MYSQL *)((MYSQLI_RESOURCE *)(obj->ptr))->ptr;
+
+ array_init(*retval);
+ if (mysql) {
+#if defined(MYSQLI_USE_MYSQLND)
+ if (mysql->mysql->error_info.error_list) {
+ MYSQLND_ERROR_LIST_ELEMENT * message;
+ zend_llist_position pos;
+ for (message = (MYSQLND_ERROR_LIST_ELEMENT *) zend_llist_get_first_ex(mysql->mysql->error_info.error_list, &pos);
+ message;
+ message = (MYSQLND_ERROR_LIST_ELEMENT *) zend_llist_get_next_ex(mysql->mysql->error_info.error_list, &pos))
+ {
+ zval * single_error;
+ MAKE_STD_ZVAL(single_error);
+ array_init(single_error);
+ add_assoc_long_ex(single_error, "errno", sizeof("errno"), message->error_no);
+ add_assoc_string_ex(single_error, "sqlstate", sizeof("sqlstate"), message->sqlstate, 1);
+ add_assoc_string_ex(single_error, "error", sizeof("error"), message->error, 1);
+ add_next_index_zval(*retval, single_error);
+ }
+ }
+#else
+ if (mysql_errno(mysql->mysql)) {
+ zval * single_error;
+ MAKE_STD_ZVAL(single_error);
+ array_init(single_error);
+ add_assoc_long_ex(single_error, "errno", sizeof("errno"), mysql_errno(mysql->mysql));
+ add_assoc_string_ex(single_error, "sqlstate", sizeof("sqlstate"), mysql_sqlstate(mysql->mysql), 1);
+ add_assoc_string_ex(single_error, "error", sizeof("error"), mysql_error(mysql->mysql), 1);
+ add_next_index_zval(*retval, single_error);
+ }
+#endif
+ }
+ return SUCCESS;
+}
+/* }}} */
+
+
/* link properties */
MYSQLI_MAP_PROPERTY_FUNC_LONG(link_errno_read, mysql_errno, MYSQLI_GET_MYSQL(MYSQLI_STATUS_INITIALIZED), ulong, "%lu")
MYSQLI_MAP_PROPERTY_FUNC_STRING(link_error_read, mysql_error, MYSQLI_GET_MYSQL(MYSQLI_STATUS_INITIALIZED))
MYSQLI_MAP_PROPERTY_FUNC_STRING(link_sqlstate_read, mysql_sqlstate, MYSQLI_GET_MYSQL(MYSQLI_STATUS_VALID))
MYSQLI_MAP_PROPERTY_FUNC_LONG(link_thread_id_read, mysql_thread_id, MYSQLI_GET_MYSQL(MYSQLI_STATUS_VALID), ulong, "%lu")
MYSQLI_MAP_PROPERTY_FUNC_LONG(link_warning_count_read, mysql_warning_count, MYSQLI_GET_MYSQL(MYSQLI_STATUS_VALID), ulong, "%lu")
+
/* result properties */
/* {{{ property result_type_read */
}
/* }}} */
+/* {{{ property stmt_error_list_read */
+static int stmt_error_list_read(mysqli_object *obj, zval **retval TSRMLS_DC)
+{
+ MY_STMT * stmt;
+
+ MAKE_STD_ZVAL(*retval);
+ CHECK_STATUS(MYSQLI_STATUS_INITIALIZED);
+
+ stmt = (MY_STMT *)((MYSQLI_RESOURCE *)(obj->ptr))->ptr;
+ array_init(*retval);
+ if (stmt && stmt->stmt) {
+#if defined(MYSQLI_USE_MYSQLND)
+ if (stmt->stmt->data && stmt->stmt->data->error_info.error_list) {
+ MYSQLND_ERROR_LIST_ELEMENT * message;
+ zend_llist_position pos;
+ for (message = (MYSQLND_ERROR_LIST_ELEMENT *) zend_llist_get_first_ex(stmt->stmt->data->error_info.error_list, &pos);
+ message;
+ message = (MYSQLND_ERROR_LIST_ELEMENT *) zend_llist_get_next_ex(stmt->stmt->data->error_info.error_list, &pos))
+ {
+ zval * single_error;
+ MAKE_STD_ZVAL(single_error);
+ array_init(single_error);
+ add_assoc_long_ex(single_error, "errno", sizeof("errno"), message->error_no);
+ add_assoc_string_ex(single_error, "sqlstate", sizeof("sqlstate"), message->sqlstate, 1);
+ add_assoc_string_ex(single_error, "error", sizeof("error"), message->error, 1);
+ add_next_index_zval(*retval, single_error);
+ }
+ }
+#else
+ if (mysql_stmt_errno(stmt->stmt)) {
+ zval * single_error;
+ MAKE_STD_ZVAL(single_error);
+ array_init(single_error);
+ add_assoc_long_ex(single_error, "errno", sizeof("errno"), mysql_stmt_errno(stmt->stmt));
+ add_assoc_string_ex(single_error, "sqlstate", sizeof("sqlstate"), mysql_stmt_sqlstate(stmt->stmt), 1);
+ add_assoc_string_ex(single_error, "error", sizeof("error"), mysql_stmt_error(stmt->stmt), 1);
+ add_next_index_zval(*retval, single_error);
+ }
+#endif
+ }
+ return SUCCESS;
+}
+/* }}} */
+
+
MYSQLI_MAP_PROPERTY_FUNC_LONG(stmt_insert_id_read, mysql_stmt_insert_id, MYSQLI_GET_STMT(MYSQLI_STATUS_VALID), my_ulonglong, MYSQLI_LLU_SPEC)
MYSQLI_MAP_PROPERTY_FUNC_LONG(stmt_num_rows_read, mysql_stmt_num_rows, MYSQLI_GET_STMT(MYSQLI_STATUS_VALID), my_ulonglong, MYSQLI_LLU_SPEC)
MYSQLI_MAP_PROPERTY_FUNC_LONG(stmt_param_count_read, mysql_stmt_param_count, MYSQLI_GET_STMT(MYSQLI_STATUS_VALID), ulong, "%lu")
{"connect_error", sizeof("connect_error") - 1, link_connect_error_read, NULL},
{"errno", sizeof("errno") - 1, link_errno_read, NULL},
{"error", sizeof("error") - 1, link_error_read, NULL},
+ {"error_list", sizeof("error_list") - 1, link_error_list_read, NULL},
{"field_count", sizeof("field_count") - 1, link_field_count_read, NULL},
{"host_info", sizeof("host_info") - 1, link_host_info_read, NULL},
{"info", sizeof("info") - 1, link_info_read, NULL},
{ZEND_ACC_PUBLIC, "connect_error", sizeof("connect_error") - 1, -1, 0, NULL, 0, NULL},
{ZEND_ACC_PUBLIC, "errno", sizeof("errno") - 1, -1, 0, NULL, 0, NULL},
{ZEND_ACC_PUBLIC, "error", sizeof("error") - 1, -1, 0, NULL, 0, NULL},
+ {ZEND_ACC_PUBLIC, "error_list", sizeof("error_list") - 1, -1, 0, NULL, 0, NULL},
{ZEND_ACC_PUBLIC, "field_count", sizeof("field_count") - 1, -1, 0, NULL, 0, NULL},
{ZEND_ACC_PUBLIC, "host_info", sizeof("host_info") - 1, -1, 0, NULL, 0, NULL},
{ZEND_ACC_PUBLIC, "info", sizeof("info") - 1, -1, 0, NULL, 0, NULL},
{"field_count", sizeof("field_count") - 1, stmt_field_count_read, NULL},
{"errno", sizeof("errno") - 1, stmt_errno_read, NULL},
{"error", sizeof("error") - 1, stmt_error_read, NULL},
+ {"error_list", sizeof("error_list") - 1, stmt_error_list_read, NULL},
{"sqlstate", sizeof("sqlstate") - 1, stmt_sqlstate_read, NULL},
{"id", sizeof("id") - 1, stmt_id_read, NULL},
{NULL, 0, NULL, NULL}
{ZEND_ACC_PUBLIC, "field_count",sizeof("field_count") - 1, -1, 0, NULL, 0, NULL},
{ZEND_ACC_PUBLIC, "errno", sizeof("errno") - 1, -1, 0, NULL, 0, NULL},
{ZEND_ACC_PUBLIC, "error", sizeof("error") - 1, -1, 0, NULL, 0, NULL},
+ {ZEND_ACC_PUBLIC, "error_list", sizeof("error_list") - 1, -1, 0, NULL, 0, NULL},
{ZEND_ACC_PUBLIC, "sqlstate", sizeof("sqlstate") - 1, -1, 0, NULL, 0, NULL},
{ZEND_ACC_PUBLIC, "id", sizeof("id") - 1, -1, 0, NULL, 0, NULL},
{0, NULL, 0, -1, 0, NULL, 0, NULL}
int(0)
[%u|b%"error"]=>
%unicode|string%(0) ""
+ [%u|b%"error_list"]=>
+ array(0) {
+ }
[%u|b%"sqlstate"]=>
%unicode|string%(5) "00000"
[%u|b%"id"]=>
int(0)
[%u|b%"error"]=>
%unicode|string%(0) ""
+ [%u|b%"error_list"]=>
+ array(0) {
+ }
[%u|b%"field_count"]=>
int(0)
[%u|b%"host_info"]=>
int(0)
[%u|b%"error"]=>
%unicode|string%(0) ""
+ [%u|b%"error_list"]=>
+ NULL
[%u|b%"field_count"]=>
NULL
[%u|b%"host_info"]=>
$mysqli->error, gettype($mysqli->error),
mysqli_error($link), gettype(mysqli_error($link)));
+ assert(mysqli_error_list($link) === $mysqli->error_list);
+ printf("mysqli->error_list = '%s'/%s ('%s'/%s)\n",
+ $mysqli->error_list, gettype($mysqli->error_list),
+ mysqli_error_list($link), gettype(mysqli_error_list($link)));
+
assert(mysqli_field_count($link) === $mysqli->field_count);
printf("mysqli->field_count = '%s'/%s ('%s'/%s)\n",
$mysqli->field_count, gettype($mysqli->field_count),
connect_error
errno
error
+error_list
field_count
host_info
info
connect_error
errno
error
+error_list
field_count
host_info
info
mysqli->client_version = '%d'/integer ('%d'/integer)
mysqli->errno = '0'/integer ('0'/integer)
mysqli->error = ''/%unicode|string% (''/%unicode|string%)
+mysqli->error_list = 'Array'/array ('Array'/array)
mysqli->field_count = '0'/integer ('0'/integer)
mysqli->insert_id = '0'/integer ('0'/integer)
mysqli->sqlstate = '00000'/%unicode|string% ('00000'/%unicode|string%)
connect_error = ''%s'
errno = 'NULL'
error = 'NULL'
+error_list = 'NULL'
field_count = 'NULL'
host_info = 'NULL'
info = 'NULL'
connect_error = '%s'
errno = 'NULL'
error = 'NULL'
+error_list = 'NULL'
field_count = 'NULL'
host_info = 'NULL'
info = 'NULL'
connect_error = '%s'
errno = 'NULL'
error = 'NULL'
+error_list = 'NULL'
field_count = 'NULL'
host_info = 'NULL'
info = 'NULL'
connect_error = '%s'
errno = 'NULL'
error = 'NULL'
+error_list = 'NULL'
field_count = 'NULL'
host_info = 'NULL'
info = 'NULL'
isDefault: yes
Modifiers: 256
+Inspecting property 'error_list'
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isDefault: yes
+Modifiers: 256
+
Inspecting property 'field_count'
isPublic: yes
isPrivate: no
Default property 'connect_error'
Default property 'errno'
Default property 'error'
+Default property 'error_list'
Default property 'field_count'
Default property 'host_info'
Default property 'info'
assert(mysqli_stmt_error($stmt) === $stmt->error);
printf("stmt->error = '%s'\n", $stmt->error);
+assert(mysqli_stmt_error_list($stmt) === $stmt->error_list);
+var_dump("stmt->error = ", $stmt->error_list);
+
assert(mysqli_stmt_field_count($stmt) === $stmt->field_count);
printf("stmt->field_count = '%s'\n", $stmt->field_count);
affected_rows
errno
error
+error_list
field_count
id
insert_id
field_count
errno
error
+error_list
sqlstate
id
stmt->affected_rows = '1'
stmt->errno = '0'
stmt->error = ''
+string(14) "stmt->error = "
+array(0) {
+}
stmt->field_count = '0'
stmt->id = '%d'
stmt->insert_id = '0'
print "done!";
?>
--EXPECTF--
-Warning: mysqli_connect(): (%d/%d): Access denied for user '%s'@'%s' (using password: YES) in %s on line %d
+Warning: mysqli_connect(): (%s/%d): Access denied for user '%s'@'%s' (using password: YES) in %s on line %d
array(1) {
[%u|b%"testing"]=>
%unicode|string%(21) "mysqli.default_socket"
print "done!";
?>
--EXPECTF--
-Warning: mysqli::mysqli(): (%d/%d): Access denied for user '%sunknown%s'@'%s' (using password: %s) in %s on line %d
+Warning: mysqli::mysqli(): (%s/%d): Access denied for user '%sunknown%s'@'%s' (using password: %s) in %s on line %d
... and now Exceptions
Access denied for user '%s'@'%s' (using password: %s)
done!
\ No newline at end of file
int(2006)
[%u|b%"error"]=>
%unicode|string%(%d) "%s"
+ [%u|b%"error_list"]=>
+ array(1) {
+ [0]=>
+ array(3) {
+ [%u|b%"errno"]=>
+ int(2006)
+ [%u|b%"sqlstate"]=>
+ %unicode|string%(5) "%s"
+ [%u|b%"error"]=>
+ %unicode|string%(%d) "%s"
+ }
+ }
[%u|b%"field_count"]=>
int(0)
[%u|b%"host_info"]=>
require_once("clean_table.inc");
?>
--EXPECTF--
-Warning: mysqli_real_connect(): (%d/%d): Access denied for user '%s'@'%s' (using password: YES) in %s on line %d
+Warning: mysqli_real_connect(): (%s/%d): Access denied for user '%s'@'%s' (using password: YES) in %s on line %d
object(mysqli)#%d (%d) {
[%u|b%"affected_rows"]=>
NULL
%s
[%u|b%"error"]=>
%s
+ [%u|b%"error_list"]=>
+ NULL
[%u|b%"field_count"]=>
NULL
[%u|b%"host_info"]=>
require_once("clean_table.inc");
?>
--EXPECTF--
-Warning: mysqli_real_connect(): (%d/%d): Access denied for user '%s'@'%s' (using password: YES) in %s on line %d
+Warning: mysqli_real_connect(): (%s/%d): Access denied for user '%s'@'%s' (using password: YES) in %s on line %d
done!
static struct st_mysqlnd_plugin_core mysqlnd_plugin_core;
+/* {{{ mysqlnd_error_list_pdtor */
+static void
+mysqlnd_error_list_pdtor(void * pDest)
+{
+ MYSQLND_ERROR_LIST_ELEMENT * element = (MYSQLND_ERROR_LIST_ELEMENT *) pDest;
+ TSRMLS_FETCH();
+ DBG_ENTER("mysqlnd_error_list_pdtor");
+ if (element->error) {
+ mnd_pefree(element->error, TRUE);
+ }
+ DBG_VOID_RETURN;
+}
+/* }}} */
+
+
/* {{{ mysqlnd_library_end */
PHPAPI void mysqlnd_library_end(TSRMLS_D)
{
mnd_pefree(conn->last_message, pers);
conn->last_message = NULL;
}
+ if (conn->error_info.error_list) {
+ zend_llist_clean(conn->error_info.error_list);
+ mnd_pefree(conn->error_info.error_list, pers);
+ conn->error_info.error_list = NULL;
+ }
conn->charset = NULL;
conn->greet_charset = NULL;
ret = NULL;
}
+ ret->error_info.error_list = mnd_pecalloc(1, sizeof(zend_llist), persistent);
+ if (!ret->error_info.error_list) {
+ ret->m->dtor(ret TSRMLS_CC);
+ ret = NULL;
+ } else {
+ zend_llist_init(ret->error_info.error_list, sizeof(MYSQLND_ERROR_LIST_ELEMENT), (llist_dtor_func_t)mysqlnd_error_list_pdtor, persistent);
+ }
+
DBG_RETURN(ret);
}
/* }}} */
strlcpy(conn->error_info.sqlstate, auth_resp_packet->sqlstate, sizeof(conn->error_info.sqlstate));
DBG_ERR_FMT("ERROR:%u [SQLSTATE:%s] %s", auth_resp_packet->error_no, auth_resp_packet->sqlstate, auth_resp_packet->error);
}
- conn->error_info.error_no = auth_resp_packet->error_no;
- strlcpy(conn->error_info.error, auth_resp_packet->error, sizeof(conn->error_info.error));
+ SET_CLIENT_ERROR(conn->error_info, auth_resp_packet->error_no, UNKNOWN_SQLSTATE, auth_resp_packet->error);
}
goto end;
}
}
ret = PACKET_READ(chg_user_resp, conn);
- conn->error_info = chg_user_resp->error_info;
+ COPY_CLIENT_ERROR(conn->error_info, chg_user_resp->error_info);
if (0xFE == chg_user_resp->response_code) {
ret = FAIL;
/* init handler: allocate read buffer and open file */
if (infile.local_infile_init(&info, (char *)filename, conn->infile.userdata TSRMLS_CC)) {
+ char tmp_buf[sizeof(conn->error_info.error)];
+ int tmp_error_no;
*is_warning = TRUE;
/* error occured */
- strcpy(conn->error_info.sqlstate, UNKNOWN_SQLSTATE);
- conn->error_info.error_no =
- infile.local_infile_error(info, conn->error_info.error, sizeof(conn->error_info.error) TSRMLS_CC);
+ tmp_error_no = infile.local_infile_error(info, tmp_buf, sizeof(tmp_buf) TSRMLS_CC);
+ SET_CLIENT_ERROR(conn->error_info, tmp_error_no, UNKNOWN_SQLSTATE, tmp_buf);
/* write empty packet to server */
ret = conn->net->m.send(conn, empty_packet, 0 TSRMLS_CC);
goto infile_error;
/* error during read occured */
if (bufsize < 0) {
+ char tmp_buf[sizeof(conn->error_info.error)];
+ int tmp_error_no;
*is_warning = TRUE;
DBG_ERR_FMT("Bufsize < 0, warning, %d %s %s", CR_SERVER_LOST, UNKNOWN_SQLSTATE, lost_conn);
- strcpy(conn->error_info.sqlstate, UNKNOWN_SQLSTATE);
- conn->error_info.error_no =
- infile.local_infile_error(info, conn->error_info.error, sizeof(conn->error_info.error) TSRMLS_CC);
+ tmp_error_no = infile.local_infile_error(info, tmp_buf, sizeof(tmp_buf) TSRMLS_CC);
+ SET_CLIENT_ERROR(conn->error_info, tmp_error_no, UNKNOWN_SQLSTATE, tmp_buf);
goto infile_error;
}
(error_info).error_no = 0; \
(error_info).error[0] = '\0'; \
strlcpy((error_info).sqlstate, "00000", sizeof((error_info).sqlstate)); \
+ if ((error_info).error_list) { \
+ zend_llist_clean((error_info).error_list); \
+ } \
}
+
#define SET_CLIENT_ERROR(error_info, a, b, c) \
- { \
+{ \
+ if (0 == (a)) { \
+ SET_EMPTY_ERROR((error_info)); \
+ } else { \
(error_info).error_no = (a); \
strlcpy((error_info).sqlstate, (b), sizeof((error_info).sqlstate)); \
strlcpy((error_info).error, (c), sizeof((error_info).error)); \
+ if ((error_info).error_list) {\
+ MYSQLND_ERROR_LIST_ELEMENT error_for_the_list = {0}; \
+ \
+ error_for_the_list.error_no = (a); \
+ strlcpy(error_for_the_list.sqlstate, (b), sizeof(error_for_the_list.sqlstate)); \
+ error_for_the_list.error = mnd_pestrdup((c), TRUE); \
+ if (error_for_the_list.error) { \
+ DBG_INF_FMT("adding error [%s] to the list", error_for_the_list.error); \
+ zend_llist_add_element((error_info).error_list, &error_for_the_list); \
+ } \
+ } \
+ } \
+}
+
+
+#define COPY_CLIENT_ERROR(error_info_to, error_info_from) \
+ { \
+ SET_CLIENT_ERROR((error_info_to), (error_info_from).error_no, (error_info_from).sqlstate, (error_info_from).error); \
}
+
#define SET_OOM_ERROR(error_info) SET_CLIENT_ERROR((error_info), CR_OUT_OF_MEMORY, UNKNOWN_SQLSTATE, mysqlnd_out_of_memory)
static void mysqlnd_stmt_separate_result_bind(MYSQLND_STMT * const stmt TSRMLS_DC);
static void mysqlnd_stmt_separate_one_result_bind(MYSQLND_STMT * const stmt, unsigned int param_no TSRMLS_DC);
+
+/* {{{ mysqlnd_ps_error_list_pdtor */
+static void
+mysqlnd_ps_error_list_pdtor(void * pDest)
+{
+ MYSQLND_ERROR_LIST_ELEMENT * element = (MYSQLND_ERROR_LIST_ELEMENT *) pDest;
+ TSRMLS_FETCH();
+ DBG_ENTER("mysqlnd_ps_error_list_pdtor");
+ if (element->error) {
+ mnd_pefree(element->error, TRUE);
+ }
+ DBG_VOID_RETURN;
+}
+/* }}} */
+
+
/* {{{ mysqlnd_stmt::store_result */
static MYSQLND_RES *
MYSQLND_METHOD(mysqlnd_stmt, store_result)(MYSQLND_STMT * const s TSRMLS_DC)
stmt->state = MYSQLND_STMT_USE_OR_STORE_CALLED;
} else {
- conn->error_info = result->stored_data->error_info;
+ COPY_CLIENT_ERROR(conn->error_info, result->stored_data->error_info);
stmt->result->m.free_result_contents(stmt->result TSRMLS_CC);
mnd_efree(stmt->result);
stmt->result = NULL;
stmt->state = MYSQLND_STMT_PREPARED;
result->type = MYSQLND_RES_PS_BUF;
} else {
- stmt->error_info = conn->error_info;
+ COPY_CLIENT_ERROR(stmt->error_info, conn->error_info);
stmt->state = MYSQLND_STMT_PREPARED;
break;
}
}
if (0xFF == prepare_resp->error_code) {
- stmt->error_info = stmt->conn->error_info = prepare_resp->error_info;
+ COPY_CLIENT_ERROR(stmt->error_info, prepare_resp->error_info);
+ COPY_CLIENT_ERROR(stmt->conn->error_info, prepare_resp->error_info);
goto done;
}
ret = PASS;
ret = mysqlnd_query_read_result_set_header(stmt->conn, s TSRMLS_CC);
if (ret == FAIL) {
- stmt->error_info = conn->error_info;
+ COPY_CLIENT_ERROR(stmt->error_info, conn->error_info);
stmt->upsert_status.affected_rows = conn->upsert_status.affected_rows;
if (CONN_GET_STATE(conn) == CONN_QUIT_SENT) {
/* close the statement here, the connection has been closed */
}
if (ret == FAIL) {
- stmt->error_info = conn->error_info;
+ COPY_CLIENT_ERROR(stmt->error_info, conn->error_info);
DBG_INF("FAIL");
DBG_RETURN(FAIL);
}
*fetched_anything = TRUE;
} else if (ret == FAIL) {
if (row_packet->error_info.error_no) {
- stmt->conn->error_info = row_packet->error_info;
- stmt->error_info = row_packet->error_info;
+ COPY_CLIENT_ERROR(stmt->conn->error_info, row_packet->error_info);
+ COPY_CLIENT_ERROR(stmt->error_info, row_packet->error_info);
}
CONN_SET_STATE(result->conn, CONN_READY);
result->unbuf->eof_reached = TRUE; /* so next time we won't get an error */
if (FAIL == stmt->conn->m->simple_command(stmt->conn, COM_STMT_FETCH, buf, sizeof(buf),
PROT_LAST /* we will handle the response packet*/,
FALSE, TRUE TSRMLS_CC)) {
- stmt->error_info = stmt->conn->error_info;
+ COPY_CLIENT_ERROR(stmt->error_info, stmt->conn->error_info);
DBG_RETURN(FAIL);
}
FAIL == (ret = conn->m->simple_command(conn, COM_STMT_RESET, cmd_buf,
sizeof(cmd_buf), PROT_OK_PACKET,
FALSE, TRUE TSRMLS_CC))) {
- stmt->error_info = conn->error_info;
+ COPY_CLIENT_ERROR(stmt->error_info, conn->error_info);
}
stmt->upsert_status = conn->upsert_status;
ret = conn->m->simple_command(conn, cmd, cmd_buf, packet_len, PROT_LAST , FALSE, TRUE TSRMLS_CC);
mnd_efree(cmd_buf);
if (FAIL == ret) {
- stmt->error_info = conn->error_info;
+ COPY_CLIENT_ERROR(stmt->error_info, conn->error_info);
}
} else {
ret = FAIL;
stmt->result->m.free_result_internal(stmt->result TSRMLS_CC);
stmt->result = NULL;
}
+ if (stmt->error_info.error_list) {
+ zend_llist_clean(stmt->error_info.error_list);
+ mnd_pefree(stmt->error_info.error_list, s->persistent);
+ stmt->error_info.error_list = NULL;
+ }
DBG_VOID_RETURN;
}
FAIL == conn->m->simple_command(conn, COM_STMT_CLOSE, cmd_buf, sizeof(cmd_buf),
PROT_LAST /* COM_STMT_CLOSE doesn't send an OK packet*/,
FALSE, TRUE TSRMLS_CC)) {
- stmt->error_info = conn->error_info;
+ COPY_CLIENT_ERROR(stmt->error_info, conn->error_info);
DBG_RETURN(FAIL);
}
}
or normal query result will close it then.
*/
stmt->conn = conn->m->get_reference(conn TSRMLS_CC);
+ stmt->error_info.error_list = mnd_pecalloc(1, sizeof(zend_llist), ret->persistent);
+ if (!stmt->error_info.error_list) {
+ break;
+ }
+ zend_llist_init(stmt->error_info.error_list, sizeof(MYSQLND_ERROR_LIST_ELEMENT), (llist_dtor_func_t) mysqlnd_ps_error_list_pdtor, conn->persistent);
DBG_RETURN(ret);
} while (0);
This will copy the error code and the messages, as they
are buffers in the struct
*/
- conn->error_info = rset_header->error_info;
+ COPY_CLIENT_ERROR(conn->error_info, rset_header->error_info);
ret = FAIL;
DBG_ERR_FMT("error=%s", rset_header->error_info.error);
/* Return back from CONN_QUERY_SENT */
}
} else if (ret == FAIL) {
if (row_packet->error_info.error_no) {
- result->conn->error_info = row_packet->error_info;
+ COPY_CLIENT_ERROR(result->conn->error_info, row_packet->error_info);
DBG_ERR_FMT("errorno=%u error=%s", row_packet->error_info.error_no, row_packet->error_info.error);
}
CONN_SET_STATE(result->conn, CONN_READY);
result->unbuf->row_count++;
} else if (ret == FAIL) {
if (row_packet->error_info.error_no) {
- result->conn->error_info = row_packet->error_info;
+ COPY_CLIENT_ERROR(result->conn->error_info, row_packet->error_info);
DBG_ERR_FMT("errorno=%u error=%s", row_packet->error_info.error_no, row_packet->error_info.error);
}
CONN_SET_STATE(result->conn, CONN_READY);
}
if (ret == FAIL) {
- set->error_info = row_packet->error_info;
+ COPY_CLIENT_ERROR(set->error_info, row_packet->error_info);
} else {
/* Position at the first row */
set->data_cursor = set->data;
ret = result->m.store_result_fetch_data(conn, result, result->meta, ps_protocol TSRMLS_CC);
if (FAIL == ret) {
if (result->stored_data) {
- conn->error_info = result->stored_data->error_info;
+ COPY_CLIENT_ERROR(conn->error_info, result->stored_data->error_info);
} else {
SET_OOM_ERROR(conn->error_info);
}
DBG_RETURN(FAIL);
}
if (field_packet->error_info.error_no) {
- conn->error_info = field_packet->error_info;
+ COPY_CLIENT_ERROR(conn->error_info, field_packet->error_info);
/* Return back from CONN_QUERY_SENT */
PACKET_FREE(field_packet);
DBG_RETURN(FAIL);
char error[MYSQLND_ERRMSG_SIZE+1];
char sqlstate[MYSQLND_SQLSTATE_LENGTH + 1];
unsigned int error_no;
+ zend_llist * error_list;
} MYSQLND_ERROR_INFO;
+typedef struct st_mysqlnd_error_list_element
+{
+ char * error;
+ char sqlstate[MYSQLND_SQLSTATE_LENGTH + 1];
+ unsigned int error_no;
+} MYSQLND_ERROR_LIST_ELEMENT;
+
+
typedef struct st_mysqlnd_infile_info
{
php_stream *fd;