DBG_RETURN(FAIL);
}
- /* Let the row packet fill our buffer and skip additional malloc + memcpy */
- row_packet->skip_extraction = stmt && stmt->result_bind? FALSE:TRUE;
-
checkpoint = result->memory_pool->checkpoint;
mysqlnd_mempool_save_state(result->memory_pool);
if (PASS == (ret = PACKET_READ(conn, row_packet)) && !row_packet->eof) {
unsigned int i, field_count = result->field_count;
- if (!row_packet->skip_extraction) {
+ if (stmt && stmt->result_bind) {
result->unbuf->m.free_last_data(result->unbuf, conn->stats);
- result->unbuf->last_row_data = row_packet->fields;
result->unbuf->last_row_buffer = row_packet->row_buffer;
- row_packet->fields = NULL;
row_packet->row_buffer.ptr = NULL;
if (PASS != result->unbuf->m.row_decoder(&result->unbuf->last_row_buffer,
}
- row_packet->skip_extraction = stmt->result_bind? FALSE:TRUE;
-
UPSERT_STATUS_RESET(stmt->upsert_status);
if (PASS == (ret = PACKET_READ(conn, row_packet)) && !row_packet->eof) {
const MYSQLND_RES_METADATA * const meta = result->meta;
unsigned int i, field_count = result->field_count;
- if (!row_packet->skip_extraction) {
+ if (stmt->result_bind) {
result->unbuf->m.free_last_data(result->unbuf, conn->stats);
- result->unbuf->last_row_data = row_packet->fields;
result->unbuf->last_row_buffer = row_packet->row_buffer;
- row_packet->fields = NULL;
row_packet->row_buffer.ptr = NULL;
if (PASS != result->unbuf->m.row_decoder(&result->unbuf->last_row_buffer,
}
DBG_INF_FMT("field_count=%u", unbuf->field_count);
- if (unbuf->last_row_data) {
- unsigned int i;
- for (i = 0; i < unbuf->field_count; i++) {
- zval_ptr_dtor_nogc(&(unbuf->last_row_data[i]));
- }
-
- /* Free last row's zvals */
- mnd_efree(unbuf->last_row_data);
- unbuf->last_row_data = NULL;
- }
if (unbuf->last_row_buffer.ptr) {
DBG_INF("Freeing last row buffer");
+ for (unsigned i = 0; i < unbuf->field_count; i++) {
+ zval_ptr_dtor_nogc(&unbuf->last_row_data[i]);
+ }
+
/* Nothing points to this buffer now, free it */
unbuf->result_set_memory_pool->free_chunk(
unbuf->result_set_memory_pool, unbuf->last_row_buffer.ptr);
MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_lengths)(const MYSQLND_RES_UNBUFFERED * const result)
{
/* simulate output of libmysql */
- return (result->last_row_data || result->eof_reached)? result->lengths : NULL;
+ return (result->last_row_buffer.ptr || result->eof_reached)? result->lengths : NULL;
}
/* }}} */
/* 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 = FALSE;
checkpoint = result->memory_pool->checkpoint;
mysqlnd_mempool_save_state(result->memory_pool);
if (PASS == (ret = PACKET_READ(conn, row_packet)) && !row_packet->eof) {
result->unbuf->m.free_last_data(result->unbuf, conn->stats);
- result->unbuf->last_row_data = row_packet->fields;
result->unbuf->last_row_buffer = row_packet->row_buffer;
- row_packet->fields = NULL;
row_packet->row_buffer.ptr = NULL;
MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_ROWS_FETCHED_FROM_CLIENT_NORMAL_UNBUF);
- if (!row_packet->skip_extraction) {
- unsigned int i, field_count = meta->field_count;
+ unsigned int i, field_count = meta->field_count;
+
+ enum_func_status rc = result->unbuf->m.row_decoder(&result->unbuf->last_row_buffer,
+ result->unbuf->last_row_data,
+ field_count,
+ row_packet->fields_metadata,
+ conn->options->int_and_float_native,
+ conn->stats);
+ if (PASS != rc) {
+ mysqlnd_mempool_restore_state(result->memory_pool);
+ result->memory_pool->checkpoint = checkpoint;
+ DBG_RETURN(FAIL);
+ }
+ {
+ *row = mnd_emalloc(field_count * sizeof(char *));
+ MYSQLND_FIELD * field = meta->fields;
+ size_t * lengths = result->unbuf->lengths;
- enum_func_status rc = result->unbuf->m.row_decoder(&result->unbuf->last_row_buffer,
- result->unbuf->last_row_data,
- field_count,
- row_packet->fields_metadata,
- conn->options->int_and_float_native,
- conn->stats);
- if (PASS != rc) {
- mysqlnd_mempool_restore_state(result->memory_pool);
- result->memory_pool->checkpoint = checkpoint;
- DBG_RETURN(FAIL);
- }
- {
- *row = mnd_emalloc(field_count * sizeof(char *));
- MYSQLND_FIELD * field = meta->fields;
- size_t * lengths = result->unbuf->lengths;
-
- for (i = 0; i < field_count; i++, field++) {
- zval * data = &result->unbuf->last_row_data[i];
- const size_t len = (Z_TYPE_P(data) == IS_STRING)? Z_STRLEN_P(data) : 0;
+ for (i = 0; i < field_count; i++, field++) {
+ zval * data = &result->unbuf->last_row_data[i];
+ const size_t len = (Z_TYPE_P(data) == IS_STRING)? Z_STRLEN_P(data) : 0;
/* BEGIN difference between normal normal fetch and _c */
- if (Z_TYPE_P(data) != IS_NULL) {
- convert_to_string(data);
- (*row)[i] = Z_STRVAL_P(data);
- } else {
- (*row)[i] = NULL;
- }
+ if (Z_TYPE_P(data) != IS_NULL) {
+ convert_to_string(data);
+ (*row)[i] = Z_STRVAL_P(data);
+ } else {
+ (*row)[i] = NULL;
+ }
/* END difference between normal normal fetch and _c */
- if (lengths) {
- lengths[i] = len;
- }
+ if (lengths) {
+ lengths[i] = len;
+ }
- if (field->max_length < len) {
- field->max_length = len;
- }
+ if (field->max_length < len) {
+ field->max_length = len;
}
}
}
/* 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;
checkpoint = result->memory_pool->checkpoint;
mysqlnd_mempool_save_state(result->memory_pool);
if (PASS == (ret = PACKET_READ(conn, row_packet)) && !row_packet->eof) {
result->unbuf->m.free_last_data(result->unbuf, conn->stats);
- result->unbuf->last_row_data = row_packet->fields;
result->unbuf->last_row_buffer = row_packet->row_buffer;
- row_packet->fields = NULL;
row_packet->row_buffer.ptr = NULL;
MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_ROWS_FETCHED_FROM_CLIENT_NORMAL_UNBUF);
- if (!row_packet->skip_extraction) {
+ if (row) {
unsigned int i, field_count = meta->field_count;
enum_func_status rc = result->unbuf->m.row_decoder(&result->unbuf->last_row_buffer,
row_packet.binary_protocol = binary_protocol;
row_packet.fields_metadata = meta->fields;
- row_packet.skip_extraction = TRUE; /* let php_mysqlnd_rowp_read() not allocate row_packet.fields, we will do it */
-
while (FAIL != (ret = PACKET_READ(conn, &row_packet)) && !row_packet.eof) {
if (!free_rows) {
MYSQLND_ROW_BUFFER * new_row_buffers;
set->row_count++;
/* So row_packet's destructor function won't efree() it */
- row_packet.fields = NULL;
row_packet.row_buffer.ptr = NULL;
/*
STAT_FLUSHED_PS_SETS);
while ((PASS == result->m.fetch_row(result, NULL, 0, &fetched_anything)) && fetched_anything == TRUE) {
- /* do nothing */;
+ MYSQLND_INC_CONN_STATISTIC(conn->stats,
+ result->type == MYSQLND_RES_NORMAL
+ ? STAT_ROWS_SKIPPED_NORMAL : STAT_ROWS_SKIPPED_PS);
}
}
DBG_RETURN(PASS);
ret->lengths = pool->get_chunk(pool, field_count * sizeof(size_t));
memset(ret->lengths, 0, field_count * sizeof(size_t));
+ ret->last_row_data = pool->get_chunk(pool, field_count * sizeof(zval));
+ memset(ret->last_row_data, 0, field_count * sizeof(zval));
+
ret->result_set_memory_pool = pool;
ret->field_count= field_count;
ret->ps = ps;
/* {{{ php_mysqlnd_rowp_read */
-/*
- if normal statements => packet->fields is created by this function,
- if PS => packet->fields is passed from outside
-*/
static enum_func_status
php_mysqlnd_rowp_read(MYSQLND_CONN_DATA * conn, void * _packet)
{
DBG_INF_FMT("server_status=%u warning_count=%u", packet->server_status, packet->warning_count);
}
} else {
+ packet->eof = FALSE;
MYSQLND_INC_CONN_STATISTIC(stats,
packet->binary_protocol? STAT_ROWS_FETCHED_FROM_SERVER_PS:
STAT_ROWS_FETCHED_FROM_SERVER_NORMAL);
-
- packet->eof = FALSE;
- /* packet->field_count is set by the user of the packet */
-
- if (!packet->skip_extraction) {
- if (!packet->fields) {
- DBG_INF("Allocating packet->fields");
- /*
- old-API will probably set packet->fields to NULL every time, though for
- unbuffered sets it makes not much sense as the zvals in this buffer matter,
- not the buffer. Constantly allocating and deallocating brings nothing.
-
- For PS - if stmt_store() is performed, thus we don't have a cursor, it will
- behave just like old-API buffered. Cursors will behave like a bit different,
- but mostly like old-API unbuffered and thus will populate this array with
- value.
- */
- packet->fields = mnd_ecalloc(packet->field_count, sizeof(zval));
- }
- } else {
- MYSQLND_INC_CONN_STATISTIC(stats,
- packet->binary_protocol? STAT_ROWS_SKIPPED_PS:
- STAT_ROWS_SKIPPED_NORMAL);
- }
}
end:
p->result_set_memory_pool->free_chunk(p->result_set_memory_pool, p->row_buffer.ptr);
p->row_buffer.ptr = NULL;
}
- /*
- Don't free packet->fields :
- - normal queries -> store_result() | fetch_row_unbuffered() will transfer
- the ownership and NULL it.
- - PS will pass in it the bound variables, we have to use them! and of course
- not free the array. As it is passed to us, we should not clean it ourselves.
- */
DBG_VOID_RETURN;
}
/* }}} */