Author: ahristov
Date: 2007-06-19 12:33:30 +0200 (Tue, 19 Jun 2007)
New Revision: 397
Added:
trunk/tests/ext/mysqli/mysqli_stmt_get_result.phpt
Modified:
trunk/mysqlnd/mysqlnd.c
trunk/mysqlnd/mysqlnd.h
trunk/mysqlnd/mysqlnd_ps.c
trunk/mysqlnd/mysqlnd_result.c
trunk/php5/ext/mysqli/mysqli_fe.c
trunk/php5/ext/mysqli/mysqli_nonapi.c
trunk/php5/ext/mysqli/php_mysqli.h
trunk/php6/ext/mysqli/mysqli_api.c
trunk/php6/ext/mysqli/mysqli_fe.c
trunk/php6/ext/mysqli/mysqli_nonapi.c
trunk/php6/ext/mysqli/php_mysqli.h
trunk/tests/ext/mysqli/002.phpt
Log:
Here comes mysql_stmt_get_result(). With this changeset
we freeze features before the RC. Comes time to check the problems
found by commitbuild.
Modified: trunk/mysqlnd/mysqlnd.c
===================================================================
--- trunk/mysqlnd/mysqlnd.c 2007-06-19 09:52:38 UTC (rev 396)
+++ trunk/mysqlnd/mysqlnd.c 2007-06-19 10:33:30 UTC (rev 397)
@@ -855,9 +855,9 @@
/* }}} */
-/* {{{ _mysqlnd_send_close */
+/* {{{ mysqlnd_send_close */
static enum_func_status
-_mysqlnd_send_close(MYSQLND * conn TSRMLS_DC)
+mysqlnd_send_close(MYSQLND * conn TSRMLS_DC)
{
enum_func_status ret = PASS;
switch (conn->state) {
@@ -914,7 +914,7 @@
MYSQLND_INC_CONN_STATISTIC(NULL, stat);
- _mysqlnd_send_close(conn TSRMLS_CC);
+ mysqlnd_send_close(conn TSRMLS_CC);
conn->m->free_reference(conn TSRMLS_CC);
@@ -943,7 +943,7 @@
This will free the object too, of course because references has
reached zero.
*/
- _mysqlnd_send_close(conn TSRMLS_CC);
+ mysqlnd_send_close(conn TSRMLS_CC);
conn->m->dtor(conn TSRMLS_CC);
}
}
@@ -995,18 +995,16 @@
/* }}} */
-/* {{{ mysqlnd_conn::client_info */
-PHPAPI const char *
-MYSQLND_METHOD(mysqlnd_conn, get_client_info)()
+/* {{{ mysqlnd_get_client_info */
+PHPAPI const char * mysqlnd_get_client_info()
{
return MYSQLND_VERSION;
}
/* }}} */
-/* {{{ mysqlnd_conn::get_client_version */
-PHPAPI unsigned int
-MYSQLND_METHOD(mysqlnd_conn, get_client_version)()
+/* {{{ mysqlnd_get_client_version */
+PHPAPI unsigned int mysqlnd_get_client_version()
{
return MYSQLND_VERSION_ID;
}
@@ -1338,7 +1336,7 @@
conn->current_result = NULL;
result->conn = conn->m->get_reference(conn);
- return result->m.use_result(result TSRMLS_CC);
+ return result->m.use_result(result, FALSE TSRMLS_CC);
}
/* }}} */
@@ -1365,7 +1363,7 @@
result = conn->current_result;
conn->current_result = NULL;
- return result->m.store_result(result, conn TSRMLS_CC);
+ return result->m.store_result(result, conn, FALSE TSRMLS_CC);
}
/* }}} */
Modified: trunk/mysqlnd/mysqlnd.h
===================================================================
--- trunk/mysqlnd/mysqlnd.h 2007-06-19 09:52:38 UTC (rev 396)
+++ trunk/mysqlnd/mysqlnd.h 2007-06-19 10:33:30 UTC (rev 397)
@@ -28,7 +28,7 @@
/* This forces inlining of some accessor functions */
-#define MYSQLND_USE_OPTIMISATIONS 1
+#define MYSQLND_USE_OPTIMISATIONS 0
/* #define MYSQLND_STRING_TO_INT_CONVERSION */
/*
@@ -368,8 +368,8 @@
mysqlnd_fetch_row_func fetch_row_normal_buffered; /* private */
mysqlnd_fetch_row_func fetch_row_normal_unbuffered; /* private */
- MYSQLND_RES * (*use_result)(MYSQLND_RES * const result TSRMLS_DC);
- MYSQLND_RES * (*store_result)(MYSQLND_RES * result, MYSQLND * const conn TSRMLS_DC);
+ MYSQLND_RES * (*use_result)(MYSQLND_RES * const result, zend_bool ps_protocol
TSRMLS_DC);
+ MYSQLND_RES * (*store_result)(MYSQLND_RES * result, MYSQLND * const conn, zend_bool ps
TSRMLS_DC);
void (*fetch_into)(MYSQLND_RES *result, unsigned int flags, zval *return_value
TSRMLS_DC ZEND_FILE_LINE_DC);
void (*fetch_all)(MYSQLND_RES *result, unsigned int flags, zval *return_value
TSRMLS_DC ZEND_FILE_LINE_DC);
mynd_ulonglong (*num_rows)(const MYSQLND_RES * const result);
@@ -402,6 +402,7 @@
enum_func_status (*execute)(MYSQLND_STMT * const stmt TSRMLS_DC);
MYSQLND_RES * (*use_result)(MYSQLND_STMT * const stmt TSRMLS_DC);
MYSQLND_RES * (*store_result)(MYSQLND_STMT * const stmt TSRMLS_DC);
+ MYSQLND_RES * (*get_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 (*reset)(MYSQLND_STMT * const stmt TSRMLS_DC);
@@ -409,7 +410,6 @@
enum_func_status (*dtor)(MYSQLND_STMT * const stmt, zend_bool implicit TSRMLS_DC); /*
use this for mysqlnd_stmt_close */
enum_func_status (*fetch)(MYSQLND_STMT * const stmt, zend_bool * const fetched_anything
TSRMLS_DC);
- void (*fetch_into)(MYSQLND_STMT *stmt, unsigned int flags, zval *return_value
TSRMLS_DC ZEND_FILE_LINE_DC);
enum_func_status (*bind_param)(MYSQLND_STMT * const stmt, MYSQLND_PARAM_BIND * const
param_bind);
enum_func_status (*bind_result)(MYSQLND_STMT * const stmt, MYSQLND_RESULT_BIND * const
result_bind);
@@ -557,6 +557,8 @@
struct st_mysqlnd_res {
+ struct st_mysqlnd_res_methods m;
+
MYSQLND *conn;
enum_mysqlnd_res_type type;
unsigned int field_count;
@@ -580,9 +582,6 @@
/* zval cache */
MYSQLND_THD_ZVAL_PCACHE *zval_cache;
- unsigned int references;
-
- struct st_mysqlnd_res_methods m;
};
@@ -616,7 +615,6 @@
MYSQLND_PARAM_BIND *param_bind;
MYSQLND_RESULT_BIND *result_bind;
zend_bool result_zvals_separated_once;
- zend_bool old_style_fetch;
mysqlnd_upsert_status upsert_status;
@@ -746,8 +744,7 @@
#define mysqlnd_num_rows(result) (result)->m.num_rows((result))
#define mysqlnd_num_fields(result) (result)->m.num_fields((result))
-PHPAPI unsigned long * _mysqlnd_fetch_lengths(MYSQLND_RES * const result);
-#define mysqlnd_fetch_lengths(result) _mysqlnd_fetch_lengths((result))
+PHPAPI unsigned long * mysqlnd_fetch_lengths(MYSQLND_RES * const result);
#define mysqlnd_field_seek(result, ofs) (result)->m.seek_field((result), (ofs))
#define mysqlnd_field_tell(result) (result)->m.field_tell((result))
@@ -755,12 +752,9 @@
#define
mysqlnd_fetch_field_direct(result,fnr) (result)->m.fetch_field_direct((result), (fnr))
/* mysqlnd metadata */
-PHPAPI const char * _mysqlnd_get_client_info();
-PHPAPI unsigned int _mysqlnd_get_client_version();
-#define mysqlnd_get_client_info _mysqlnd_get_client_info
-#define mysqlnd_get_client_version _mysqlnd_get_client_version
+PHPAPI const char * mysqlnd_get_client_info();
+PHPAPI unsigned int mysqlnd_get_client_version();
-
/* PS */
#define mysqlnd_stmt_insert_id(stmt) (stmt)->m->get_last_insert_id((stmt))
#define mysqlnd_stmt_affected_rows(stmt) (stmt)->m->get_affected_rows((stmt))
@@ -776,7 +770,7 @@
-const char * mysqlnd_field_type_name(enum mysqlnd_field_types field_type);
+const char * mysqlnd_field_type_name(enum mysqlnd_field_types field_type);
/* LOAD DATA LOCAL */
PHPAPI void mysqlnd_local_infile_default(MYSQLND *conn);
@@ -806,6 +800,7 @@
/* PS */
#define mysqlnd_stmt_init(conn) (conn)->m->stmt_init((conn))
#define mysqlnd_stmt_store_result(stmt) (!mysqlnd_stmt_field_count((stmt)) ?
PASS:((stmt)->m->store_result((stmt) TSRMLS_CC)? PASS:FAIL))
+#define mysqlnd_stmt_get_result(stmt) (stmt)->m->get_result((stmt) TSRMLS_CC)
#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)
@@ -823,8 +818,6 @@
#define mysqlnd_stmt_attr_get(stmt, attr, value) (stmt)->m->get_attribute((stmt),
(attr), (value))
#define mysqlnd_stmt_attr_set(stmt, attr, value) (stmt)->m->set_attribute((stmt),
(attr), (value))
-#define mysqlnd_stmt_fetch_into(s, f, ret) (s)->m->fetch_into((s), (f), (ret)
TSRMLS_CC ZEND_FILE_LINE_CC)
-
#define mysqlnd_stmt_fetch(stmt, fetched) (stmt)->m->fetch((stmt), (fetched)
TSRMLS_CC)
Modified: trunk/mysqlnd/mysqlnd_ps.c
===================================================================
--- trunk/mysqlnd/mysqlnd_ps.c 2007-06-19 09:52:38 UTC (rev 396)
+++ trunk/mysqlnd/mysqlnd_ps.c 2007-06-19 10:33:30 UTC (rev 397)
@@ -129,6 +129,61 @@
/* }}} */
+/* {{{ mysqlnd_stmt::get_result */
+static MYSQLND_RES *
+MYSQLND_METHOD(mysqlnd_stmt, get_result)(MYSQLND_STMT * const stmt TSRMLS_DC)
+{
+ MYSQLND *conn = stmt->conn;
+ MYSQLND_RES *result;
+
+ /* be compliant with libmysql - NULL will turn */
+ if (!stmt->field_count) {
+ return NULL;
+ }
+
+ if (stmt->cursor_exists) {
+ /* Silently convert buffered to unbuffered, for now */
+ return stmt->m->use_result(stmt TSRMLS_CC);
+ }
+
+ /* Nothing to store for UPSERT/LOAD DATA*/
+ if (conn->state != CONN_FETCHING_DATA ||
+ stmt->state != MYSQLND_STMT_WAITING_USE_OR_STORE)
+ {
+ SET_CLIENT_ERROR(conn->error_info, CR_COMMANDS_OUT_OF_SYNC,
+ UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
+ return NULL;
+ }
+
+ SET_EMPTY_ERROR(stmt->error_info);
+ SET_EMPTY_ERROR(stmt->conn->error_info);
+ MYSQLND_INC_CONN_STATISTIC(&conn->stats, STAT_BUFFERED_SETS);
+
+ result = mysqlnd_result_init(stmt->result->field_count,
+ mysqlnd_palloc_get_thd_cache_reference(conn->zval_cache));
+
+ result->meta =
stmt->result->meta->m->clone_metadata(stmt->result->meta, FALSE);
+
+ /* Not set for SHOW statements at PREPARE stage */
+ if (stmt->result->conn) {
+ stmt->result->conn->m->free_reference(stmt->result->conn TSRMLS_CC);
+ stmt->result->conn = NULL; /* store result does not reference the connection */
+ }
+
+ if ((result = result->m.store_result(result, conn, TRUE TSRMLS_CC))) {
+ stmt->upsert_status.affected_rows = result->data->row_count;
+ stmt->state = MYSQLND_STMT_PREPARED;
+ result->type = MYSQLND_RES_PS;
+ } else {
+ stmt->error_info = conn->error_info;
+ stmt->state = MYSQLND_STMT_PREPARED;
+ }
+
+ return result;
+}
+/* }}} */
+
+
/* {{{ mysqlnd_stmt_skip_metadata */
static enum_func_status
mysqlnd_stmt_skip_metadata(MYSQLND_STMT *stmt TSRMLS_DC)
@@ -317,7 +372,7 @@
The bound variables point to them only if the user has started
to fetch data (MYSQLND_STMT_USER_FETCHING).
We need to check 'result_zvals_separated_once' or we will leak
- in the following scenation
+ in the following scenario
prepare("select 1 from dual");
execute();
fetch(); <-- no binding, but that's not a problem
@@ -758,16 +813,8 @@
/* Execute only once. We have to free the previous contents of user's bound vars */
stmt->default_rset_handler(stmt TSRMLS_CC);
- stmt->state = MYSQLND_STMT_USER_FETCHING;
- } else {
- if (stmt->old_style_fetch == TRUE) {
- SET_STMT_ERROR(stmt, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE,
- "Cannot mix normal fetching with bound variables fetching");
- return FAIL;
- }
- stmt->state = MYSQLND_STMT_USER_FETCHING;
}
- stmt->old_style_fetch = FALSE;
+ stmt->state = MYSQLND_STMT_USER_FETCHING;
SET_EMPTY_ERROR(stmt->error_info);
SET_EMPTY_ERROR(stmt->conn->error_info);
@@ -1014,18 +1061,6 @@
return FAIL;
}
- if (stmt->state > MYSQLND_STMT_WAITING_USE_OR_STORE &&
- stmt->old_style_fetch == TRUE)
- {
- SET_STMT_ERROR(stmt, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE,
- "Cannot mix bound variables fetching with normal fetching. "
- "Normal fetch already started.");
- if (result_bind) {
- efree(result_bind);
- }
- return FAIL;
- }
-
if (stmt->field_count) {
if (!result_bind) {
return FAIL;
@@ -1158,7 +1193,9 @@
{
MYSQLND_RES *result;
- if (!stmt->field_count || !stmt->conn || !stmt->result) {
+ if (!stmt->field_count || !stmt->conn || !stmt->result ||
+ !stmt->result->meta)
+ {
return NULL;
}
@@ -1441,71 +1478,13 @@
/* }}} */
-/* {{{ mysqlnd_stmt::fetch_into */
-static void
-MYSQLND_METHOD(mysqlnd_stmt, fetch_into)(MYSQLND_STMT *stmt, unsigned int flags,
- zval *return_value TSRMLS_DC ZEND_FILE_LINE_DC)
-{
- zend_bool fetched_anything;
-
- if (!stmt->result || stmt->state < MYSQLND_STMT_WAITING_USE_OR_STORE) {
- RETURN_NULL();
- } else if (stmt->default_rset_handler == stmt->m->use_result) {
- SET_STMT_ERROR(stmt, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE,
- "Unbuffered old style fetching is not supported");
- RETURN_NULL();
- } else if (stmt->state == MYSQLND_STMT_WAITING_USE_OR_STORE) {
- /* Execute only once. We have to free the previous contents of user's bound vars */
-
- stmt->default_rset_handler(stmt TSRMLS_CC);
- stmt->state = MYSQLND_STMT_USER_FETCHING;
- stmt->result->m.fetch_row = stmt->result->m.fetch_row_normal_buffered;
- stmt->old_style_fetch = TRUE;
- } else if (stmt->state == MYSQLND_STMT_USE_OR_STORE_CALLED) {
- stmt->state = MYSQLND_STMT_USER_FETCHING;
- stmt->result->m.fetch_row = stmt->result->m.fetch_row_normal_buffered;
- stmt->old_style_fetch = TRUE;
- } else {
- if (stmt->old_style_fetch != TRUE) {
- SET_STMT_ERROR(stmt, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE,
- "Cannot mix binding with normal fetching");
- RETURN_NULL();
- }
- }
-
- SET_EMPTY_ERROR(stmt->error_info);
- SET_EMPTY_ERROR(stmt->conn->error_info);
- MYSQLND_INC_CONN_STATISTIC(&stmt->conn->stats, STAT_ROWS_FETCHED_FROM_CLIENT);
-
- /*
- Hint Zend how many elements we will have in the hash. Thus it won't
- extend and rehash the hash constantly.
- */
- mysqlnd_array_init(return_value, mysqlnd_num_fields(stmt->result) * 2);
- if (FAIL == stmt->result->m.fetch_row(stmt->result, (void *)return_value,
flags,
- &fetched_anything TSRMLS_CC))
- {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error while reading a row");
- RETURN_FALSE;
- } else if (fetched_anything == FALSE) {
- zval_dtor(return_value);
- RETURN_NULL();
- }
- /*
- return_value is IS_NULL for no more data and an array for data. Thus it's ok
- to return here.
- */
-}
-/* }}} */
-
-
-
static
struct st_mysqlnd_stmt_methods mysqlnd_stmt_methods = {
MYSQLND_METHOD(mysqlnd_stmt, prepare),
MYSQLND_METHOD(mysqlnd_stmt, execute),
MYSQLND_METHOD(mysqlnd_stmt, use_result),
MYSQLND_METHOD(mysqlnd_stmt, store_result),
+ MYSQLND_METHOD(mysqlnd_stmt, get_result),
MYSQLND_METHOD(mysqlnd_stmt, free_result),
MYSQLND_METHOD(mysqlnd_stmt, data_seek),
MYSQLND_METHOD(mysqlnd_stmt, reset),
@@ -1513,7 +1492,6 @@
MYSQLND_METHOD_PRIVATE(mysqlnd_stmt, dtor),
MYSQLND_METHOD(mysqlnd_stmt, fetch),
- MYSQLND_METHOD(mysqlnd_stmt, fetch_into),
MYSQLND_METHOD(mysqlnd_stmt, bind_param),
MYSQLND_METHOD(mysqlnd_stmt, bind_result),
Modified: trunk/mysqlnd/mysqlnd_result.c
===================================================================
--- trunk/mysqlnd/mysqlnd_result.c 2007-06-19 09:52:38 UTC (rev 396)
+++ trunk/mysqlnd/mysqlnd_result.c 2007-06-19 10:33:30 UTC (rev 397)
@@ -134,20 +134,14 @@
/* }}} */
-
-
/* {{{ mysqlnd_internal_free_result_contents */
+static
void mysqlnd_internal_free_result_contents(MYSQLND_RES *result TSRMLS_DC)
{
-
result->m.free_result_buffers(result TSRMLS_CC);
if (result->row_packet) {
- if (result->type == MYSQLND_RES_NORMAL) {
- PACKET_FREE(result->row_packet);
- } else {
- PACKET_FREE(result->row_packet);
- }
+ PACKET_FREE(result->row_packet);
result->row_packet = NULL;
}
@@ -167,12 +161,13 @@
/* {{{ mysqlnd_internal_free_result */
+static
void mysqlnd_internal_free_result(MYSQLND_RES *result TSRMLS_DC)
{
/*
result->conn is an address if this is an unbuffered query.
In this case, decrement the reference counter in the connection
- object and if needed free the latter. If quit_sent is no
+ object and if needed free the latter.
*/
if (result->conn) {
result->conn->m->free_reference(result->conn TSRMLS_CC);
@@ -185,6 +180,7 @@
/* }}} */
+/* {{{ mysqlnd_res::read_result_metadata */
static enum_func_status
MYSQLND_METHOD(mysqlnd_res, read_result_metadata)(MYSQLND_RES *result, MYSQLND *conn
TSRMLS_DC)
{
@@ -192,7 +188,7 @@
Make it safe to call it repeatedly for PS -
better free and allocate a new because the number of field might change
(select *) with altered table. Also for statements which skip the PS
- infrastructure.
+ infrastructure!
*/
if (result->meta) {
result->meta->m->free_metadata(result->meta, FALSE TSRMLS_CC);
@@ -218,6 +214,7 @@
return PASS;
}
+/* }}} */
/* {{{ mysqlnd_query_read_result_set_header */
@@ -392,7 +389,7 @@
/*
If:
- unbuffered result
- - first row hs not been read
+ - first row has not been read
- last_row has been read
*/
if (result->data->data_cursor == NULL ||
@@ -421,9 +418,8 @@
/* }}} */
-/* {{{ _mysqlnd_fetch_lengths */
-PHPAPI unsigned long *
-MYSQLND_METHOD(mysqlnd_res, fetch_lengths)(MYSQLND_RES * const result)
+/* {{{ mysqlnd_res::fetch_lengths */
+PHPAPI unsigned long * mysqlnd_fetch_lengths(MYSQLND_RES * const result)
{
return result->m.fetch_lengths? result->m.fetch_lengths(result):NULL;
}
@@ -562,7 +558,7 @@
/* {{{ mysqlnd_res::use_result */
MYSQLND_RES *
-MYSQLND_METHOD(mysqlnd_res, use_result)(MYSQLND_RES * const result TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_res, use_result)(MYSQLND_RES * const result, zend_bool ps
TSRMLS_DC)
{
result->type = MYSQLND_RES_NORMAL;
result->m.fetch_row = result->m.fetch_row_normal_unbuffered;
@@ -663,6 +659,7 @@
#define STORE_RESULT_PREALLOCATED_SET 32
+/* {{{ mysqlnd_store_result_fetch_data */
enum_func_status
mysqlnd_store_result_fetch_data(MYSQLND * const conn, MYSQLND_RES *result,
MYSQLND_RES_METADATA *meta,
@@ -770,12 +767,14 @@
return ret;
}
+/* }}} */
-/* {{{ _mysqlnd_store_result */
+/* {{{ mysqlnd_res::store_result */
MYSQLND_RES *
MYSQLND_METHOD(mysqlnd_res, store_result)(MYSQLND_RES * result,
- MYSQLND * const conn TSRMLS_DC)
+ MYSQLND * const conn,
+ zend_bool ps_protocol TSRMLS_DC)
{
enum_func_status ret;
zend_bool to_cache = FALSE;
@@ -790,7 +789,7 @@
result->lengths = ecalloc(result->field_count, sizeof(unsigned long));
ret = mysqlnd_store_result_fetch_data(conn, result, result->meta,
- FALSE, TRUE, to_cache TSRMLS_CC);
+ ps_protocol, TRUE, to_cache TSRMLS_CC);
if (PASS == ret) {
/* libmysql's documentation says it should be so for SELECT statements */
conn->upsert_status.affected_rows = result->data->row_count;
@@ -1000,7 +999,6 @@
ret->field_count = field_count;
ret->zval_cache = cache;
- ret->references = 1;
ret->m.use_result = MYSQLND_METHOD(mysqlnd_res, use_result);
ret->m.store_result = MYSQLND_METHOD(mysqlnd_res, store_result);
Modified: trunk/php5/ext/mysqli/mysqli_fe.c
===================================================================
--- trunk/php5/ext/mysqli/mysqli_fe.c 2007-06-19 09:52:38 UTC (rev 396)
+++ trunk/php5/ext/mysqli/mysqli_fe.c 2007-06-19 10:33:30 UTC (rev 397)
@@ -148,6 +148,9 @@
PHP_FE(mysqli_stmt_bind_result, second_arg_force_by_ref_rest)
PHP_FE(mysqli_stmt_fetch, NULL)
PHP_FE(mysqli_stmt_free_result, NULL)
+#if defined(HAVE_MYSQLND)
+ PHP_FE(mysqli_stmt_get_result, NULL)
+#endif
PHP_FE(mysqli_stmt_get_warnings, NULL)
PHP_FE(mysqli_stmt_insert_id, NULL)
PHP_FE(mysqli_stmt_reset, NULL)
@@ -301,6 +304,9 @@
PHP_FALIAS(reset,mysqli_stmt_reset,NULL)
PHP_FALIAS(prepare,mysqli_stmt_prepare, NULL)
PHP_FALIAS(store_result,mysqli_stmt_store_result,NULL)
+#if defined(HAVE_MYSQLND)
+ PHP_FALIAS(get_result,mysqli_stmt_get_result,NULL)
+#endif
{NULL, NULL, NULL}
};
/* }}} */
Modified: trunk/php5/ext/mysqli/mysqli_nonapi.c
===================================================================
--- trunk/php5/ext/mysqli/mysqli_nonapi.c 2007-06-19 09:52:38 UTC (rev 396)
+++ trunk/php5/ext/mysqli/mysqli_nonapi.c 2007-06-19 10:33:30 UTC (rev 397)
@@ -436,6 +436,36 @@
}
/* }}} */
+
+#if defined(HAVE_MYSQLND)
+/* {{{ proto object mysqli_stmt_get_result(object link) U
+ Buffer result set on client */
+PHP_FUNCTION(mysqli_stmt_get_result)
+{
+ MYSQL_RES *result;
+ MYSQLI_RESOURCE *mysqli_resource;
+ 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, MY_STMT *, &mysql_stmt, "mysqli_stmt",
MYSQLI_STATUS_VALID);
+
+ if (!(result = mysqlnd_stmt_get_result(stmt->stmt))) {
+ MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
+ RETURN_FALSE;
+ }
+
+ mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
+ mysqli_resource->ptr = (void *)result;
+ mysqli_resource->status = MYSQLI_STATUS_VALID;
+ MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_result_class_entry);
+}
+/* }}} */
+#endif
+
+
/* {{{ proto object mysqli_get_warnings(object link) */
PHP_FUNCTION(mysqli_get_warnings)
{
Modified: trunk/php5/ext/mysqli/php_mysqli.h
===================================================================
--- trunk/php5/ext/mysqli/php_mysqli.h 2007-06-19 09:52:38 UTC (rev 396)
+++ trunk/php5/ext/mysqli/php_mysqli.h 2007-06-19 10:33:30 UTC (rev 397)
@@ -438,6 +438,9 @@
PHP_FUNCTION(mysqli_stmt_errno);
PHP_FUNCTION(mysqli_stmt_error);
PHP_FUNCTION(mysqli_stmt_free_result);
+#if defined(HAVE_MYSQLND)
+PHP_FUNCTION(mysqli_stmt_get_result);
+#endif
PHP_FUNCTION(mysqli_stmt_get_warnings);
PHP_FUNCTION(mysqli_stmt_reset);
PHP_FUNCTION(mysqli_stmt_insert_id);
Modified: trunk/php6/ext/mysqli/mysqli_api.c
===================================================================
--- trunk/php6/ext/mysqli/mysqli_api.c 2007-06-19 09:52:38 UTC (rev 396)
+++ trunk/php6/ext/mysqli/mysqli_api.c 2007-06-19 10:33:30 UTC (rev 397)
@@ -2308,6 +2308,7 @@
}
/* }}} */
+
/* {{{ proto int mysqli_thread_id(object link) U
Return the current thread ID */
PHP_FUNCTION(mysqli_thread_id)
Modified: trunk/php6/ext/mysqli/mysqli_fe.c
===================================================================
--- trunk/php6/ext/mysqli/mysqli_fe.c 2007-06-19 09:52:38 UTC (rev 396)
+++ trunk/php6/ext/mysqli/mysqli_fe.c 2007-06-19 10:33:30 UTC (rev 397)
@@ -154,6 +154,9 @@
PHP_FE(mysqli_stmt_fetch, NULL)
PHP_FE(mysqli_stmt_free_result, NULL)
PHP_FE(mysqli_stmt_get_warnings, NULL)
+#if defined(HAVE_MYSQLND)
+ PHP_FE(mysqli_stmt_get_result, NULL)
+#endif
PHP_FE(mysqli_stmt_insert_id, NULL)
PHP_FE(mysqli_stmt_reset, NULL)
PHP_FE(mysqli_stmt_param_count, NULL)
@@ -301,6 +304,7 @@
PHP_FALIAS(reset,mysqli_stmt_reset,NULL)
PHP_FALIAS(prepare,mysqli_stmt_prepare, NULL)
PHP_FALIAS(store_result,mysqli_stmt_store_result,NULL)
+ PHP_FALIAS(get_result,mysqli_stmt_get_result,NULL)
{NULL, NULL, NULL}
};
/* }}} */
Modified: trunk/php6/ext/mysqli/mysqli_nonapi.c
===================================================================
--- trunk/php6/ext/mysqli/mysqli_nonapi.c 2007-06-19 09:52:38 UTC (rev 396)
+++ trunk/php6/ext/mysqli/mysqli_nonapi.c 2007-06-19 10:33:30 UTC (rev 397)
@@ -447,6 +447,36 @@
}
/* }}} */
+
+#if defined(HAVE_MYSQLND)
+/* {{{ proto object mysqli_stmt_get_result(object link) U
+ Buffer result set on client */
+PHP_FUNCTION(mysqli_stmt_get_result)
+{
+ MYSQL_RES *result;
+ MYSQLI_RESOURCE *mysqli_resource;
+ 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, MY_STMT *, &mysql_stmt, "mysqli_stmt",
MYSQLI_STATUS_VALID);
+
+ if (!(result = mysqlnd_stmt_get_result(stmt->stmt))) {
+ MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
+ RETURN_FALSE;
+ }
+
+ mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
+ mysqli_resource->ptr = (void *)result;
+ mysqli_resource->status = MYSQLI_STATUS_VALID;
+ MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_result_class_entry);
+}
+/* }}} */
+#endif
+
+
/* {{{ proto object mysqli_get_warnings(object link) U */
PHP_FUNCTION(mysqli_get_warnings)
{
Modified: trunk/php6/ext/mysqli/php_mysqli.h
===================================================================
--- trunk/php6/ext/mysqli/php_mysqli.h 2007-06-19 09:52:38 UTC (rev 396)
+++ trunk/php6/ext/mysqli/php_mysqli.h 2007-06-19 10:33:30 UTC (rev 397)
@@ -447,6 +447,9 @@
PHP_FUNCTION(mysqli_stmt_errno);
PHP_FUNCTION(mysqli_stmt_error);
PHP_FUNCTION(mysqli_stmt_free_result);
+#if defined(HAVE_MYSQLND)
+PHP_FUNCTION(mysqli_stmt_get_result);
+#endif
PHP_FUNCTION(mysqli_stmt_get_warnings);
PHP_FUNCTION(mysqli_stmt_reset);
PHP_FUNCTION(mysqli_stmt_insert_id);
Modified: trunk/tests/ext/mysqli/002.phpt
===================================================================
--- trunk/tests/ext/mysqli/002.phpt 2007-06-19 09:52:38 UTC (rev 396)
+++ trunk/tests/ext/mysqli/002.phpt 2007-06-19 10:33:30 UTC (rev 397)
@@ -92,4 +92,4 @@
[10]=>
unicode(4) "1000"
}
-done!
\ No newline at end of file
+done!
Added: trunk/tests/ext/mysqli/mysqli_stmt_get_result.phpt
===================================================================
--- trunk/tests/ext/mysqli/mysqli_stmt_get_result.phpt 2007-06-19 09:52:38 UTC (rev 396)
+++ trunk/tests/ext/mysqli/mysqli_stmt_get_result.phpt 2007-06-19 10:33:30 UTC (rev 397)
@@ -0,0 +1,178 @@
+--TEST--
+mysqli_stmt_get_result()
+--SKIPIF--
+<?php require_once('skipif.inc'); ?>
+<?php require_once('skipifemb.inc'); ?>
+<?php if (!function_exists('mysqli_stmt_get_result')) die('skip mysqli_stmt_get_result
not available')?>
+--FILE--
+<?php
+ /*
+ NOTE: no datatype tests here! This is done by
+ mysqli_stmt_bind_result.phpt already. Restrict
+ this test case to the basics.
+ */
+ include "connect.inc";
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_fetch()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_fetch($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ // stmt object status test
+ if (NULL !== ($tmp = mysqli_stmt_fetch($stmt)))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), var_export($tmp, 1));
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id LIMIT 2"))
+ printf("[005] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ // FIXME - different versions return different values ?!
+ if ((NULL !== ($tmp = mysqli_stmt_get_result($stmt))) && (false !== $tmp))
+ printf("[006] Expecting NULL or boolean/false, got %s/%s\n", gettype($tmp),
var_export($tmp, 1));
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[007] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_store_result($stmt))
+ printf("[008] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (is_object($tmp = mysqli_stmt_store_result($stmt)))
+ printf("[009] non-object, got %s/%s\n", gettype($tmp), var_export($tmp, 1));
+
+ mysqli_stmt_close($stmt);
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[010] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ // stmt object status test
+ if (NULL !== ($tmp = mysqli_stmt_fetch($stmt)))
+ printf("[011] Expecting NULL, got %s/%s\n", gettype($tmp), var_export($tmp, 1));
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id LIMIT 2"))
+ printf("[012] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ // FIXME - different versions return different values ?!
+ if ((NULL !== ($tmp = mysqli_stmt_get_result($stmt))) && (false !== $tmp))
+ printf("[013] Expecting NULL or boolean/false, got %s/%s\n", gettype($tmp),
var_export($tmp, 1));
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[014] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!is_object($tmp = mysqli_stmt_get_result($stmt)))
+ printf("[016] NULL, got %s/%s\n", gettype($tmp), var_export($tmp, 1));
+
+ mysqli_free_result($tmp);
+ mysqli_stmt_close($stmt);
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[017] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ // stmt object status test
+ if (NULL !== ($tmp = mysqli_stmt_get_result($stmt)))
+ printf("[018] Expecting NULL, got %s/%s\n", gettype($tmp), var_export($tmp, 1));
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id LIMIT 2"))
+ printf("[019] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (false !== ($tmp = mysqli_stmt_get_result($stmt)))
+ printf("[020] Expecting false, got %s/%s\n", gettype($tmp), var_export($tmp, 1));
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[023] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!is_object($tmp = mysqli_stmt_get_result($stmt)))
+ printf("[024] Expecting object, got %s/%s\n", gettype($tmp), var_export($tmp, 1));
+
+ if (false !== ($tmp = mysqli_stmt_fetch($stmt)))
+ printf("[025] false, got %s/%s\n", gettype($tmp), var_export($tmp, 1));
+
+ if (true !== ($tmp = mysqli_stmt_bind_result($stmt, $id, $label))) {
+ printf("[026] [%d] [%s]\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ printf("[027] [%d] [%s]\n", mysqli_errno($link), mysqli_error($link));
+ printf("[028] Expecting boolean/true, got %s/%s\n", gettype($tmp), var_export($tmp,
1));
+ }
+
+ if (false !== ($tmp = mysqli_stmt_fetch($stmt)))
+ printf("[029] false, got %s/%s\n", gettype($tmp), var_export($tmp, 1));
+
+ mysqli_stmt_close($stmt);
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[032] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id LIMIT 2"))
+ printf("[033] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[034] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = NULL;
+ $label = NULL;
+ if (true !== ($tmp = mysqli_stmt_bind_result($stmt, $id, $label)))
+ printf("[035] Expecting boolean/true, got %s/%s\n", gettype($tmp), var_export($tmp,
1));
+
+ if (!is_object($tmp = $result = mysqli_stmt_get_result($stmt)))
+ printf("[036] Expecting array, got %s/%s, [%d] %s\n",
+ gettype($tmp), var_export($tmp, 1),
+ mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (false !== ($tmp = mysqli_stmt_fetch($stmt)))
+ printf("[037] Expecting boolean/false, got %s/%s, [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ printf("[038] [%d] [%s]\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ printf("[039] [%d] [%s]\n", mysqli_errno($link), mysqli_error($link));
+ while ($row = mysqli_fetch_assoc($result)) {
+ var_dump($row);
+ }
+ mysqli_free_result($result);
+
+ if (!mysqli_kill($link, mysqli_thread_id($link)))
+ printf("[040] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (false !== ($tmp = mysqli_stmt_get_result($stmt)))
+ printf("[041] Expecting false, got %s/%s\n", gettype($tmp), var_export($tmp, 1));
+
+ mysqli_stmt_close($stmt);
+
+ if (NULL !== ($tmp = mysqli_stmt_fetch($stmt)))
+ printf("[042] Expecting NULL, got %s/%s\n", gettype($tmp), var_export($tmp, 1));
+
+ mysqli_close($link);
+
+ print "done!\n";
+?>
+--EXPECTF--
+Warning: mysqli_stmt_fetch(): invalid object or resource mysqli_stmt
+ in %s on line %d
+
+Warning: mysqli_stmt_fetch(): invalid object or resource mysqli_stmt
+ in %s on line %d
+
+Warning: mysqli_stmt_get_result(): invalid object or resource mysqli_stmt
+ in %s on line %d
+[038] [0] []
+[039] [0] []
+array(2) {
+ ["id"]=>
+ int(1)
+ ["label"]=>
+ %s(1) "a"
+}
+array(2) {
+ ["id"]=>
+ int(2)
+ ["label"]=>
+ %s(1) "b"
+}
+
+Warning: mysqli_stmt_fetch(): Couldn't fetch mysqli_stmt in %s on line %d
+done!
| Thread |
|---|
| • PHP mysqlnd svn commit: r397 - in trunk: mysqlnd php5/ext/mysqli php6/ext/mysqli tests/ext/mysqli | ahristov | 19 Jun |