Author: ahristov
Date: 2007-02-28 15:42:48 +0100 (Wed, 28 Feb 2007)
New Revision: 79
Modified:
trunk/ext/mysqli/mysqlnd/mysqlnd.c
trunk/ext/mysqli/mysqlnd/mysqlnd.h
trunk/ext/mysqli/mysqlnd/mysqlnd_ps.c
Log:
Make mysqlnd_stmt_free_result() work and be compatible with
libmysql.
free_result() before store_result() flushes the line. Actually parts
of the code is generic, as PS and non-PS share same packet extraction.
Thus they can share also the line flushing. Not far from being possible
to have PS be used in the old-way - fetching arrays instead of binding.
Modified: trunk/ext/mysqli/mysqlnd/mysqlnd.c
===================================================================
--- trunk/ext/mysqli/mysqlnd/mysqlnd.c 2007-02-28 10:32:02 UTC (rev 78)
+++ trunk/ext/mysqli/mysqlnd/mysqlnd.c 2007-02-28 14:42:48 UTC (rev 79)
@@ -186,21 +186,14 @@
result->row_count = 0;
}
+#ifndef WE_WANT_TO_USE_ROW_BUFFER_IN_ROWP_READ
if (result->row_buffer) {
efree(result->row_buffer);
result->row_buffer = NULL;
result->row_buffer_len = 0;
}
+#endif
- if (result->row_packet) {
- if (result->type == MYSQLND_RES_NORMAL) {
- PACKET_FREE(result->row_packet);
- } else {
- PACKET_FREE(result->row_packet);
- }
- result->row_packet = NULL;
- }
-
if (result->lengths) {
efree(result->lengths);
result->lengths = NULL;
@@ -217,6 +210,15 @@
result->m.free_result_buffers(result);
+ if (result->row_packet) {
+ if (result->type == MYSQLND_RES_NORMAL) {
+ PACKET_FREE(result->row_packet);
+ } else {
+ PACKET_FREE(result->row_packet);
+ }
+ result->row_packet = NULL;
+ }
+
result->conn = NULL;
if (meta) {
@@ -1130,7 +1132,7 @@
row_packet->fields = NULL;
row_packet->row_buffer = NULL;
- if (row) {
+ if (!row_packet->skip_extraction) {
HashTable *row_ht = Z_ARRVAL_P(row);
for (i = 0; i < field_count; i++) {
zval *data = result->last_row_data[i];
@@ -1411,7 +1413,7 @@
/* Unbuffered sets */
if (result->conn && !result->eof_reached) {
/* We have to fetch all data to clean the line */
- while ((PASS == mysqlnd_fetch_row_unbuffered(result, NULL, 0, &fetched_anything
TSRMLS_CC)) &&
+ while ((PASS == result->m.fetch_row(result, NULL, 0, &fetched_anything
TSRMLS_CC)) &&
fetched_anything == TRUE) {
}
}
@@ -1702,8 +1704,6 @@
{
enum_func_status ret;
-
-
switch (conn->state) {
case CONN_READY:
ret = mysqlnd_simple_command(conn, COM_QUIT, NULL, 0, PROT_LAST,
Modified: trunk/ext/mysqli/mysqlnd/mysqlnd.h
===================================================================
--- trunk/ext/mysqli/mysqlnd/mysqlnd.h 2007-02-28 10:32:02 UTC (rev 78)
+++ trunk/ext/mysqli/mysqlnd/mysqlnd.h 2007-02-28 14:42:48 UTC (rev 79)
@@ -523,6 +523,7 @@
enum_func_status (*prepare)(MYSQLND_STMT * const stmt, const char * const query,
unsigned int query_len TSRMLS_DC);
enum_func_status (*execute)(MYSQLND_STMT * const stmt TSRMLS_DC);
MYSQLND_RES * (*store_result)(MYSQLND_STMT * const stmt TSRMLS_DC);
+ enum_func_status (*free_result)(MYSQLND_STMT * const stmt TSRMLS_DC);
enum_func_status (*seek_data)(const MYSQLND_STMT * const stmt, mynd_ulonglong row);
enum_func_status (*close)(MYSQLND_STMT * const stmt TSRMLS_DC); /* private */
enum_func_status (*dtor)(MYSQLND_STMT * const stmt TSRMLS_DC); /* use this for
mysqlnd_stmt_close */
@@ -660,10 +661,12 @@
For future use in php_mysqlnd_rowp_read() .
For one time allocation of the row buffer
*/
+#ifndef WE_WANT_TO_USE_ROW_BUFFER_IN_ROWP_READ
zend_uchar *row_buffer;
unsigned int row_buffer_len;
+#endif
- php_mysql_packet_row *row_packet;
+ php_mysql_packet_row *row_packet; /* Unused for PS */
/* zval cache */
MYSQLND_ZVAL_PCACHE *zval_cache;
@@ -888,10 +891,11 @@
/* PS */
#define mysqlnd_stmt_init(conn) (conn)->m->stmt_init((conn))
-#define mysqlnd_stmt_store_result(stmt) (stmt)->m->store_result((stmt) TSRMLS_CC)
+#define mysqlnd_stmt_store_result(stmt) ((stmt)->m->store_result((stmt)
TSRMLS_CC)? PASS:FAIL)
#define mysqlnd_stmt_data_seek(stmt, row) (stmt)->m->seek_data((stmt), (row))
#define mysqlnd_stmt_prepare(stmt, q, qlen) (stmt)->m->prepare((stmt), (q), (qlen)
TSRMLS_CC)
#define mysqlnd_stmt_execute(stmt) (stmt)->m->execute((stmt) TSRMLS_CC)
+#define mysqlnd_stmt_free_result(stmt) (stmt)->m->free_result((stmt) TSRMLS_CC)
#define mysqlnd_stmt_close(stmt) (stmt)->m->dtor((stmt) TSRMLS_CC)
Modified: trunk/ext/mysqli/mysqlnd/mysqlnd_ps.c
===================================================================
--- trunk/ext/mysqli/mysqlnd/mysqlnd_ps.c 2007-02-28 10:32:02 UTC (rev 78)
+++ trunk/ext/mysqli/mysqlnd/mysqlnd_ps.c 2007-02-28 14:42:48 UTC (rev 79)
@@ -82,6 +82,7 @@
MYSQLND_INC_CONN_STATISTIC(&conn->stats, STAT_PS_BUFFERED_SETS);
result = stmt->result;
+ result->type = MYSQLND_RES_PS;
result->m.fetch_row = mysqlnd_fetch_stmt_row_buffered;
result->m.fetch_lengths = NULL;/* makes no sense */
result->zval_cache = NULL;
@@ -161,6 +162,7 @@
stmt->state = MYSQLND_STMT_PREPARED;
}
conn->state = CONN_READY;
+
return result;
}
/* }}} */
@@ -282,17 +284,15 @@
/* Because results reference the connection. */
stmt_to_prepare->conn->references++;
/* Allocate the result now as it is needed for the reading of metadata */
- result = mysqlnd_result_init(stmt_to_prepare->field_count, NULL);
+ stmt_to_prepare->result = result =
mysqlnd_result_init(stmt_to_prepare->field_count, NULL);
+ result->conn = stmt_to_prepare->conn;
+
result->type = MYSQLND_RES_PS;
if (FAIL == mysqlnd_read_result_metadata(stmt_to_prepare->conn, result TSRMLS_CC) ||
FAIL == mysqlnd_stmt_prepare_read_eof(stmt_to_prepare TSRMLS_CC)) {
- efree(result);
goto fail;
}
- result->conn = stmt_to_prepare->conn;
-
- stmt_to_prepare->result = result;
}
if (stmt_to_prepare != stmt) {
@@ -303,13 +303,15 @@
memcpy(stmt, stmt_to_prepare, sizeof(MYSQLND_STMT));
efree(stmt_to_prepare);
}
-
+ stmt->state = MYSQLND_STMT_PREPARED;
return PASS;
fail:
if (stmt_to_prepare != stmt) {
stmt_to_prepare->m->dtor(stmt_to_prepare TSRMLS_CC);
}
+ stmt->state = MYSQLND_STMT_INITTED;
+
return FAIL;
}
/* }}} */
@@ -320,10 +322,10 @@
_mysqlnd_stmt_execute(MYSQLND_STMT * const stmt TSRMLS_DC)
{
enum_func_status ret;
- zend_bool free_request;
- zend_uchar *request;
- size_t request_len;
- MYSQLND *conn = stmt->conn;
+ MYSQLND *conn = stmt->conn;
+ zend_uchar *request;
+ size_t request_len;
+ zend_bool free_request;
SET_ERROR_AFF_ROWS(stmt);
SET_ERROR_AFF_ROWS(stmt->conn);
@@ -397,7 +399,8 @@
} else if (conn->last_query_type == QUERY_LOAD_LOCAL) {
return PASS;
}
-
+
+ stmt->result->type = MYSQLND_RES_PS;
stmt->result->field_count = conn->field_count;
stmt->result->lengths = NULL;
if (stmt->field_count) {
@@ -496,7 +499,7 @@
return FAIL;
}
/* Let the row packet fill our buffer and skip additional malloc + memcpy */
- row_packet->skip_extraction = FALSE;
+ row_packet->skip_extraction = stmt? TRUE:FALSE;
/*
If we skip rows (row == NULL) we have to
@@ -510,21 +513,23 @@
row_packet->fields = NULL;
row_packet->row_buffer = NULL;
- for (i = 0; i < field_count; i++) {
- if (stmt->result_bind[i].bound == TRUE) {
- zval *data = result->last_row_data[i];
- /*
- stmt->result_bind[i].zv has been already destructed
- in mysqlnd_unbuffered_free_last_data()
- */
+ if (!row_packet->skip_extraction) {
+ for (i = 0; i < field_count; i++) {
+ if (stmt->result_bind[i].bound == TRUE) {
+ zval *data = result->last_row_data[i];
+ /*
+ stmt->result_bind[i].zv has been already destructed
+ in mysqlnd_unbuffered_free_last_data()
+ */
- if (IS_NULL != (Z_TYPE_P(stmt->result_bind[i].zv) = Z_TYPE_P(data)) ) {
- stmt->result_bind[i].zv->value = data->value;
+ if (IS_NULL != (Z_TYPE_P(stmt->result_bind[i].zv) = Z_TYPE_P(data)) ) {
+ stmt->result_bind[i].zv->value = data->value;
- if ((Z_TYPE_P(data) == IS_STRING || Z_TYPE_P(data) == IS_UNICODE)
- && (result->fields[i].max_length < Z_STRLEN_P(data)))
- {
- result->fields[i].max_length = Z_STRLEN_P(data);
+ if ((Z_TYPE_P(data) == IS_STRING || Z_TYPE_P(data) == IS_UNICODE)
+ && (result->fields[i].max_length < Z_STRLEN_P(data)))
+ {
+ result->fields[i].max_length = Z_STRLEN_P(data);
+ }
}
}
}
@@ -999,6 +1004,46 @@
/* }}} */
+/* {{{ _mysqlnd_stmt_free_result */
+static enum_func_status
+_mysqlnd_stmt_free_result(MYSQLND_STMT * const stmt TSRMLS_DC)
+{
+ if (!stmt->result) {
+ return PASS;
+ }
+
+ if (stmt->state == MYSQLND_STMT_WAITING_USE_OR_STORE) {
+ /* Do implicit use_result and then flush the result */
+ stmt->default_rset_handler = _mysqlnd_stmt_store_result;
+ stmt->default_rset_handler(stmt TSRMLS_CC);
+ }
+
+ if (stmt->state > MYSQLND_STMT_WAITING_USE_OR_STORE) {
+ /* Flush if anything is left and unbuffered set */
+ stmt->result->m.skip_result(stmt->result TSRMLS_CC);
+ /*
+ Separate the bound variables, which point to the result set, then
+ destroy the set.
+ */
+ if (stmt->result_bind) {
+ mysqlnd_stmt_separate_result_bind(stmt);
+ }
+
+ /* Now we can destroy the result set */
+ stmt->result->m.free_result_buffers(stmt->result);
+ }
+
+ /* As the buffers have been freed, we should go back to PREPARED */
+ stmt->state = MYSQLND_STMT_PREPARED;
+
+ /* Line is free! */
+ stmt->conn->state = CONN_READY;
+
+ return PASS;
+}
+/* }}} */
+
+
/* {{{ mysqlnd_stmt_separate_result_bind */
void mysqlnd_stmt_separate_result_bind(MYSQLND_STMT *stmt)
{
@@ -1103,6 +1148,7 @@
_mysqlnd_stmt_prepare,
_mysqlnd_stmt_execute,
_mysqlnd_stmt_store_result,
+ _mysqlnd_stmt_free_result,
_mysqlnd_stmt_data_seek,
_mysqlnd_stmt_close,
_mysqlnd_stmt_dtor,
| Thread |
|---|
| • PHP mysqlnd svn commit: r79 - trunk/ext/mysqli/mysqlnd | ahristov | 28 Feb |