mirror of
https://github.com/php/php-src.git
synced 2024-09-22 10:27:25 +00:00
Handle problems in the row_decoder, return type used to be void,
now it can return on problems.
This commit is contained in:
parent
b61d7501c9
commit
047d6f2855
@ -680,6 +680,7 @@ mysqlnd_fetch_stmt_row_buffered(MYSQLND_RES *result, void *param, unsigned int f
|
||||
unsigned int field_count = result->meta->field_count;
|
||||
|
||||
DBG_ENTER("mysqlnd_fetch_stmt_row_buffered");
|
||||
*fetched_anything = FALSE;
|
||||
DBG_INF_FMT("stmt=%lu", stmt->stmt_id);
|
||||
|
||||
/* If we haven't read everything */
|
||||
@ -694,15 +695,18 @@ mysqlnd_fetch_stmt_row_buffered(MYSQLND_RES *result, void *param, unsigned int f
|
||||
|
||||
if (NULL == current_row[0]) {
|
||||
uint64_t row_num = (set->data_cursor - set->data) / field_count;
|
||||
enum_func_status rc = result->m.row_decoder(set->row_buffers[row_num],
|
||||
current_row,
|
||||
meta->field_count,
|
||||
meta->fields,
|
||||
result->stored_data->persistent,
|
||||
result->conn->options.numeric_and_datetime_as_unicode,
|
||||
result->conn->options.int_and_float_native,
|
||||
result->conn->stats TSRMLS_CC);
|
||||
if (PASS != rc) {
|
||||
DBG_RETURN(FAIL);
|
||||
}
|
||||
set->initialized_rows++;
|
||||
result->m.row_decoder(set->row_buffers[row_num],
|
||||
current_row,
|
||||
meta->field_count,
|
||||
meta->fields,
|
||||
result->stored_data->persistent,
|
||||
result->conn->options.numeric_and_datetime_as_unicode,
|
||||
result->conn->options.int_and_float_native,
|
||||
result->conn->stats TSRMLS_CC);
|
||||
if (stmt->update_max_length) {
|
||||
for (i = 0; i < result->field_count; i++) {
|
||||
/*
|
||||
@ -757,7 +761,6 @@ mysqlnd_fetch_stmt_row_buffered(MYSQLND_RES *result, void *param, unsigned int f
|
||||
DBG_INF("row fetched");
|
||||
} else {
|
||||
set->data_cursor = NULL;
|
||||
*fetched_anything = FALSE;
|
||||
DBG_INF("no more data");
|
||||
}
|
||||
DBG_INF("PASS");
|
||||
@ -777,9 +780,10 @@ mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES *result, void *param, unsigned int
|
||||
|
||||
DBG_ENTER("mysqlnd_stmt_fetch_row_unbuffered");
|
||||
|
||||
*fetched_anything = FALSE;
|
||||
|
||||
if (result->unbuf->eof_reached) {
|
||||
/* No more rows obviously */
|
||||
*fetched_anything = FALSE;
|
||||
DBG_INF("eof reached");
|
||||
DBG_RETURN(PASS);
|
||||
}
|
||||
@ -798,8 +802,6 @@ mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES *result, void *param, unsigned int
|
||||
*/
|
||||
if (PASS == (ret = PACKET_READ(row_packet, result->conn)) && !row_packet->eof) {
|
||||
unsigned int i, field_count = result->field_count;
|
||||
result->unbuf->row_count++;
|
||||
*fetched_anything = TRUE;
|
||||
|
||||
if (!row_packet->skip_extraction) {
|
||||
result->m.unbuffered_free_last_data(result TSRMLS_CC);
|
||||
@ -810,14 +812,17 @@ mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES *result, void *param, unsigned int
|
||||
row_packet->fields = NULL;
|
||||
row_packet->row_buffer = NULL;
|
||||
|
||||
result->m.row_decoder(result->unbuf->last_row_buffer,
|
||||
result->unbuf->last_row_data,
|
||||
row_packet->field_count,
|
||||
row_packet->fields_metadata,
|
||||
FALSE,
|
||||
result->conn->options.numeric_and_datetime_as_unicode,
|
||||
result->conn->options.int_and_float_native,
|
||||
result->conn->stats TSRMLS_CC);
|
||||
if (PASS != result->m.row_decoder(result->unbuf->last_row_buffer,
|
||||
result->unbuf->last_row_data,
|
||||
row_packet->field_count,
|
||||
row_packet->fields_metadata,
|
||||
FALSE,
|
||||
result->conn->options.numeric_and_datetime_as_unicode,
|
||||
result->conn->options.int_and_float_native,
|
||||
result->conn->stats TSRMLS_CC))
|
||||
{
|
||||
DBG_RETURN(FAIL);
|
||||
}
|
||||
|
||||
for (i = 0; i < field_count; i++) {
|
||||
if (stmt->result_bind[i].bound == TRUE) {
|
||||
@ -858,8 +863,10 @@ mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES *result, void *param, unsigned int
|
||||
row_packet->row_buffer->free_chunk(row_packet->row_buffer TSRMLS_CC);
|
||||
row_packet->row_buffer = NULL;
|
||||
}
|
||||
|
||||
result->unbuf->row_count++;
|
||||
*fetched_anything = TRUE;
|
||||
} else if (ret == FAIL) {
|
||||
*fetched_anything = FALSE;
|
||||
if (row_packet->error_info.error_no) {
|
||||
stmt->conn->error_info = row_packet->error_info;
|
||||
stmt->error_info = row_packet->error_info;
|
||||
@ -867,7 +874,6 @@ mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES *result, void *param, unsigned int
|
||||
CONN_SET_STATE(result->conn, CONN_READY);
|
||||
result->unbuf->eof_reached = TRUE; /* so next time we won't get an error */
|
||||
} else if (row_packet->eof) {
|
||||
*fetched_anything = FALSE;
|
||||
DBG_INF("EOF");
|
||||
/* Mark the connection as usable again */
|
||||
result->unbuf->eof_reached = TRUE;
|
||||
@ -975,8 +981,6 @@ mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES *result, void *param, unsigned int fla
|
||||
|
||||
if (PASS == (ret = PACKET_READ(row_packet, result->conn)) && !row_packet->eof) {
|
||||
unsigned int i, field_count = result->field_count;
|
||||
result->unbuf->row_count++;
|
||||
*fetched_anything = TRUE;
|
||||
|
||||
DBG_INF_FMT("skip_extraction=%d", row_packet->skip_extraction);
|
||||
if (!row_packet->skip_extraction) {
|
||||
@ -988,14 +992,17 @@ mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES *result, void *param, unsigned int fla
|
||||
row_packet->fields = NULL;
|
||||
row_packet->row_buffer = NULL;
|
||||
|
||||
result->m.row_decoder(result->unbuf->last_row_buffer,
|
||||
result->unbuf->last_row_data,
|
||||
row_packet->field_count,
|
||||
row_packet->fields_metadata,
|
||||
FALSE,
|
||||
result->conn->options.numeric_and_datetime_as_unicode,
|
||||
result->conn->options.int_and_float_native,
|
||||
result->conn->stats TSRMLS_CC);
|
||||
if (PASS != result->m.row_decoder(result->unbuf->last_row_buffer,
|
||||
result->unbuf->last_row_data,
|
||||
row_packet->field_count,
|
||||
row_packet->fields_metadata,
|
||||
FALSE,
|
||||
result->conn->options.numeric_and_datetime_as_unicode,
|
||||
result->conn->options.int_and_float_native,
|
||||
result->conn->stats TSRMLS_CC))
|
||||
{
|
||||
DBG_RETURN(FAIL);
|
||||
}
|
||||
|
||||
/* If no result bind, do nothing. We consumed the data */
|
||||
for (i = 0; i < field_count; i++) {
|
||||
@ -1044,6 +1051,9 @@ mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES *result, void *param, unsigned int fla
|
||||
row_packet->row_buffer = NULL;
|
||||
}
|
||||
MYSQLND_INC_CONN_STATISTIC(stmt->conn->stats, STAT_ROWS_FETCHED_FROM_CLIENT_PS_CURSOR);
|
||||
|
||||
result->unbuf->row_count++;
|
||||
*fetched_anything = TRUE;
|
||||
} else {
|
||||
*fetched_anything = FALSE;
|
||||
|
||||
|
@ -35,31 +35,36 @@
|
||||
|
||||
|
||||
/* {{{ mysqlnd_res::initialize_result_set_rest */
|
||||
static void
|
||||
static enum_func_status
|
||||
MYSQLND_METHOD(mysqlnd_res, initialize_result_set_rest)(MYSQLND_RES * const result TSRMLS_DC)
|
||||
{
|
||||
unsigned int i;
|
||||
zval **data_cursor = result->stored_data->data;
|
||||
zval **data_begin = result->stored_data->data;
|
||||
unsigned int field_count = result->meta->field_count;
|
||||
unsigned int row_count = result->stored_data->row_count;
|
||||
zval **data_cursor = result->stored_data? result->stored_data->data:NULL;
|
||||
zval **data_begin = result->stored_data? result->stored_data->data:NULL;
|
||||
unsigned int field_count = result->meta? result->meta->field_count : 0;
|
||||
unsigned int row_count = result->stored_data? result->stored_data->row_count:0;
|
||||
enum_func_status ret = PASS;
|
||||
DBG_ENTER("mysqlnd_res::initialize_result_set_rest");
|
||||
|
||||
if (!data_cursor || row_count == result->stored_data->initialized_rows) {
|
||||
DBG_VOID_RETURN;
|
||||
DBG_RETURN(ret);
|
||||
}
|
||||
while ((data_cursor - data_begin) < (row_count * field_count)) {
|
||||
if (NULL == data_cursor[0]) {
|
||||
enum_func_status rc = result->m.row_decoder(
|
||||
result->stored_data->row_buffers[(data_cursor - data_begin) / field_count],
|
||||
data_cursor,
|
||||
result->meta->field_count,
|
||||
result->meta->fields,
|
||||
result->stored_data->persistent,
|
||||
result->conn->options.numeric_and_datetime_as_unicode,
|
||||
result->conn->options.int_and_float_native,
|
||||
result->conn->stats TSRMLS_CC);
|
||||
if (rc != PASS) {
|
||||
ret = FAIL;
|
||||
break;
|
||||
}
|
||||
result->stored_data->initialized_rows++;
|
||||
result->m.row_decoder(
|
||||
result->stored_data->row_buffers[(data_cursor - data_begin) / field_count],
|
||||
data_cursor,
|
||||
result->meta->field_count,
|
||||
result->meta->fields,
|
||||
result->stored_data->persistent,
|
||||
result->conn->options.numeric_and_datetime_as_unicode,
|
||||
result->conn->options.int_and_float_native,
|
||||
result->conn->stats TSRMLS_CC);
|
||||
for (i = 0; i < result->field_count; i++) {
|
||||
/*
|
||||
NULL fields are 0 length, 0 is not more than 0
|
||||
@ -76,7 +81,7 @@ MYSQLND_METHOD(mysqlnd_res, initialize_result_set_rest)(MYSQLND_RES * const resu
|
||||
}
|
||||
data_cursor += field_count;
|
||||
}
|
||||
DBG_VOID_RETURN;
|
||||
DBG_RETURN(ret);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@ -633,6 +638,10 @@ mysqlnd_fetch_row_unbuffered_c(MYSQLND_RES * result TSRMLS_DC)
|
||||
UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
|
||||
DBG_RETURN(retrow);
|
||||
}
|
||||
if (!row_packet) {
|
||||
/* Not fully initialized object that is being cleaned up */
|
||||
DBG_RETURN(retrow);
|
||||
}
|
||||
/* Let the row packet fill our buffer and skip additional mnd_malloc + memcpy */
|
||||
row_packet->skip_extraction = FALSE;
|
||||
|
||||
@ -656,14 +665,17 @@ mysqlnd_fetch_row_unbuffered_c(MYSQLND_RES * result TSRMLS_DC)
|
||||
MYSQLND_FIELD *field = result->meta->fields;
|
||||
struct mysqlnd_field_hash_key *zend_hash_key = result->meta->zend_hash_keys;
|
||||
|
||||
result->m.row_decoder(result->unbuf->last_row_buffer,
|
||||
result->unbuf->last_row_data,
|
||||
row_packet->field_count,
|
||||
row_packet->fields_metadata,
|
||||
FALSE,
|
||||
result->conn->options.numeric_and_datetime_as_unicode,
|
||||
result->conn->options.int_and_float_native,
|
||||
result->conn->stats TSRMLS_CC);
|
||||
enum_func_status rc = result->m.row_decoder(result->unbuf->last_row_buffer,
|
||||
result->unbuf->last_row_data,
|
||||
row_packet->field_count,
|
||||
row_packet->fields_metadata,
|
||||
FALSE,
|
||||
result->conn->options.numeric_and_datetime_as_unicode,
|
||||
result->conn->options.int_and_float_native,
|
||||
result->conn->stats TSRMLS_CC);
|
||||
if (PASS != rc) {
|
||||
DBG_RETURN(retrow);
|
||||
}
|
||||
|
||||
retrow = mnd_malloc(result->field_count * sizeof(char *));
|
||||
if (retrow) {
|
||||
@ -733,15 +745,19 @@ mysqlnd_fetch_row_unbuffered(MYSQLND_RES * result, void *param, unsigned int fla
|
||||
DBG_ENTER("mysqlnd_fetch_row_unbuffered");
|
||||
DBG_INF_FMT("flags=%d", flags);
|
||||
|
||||
*fetched_anything = FALSE;
|
||||
if (result->unbuf->eof_reached) {
|
||||
/* No more rows obviously */
|
||||
*fetched_anything = FALSE;
|
||||
DBG_RETURN(PASS);
|
||||
}
|
||||
if (CONN_GET_STATE(result->conn) != CONN_FETCHING_DATA) {
|
||||
SET_CLIENT_ERROR(result->conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
|
||||
DBG_RETURN(FAIL);
|
||||
}
|
||||
if (!row_packet) {
|
||||
/* Not fully initialized object that is being cleaned up */
|
||||
DBG_RETURN(FAIL);
|
||||
}
|
||||
/* Let the row packet fill our buffer and skip additional mnd_malloc + memcpy */
|
||||
row_packet->skip_extraction = row? FALSE:TRUE;
|
||||
|
||||
@ -750,9 +766,6 @@ mysqlnd_fetch_row_unbuffered(MYSQLND_RES * result, void *param, unsigned int fla
|
||||
result->m.unbuffered_free_last_data() before it. The function returns always true.
|
||||
*/
|
||||
if (PASS == (ret = PACKET_READ(row_packet, result->conn)) && !row_packet->eof) {
|
||||
result->unbuf->row_count++;
|
||||
*fetched_anything = TRUE;
|
||||
|
||||
result->m.unbuffered_free_last_data(result TSRMLS_CC);
|
||||
|
||||
result->unbuf->last_row_data = row_packet->fields;
|
||||
@ -760,7 +773,6 @@ mysqlnd_fetch_row_unbuffered(MYSQLND_RES * result, void *param, unsigned int fla
|
||||
row_packet->fields = NULL;
|
||||
row_packet->row_buffer = NULL;
|
||||
|
||||
|
||||
MYSQLND_INC_CONN_STATISTIC(result->conn->stats, STAT_ROWS_FETCHED_FROM_CLIENT_NORMAL_UNBUF);
|
||||
|
||||
if (!row_packet->skip_extraction) {
|
||||
@ -770,15 +782,17 @@ mysqlnd_fetch_row_unbuffered(MYSQLND_RES * result, void *param, unsigned int fla
|
||||
unsigned int i, field_count = result->field_count;
|
||||
unsigned long *lengths = result->lengths;
|
||||
|
||||
result->m.row_decoder(result->unbuf->last_row_buffer,
|
||||
result->unbuf->last_row_data,
|
||||
field_count,
|
||||
row_packet->fields_metadata,
|
||||
FALSE,
|
||||
result->conn->options.numeric_and_datetime_as_unicode,
|
||||
result->conn->options.int_and_float_native,
|
||||
result->conn->stats TSRMLS_CC);
|
||||
|
||||
enum_func_status rc = result->m.row_decoder(result->unbuf->last_row_buffer,
|
||||
result->unbuf->last_row_data,
|
||||
field_count,
|
||||
row_packet->fields_metadata,
|
||||
FALSE,
|
||||
result->conn->options.numeric_and_datetime_as_unicode,
|
||||
result->conn->options.int_and_float_native,
|
||||
result->conn->stats TSRMLS_CC);
|
||||
if (PASS != rc) {
|
||||
DBG_RETURN(FAIL);
|
||||
}
|
||||
for (i = 0; i < field_count; i++, field++, zend_hash_key++) {
|
||||
zval *data = result->unbuf->last_row_data[i];
|
||||
unsigned int len = (Z_TYPE_P(data) == IS_NULL)? 0:Z_STRLEN_P(data);
|
||||
@ -825,12 +839,13 @@ mysqlnd_fetch_row_unbuffered(MYSQLND_RES * result, void *param, unsigned int fla
|
||||
}
|
||||
}
|
||||
}
|
||||
*fetched_anything = TRUE;
|
||||
result->unbuf->row_count++;
|
||||
} else if (ret == FAIL) {
|
||||
if (row_packet->error_info.error_no) {
|
||||
result->conn->error_info = row_packet->error_info;
|
||||
DBG_ERR_FMT("errorno=%d error=%s", row_packet->error_info.error_no, row_packet->error_info.error);
|
||||
}
|
||||
*fetched_anything = FALSE;
|
||||
CONN_SET_STATE(result->conn, CONN_READY);
|
||||
result->unbuf->eof_reached = TRUE; /* so next time we won't get an error */
|
||||
} else if (row_packet->eof) {
|
||||
@ -849,7 +864,6 @@ mysqlnd_fetch_row_unbuffered(MYSQLND_RES * result, void *param, unsigned int fla
|
||||
CONN_SET_STATE(result->conn, CONN_READY);
|
||||
}
|
||||
result->m.unbuffered_free_last_data(result TSRMLS_CC);
|
||||
*fetched_anything = FALSE;
|
||||
}
|
||||
|
||||
DBG_INF_FMT("ret=%s fetched=%d", ret == PASS? "PASS":"FAIL", *fetched_anything);
|
||||
@ -867,11 +881,6 @@ MYSQLND_METHOD(mysqlnd_res, use_result)(MYSQLND_RES * const result, zend_bool ps
|
||||
|
||||
SET_EMPTY_ERROR(result->conn->error_info);
|
||||
|
||||
result->result_set_memory_pool = mysqlnd_mempool_create(MYSQLND_G(mempool_default_size) TSRMLS_CC);
|
||||
result->unbuf = mnd_ecalloc(1, sizeof(MYSQLND_RES_UNBUFFERED));
|
||||
if (!result->result_set_memory_pool || !result->unbuf) {
|
||||
goto oom;
|
||||
}
|
||||
|
||||
if (ps == FALSE) {
|
||||
result->type = MYSQLND_RES_NORMAL;
|
||||
@ -884,12 +893,19 @@ MYSQLND_METHOD(mysqlnd_res, use_result)(MYSQLND_RES * const result, zend_bool ps
|
||||
}
|
||||
} else {
|
||||
result->type = MYSQLND_RES_PS_UNBUF;
|
||||
result->m.fetch_row = NULL;
|
||||
/* result->m.fetch_row() will be set in mysqlnd_ps.c */
|
||||
result->m.fetch_lengths = NULL; /* makes no sense */
|
||||
result->m.row_decoder = php_mysqlnd_rowp_read_binary_protocol;
|
||||
result->lengths = NULL;
|
||||
}
|
||||
|
||||
result->result_set_memory_pool = mysqlnd_mempool_create(MYSQLND_G(mempool_default_size) TSRMLS_CC);
|
||||
result->unbuf = mnd_ecalloc(1, sizeof(MYSQLND_RES_UNBUFFERED));
|
||||
if (!result->result_set_memory_pool || !result->unbuf) {
|
||||
goto oom;
|
||||
}
|
||||
|
||||
/*
|
||||
Will be freed in the mysqlnd_internal_free_result_contents() called
|
||||
by the resource destructor. mysqlnd_fetch_row_unbuffered() expects
|
||||
@ -935,15 +951,18 @@ mysqlnd_fetch_row_buffered_c(MYSQLND_RES * result TSRMLS_DC)
|
||||
|
||||
if (NULL == current_row[0]) {
|
||||
uint64_t row_num = (set->data_cursor - set->data) / result->meta->field_count;
|
||||
enum_func_status rc = result->m.row_decoder(set->row_buffers[row_num],
|
||||
current_row,
|
||||
result->meta->field_count,
|
||||
result->meta->fields,
|
||||
FALSE,
|
||||
result->conn->options.numeric_and_datetime_as_unicode,
|
||||
result->conn->options.int_and_float_native,
|
||||
result->conn->stats TSRMLS_CC);
|
||||
if (rc != PASS) {
|
||||
DBG_RETURN(ret);
|
||||
}
|
||||
set->initialized_rows++;
|
||||
result->m.row_decoder(set->row_buffers[row_num],
|
||||
current_row,
|
||||
result->meta->field_count,
|
||||
result->meta->fields,
|
||||
FALSE,
|
||||
result->conn->options.numeric_and_datetime_as_unicode,
|
||||
result->conn->options.int_and_float_native,
|
||||
result->conn->stats TSRMLS_CC);
|
||||
for (i = 0; i < result->field_count; i++) {
|
||||
/*
|
||||
NULL fields are 0 length, 0 is not more than 0
|
||||
@ -992,6 +1011,7 @@ mysqlnd_fetch_row_buffered(MYSQLND_RES * result, void *param, unsigned int flags
|
||||
unsigned int i;
|
||||
zval *row = (zval *) param;
|
||||
MYSQLND_RES_BUFFERED *set = result->stored_data;
|
||||
enum_func_status ret = FAIL;
|
||||
|
||||
DBG_ENTER("mysqlnd_fetch_row_buffered");
|
||||
DBG_INF_FMT("flags=%u row=%p", flags, row);
|
||||
@ -1006,15 +1026,18 @@ mysqlnd_fetch_row_buffered(MYSQLND_RES * result, void *param, unsigned int flags
|
||||
|
||||
if (NULL == current_row[0]) {
|
||||
uint64_t row_num = (set->data_cursor - set->data) / result->meta->field_count;
|
||||
enum_func_status rc = result->m.row_decoder(set->row_buffers[row_num],
|
||||
current_row,
|
||||
result->meta->field_count,
|
||||
result->meta->fields,
|
||||
result->stored_data->persistent,
|
||||
result->conn->options.numeric_and_datetime_as_unicode,
|
||||
result->conn->options.int_and_float_native,
|
||||
result->conn->stats TSRMLS_CC);
|
||||
if (rc != PASS) {
|
||||
DBG_RETURN(FAIL);
|
||||
}
|
||||
set->initialized_rows++;
|
||||
result->m.row_decoder(set->row_buffers[row_num],
|
||||
current_row,
|
||||
result->meta->field_count,
|
||||
result->meta->fields,
|
||||
result->stored_data->persistent,
|
||||
result->conn->options.numeric_and_datetime_as_unicode,
|
||||
result->conn->options.int_and_float_native,
|
||||
result->conn->stats TSRMLS_CC);
|
||||
for (i = 0; i < result->field_count; i++) {
|
||||
/*
|
||||
NULL fields are 0 length, 0 is not more than 0
|
||||
@ -1070,13 +1093,15 @@ mysqlnd_fetch_row_buffered(MYSQLND_RES * result, void *param, unsigned int flags
|
||||
set->data_cursor += result->meta->field_count;
|
||||
*fetched_anything = TRUE;
|
||||
MYSQLND_INC_GLOBAL_STATISTIC(STAT_ROWS_FETCHED_FROM_CLIENT_NORMAL_BUF);
|
||||
ret = PASS;
|
||||
} else {
|
||||
set->data_cursor = NULL;
|
||||
*fetched_anything = FALSE;
|
||||
ret = PASS;
|
||||
DBG_INF("EOF reached");
|
||||
}
|
||||
DBG_INF_FMT("ret=PASS fetched=%d", *fetched_anything);
|
||||
DBG_RETURN(PASS);
|
||||
DBG_RETURN(ret);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@ -1210,11 +1235,11 @@ MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND * const conn, MYSQL
|
||||
/* libmysql's documentation says it should be so for SELECT statements */
|
||||
conn->upsert_status.affected_rows = set->row_count;
|
||||
}
|
||||
DBG_INF_FMT("ret=%s row_count=%u warnings=%u server_status=%u", ret == PASS? "PASS":"FAIL",
|
||||
set->row_count, conn->upsert_status.warning_count, conn->upsert_status.server_status);
|
||||
end:
|
||||
PACKET_FREE(row_packet);
|
||||
|
||||
DBG_INF_FMT("ret=%s row_count=%u warnings=%u server_status=%u", ret == PASS? "PASS":"FAIL",
|
||||
set->row_count, conn->upsert_status.warning_count, conn->upsert_status.server_status);
|
||||
DBG_RETURN(ret);
|
||||
}
|
||||
/* }}} */
|
||||
@ -1232,6 +1257,12 @@ MYSQLND_METHOD(mysqlnd_res, store_result)(MYSQLND_RES * result,
|
||||
DBG_ENTER("mysqlnd_res::store_result");
|
||||
DBG_INF_FMT("conn=%d ps_protocol=%d", conn->thread_id, ps_protocol);
|
||||
|
||||
/* We need the conn because we are doing lazy zval initialization in buffered_fetch_row */
|
||||
result->conn = conn->m->get_reference(conn TSRMLS_CC);
|
||||
result->type = MYSQLND_RES_NORMAL;
|
||||
result->m.fetch_row = result->m.fetch_row_normal_buffered;
|
||||
result->m.fetch_lengths = mysqlnd_fetch_lengths_buffered;
|
||||
|
||||
result->result_set_memory_pool = mysqlnd_mempool_create(MYSQLND_G(mempool_default_size) TSRMLS_CC);
|
||||
result->lengths = mnd_ecalloc(result->field_count, sizeof(unsigned long));
|
||||
if (!result->result_set_memory_pool || !result->lengths) {
|
||||
@ -1239,17 +1270,15 @@ MYSQLND_METHOD(mysqlnd_res, store_result)(MYSQLND_RES * result,
|
||||
DBG_RETURN(NULL);
|
||||
}
|
||||
|
||||
/* We need the conn because we are doing lazy zval initialization in buffered_fetch_row */
|
||||
result->conn = conn->m->get_reference(conn TSRMLS_CC);
|
||||
result->type = MYSQLND_RES_NORMAL;
|
||||
result->m.fetch_row = result->m.fetch_row_normal_buffered;
|
||||
result->m.fetch_lengths = mysqlnd_fetch_lengths_buffered;
|
||||
|
||||
CONN_SET_STATE(conn, CONN_FETCHING_DATA);
|
||||
|
||||
ret = result->m.store_result_fetch_data(conn, result, result->meta, ps_protocol, to_cache TSRMLS_CC);
|
||||
if (FAIL == ret) {
|
||||
conn->error_info = result->stored_data->error_info;
|
||||
if (result->stored_data) {
|
||||
conn->error_info = result->stored_data->error_info;
|
||||
} else {
|
||||
SET_OOM_ERROR(conn->error_info);
|
||||
}
|
||||
DBG_RETURN(NULL);
|
||||
}
|
||||
/* libmysql's documentation says it should be so for SELECT statements */
|
||||
@ -1357,24 +1386,28 @@ static const MYSQLND_FIELD *
|
||||
MYSQLND_METHOD(mysqlnd_res, fetch_field)(MYSQLND_RES * const result TSRMLS_DC)
|
||||
{
|
||||
DBG_ENTER("mysqlnd_res::fetch_field");
|
||||
if (result->meta) {
|
||||
/*
|
||||
We optimize the result set, so we don't convert all the data from raw buffer format to
|
||||
zval arrays during store. In the case someone doesn't read all the lines this will
|
||||
save time. However, when a metadata call is done, we need to calculate max_length.
|
||||
We don't have control whether max_length will be used, unfortunately. Otherwise we
|
||||
could have been able to skip that step.
|
||||
Well, if the mysqli API switches from returning stdClass to class like mysqli_field_metadata,
|
||||
then we can have max_length as dynamic property, which will be calculated during runtime and
|
||||
not during mysqli_fetch_field() time.
|
||||
*/
|
||||
if (result->stored_data && (result->stored_data->initialized_rows < result->stored_data->row_count)) {
|
||||
DBG_INF_FMT("We have decode the whole result set to be able to satisfy this meta request");
|
||||
/* we have to initialize the rest to get the updated max length */
|
||||
result->m.initialize_result_set_rest(result TSRMLS_CC);
|
||||
do {
|
||||
if (result->meta) {
|
||||
/*
|
||||
We optimize the result set, so we don't convert all the data from raw buffer format to
|
||||
zval arrays during store. In the case someone doesn't read all the lines this will
|
||||
save time. However, when a metadata call is done, we need to calculate max_length.
|
||||
We don't have control whether max_length will be used, unfortunately. Otherwise we
|
||||
could have been able to skip that step.
|
||||
Well, if the mysqli API switches from returning stdClass to class like mysqli_field_metadata,
|
||||
then we can have max_length as dynamic property, which will be calculated during runtime and
|
||||
not during mysqli_fetch_field() time.
|
||||
*/
|
||||
if (result->stored_data && (result->stored_data->initialized_rows < result->stored_data->row_count)) {
|
||||
DBG_INF_FMT("We have decode the whole result set to be able to satisfy this meta request");
|
||||
/* we have to initialize the rest to get the updated max length */
|
||||
if (PASS != result->m.initialize_result_set_rest(result TSRMLS_CC)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
DBG_RETURN(result->meta->m->fetch_field(result->meta TSRMLS_CC));
|
||||
}
|
||||
DBG_RETURN(result->meta->m->fetch_field(result->meta TSRMLS_CC));
|
||||
}
|
||||
} while (0);
|
||||
DBG_RETURN(NULL);
|
||||
}
|
||||
/* }}} */
|
||||
@ -1385,24 +1418,28 @@ static const MYSQLND_FIELD *
|
||||
MYSQLND_METHOD(mysqlnd_res, fetch_field_direct)(MYSQLND_RES * const result, MYSQLND_FIELD_OFFSET fieldnr TSRMLS_DC)
|
||||
{
|
||||
DBG_ENTER("mysqlnd_res::fetch_field_direct");
|
||||
if (result->meta) {
|
||||
/*
|
||||
We optimize the result set, so we don't convert all the data from raw buffer format to
|
||||
zval arrays during store. In the case someone doesn't read all the lines this will
|
||||
save time. However, when a metadata call is done, we need to calculate max_length.
|
||||
We don't have control whether max_length will be used, unfortunately. Otherwise we
|
||||
could have been able to skip that step.
|
||||
Well, if the mysqli API switches from returning stdClass to class like mysqli_field_metadata,
|
||||
then we can have max_length as dynamic property, which will be calculated during runtime and
|
||||
not during mysqli_fetch_field_direct() time.
|
||||
*/
|
||||
if (result->stored_data && (result->stored_data->initialized_rows < result->stored_data->row_count)) {
|
||||
DBG_INF_FMT("We have decode the whole result set to be able to satisfy this meta request");
|
||||
/* we have to initialized the rest to get the updated max length */
|
||||
result->m.initialize_result_set_rest(result TSRMLS_CC);
|
||||
do {
|
||||
if (result->meta) {
|
||||
/*
|
||||
We optimize the result set, so we don't convert all the data from raw buffer format to
|
||||
zval arrays during store. In the case someone doesn't read all the lines this will
|
||||
save time. However, when a metadata call is done, we need to calculate max_length.
|
||||
We don't have control whether max_length will be used, unfortunately. Otherwise we
|
||||
could have been able to skip that step.
|
||||
Well, if the mysqli API switches from returning stdClass to class like mysqli_field_metadata,
|
||||
then we can have max_length as dynamic property, which will be calculated during runtime and
|
||||
not during mysqli_fetch_field_direct() time.
|
||||
*/
|
||||
if (result->stored_data && (result->stored_data->initialized_rows < result->stored_data->row_count)) {
|
||||
DBG_INF_FMT("We have decode the whole result set to be able to satisfy this meta request");
|
||||
/* we have to initialized the rest to get the updated max length */
|
||||
if (PASS != result->m.initialize_result_set_rest(result TSRMLS_CC)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
DBG_RETURN(result->meta->m->fetch_field_direct(result->meta, fieldnr TSRMLS_CC));
|
||||
}
|
||||
DBG_RETURN(result->meta->m->fetch_field_direct(result->meta, fieldnr TSRMLS_CC));
|
||||
}
|
||||
} while (0);
|
||||
|
||||
DBG_RETURN(NULL);
|
||||
}
|
||||
@ -1414,13 +1451,17 @@ static const MYSQLND_FIELD *
|
||||
MYSQLND_METHOD(mysqlnd_res, fetch_fields)(MYSQLND_RES * const result TSRMLS_DC)
|
||||
{
|
||||
DBG_ENTER("mysqlnd_res::fetch_fields");
|
||||
if (result->meta) {
|
||||
if (result->stored_data && (result->stored_data->initialized_rows < result->stored_data->row_count)) {
|
||||
/* we have to initialize the rest to get the updated max length */
|
||||
result->m.initialize_result_set_rest(result TSRMLS_CC);
|
||||
do {
|
||||
if (result->meta) {
|
||||
if (result->stored_data && (result->stored_data->initialized_rows < result->stored_data->row_count)) {
|
||||
/* we have to initialize the rest to get the updated max length */
|
||||
if (PASS != result->m.initialize_result_set_rest(result TSRMLS_CC)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
DBG_RETURN(result->meta->m->fetch_fields(result->meta TSRMLS_CC));
|
||||
}
|
||||
DBG_RETURN(result->meta->m->fetch_fields(result->meta TSRMLS_CC));
|
||||
}
|
||||
} while (0);
|
||||
DBG_RETURN(NULL);
|
||||
}
|
||||
/* }}} */
|
||||
|
@ -503,7 +503,7 @@ typedef const MYSQLND_FIELD *(*func_mysqlnd_res__fetch_fields)(MYSQLND_RES * con
|
||||
typedef enum_func_status (*func_mysqlnd_res__read_result_metadata)(MYSQLND_RES *result, MYSQLND * conn TSRMLS_DC);
|
||||
typedef unsigned long * (*func_mysqlnd_res__fetch_lengths)(MYSQLND_RES * const result TSRMLS_DC);
|
||||
typedef enum_func_status (*func_mysqlnd_res__store_result_fetch_data)(MYSQLND * const conn, MYSQLND_RES *result, MYSQLND_RES_METADATA *meta, zend_bool binary_protocol, zend_bool to_cache TSRMLS_DC);
|
||||
typedef void (*func_mysqlnd_res__initialize_result_set_rest)(MYSQLND_RES * const result TSRMLS_DC);
|
||||
typedef enum_func_status (*func_mysqlnd_res__initialize_result_set_rest)(MYSQLND_RES * const result TSRMLS_DC);
|
||||
|
||||
typedef void (*func_mysqlnd_res__free_result_buffers)(MYSQLND_RES * result TSRMLS_DC); /* private */
|
||||
typedef enum_func_status (*func_mysqlnd_res__free_result)(MYSQLND_RES * result, zend_bool implicit TSRMLS_DC);
|
||||
@ -513,7 +513,7 @@ typedef void (*func_mysqlnd_res__free_buffered_data)(MYSQLND_RES *result TSRM
|
||||
typedef void (*func_mysqlnd_res__unbuffered_free_last_data)(MYSQLND_RES *result TSRMLS_DC);
|
||||
|
||||
/* for decoding - binary or text protocol */
|
||||
typedef void (*func_mysqlnd_res__row_decoder)(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval ** fields,
|
||||
typedef enum_func_status (*func_mysqlnd_res__row_decoder)(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval ** fields,
|
||||
unsigned int field_count, MYSQLND_FIELD *fields_metadata,
|
||||
zend_bool persistent,
|
||||
zend_bool as_unicode, zend_bool as_int_or_float,
|
||||
|
@ -1202,7 +1202,7 @@ php_mysqlnd_read_row_ex(MYSQLND * conn, MYSQLND_MEMORY_POOL * result_set_memory_
|
||||
|
||||
|
||||
/* {{{ php_mysqlnd_rowp_read_binary_protocol */
|
||||
void
|
||||
enum_func_status
|
||||
php_mysqlnd_rowp_read_binary_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval ** fields,
|
||||
unsigned int field_count, MYSQLND_FIELD *fields_metadata,
|
||||
zend_bool persistent,
|
||||
@ -1217,7 +1217,9 @@ php_mysqlnd_rowp_read_binary_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zv
|
||||
DBG_ENTER("php_mysqlnd_rowp_read_binary_protocol");
|
||||
|
||||
end_field = (current_field = start_field = fields) + field_count;
|
||||
|
||||
if (!current_field) {
|
||||
DBG_RETURN(FAIL);
|
||||
}
|
||||
|
||||
/* skip the first byte, not EODATA_MARKER -> 0x0, status */
|
||||
p++;
|
||||
@ -1228,6 +1230,9 @@ php_mysqlnd_rowp_read_binary_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zv
|
||||
for (i = 0; current_field < end_field; current_field++, i++) {
|
||||
DBG_INF("Directly creating zval");
|
||||
MAKE_STD_ZVAL(*current_field);
|
||||
if (!*current_field) {
|
||||
DBG_RETURN(FAIL);
|
||||
}
|
||||
|
||||
DBG_INF_FMT("Into zval=%p decoding column %d [%s.%s.%s] type=%d field->flags&unsigned=%d flags=%u is_bit=%d as_unicode=%d",
|
||||
*current_field, i,
|
||||
@ -1282,13 +1287,13 @@ php_mysqlnd_rowp_read_binary_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zv
|
||||
}
|
||||
}
|
||||
|
||||
DBG_VOID_RETURN;
|
||||
DBG_RETURN(PASS);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ php_mysqlnd_rowp_read_text_protocol */
|
||||
void
|
||||
enum_func_status
|
||||
php_mysqlnd_rowp_read_text_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval ** fields,
|
||||
unsigned int field_count, MYSQLND_FIELD *fields_metadata,
|
||||
zend_bool persistent,
|
||||
@ -1305,6 +1310,10 @@ php_mysqlnd_rowp_read_text_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval
|
||||
DBG_ENTER("php_mysqlnd_rowp_read_text_protocol");
|
||||
|
||||
end_field = (current_field = start_field = fields) + field_count;
|
||||
if (!current_field) {
|
||||
DBG_RETURN(FAIL);
|
||||
}
|
||||
|
||||
for (i = 0; current_field < end_field; current_field++, i++) {
|
||||
/* Don't reverse the order. It is significant!*/
|
||||
zend_uchar *this_field_len_pos = p;
|
||||
@ -1313,6 +1322,9 @@ php_mysqlnd_rowp_read_text_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval
|
||||
|
||||
DBG_INF("Directly creating zval");
|
||||
MAKE_STD_ZVAL(*current_field);
|
||||
if (!*current_field) {
|
||||
DBG_RETURN(FAIL);
|
||||
}
|
||||
|
||||
if (current_field > start_field && last_field_was_string) {
|
||||
/*
|
||||
@ -1503,7 +1515,7 @@ php_mysqlnd_rowp_read_text_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval
|
||||
row_buffer->ptr[data_size] = '\0';
|
||||
}
|
||||
|
||||
DBG_VOID_RETURN;
|
||||
DBG_RETURN(PASS);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
@ -257,14 +257,14 @@ zend_uchar * php_mysqlnd_net_store_length(zend_uchar *packet, uint64_t length);
|
||||
PHPAPI const extern char * const mysqlnd_empty_string;
|
||||
|
||||
|
||||
void php_mysqlnd_rowp_read_binary_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval ** fields,
|
||||
enum_func_status php_mysqlnd_rowp_read_binary_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval ** fields,
|
||||
unsigned int field_count, MYSQLND_FIELD *fields_metadata,
|
||||
zend_bool persistent,
|
||||
zend_bool as_unicode, zend_bool as_int_or_float,
|
||||
MYSQLND_STATS * stats TSRMLS_DC);
|
||||
|
||||
|
||||
void php_mysqlnd_rowp_read_text_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval ** fields,
|
||||
enum_func_status php_mysqlnd_rowp_read_text_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval ** fields,
|
||||
unsigned int field_count, MYSQLND_FIELD *fields_metadata,
|
||||
zend_bool persistent,
|
||||
zend_bool as_unicode, zend_bool as_int_or_float,
|
||||
|
Loading…
Reference in New Issue
Block a user