mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
Compressed protocol support + extensibility for mysqlnd
This commit is contained in:
parent
4e010297f1
commit
5143fe41e2
15 changed files with 842 additions and 355 deletions
|
@ -21,5 +21,10 @@ if (PHP_MYSQLND != "no") {
|
|||
"mysqlnd_wireprotocol.c " +
|
||||
"php_mysqlnd.c";
|
||||
EXTENSION("mysqlnd", mysqlnd_source, false);
|
||||
if (((PHP_ZLIB=="no") && (CHECK_LIB("zlib_a.lib;zlib.lib", "mysqlnd", PHP_MYSQLND))) ||
|
||||
(PHP_ZLIB_SHARED && CHECK_LIB("zlib.lib", "mysqlnd", PHP_MYSQLND)) || (PHP_ZLIB == "yes" && (!PHP_ZLIB_SHARED)))
|
||||
{
|
||||
AC_DEFINE("MYSQLND_COMPRESSION_ENABLED", 1, "Compression support");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,11 +2,21 @@ dnl
|
|||
dnl $Id$
|
||||
dnl config.m4 for mysqlnd driver
|
||||
|
||||
|
||||
PHP_ARG_ENABLE(mysqlnd_threading, whether to enable threaded fetch in mysqlnd,
|
||||
[ --enable-mysqlnd-threading
|
||||
EXPERIMENTAL: Enable mysqlnd threaded fetch.
|
||||
Note: This forces ZTS on!], no, no)
|
||||
|
||||
PHP_ARG_ENABLE(disable_mysqlnd_compression_support, whether to disable compressed protocol support in mysqlnd,
|
||||
[ --disable-mysqlnd-compression-support
|
||||
Enable support for the MySQL compressed protocol in mysqlnd], yes)
|
||||
|
||||
if test -z "$PHP_ZLIB_DIR"; then
|
||||
PHP_ARG_WITH(zlib-dir, for the location of libz,
|
||||
[ --with-zlib-dir[=DIR] mysqlnd: Set the path to libz install prefix], no, no)
|
||||
fi
|
||||
|
||||
dnl If some extension uses mysqlnd it will get compiled in PHP core
|
||||
if test "$PHP_MYSQLND_ENABLED" = "yes"; then
|
||||
mysqlnd_sources="mysqlnd.c mysqlnd_charset.c mysqlnd_wireprotocol.c \
|
||||
|
@ -23,6 +33,17 @@ if test "$PHP_MYSQLND_ENABLED" = "yes"; then
|
|||
PHP_BUILD_THREAD_SAFE
|
||||
AC_DEFINE([MYSQLND_THREADED], 1, [Use mysqlnd internal threading])
|
||||
fi
|
||||
|
||||
if test "$PHP_MYSQLND_COMPRESSION_SUPPORT" != "no"; then
|
||||
AC_DEFINE([MYSQLND_COMPRESSION_ENABLED], 1, [Enable compressed protocol support])
|
||||
if test "$PHP_ZLIB_DIR" != "no"; then
|
||||
PHP_ADD_LIBRARY_WITH_PATH(z, $PHP_ZLIB_DIR, MYSQLND_SHARED_LIBADD)
|
||||
MYSQLND_LIBS="$MYSQLND_LIBS -L$PHP_ZLIB_DIR/$PHP_LIBDIR -lz"
|
||||
else
|
||||
PHP_ADD_LIBRARY(z,, MYSQLND_SHARED_LIBADD)
|
||||
MYSQLND_LIBS="$MYSQLND_LIBS -lz"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$PHP_MYSQLND_ENABLED" = "yes" || test "$PHP_MYSQLI" != "no"; then
|
||||
|
|
|
@ -27,9 +27,8 @@
|
|||
#include "mysqlnd_statistics.h"
|
||||
#include "mysqlnd_charset.h"
|
||||
#include "mysqlnd_debug.h"
|
||||
#include "mysqlnd_block_alloc.h"
|
||||
/* for php_get_current_user() */
|
||||
#include "ext/standard/basic_functions.h"
|
||||
#include "ext/standard/basic_functions.h"
|
||||
|
||||
/* the server doesn't support 4byte utf8, but let's make it forward compatible */
|
||||
#define MYSQLND_MAX_ALLOWED_USER_LEN 256 /* 64 char * 4byte */
|
||||
|
@ -65,7 +64,6 @@ const char * const mysqlnd_out_of_sync = "Commands out of sync; you can't run th
|
|||
MYSQLND_STATS *mysqlnd_global_stats = NULL;
|
||||
static zend_bool mysqlnd_library_initted = FALSE;
|
||||
|
||||
|
||||
static enum_func_status mysqlnd_send_close(MYSQLND * conn TSRMLS_DC);
|
||||
|
||||
static struct st_mysqlnd_conn_methods *mysqlnd_conn_methods;
|
||||
|
@ -153,10 +151,15 @@ MYSQLND_METHOD(mysqlnd_conn, free_contents)(MYSQLND *conn TSRMLS_DC)
|
|||
php_stream_free(conn->net.stream, PHP_STREAM_FREE_CLOSE_PERSISTENT | PHP_STREAM_FREE_RSRC_DTOR);
|
||||
} else {
|
||||
php_stream_free(conn->net.stream, PHP_STREAM_FREE_CLOSE);
|
||||
|
||||
|
||||
}
|
||||
conn->net.stream = NULL;
|
||||
}
|
||||
#ifdef MYSQLND_COMPRESSION_ENABLED
|
||||
if (conn->net.uncompressed_data) {
|
||||
conn->net.uncompressed_data->free(&conn->net.uncompressed_data TSRMLS_CC);
|
||||
}
|
||||
#endif
|
||||
|
||||
DBG_INF("Freeing memory of members");
|
||||
if (conn->host) {
|
||||
|
@ -213,10 +216,6 @@ MYSQLND_METHOD(mysqlnd_conn, free_contents)(MYSQLND *conn TSRMLS_DC)
|
|||
mysqlnd_palloc_free_thd_cache_reference(&conn->zval_cache);
|
||||
conn->zval_cache = NULL;
|
||||
}
|
||||
if (conn->result_set_memory_pool) {
|
||||
mysqlnd_mempool_destroy(conn->result_set_memory_pool TSRMLS_CC);
|
||||
conn->result_set_memory_pool = NULL;
|
||||
}
|
||||
if (conn->qcache) {
|
||||
DBG_INF("Freeing qcache reference");
|
||||
mysqlnd_qcache_free_cache_reference(&conn->qcache);
|
||||
|
@ -296,7 +295,7 @@ mysqlnd_simple_command_handle_response(MYSQLND *conn, enum php_mysql_packet_type
|
|||
if (0xFF == ok_response.field_count) {
|
||||
/* The server signalled error. Set the error */
|
||||
SET_CLIENT_ERROR(conn->error_info, ok_response.error_no,
|
||||
ok_response.sqlstate, ok_response.error);
|
||||
ok_response.sqlstate, ok_response.error);
|
||||
ret = FAIL;
|
||||
/*
|
||||
Cover a protocol design error: error packet does not
|
||||
|
@ -374,7 +373,7 @@ mysqlnd_simple_command_handle_response(MYSQLND *conn, enum php_mysql_packet_type
|
|||
enum_func_status
|
||||
mysqlnd_simple_command(MYSQLND *conn, enum php_mysqlnd_server_command command,
|
||||
const char * const arg, size_t arg_len,
|
||||
enum php_mysql_packet_type ok_packet, zend_bool silent,
|
||||
enum php_mysql_packet_type ok_packet, zend_bool silent,
|
||||
zend_bool ignore_upsert_status TSRMLS_DC)
|
||||
{
|
||||
enum_func_status ret = PASS;
|
||||
|
@ -454,7 +453,7 @@ MYSQLND_METHOD(mysqlnd_conn, set_server_option)(MYSQLND * const conn,
|
|||
|
||||
|
||||
/* {{{ _mysqlnd_restart_psession */
|
||||
PHPAPI void _mysqlnd_restart_psession(MYSQLND *conn, MYSQLND_THD_ZVAL_PCACHE *cache TSRMLS_DC)
|
||||
PHPAPI void _mysqlnd_restart_psession(MYSQLND *conn, MYSQLND_THD_ZVAL_PCACHE *cache TSRMLS_DC)
|
||||
{
|
||||
DBG_ENTER("_mysqlnd_restart_psession");
|
||||
MYSQLND_INC_CONN_STATISTIC(&conn->stats, STAT_CONNECT_REUSED);
|
||||
|
@ -484,8 +483,9 @@ PHPAPI void _mysqlnd_end_psession(MYSQLND *conn TSRMLS_DC)
|
|||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_connect */
|
||||
PHPAPI MYSQLND *mysqlnd_connect(MYSQLND *conn,
|
||||
/* {{{ mysqlnd_conn::connect */
|
||||
static enum_func_status
|
||||
MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND *conn,
|
||||
const char *host, const char *user,
|
||||
const char *passwd, unsigned int passwd_len,
|
||||
const char *db, unsigned int db_len,
|
||||
|
@ -505,12 +505,14 @@ PHPAPI MYSQLND *mysqlnd_connect(MYSQLND *conn,
|
|||
zend_bool unix_socket = FALSE;
|
||||
const MYSQLND_CHARSET * charset;
|
||||
zend_bool reconnect = FALSE;
|
||||
zend_bool saved_compression = FALSE;
|
||||
|
||||
php_mysql_packet_greet greet_packet;
|
||||
php_mysql_packet_auth *auth_packet;
|
||||
php_mysql_packet_ok ok_packet;
|
||||
|
||||
DBG_ENTER("mysqlnd_connect");
|
||||
DBG_ENTER("mysqlnd_conn::connect");
|
||||
|
||||
DBG_INF_FMT("host=%s user=%s db=%s port=%d flags=%d persistent=%d state=%d",
|
||||
host?host:"", user?user:"", db?db:"", port, mysql_flags,
|
||||
conn? conn->persistent:0, conn? CONN_GET_STATE(conn):-1);
|
||||
|
@ -531,6 +533,15 @@ PHPAPI MYSQLND *mysqlnd_connect(MYSQLND *conn,
|
|||
MYSQLND_DEC_CONN_STATISTIC(&conn->stats, STAT_OPENED_PERSISTENT_CONNECTIONS);
|
||||
}
|
||||
/* Now reconnect using the same handle */
|
||||
if (conn->net.compressed) {
|
||||
/*
|
||||
we need to save the state. As we will re-connect, net.compressed should be off, or
|
||||
we will look for a compression header as part of the greet message, but there will
|
||||
be none.
|
||||
*/
|
||||
saved_compression = TRUE;
|
||||
conn->net.compressed = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!host || !host[0]) {
|
||||
|
@ -558,30 +569,25 @@ PHPAPI MYSQLND *mysqlnd_connect(MYSQLND *conn,
|
|||
}
|
||||
transport_len = spprintf(&transport, 0, "unix://%s", socket);
|
||||
unix_socket = TRUE;
|
||||
} else
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
transport_len = spprintf(&transport, 0, "tcp://%s:%d", host, port);
|
||||
}
|
||||
DBG_INF_FMT("transport=%p", transport);
|
||||
DBG_INF_FMT("transport=%s", transport);
|
||||
|
||||
|
||||
PACKET_INIT_ALLOCA(greet_packet, PROT_GREET_PACKET);
|
||||
PACKET_INIT(auth_packet, PROT_AUTH_PACKET, php_mysql_packet_auth *, FALSE);
|
||||
PACKET_INIT_ALLOCA(ok_packet, PROT_OK_PACKET);
|
||||
|
||||
if (!conn) {
|
||||
conn = mysqlnd_init(FALSE);
|
||||
self_alloced = TRUE;
|
||||
}
|
||||
|
||||
if (conn->persistent) {
|
||||
hashed_details_len = spprintf(&hashed_details, 0, "%p", conn);
|
||||
DBG_INF_FMT("hashed_details=%s", hashed_details);
|
||||
}
|
||||
}
|
||||
|
||||
CONN_SET_STATE(conn, CONN_ALLOCED);
|
||||
conn->net.packet_no = 0;
|
||||
conn->net.packet_no = conn->net.compressed_envelope_packet_no = 0;
|
||||
|
||||
if (conn->options.timeout_connect) {
|
||||
tv.tv_sec = conn->options.timeout_connect;
|
||||
|
@ -596,7 +602,7 @@ PHPAPI MYSQLND *mysqlnd_connect(MYSQLND *conn,
|
|||
conn->scheme_len = strlen(conn->scheme);
|
||||
DBG_INF(conn->scheme);
|
||||
conn->net.stream = php_stream_xport_create(conn->scheme, transport_len, streams_options, streams_flags,
|
||||
hashed_details,
|
||||
hashed_details,
|
||||
(conn->options.timeout_connect) ? &tv : NULL,
|
||||
NULL /*ctx*/, &errstr, &errcode);
|
||||
DBG_INF_FMT("stream=%p", conn->net.stream);
|
||||
|
@ -651,6 +657,13 @@ PHPAPI MYSQLND *mysqlnd_connect(MYSQLND *conn,
|
|||
mysqlnd_set_sock_no_delay(conn->net.stream);
|
||||
}
|
||||
|
||||
{
|
||||
unsigned int buf_size;
|
||||
buf_size = MYSQLND_G(net_read_buffer_size); /* this is long, cast to unsigned int*/
|
||||
conn->m->set_client_option(conn, MYSQLND_OPT_NET_READ_BUFFER_SIZE, (char *)&buf_size TSRMLS_CC);
|
||||
}
|
||||
|
||||
|
||||
if (FAIL == PACKET_READ_ALLOCA(greet_packet, conn)) {
|
||||
DBG_ERR("Error while reading greeting packet");
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error while reading greeting packet. PID=%d", getpid());
|
||||
|
@ -659,7 +672,7 @@ PHPAPI MYSQLND *mysqlnd_connect(MYSQLND *conn,
|
|||
DBG_ERR_FMT("errorno=%d error=%s", greet_packet.error_no, greet_packet.error);
|
||||
SET_CLIENT_ERROR(conn->error_info, greet_packet.error_no,
|
||||
greet_packet.sqlstate, greet_packet.error);
|
||||
goto err;
|
||||
goto err;
|
||||
} else if (greet_packet.pre41) {
|
||||
DBG_ERR_FMT("Connecting to 3.22, 3.23 & 4.0 is not supported. Server is %-.32s",
|
||||
greet_packet.server_version);
|
||||
|
@ -707,7 +720,7 @@ PHPAPI MYSQLND *mysqlnd_connect(MYSQLND *conn,
|
|||
if (!PACKET_WRITE(auth_packet, conn)) {
|
||||
CONN_SET_STATE(conn, CONN_QUIT_SENT);
|
||||
SET_CLIENT_ERROR(conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);
|
||||
goto err;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (FAIL == PACKET_READ_ALLOCA(ok_packet, conn) || ok_packet.field_count >= 0xFE) {
|
||||
|
@ -730,6 +743,15 @@ PHPAPI MYSQLND *mysqlnd_connect(MYSQLND *conn,
|
|||
}
|
||||
} else {
|
||||
CONN_SET_STATE(conn, CONN_READY);
|
||||
if (!self_alloced && saved_compression) {
|
||||
conn->net.compressed = TRUE;
|
||||
}
|
||||
/*
|
||||
If a connect on a existing handle is performed and mysql_flags is
|
||||
passed which doesn't CLIENT_COMPRESS, then we need to overwrite the value
|
||||
which we set based on saved_compression.
|
||||
*/
|
||||
conn->net.compressed = mysql_flags & CLIENT_COMPRESS? TRUE:FALSE;
|
||||
|
||||
conn->user = pestrdup(user, conn->persistent);
|
||||
conn->user_len = strlen(conn->user);
|
||||
|
@ -781,19 +803,18 @@ PHPAPI MYSQLND *mysqlnd_connect(MYSQLND *conn,
|
|||
|
||||
buf_size = MYSQLND_G(net_cmd_buffer_size); /* this is long, cast to unsigned int*/
|
||||
conn->m->set_client_option(conn, MYSQLND_OPT_NET_CMD_BUFFER_SIZE,
|
||||
(char *)&buf_size TSRMLS_CC);
|
||||
(char *)&buf_size TSRMLS_CC);
|
||||
}
|
||||
|
||||
MYSQLND_INC_CONN_STATISTIC_W_VALUE2(&conn->stats, STAT_CONNECT_SUCCESS, 1, STAT_OPENED_CONNECTIONS, 1);
|
||||
if (reconnect) {
|
||||
MYSQLND_INC_GLOBAL_STATISTIC(STAT_RECONNECT);
|
||||
MYSQLND_INC_GLOBAL_STATISTIC(STAT_RECONNECT);
|
||||
}
|
||||
if (conn->persistent) {
|
||||
MYSQLND_INC_CONN_STATISTIC_W_VALUE2(&conn->stats, STAT_PCONNECT_SUCCESS, 1, STAT_OPENED_PERSISTENT_CONNECTIONS, 1);
|
||||
}
|
||||
|
||||
DBG_INF_FMT("connection_id=%llu", conn->thread_id);
|
||||
conn->result_set_memory_pool = mysqlnd_mempool_create(16000 TSRMLS_CC);
|
||||
#if PHP_MAJOR_VERSION >= 6
|
||||
{
|
||||
unsigned int as_unicode = 1;
|
||||
|
@ -838,7 +859,7 @@ PHPAPI MYSQLND *mysqlnd_connect(MYSQLND *conn,
|
|||
PACKET_FREE(auth_packet);
|
||||
PACKET_FREE_ALLOCA(ok_packet);
|
||||
|
||||
DBG_RETURN(conn);
|
||||
DBG_RETURN(PASS);
|
||||
}
|
||||
err:
|
||||
PACKET_FREE_ALLOCA(greet_packet);
|
||||
|
@ -858,24 +879,56 @@ err:
|
|||
conn->scheme = NULL;
|
||||
}
|
||||
|
||||
if (self_alloced) {
|
||||
/*
|
||||
We have alloced, thus there are no references to this
|
||||
object - we are free to kill it!
|
||||
*/
|
||||
conn->m->dtor(conn TSRMLS_CC);
|
||||
} else {
|
||||
/* This will also close conn->net.stream if it has been opened */
|
||||
conn->m->free_contents(conn TSRMLS_CC);
|
||||
MYSQLND_INC_CONN_STATISTIC(&conn->stats, STAT_CONNECT_FAILURE);
|
||||
/* This will also close conn->net.stream if it has been opened */
|
||||
conn->m->free_contents(conn TSRMLS_CC);
|
||||
MYSQLND_INC_CONN_STATISTIC(&conn->stats, STAT_CONNECT_FAILURE);
|
||||
|
||||
DBG_RETURN(FAIL);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_connect */
|
||||
PHPAPI MYSQLND * mysqlnd_connect(MYSQLND * conn,
|
||||
const char *host, const char *user,
|
||||
const char *passwd, unsigned int passwd_len,
|
||||
const char *db, unsigned int db_len,
|
||||
unsigned int port,
|
||||
const char *socket,
|
||||
unsigned int mysql_flags,
|
||||
MYSQLND_THD_ZVAL_PCACHE *zval_cache
|
||||
TSRMLS_DC)
|
||||
{
|
||||
enum_func_status ret;
|
||||
zend_bool self_alloced = FALSE;
|
||||
|
||||
DBG_ENTER("mysqlnd_connect");
|
||||
DBG_INF_FMT("host=%s user=%s db=%s port=%d flags=%d", host?host:"", user?user:"", db?db:"", port, mysql_flags);
|
||||
|
||||
if (!conn) {
|
||||
conn = mysqlnd_init(FALSE);
|
||||
self_alloced = TRUE;
|
||||
}
|
||||
DBG_RETURN(NULL);
|
||||
|
||||
ret = conn->m->connect(conn, host, user, passwd, passwd_len, db, db_len, port, socket, mysql_flags, zval_cache TSRMLS_CC);
|
||||
|
||||
if (ret == FAIL) {
|
||||
if (self_alloced) {
|
||||
/*
|
||||
We have alloced, thus there are no references to this
|
||||
object - we are free to kill it!
|
||||
*/
|
||||
conn->m->dtor(conn TSRMLS_CC);
|
||||
}
|
||||
DBG_RETURN(NULL);
|
||||
}
|
||||
DBG_RETURN(conn);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_conn::query */
|
||||
/*
|
||||
/*
|
||||
If conn->error_info.error_no is not zero, then we had an error.
|
||||
Still the result from the query is PASS
|
||||
*/
|
||||
|
@ -896,7 +949,7 @@ MYSQLND_METHOD(mysqlnd_conn, query)(MYSQLND *conn, const char *query, unsigned i
|
|||
Here read the result set. We don't do it in simple_command because it need
|
||||
information from the ok packet. We will fetch it ourselves.
|
||||
*/
|
||||
ret = mysqlnd_query_read_result_set_header(conn, NULL TSRMLS_CC);
|
||||
ret = conn->m->query_read_result_set_header(conn, NULL TSRMLS_CC);
|
||||
if (ret == PASS && conn->last_query_type == QUERY_UPSERT && conn->upsert_status.affected_rows) {
|
||||
MYSQLND_INC_CONN_STATISTIC_W_VALUE(&conn->stats, STAT_ROWS_AFFECTED_NORMAL, conn->upsert_status.affected_rows);
|
||||
}
|
||||
|
@ -932,9 +985,9 @@ MYSQLND_METHOD(mysqlnd_conn, reap_query)(MYSQLND * conn TSRMLS_DC)
|
|||
|
||||
if (state <= CONN_READY || state == CONN_QUIT_SENT) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Connection not opened, clear or has been closed");
|
||||
DBG_RETURN(FAIL);
|
||||
DBG_RETURN(FAIL);
|
||||
}
|
||||
DBG_RETURN(mysqlnd_query_read_result_set_header(conn, NULL TSRMLS_CC));
|
||||
DBG_RETURN(conn->m->query_read_result_set_header(conn, NULL TSRMLS_CC));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
@ -967,7 +1020,7 @@ MYSQLND ** mysqlnd_stream_array_check_for_readiness(MYSQLND ** conn_array TSRMLS
|
|||
}
|
||||
p++;
|
||||
}
|
||||
*ret_p = NULL;
|
||||
*ret_p = NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -988,7 +1041,7 @@ static int mysqlnd_stream_array_to_fd_set(MYSQLND **conn_array, fd_set *fds, php
|
|||
* */
|
||||
if (SUCCESS == php_stream_cast((*p)->net.stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL,
|
||||
(void*)&this_fd, 1) && this_fd >= 0) {
|
||||
|
||||
|
||||
PHP_SAFE_FD_SET(this_fd, fds);
|
||||
|
||||
if (this_fd > *max_fd) {
|
||||
|
@ -1027,7 +1080,7 @@ static int mysqlnd_stream_array_from_fd_set(MYSQLND **conn_array, fd_set *fds TS
|
|||
fwd++;
|
||||
}
|
||||
*bckwd = NULL;/* NULL-terminate the list */
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1088,14 +1141,14 @@ _mysqlnd_poll(MYSQLND **r_array, MYSQLND **e_array, MYSQLND ***dont_poll, long s
|
|||
/* Solaris + BSD do not like microsecond values which are >= 1 sec */
|
||||
if (usec > 999999) {
|
||||
tv.tv_sec = sec + (usec / 1000000);
|
||||
tv.tv_usec = usec % 1000000;
|
||||
tv.tv_usec = usec % 1000000;
|
||||
} else {
|
||||
tv.tv_sec = sec;
|
||||
tv.tv_usec = usec;
|
||||
}
|
||||
|
||||
tv_p = &tv;
|
||||
|
||||
|
||||
retval = php_select(max_fd + 1, &rfds, &wfds, &efds, tv_p);
|
||||
|
||||
if (retval == -1) {
|
||||
|
@ -1145,7 +1198,7 @@ MYSQLND_METHOD(mysqlnd_conn, list_fields)(MYSQLND *conn, const char *table, cons
|
|||
|
||||
if (achtung_wild && (wild_len = strlen(achtung_wild))) {
|
||||
memcpy(p, achtung_wild, MIN(wild_len, MYSQLND_MAX_ALLOWED_DB_LEN * 4));
|
||||
p += wild_len;
|
||||
p += wild_len;
|
||||
*p++ = '\0';
|
||||
}
|
||||
|
||||
|
@ -1193,14 +1246,14 @@ MYSQLND_METHOD(mysqlnd_conn, list_method)(MYSQLND *conn, const char *query,
|
|||
if (achtung_wild) {
|
||||
show_query_len = spprintf(&show_query, 0, query, par1, achtung_wild);
|
||||
} else {
|
||||
show_query_len = spprintf(&show_query, 0, query, par1);
|
||||
show_query_len = spprintf(&show_query, 0, query, par1);
|
||||
}
|
||||
} else {
|
||||
if (achtung_wild) {
|
||||
show_query_len = spprintf(&show_query, 0, query, achtung_wild);
|
||||
} else {
|
||||
show_query_len = strlen(show_query = (char *)query);
|
||||
}
|
||||
show_query_len = strlen(show_query = (char *)query);
|
||||
}
|
||||
}
|
||||
|
||||
if (PASS == conn->m->query(conn, show_query, show_query_len TSRMLS_CC)) {
|
||||
|
@ -1739,7 +1792,7 @@ MYSQLND_METHOD(mysqlnd_conn, get_server_version)(const MYSQLND * const conn)
|
|||
minor = strtol(p, &p, 10);
|
||||
p += 1; /* consume the dot */
|
||||
patch = strtol(p, &p, 10);
|
||||
|
||||
|
||||
return (unsigned long)(major * 10000L + (unsigned long)(minor * 100L + patch));
|
||||
}
|
||||
/* }}} */
|
||||
|
@ -1775,7 +1828,7 @@ MYSQLND_METHOD(mysqlnd_conn, next_result)(MYSQLND * const conn TSRMLS_DC)
|
|||
We are sure that there is a result set, since conn->state is set accordingly
|
||||
in mysqlnd_store_result() or mysqlnd_fetch_row_unbuffered()
|
||||
*/
|
||||
if (FAIL == (ret = mysqlnd_query_read_result_set_header(conn, NULL TSRMLS_CC))) {
|
||||
if (FAIL == (ret = conn->m->query_read_result_set_header(conn, NULL TSRMLS_CC))) {
|
||||
/*
|
||||
There can be an error in the middle of a multi-statement, which will cancel the multi-statement.
|
||||
So there are no more results and we should just return FALSE, error_no has been set
|
||||
|
@ -2192,6 +2245,8 @@ MYSQLND_METHOD(mysqlnd_conn, get_connection_stats)(const MYSQLND * const conn,
|
|||
MYSQLND_STMT * _mysqlnd_stmt_init(MYSQLND * const conn TSRMLS_DC);
|
||||
|
||||
MYSQLND_CLASS_METHODS_START(mysqlnd_conn)
|
||||
MYSQLND_METHOD(mysqlnd_conn, connect),
|
||||
|
||||
MYSQLND_METHOD(mysqlnd_conn, escape_string),
|
||||
MYSQLND_METHOD(mysqlnd_conn, set_charset),
|
||||
MYSQLND_METHOD(mysqlnd_conn, query),
|
||||
|
@ -2244,6 +2299,8 @@ MYSQLND_CLASS_METHODS_START(mysqlnd_conn)
|
|||
|
||||
MYSQLND_METHOD_PRIVATE(mysqlnd_conn, dtor),
|
||||
|
||||
mysqlnd_query_read_result_set_header,
|
||||
|
||||
MYSQLND_METHOD_PRIVATE(mysqlnd_conn, get_reference),
|
||||
MYSQLND_METHOD_PRIVATE(mysqlnd_conn, free_reference),
|
||||
MYSQLND_METHOD_PRIVATE(mysqlnd_conn, get_state),
|
||||
|
@ -2254,7 +2311,8 @@ MYSQLND_CLASS_METHODS_END;
|
|||
/* {{{ mysqlnd_init */
|
||||
PHPAPI MYSQLND *_mysqlnd_init(zend_bool persistent TSRMLS_DC)
|
||||
{
|
||||
MYSQLND *ret = mnd_pecalloc(1, sizeof(MYSQLND), persistent);
|
||||
size_t alloc_size = sizeof(MYSQLND) + mysqlnd_plugin_count() * sizeof(void *);
|
||||
MYSQLND *ret = mnd_pecalloc(1, alloc_size, persistent);
|
||||
|
||||
DBG_ENTER("mysqlnd_init");
|
||||
DBG_INF_FMT("persistent=%d", persistent);
|
||||
|
@ -2265,6 +2323,9 @@ PHPAPI MYSQLND *_mysqlnd_init(zend_bool persistent TSRMLS_DC)
|
|||
ret->m = mysqlnd_conn_methods;
|
||||
ret->m->get_reference(ret TSRMLS_CC);
|
||||
|
||||
ret->net.stream_read = mysqlnd_read_from_stream;
|
||||
ret->net.stream_write = mysqlnd_stream_write;
|
||||
|
||||
#ifdef MYSQLND_THREADED
|
||||
ret->LOCK_state = tsrm_mutex_alloc();
|
||||
|
||||
|
@ -2305,6 +2366,37 @@ PHPAPI void mysqlnd_conn_set_methods(struct st_mysqlnd_conn_methods *methods)
|
|||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
static unsigned int mysqlnd_plugins_counter = 0;
|
||||
|
||||
/* {{{ mysqlnd_plugin_register */
|
||||
PHPAPI unsigned int mysqlnd_plugin_register()
|
||||
{
|
||||
return mysqlnd_plugins_counter++;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_plugin_count */
|
||||
unsigned int mysqlnd_plugin_count()
|
||||
{
|
||||
return mysqlnd_plugins_counter;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ _mysqlnd_plugin_get_plugin_connection_data */
|
||||
PHPAPI void ** _mysqlnd_plugin_get_plugin_connection_data(const MYSQLND * conn, unsigned int plugin_id TSRMLS_DC)
|
||||
{
|
||||
DBG_ENTER("_mysqlnd_plugin_get_plugin_connection_data");
|
||||
DBG_INF_FMT("plugin_id=%u", plugin_id);
|
||||
if (!conn || plugin_id >= mysqlnd_plugin_count()) {
|
||||
return NULL;
|
||||
}
|
||||
DBG_RETURN((void *)conn + sizeof(MYSQLND) + plugin_id * sizeof(void *));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
minimal.
|
||||
*/
|
||||
#if PHP_DEBUG
|
||||
#define MYSQLND_DO_WIRE_CHECK_BEFORE_COMMAND 1
|
||||
//#define MYSQLND_DO_WIRE_CHECK_BEFORE_COMMAND 1
|
||||
#endif
|
||||
|
||||
#if PHP_DEBUG && !defined(PHP_WIN32)
|
||||
|
@ -65,6 +65,15 @@
|
|||
void mysqlnd_library_init(TSRMLS_D);
|
||||
void mysqlnd_library_end(TSRMLS_D);
|
||||
|
||||
PHPAPI unsigned int mysqlnd_plugin_register();
|
||||
unsigned int mysqlnd_plugin_count();
|
||||
PHPAPI void ** _mysqlnd_plugin_get_plugin_connection_data(const MYSQLND * conn, unsigned int plugin_id TSRMLS_DC);
|
||||
#define mysqlnd_plugin_get_plugin_connection_data(c, p_id) _mysqlnd_plugin_get_plugin_connection_data((c), (p_id) TSRMLS_CC)
|
||||
|
||||
PHPAPI void ** _mysqlnd_plugin_get_plugin_result_data(const MYSQLND_RES * result, unsigned int plugin_id TSRMLS_DC);
|
||||
#define mysqlnd_plugin_get_plugin_result_data(r, p_id) _mysqlnd_plugin_get_plugin_result_data((r), (p_id) TSRMLS_CC)
|
||||
|
||||
|
||||
PHPAPI struct st_mysqlnd_conn_methods * mysqlnd_conn_get_methods();
|
||||
PHPAPI void mysqlnd_conn_set_methods(struct st_mysqlnd_conn_methods *methods);
|
||||
|
||||
|
|
|
@ -171,7 +171,7 @@ static unsigned int check_mb_eucjpms(const char *start, const char *end)
|
|||
if (valid_eucjpms_ss2(start[0]) && (end - start) > 1 && valid_eucjpms_kata(start[1])) {
|
||||
return 2;
|
||||
}
|
||||
if (valid_eucjpms_ss3(start[0]) && (end - start) > 2 && valid_eucjpms(start[1]) &&
|
||||
if (valid_eucjpms_ss3(start[0]) && (end - start) > 2 && valid_eucjpms(start[1]) &&
|
||||
valid_eucjpms(start[2])) {
|
||||
return 2;
|
||||
}
|
||||
|
@ -199,7 +199,7 @@ static unsigned int mysqlnd_mbcharlen_eucjpms(unsigned int jpms)
|
|||
|
||||
static unsigned int check_mb_gb2312(const char *start, const char *end)
|
||||
{
|
||||
return (valid_gb2312_head((unsigned int)start[0]) && end - start > 1 &&
|
||||
return (valid_gb2312_head((unsigned int)start[0]) && end - start > 1 &&
|
||||
valid_gb2312_tail((unsigned int)start[1])) ? 2 : 0;
|
||||
}
|
||||
|
||||
|
@ -311,7 +311,7 @@ const MYSQLND_CHARSET mysqlnd_charsets[] =
|
|||
{ 19, "euckr", "euckr_korean_ci", 1, 2, "", mysqlnd_mbcharlen_euckr, check_mb_euckr},
|
||||
{ 22, "koi8u", "koi8u_general_ci", 1, 1, "", NULL, NULL},
|
||||
{ 24, "gb2312", "gb2312_chinese_ci", 1, 2, "", mysqlnd_mbcharlen_gb2312, check_mb_gb2312},
|
||||
{ 25, "greek", "greek_general_ci", 1, 1, "", NULL, NULL},
|
||||
{ 25, "greek", "greek_general_ci", 1, 1, "", NULL, NULL},
|
||||
{ 26, "cp1250", "cp1250_general_ci", 1, 1, "", NULL, NULL},
|
||||
{ 28, "gbk", "gbk_chinese_ci", 1, 2, "", mysqlnd_mbcharlen_gbk, check_mb_gbk},
|
||||
{ 30, "latin5", "latin5_turkish_ci", 1, 1, "", NULL, NULL},
|
||||
|
@ -449,7 +449,7 @@ const MYSQLND_CHARSET mysqlnd_charsets60[] =
|
|||
{ 19, "euckr", "euckr_korean_ci", 1, 2, "", mysqlnd_mbcharlen_euckr, check_mb_euckr},
|
||||
{ 22, "koi8u", "koi8u_general_ci", 1, 1, "", NULL, NULL},
|
||||
{ 24, "gb2312", "gb2312_chinese_ci", 1, 2, "", mysqlnd_mbcharlen_gb2312, check_mb_gb2312},
|
||||
{ 25, "greek", "greek_general_ci", 1, 1, "", NULL, NULL},
|
||||
{ 25, "greek", "greek_general_ci", 1, 1, "", NULL, NULL},
|
||||
{ 26, "cp1250", "cp1250_general_ci", 1, 1, "", NULL, NULL},
|
||||
{ 28, "gbk", "gbk_chinese_ci", 1, 2, "", mysqlnd_mbcharlen_gbk, check_mb_gbk},
|
||||
{ 30, "latin5", "latin5_turkish_ci", 1, 1, "", NULL, NULL},
|
||||
|
@ -635,7 +635,7 @@ PHPAPI ulong mysqlnd_cset_escape_quotes(const MYSQLND_CHARSET * const cset, char
|
|||
for (;escapestr < end; escapestr++) {
|
||||
unsigned int len = 0;
|
||||
/* check unicode characters */
|
||||
|
||||
|
||||
if (cset->char_maxlen > 1 && (len = cset->mb_valid(escapestr, end))) {
|
||||
|
||||
/* check possible overflow */
|
||||
|
@ -685,7 +685,8 @@ PHPAPI ulong mysqlnd_cset_escape_slashes(const MYSQLND_CHARSET * const cset, cha
|
|||
zend_bool escape_overflow = FALSE;
|
||||
|
||||
DBG_ENTER("mysqlnd_cset_escape_slashes");
|
||||
|
||||
DBG_INF_FMT("charset=%s", cset->name);
|
||||
|
||||
for (;escapestr < end; escapestr++) {
|
||||
char esc = '\0';
|
||||
unsigned int len = 0;
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
#endif
|
||||
|
||||
|
||||
#define MYSQLND_MIN_COMPRESS_LEN 0
|
||||
|
||||
#define MYSQLND_MAX_PACKET_SIZE (256L*256L*256L-1)
|
||||
|
||||
#define MYSQLND_ERRMSG_SIZE 512
|
||||
|
|
|
@ -75,7 +75,7 @@ int mysqlnd_local_infile_init(void **ptr, char *filename, void **userdata TSRMLS
|
|||
|
||||
if (info->fd == NULL) {
|
||||
snprintf((char *)info->error_msg, sizeof(info->error_msg), "Can't find file '%-.64s'.", filename);
|
||||
info->error_no = MYSQLND_EE_FILENOTFOUND;
|
||||
info->error_no = MYSQLND_EE_FILENOTFOUND;
|
||||
DBG_RETURN(1);
|
||||
}
|
||||
|
||||
|
@ -196,7 +196,7 @@ mysqlnd_handle_local_infile(MYSQLND *conn, const char *filename, zend_bool *is_w
|
|||
infile = conn->infile;
|
||||
/* allocate buffer for reading data */
|
||||
buf = (char *)mnd_ecalloc(1, buflen);
|
||||
|
||||
|
||||
*is_warning = FALSE;
|
||||
|
||||
/* init handler: allocate read buffer and open file */
|
||||
|
|
|
@ -42,8 +42,7 @@
|
|||
#endif
|
||||
|
||||
#define MYSQLND_CLASS_METHOD_TABLE_NAME(class) mysqlnd_##class##_methods
|
||||
#define MYSQLND_CLASS_METHODS_START(class) static \
|
||||
struct st_##class##_methods MYSQLND_CLASS_METHOD_TABLE_NAME(class) = {
|
||||
#define MYSQLND_CLASS_METHODS_START(class) struct st_##class##_methods MYSQLND_CLASS_METHOD_TABLE_NAME(class) = {
|
||||
#define MYSQLND_CLASS_METHODS_END }
|
||||
|
||||
#if PHP_MAJOR_VERSION < 6
|
||||
|
|
|
@ -110,10 +110,9 @@ MYSQLND_METHOD(mysqlnd_stmt, store_result)(MYSQLND_STMT * const stmt TSRMLS_DC)
|
|||
result->zval_cache = mysqlnd_palloc_get_thd_cache_reference(conn->zval_cache);
|
||||
}
|
||||
|
||||
/* Create room for 'next_extend' rows */
|
||||
result->result_set_memory_pool = mysqlnd_mempool_create(16000 TSRMLS_CC);
|
||||
|
||||
ret = mysqlnd_store_result_fetch_data(conn, result, result->meta,
|
||||
TRUE, to_cache TSRMLS_CC);
|
||||
ret = result->m.store_result_fetch_data(conn, result, result->meta, TRUE, to_cache TSRMLS_CC);
|
||||
|
||||
if (PASS == ret) {
|
||||
/* libmysql API docs say it should be so for SELECT statements */
|
||||
|
@ -187,8 +186,7 @@ MYSQLND_METHOD(mysqlnd_stmt, background_store_result)(MYSQLND_STMT * const stmt
|
|||
result->conn = NULL; /* store result does not reference the connection */
|
||||
}
|
||||
|
||||
ret = mysqlnd_store_result_fetch_data(conn, result, result->meta,
|
||||
TRUE, to_cache TSRMLS_CC);
|
||||
ret = result->m.store_result_fetch_data(conn, result, result->meta, TRUE, to_cache TSRMLS_CC);
|
||||
|
||||
if (PASS == ret) {
|
||||
/* libmysql API docs say it should be so for SELECT statements */
|
||||
|
@ -740,7 +738,11 @@ mysqlnd_fetch_stmt_row_buffered(MYSQLND_RES *result, void *param, unsigned int f
|
|||
current_row,
|
||||
meta->field_count,
|
||||
meta->fields,
|
||||
result->conn TSRMLS_CC);
|
||||
result->stored_data->persistent,
|
||||
result->conn->options.numeric_and_datetime_as_unicode,
|
||||
result->conn->options.int_and_float_native,
|
||||
result->conn->zval_cache,
|
||||
&result->conn->stats TSRMLS_CC);
|
||||
if (stmt->update_max_length) {
|
||||
for (i = 0; i < result->field_count; i++) {
|
||||
/*
|
||||
|
@ -832,7 +834,7 @@ mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES *result, void *param, unsigned int
|
|||
|
||||
/*
|
||||
If we skip rows (stmt == NULL || stmt->result_bind == NULL) we have to
|
||||
mysqlnd_unbuffered_free_last_data() before it. The function returns always true.
|
||||
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) {
|
||||
unsigned int i, field_count = result->field_count;
|
||||
|
@ -840,7 +842,7 @@ mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES *result, void *param, unsigned int
|
|||
*fetched_anything = TRUE;
|
||||
|
||||
if (!row_packet->skip_extraction) {
|
||||
mysqlnd_unbuffered_free_last_data(result TSRMLS_CC);
|
||||
result->m.unbuffered_free_last_data(result TSRMLS_CC);
|
||||
|
||||
DBG_INF("extracting data");
|
||||
result->unbuf->last_row_data = row_packet->fields;
|
||||
|
@ -852,14 +854,18 @@ mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES *result, void *param, unsigned int
|
|||
result->unbuf->last_row_data,
|
||||
row_packet->field_count,
|
||||
row_packet->fields_metadata,
|
||||
result->conn TSRMLS_CC);
|
||||
FALSE,
|
||||
result->conn->options.numeric_and_datetime_as_unicode,
|
||||
result->conn->options.int_and_float_native,
|
||||
result->conn->zval_cache,
|
||||
&result->conn->stats TSRMLS_CC);
|
||||
|
||||
for (i = 0; i < field_count; i++) {
|
||||
if (stmt->result_bind[i].bound == TRUE) {
|
||||
zval *data = result->unbuf->last_row_data[i];
|
||||
/*
|
||||
stmt->result_bind[i].zv has been already destructed
|
||||
in mysqlnd_unbuffered_free_last_data()
|
||||
in result->m.unbuffered_free_last_data()
|
||||
*/
|
||||
#ifndef WE_DONT_COPY_IN_BUFFERED_AND_UNBUFFERED_BECAUSEOF_IS_REF
|
||||
zval_dtor(stmt->result_bind[i].zv);
|
||||
|
@ -885,7 +891,7 @@ mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES *result, void *param, unsigned int
|
|||
} else {
|
||||
DBG_INF("skipping extraction");
|
||||
/*
|
||||
Data has been allocated and usually mysqlnd_unbuffered_free_last_data()
|
||||
Data has been allocated and usually result->m.unbuffered_free_last_data()
|
||||
frees it but we can't call this function as it will cause problems with
|
||||
the bound variables. Thus we need to do part of what it does or Zend will
|
||||
report leaks.
|
||||
|
@ -1014,7 +1020,7 @@ mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES *result, void *param, unsigned int fla
|
|||
|
||||
DBG_INF_FMT("skip_extraction=%d", row_packet->skip_extraction);
|
||||
if (!row_packet->skip_extraction) {
|
||||
mysqlnd_unbuffered_free_last_data(result TSRMLS_CC);
|
||||
result->m.unbuffered_free_last_data(result TSRMLS_CC);
|
||||
|
||||
DBG_INF("extracting data");
|
||||
result->unbuf->last_row_data = row_packet->fields;
|
||||
|
@ -1026,7 +1032,11 @@ mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES *result, void *param, unsigned int fla
|
|||
result->unbuf->last_row_data,
|
||||
row_packet->field_count,
|
||||
row_packet->fields_metadata,
|
||||
result->conn TSRMLS_CC);
|
||||
FALSE,
|
||||
result->conn->options.numeric_and_datetime_as_unicode,
|
||||
result->conn->options.int_and_float_native,
|
||||
result->conn->zval_cache,
|
||||
&result->conn->stats TSRMLS_CC);
|
||||
|
||||
/* If no result bind, do nothing. We consumed the data */
|
||||
for (i = 0; i < field_count; i++) {
|
||||
|
@ -1034,7 +1044,7 @@ mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES *result, void *param, unsigned int fla
|
|||
zval *data = result->unbuf->last_row_data[i];
|
||||
/*
|
||||
stmt->result_bind[i].zv has been already destructed
|
||||
in mysqlnd_unbuffered_free_last_data()
|
||||
in result->m.unbuffered_free_last_data()
|
||||
*/
|
||||
#ifndef WE_DONT_COPY_IN_BUFFERED_AND_UNBUFFERED_BECAUSEOF_IS_REF
|
||||
zval_dtor(stmt->result_bind[i].zv);
|
||||
|
@ -1060,7 +1070,7 @@ mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES *result, void *param, unsigned int fla
|
|||
} else {
|
||||
DBG_INF("skipping extraction");
|
||||
/*
|
||||
Data has been allocated and usually mysqlnd_unbuffered_free_last_data()
|
||||
Data has been allocated and usually result->m.unbuffered_free_last_data()
|
||||
frees it but we can't call this function as it will cause problems with
|
||||
the bound variables. Thus we need to do part of what it does or Zend will
|
||||
report leaks.
|
||||
|
@ -1708,7 +1718,7 @@ MYSQLND_METHOD(mysqlnd_stmt, result_metadata)(MYSQLND_STMT * const stmt TSRMLS_D
|
|||
|
||||
if (stmt->update_max_length && stmt->result->stored_data) {
|
||||
/* stored result, we have to update the max_length before we clone the meta data :( */
|
||||
mysqlnd_res_initialize_result_set_rest(stmt->result TSRMLS_CC);
|
||||
stmt->result->m.initialize_result_set_rest(stmt->result TSRMLS_CC);
|
||||
}
|
||||
/*
|
||||
TODO: This implementation is kind of a hack,
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "php.h"
|
||||
#include "mysqlnd.h"
|
||||
#include "mysqlnd_wireprotocol.h"
|
||||
#include "mysqlnd_block_alloc.h"
|
||||
#include "mysqlnd_priv.h"
|
||||
#include "mysqlnd_result.h"
|
||||
#include "mysqlnd_result_meta.h"
|
||||
|
@ -92,15 +93,16 @@ void * mysqlnd_fetch_thread(void *arg)
|
|||
#endif /* MYSQLND_THREADED */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_res_initialize_result_set_rest */
|
||||
void mysqlnd_res_initialize_result_set_rest(MYSQLND_RES * const result TSRMLS_DC)
|
||||
/* {{{ mysqlnd_res::initialize_result_set_rest */
|
||||
static void
|
||||
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;
|
||||
DBG_ENTER("mysqlnd_res_initialize_result_set_rest");
|
||||
DBG_ENTER("mysqlnd_res::initialize_result_set_rest");
|
||||
|
||||
if (!data_cursor || row_count == result->stored_data->initialized_rows) {
|
||||
DBG_VOID_RETURN;
|
||||
|
@ -113,7 +115,11 @@ void mysqlnd_res_initialize_result_set_rest(MYSQLND_RES * const result TSRMLS_DC
|
|||
data_cursor,
|
||||
result->meta->field_count,
|
||||
result->meta->fields,
|
||||
result->conn TSRMLS_CC);
|
||||
result->stored_data->persistent,
|
||||
result->conn->options.numeric_and_datetime_as_unicode,
|
||||
result->conn->options.int_and_float_native,
|
||||
result->conn->zval_cache,
|
||||
&result->conn->stats TSRMLS_CC);
|
||||
for (i = 0; i < result->field_count; i++) {
|
||||
/*
|
||||
NULL fields are 0 length, 0 is not more than 0
|
||||
|
@ -135,12 +141,13 @@ void mysqlnd_res_initialize_result_set_rest(MYSQLND_RES * const result TSRMLS_DC
|
|||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_unbuffered_free_last_data */
|
||||
void mysqlnd_unbuffered_free_last_data(MYSQLND_RES *result TSRMLS_DC)
|
||||
/* {{{ mysqlnd_res::unbuffered_free_last_data */
|
||||
static void
|
||||
MYSQLND_METHOD(mysqlnd_res, unbuffered_free_last_data)(MYSQLND_RES * result TSRMLS_DC)
|
||||
{
|
||||
MYSQLND_RES_UNBUFFERED *unbuf = result->unbuf;
|
||||
|
||||
DBG_ENTER("mysqlnd_unbuffered_free_last_data");
|
||||
DBG_ENTER("mysqlnd_res::unbuffered_free_last_data");
|
||||
|
||||
if (!unbuf) {
|
||||
DBG_VOID_RETURN;
|
||||
|
@ -186,15 +193,16 @@ void mysqlnd_unbuffered_free_last_data(MYSQLND_RES *result TSRMLS_DC)
|
|||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_free_buffered_data */
|
||||
void mysqlnd_free_buffered_data(MYSQLND_RES *result TSRMLS_DC)
|
||||
/* {{{ mysqlnd_res::free_buffered_data */
|
||||
static void
|
||||
MYSQLND_METHOD(mysqlnd_res, free_buffered_data)(MYSQLND_RES *result TSRMLS_DC)
|
||||
{
|
||||
MYSQLND_THD_ZVAL_PCACHE *zval_cache = result->zval_cache;
|
||||
MYSQLND_RES_BUFFERED *set = result->stored_data;
|
||||
unsigned int field_count = result->field_count;
|
||||
int row;
|
||||
|
||||
DBG_ENTER("mysqlnd_free_buffered_data");
|
||||
DBG_ENTER("mysqlnd_res::free_buffered_data");
|
||||
DBG_INF_FMT("Freeing "MYSQLND_LLU_SPEC" row(s)", set->row_count);
|
||||
|
||||
DBG_INF_FMT("before: real_usage=%lu usage=%lu", zend_memory_usage(TRUE TSRMLS_CC), zend_memory_usage(FALSE TSRMLS_CC));
|
||||
|
@ -332,11 +340,11 @@ MYSQLND_METHOD(mysqlnd_res, free_result_buffers)(MYSQLND_RES *result TSRMLS_DC)
|
|||
DBG_INF_FMT("%s", result->unbuf? "unbuffered":(result->stored_data? "buffered":"unknown"));
|
||||
|
||||
if (result->unbuf) {
|
||||
mysqlnd_unbuffered_free_last_data(result TSRMLS_CC);
|
||||
result->m.unbuffered_free_last_data(result TSRMLS_CC);
|
||||
mnd_efree(result->unbuf);
|
||||
result->unbuf = NULL;
|
||||
} else if (result->stored_data) {
|
||||
mysqlnd_free_buffered_data(result TSRMLS_CC);
|
||||
result->m.free_buffered_data(result TSRMLS_CC);
|
||||
result->stored_data = NULL;
|
||||
}
|
||||
#ifdef MYSQLND_THREADED
|
||||
|
@ -357,6 +365,12 @@ MYSQLND_METHOD(mysqlnd_res, free_result_buffers)(MYSQLND_RES *result TSRMLS_DC)
|
|||
result->row_packet = NULL;
|
||||
}
|
||||
|
||||
if (result->result_set_memory_pool) {
|
||||
DBG_INF("Freeing memory pool");
|
||||
mysqlnd_mempool_destroy(result->result_set_memory_pool TSRMLS_CC);
|
||||
result->result_set_memory_pool = NULL;
|
||||
}
|
||||
|
||||
DBG_VOID_RETURN;
|
||||
}
|
||||
/* }}} */
|
||||
|
@ -759,12 +773,12 @@ mysqlnd_fetch_row_unbuffered_c(MYSQLND_RES *result TSRMLS_DC)
|
|||
|
||||
/*
|
||||
If we skip rows (row == NULL) we have to
|
||||
mysqlnd_unbuffered_free_last_data() before it. The function returns always true.
|
||||
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++;
|
||||
|
||||
mysqlnd_unbuffered_free_last_data(result TSRMLS_CC);
|
||||
result->m.unbuffered_free_last_data(result TSRMLS_CC);
|
||||
|
||||
result->unbuf->last_row_data = row_packet->fields;
|
||||
result->unbuf->last_row_buffer = row_packet->row_buffer;
|
||||
|
@ -781,7 +795,11 @@ mysqlnd_fetch_row_unbuffered_c(MYSQLND_RES *result TSRMLS_DC)
|
|||
result->unbuf->last_row_data,
|
||||
row_packet->field_count,
|
||||
row_packet->fields_metadata,
|
||||
result->conn TSRMLS_CC);
|
||||
FALSE,
|
||||
result->conn->options.numeric_and_datetime_as_unicode,
|
||||
result->conn->options.int_and_float_native,
|
||||
result->conn->zval_cache,
|
||||
&result->conn->stats TSRMLS_CC);
|
||||
|
||||
retrow = mnd_malloc(result->field_count * sizeof(char *));
|
||||
|
||||
|
@ -829,7 +847,7 @@ mysqlnd_fetch_row_unbuffered_c(MYSQLND_RES *result TSRMLS_DC)
|
|||
} else {
|
||||
CONN_SET_STATE(result->conn, CONN_READY);
|
||||
}
|
||||
mysqlnd_unbuffered_free_last_data(result TSRMLS_CC);
|
||||
result->m.unbuffered_free_last_data(result TSRMLS_CC);
|
||||
}
|
||||
|
||||
DBG_RETURN(retrow);
|
||||
|
@ -864,13 +882,13 @@ mysqlnd_fetch_row_unbuffered(MYSQLND_RES *result, void *param, unsigned int flag
|
|||
|
||||
/*
|
||||
If we skip rows (row == NULL) we have to
|
||||
mysqlnd_unbuffered_free_last_data() before it. The function returns always true.
|
||||
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;
|
||||
|
||||
mysqlnd_unbuffered_free_last_data(result TSRMLS_CC);
|
||||
result->m.unbuffered_free_last_data(result TSRMLS_CC);
|
||||
|
||||
result->unbuf->last_row_data = row_packet->fields;
|
||||
result->unbuf->last_row_buffer = row_packet->row_buffer;
|
||||
|
@ -891,7 +909,11 @@ mysqlnd_fetch_row_unbuffered(MYSQLND_RES *result, void *param, unsigned int flag
|
|||
result->unbuf->last_row_data,
|
||||
field_count,
|
||||
row_packet->fields_metadata,
|
||||
result->conn TSRMLS_CC);
|
||||
FALSE,
|
||||
result->conn->options.numeric_and_datetime_as_unicode,
|
||||
result->conn->options.int_and_float_native,
|
||||
result->conn->zval_cache,
|
||||
&result->conn->stats TSRMLS_CC);
|
||||
|
||||
for (i = 0; i < field_count; i++, field++, zend_hash_key++) {
|
||||
zval *data = result->unbuf->last_row_data[i];
|
||||
|
@ -962,7 +984,7 @@ mysqlnd_fetch_row_unbuffered(MYSQLND_RES *result, void *param, unsigned int flag
|
|||
} else {
|
||||
CONN_SET_STATE(result->conn, CONN_READY);
|
||||
}
|
||||
mysqlnd_unbuffered_free_last_data(result TSRMLS_CC);
|
||||
result->m.unbuffered_free_last_data(result TSRMLS_CC);
|
||||
*fetched_anything = FALSE;
|
||||
}
|
||||
|
||||
|
@ -996,6 +1018,8 @@ MYSQLND_METHOD(mysqlnd_res, use_result)(MYSQLND_RES * const result, zend_bool ps
|
|||
}
|
||||
result->unbuf = mnd_ecalloc(1, sizeof(MYSQLND_RES_UNBUFFERED));
|
||||
|
||||
result->result_set_memory_pool = mysqlnd_mempool_create(16000 TSRMLS_CC);
|
||||
|
||||
/*
|
||||
Will be freed in the mysqlnd_internal_free_result_contents() called
|
||||
by the resource destructor. mysqlnd_fetch_row_unbuffered() expects
|
||||
|
@ -1003,6 +1027,7 @@ MYSQLND_METHOD(mysqlnd_res, use_result)(MYSQLND_RES * const result, zend_bool ps
|
|||
*/
|
||||
/* FALSE = non-persistent */
|
||||
PACKET_INIT(result->row_packet, PROT_ROW_PACKET, php_mysql_packet_row *, FALSE);
|
||||
result->row_packet->result_set_memory_pool = result->result_set_memory_pool;
|
||||
result->row_packet->field_count = result->field_count;
|
||||
result->row_packet->binary_protocol = ps;
|
||||
result->row_packet->fields_metadata = result->meta->fields;
|
||||
|
@ -1039,7 +1064,11 @@ mysqlnd_fetch_row_buffered_c(MYSQLND_RES *result TSRMLS_DC)
|
|||
current_row,
|
||||
result->meta->field_count,
|
||||
result->meta->fields,
|
||||
result->conn TSRMLS_CC);
|
||||
FALSE,
|
||||
result->conn->options.numeric_and_datetime_as_unicode,
|
||||
result->conn->options.int_and_float_native,
|
||||
result->conn->zval_cache,
|
||||
&result->conn->stats TSRMLS_CC);
|
||||
for (i = 0; i < result->field_count; i++) {
|
||||
/*
|
||||
NULL fields are 0 length, 0 is not more than 0
|
||||
|
@ -1105,7 +1134,11 @@ mysqlnd_fetch_row_buffered(MYSQLND_RES *result, void *param, unsigned int flags,
|
|||
current_row,
|
||||
result->meta->field_count,
|
||||
result->meta->fields,
|
||||
result->conn TSRMLS_CC);
|
||||
result->stored_data->persistent,
|
||||
result->conn->options.numeric_and_datetime_as_unicode,
|
||||
result->conn->options.int_and_float_native,
|
||||
result->conn->zval_cache,
|
||||
&result->conn->stats TSRMLS_CC);
|
||||
for (i = 0; i < result->field_count; i++) {
|
||||
/*
|
||||
NULL fields are 0 length, 0 is not more than 0
|
||||
|
@ -1174,19 +1207,19 @@ mysqlnd_fetch_row_buffered(MYSQLND_RES *result, void *param, unsigned int flags,
|
|||
|
||||
#define STORE_RESULT_PREALLOCATED_SET_IF_NOT_EMPTY 2
|
||||
|
||||
/* {{{ mysqlnd_store_result_fetch_data */
|
||||
/* {{{ mysqlnd_res::store_result_fetch_data */
|
||||
enum_func_status
|
||||
mysqlnd_store_result_fetch_data(MYSQLND * const conn, MYSQLND_RES *result,
|
||||
MYSQLND_RES_METADATA *meta,
|
||||
zend_bool binary_protocol,
|
||||
zend_bool to_cache TSRMLS_DC)
|
||||
MYSQLND_METHOD(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)
|
||||
{
|
||||
enum_func_status ret;
|
||||
php_mysql_packet_row *row_packet;
|
||||
unsigned int next_extend = STORE_RESULT_PREALLOCATED_SET_IF_NOT_EMPTY, free_rows = 1;
|
||||
MYSQLND_RES_BUFFERED *set;
|
||||
|
||||
DBG_ENTER("mysqlnd_store_result_fetch_data");
|
||||
DBG_ENTER("mysqlnd_res::store_result_fetch_data");
|
||||
DBG_INF_FMT("conn=%llu binary_proto=%d to_cache=%d",
|
||||
conn->thread_id, binary_protocol, to_cache);
|
||||
|
||||
|
@ -1203,6 +1236,7 @@ mysqlnd_store_result_fetch_data(MYSQLND * const conn, MYSQLND_RES *result,
|
|||
|
||||
/* non-persistent */
|
||||
PACKET_INIT(row_packet, PROT_ROW_PACKET, php_mysql_packet_row *, FALSE);
|
||||
row_packet->result_set_memory_pool = result->result_set_memory_pool;
|
||||
row_packet->field_count = meta->field_count;
|
||||
row_packet->binary_protocol = binary_protocol;
|
||||
row_packet->fields_metadata = meta->fields;
|
||||
|
@ -1303,10 +1337,10 @@ MYSQLND_METHOD(mysqlnd_res, store_result)(MYSQLND_RES * result,
|
|||
|
||||
CONN_SET_STATE(conn, CONN_FETCHING_DATA);
|
||||
|
||||
result->result_set_memory_pool = mysqlnd_mempool_create(16000 TSRMLS_CC);
|
||||
result->lengths = mnd_ecalloc(result->field_count, sizeof(unsigned long));
|
||||
|
||||
ret = mysqlnd_store_result_fetch_data(conn, result, result->meta,
|
||||
ps_protocol, to_cache TSRMLS_CC);
|
||||
ret = result->m.store_result_fetch_data(conn, result, result->meta, ps_protocol, to_cache TSRMLS_CC);
|
||||
if (PASS == ret) {
|
||||
/* libmysql's documentation says it should be so for SELECT statements */
|
||||
conn->upsert_status.affected_rows = result->stored_data->row_count;
|
||||
|
@ -1369,7 +1403,10 @@ mysqlnd_fetch_row_async_buffered(MYSQLND_RES *result, void *param, unsigned int
|
|||
current_row,
|
||||
result->meta->field_count,
|
||||
result->meta->fields,
|
||||
result->conn TSRMLS_CC);
|
||||
result->conn->options.numeric_and_datetime_as_unicode,
|
||||
result->conn->options.int_and_float_native,
|
||||
result->conn->zval_cache,
|
||||
&result->conn->stats TSRMLS_CC);
|
||||
|
||||
for (i = 0; i < result->field_count; i++) {
|
||||
/*
|
||||
|
@ -1463,6 +1500,7 @@ mysqlnd_background_store_result_fetch_data(MYSQLND_RES *result TSRMLS_DC)
|
|||
|
||||
/* persistent */
|
||||
PACKET_INIT(row_packet, PROT_ROW_PACKET, php_mysql_packet_row *, TRUE);
|
||||
row_packet->result_set_memory_pool = result->result_set_memory_pool;
|
||||
row_packet->field_count = result->meta->field_count;
|
||||
row_packet->binary_protocol = result->m.row_decoder == php_mysqlnd_rowp_read_binary_protocol;
|
||||
row_packet->fields_metadata = result->meta->fields;
|
||||
|
@ -1496,7 +1534,10 @@ mysqlnd_background_store_result_fetch_data(MYSQLND_RES *result TSRMLS_DC)
|
|||
set->data[set->row_count],
|
||||
result->meta->field_count,
|
||||
result->meta->fields,
|
||||
result->conn TSRMLS_CC);
|
||||
result->conn->options.numeric_and_datetime_as_unicode,
|
||||
result->conn->options.int_and_float_native,
|
||||
result->conn->zval_cache,
|
||||
&result->conn->stats TSRMLS_CC);
|
||||
|
||||
for (i = 0; i < result->field_count; i++) {
|
||||
/*
|
||||
|
@ -1748,7 +1789,7 @@ MYSQLND_METHOD(mysqlnd_res, fetch_field)(MYSQLND_RES * const result TSRMLS_DC)
|
|||
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 */
|
||||
mysqlnd_res_initialize_result_set_rest(result TSRMLS_CC);
|
||||
result->m.initialize_result_set_rest(result TSRMLS_CC);
|
||||
}
|
||||
DBG_RETURN(result->meta->m->fetch_field(result->meta TSRMLS_CC));
|
||||
}
|
||||
|
@ -1777,7 +1818,7 @@ MYSQLND_METHOD(mysqlnd_res, fetch_field_direct)(MYSQLND_RES * const result,
|
|||
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 */
|
||||
mysqlnd_res_initialize_result_set_rest(result TSRMLS_CC);
|
||||
result->m.initialize_result_set_rest(result TSRMLS_CC);
|
||||
}
|
||||
DBG_RETURN(result->meta->m->fetch_field_direct(result->meta, fieldnr TSRMLS_CC));
|
||||
}
|
||||
|
@ -1795,7 +1836,7 @@ MYSQLND_METHOD(mysqlnd_res, fetch_fields)(MYSQLND_RES * const result TSRMLS_DC)
|
|||
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 */
|
||||
mysqlnd_res_initialize_result_set_rest(result TSRMLS_CC);
|
||||
result->m.initialize_result_set_rest(result TSRMLS_CC);
|
||||
}
|
||||
DBG_RETURN(result->meta->m->fetch_fields(result->meta TSRMLS_CC));
|
||||
}
|
||||
|
@ -1978,7 +2019,8 @@ MYSQLND_METHOD(mysqlnd_res, fetch_field_data)(MYSQLND_RES *result, unsigned int
|
|||
/* {{{ mysqlnd_result_init */
|
||||
MYSQLND_RES *mysqlnd_result_init(unsigned int field_count, MYSQLND_THD_ZVAL_PCACHE *cache TSRMLS_DC)
|
||||
{
|
||||
MYSQLND_RES *ret = mnd_ecalloc(1, sizeof(MYSQLND_RES));
|
||||
size_t alloc_size = sizeof(MYSQLND_RES) + mysqlnd_plugin_count() * sizeof(void *);
|
||||
MYSQLND_RES *ret = mnd_ecalloc(1, alloc_size);
|
||||
|
||||
DBG_ENTER("mysqlnd_result_init");
|
||||
DBG_INF_FMT("field_count=%u cache=%p", field_count, cache);
|
||||
|
@ -2007,8 +2049,13 @@ MYSQLND_RES *mysqlnd_result_init(unsigned int field_count, MYSQLND_THD_ZVAL_PCAC
|
|||
ret->m.free_result_buffers = MYSQLND_METHOD(mysqlnd_res, free_result_buffers);
|
||||
ret->m.free_result_internal = mysqlnd_internal_free_result;
|
||||
ret->m.free_result_contents = mysqlnd_internal_free_result_contents;
|
||||
ret->m.free_buffered_data = MYSQLND_METHOD(mysqlnd_res, free_buffered_data);
|
||||
ret->m.unbuffered_free_last_data = MYSQLND_METHOD(mysqlnd_res, unbuffered_free_last_data);
|
||||
|
||||
ret->m.read_result_metadata = MYSQLND_METHOD(mysqlnd_res, read_result_metadata);
|
||||
ret->m.store_result_fetch_data = MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data);
|
||||
ret->m.initialize_result_set_rest = MYSQLND_METHOD(mysqlnd_res, initialize_result_set_rest);
|
||||
|
||||
ret->m.fetch_row_normal_buffered = mysqlnd_fetch_row_buffered;
|
||||
ret->m.fetch_row_normal_unbuffered = mysqlnd_fetch_row_unbuffered;
|
||||
ret->m.row_decoder = NULL;
|
||||
|
@ -2017,6 +2064,19 @@ MYSQLND_RES *mysqlnd_result_init(unsigned int field_count, MYSQLND_THD_ZVAL_PCAC
|
|||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ _mysqlnd_plugin_get_plugin_result_data */
|
||||
PHPAPI void ** _mysqlnd_plugin_get_plugin_result_data(const MYSQLND_RES * result, unsigned int plugin_id TSRMLS_DC)
|
||||
{
|
||||
DBG_ENTER("_mysqlnd_plugin_get_plugin_result_data");
|
||||
DBG_INF_FMT("plugin_id=%u", plugin_id);
|
||||
if (!result || plugin_id >= mysqlnd_plugin_count()) {
|
||||
return NULL;
|
||||
}
|
||||
DBG_RETURN((void *)result + sizeof(MYSQLND_RES) + plugin_id * sizeof(void *));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
|
|
|
@ -25,19 +25,8 @@
|
|||
|
||||
MYSQLND_RES *mysqlnd_result_init(unsigned int field_count, MYSQLND_THD_ZVAL_PCACHE *cache TSRMLS_DC);
|
||||
|
||||
void mysqlnd_unbuffered_free_last_data(MYSQLND_RES *result TSRMLS_DC);
|
||||
|
||||
enum_func_status
|
||||
mysqlnd_store_result_fetch_data(MYSQLND * const conn, MYSQLND_RES *result,
|
||||
MYSQLND_RES_METADATA *meta,
|
||||
zend_bool binary_protocol,
|
||||
zend_bool to_cache TSRMLS_DC);
|
||||
|
||||
enum_func_status mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT *stmt TSRMLS_DC);
|
||||
|
||||
void mysqlnd_res_initialize_result_set_rest(MYSQLND_RES * const result TSRMLS_DC);
|
||||
|
||||
|
||||
#ifdef MYSQLND_THREADED
|
||||
void * mysqlnd_fetch_thread(void *arg);
|
||||
#endif
|
||||
|
|
|
@ -48,7 +48,7 @@ struct st_mysqlnd_memory_pool_chunk
|
|||
uint64_t app;
|
||||
MYSQLND_MEMORY_POOL *pool;
|
||||
zend_uchar *ptr;
|
||||
unsigned int size;
|
||||
unsigned int size;
|
||||
void (*resize_chunk)(MYSQLND_MEMORY_POOL_CHUNK * chunk, unsigned int size TSRMLS_DC);
|
||||
void (*free_chunk)(MYSQLND_MEMORY_POOL_CHUNK * chunk, zend_bool cache_it TSRMLS_DC);
|
||||
zend_bool from_pool;
|
||||
|
@ -217,23 +217,44 @@ typedef struct st_mysqlnd_stats
|
|||
} MYSQLND_STATS;
|
||||
|
||||
|
||||
typedef struct st_mysqlnd_read_buffer {
|
||||
zend_uchar * data;
|
||||
size_t offset;
|
||||
size_t size;
|
||||
size_t len;
|
||||
zend_bool (*is_empty)(struct st_mysqlnd_read_buffer *);
|
||||
void (*read)(struct st_mysqlnd_read_buffer *, size_t count, zend_uchar * dest);
|
||||
size_t (*bytes_left)(struct st_mysqlnd_read_buffer *);
|
||||
void (*free)(struct st_mysqlnd_read_buffer ** TSRMLS_DC);
|
||||
} MYSQLND_READ_BUFFER;
|
||||
|
||||
|
||||
typedef struct st_mysqlnd_net
|
||||
{
|
||||
php_stream *stream;
|
||||
php_stream *stream;
|
||||
enum_func_status (*stream_read)(MYSQLND * conn, zend_uchar * buffer, size_t count TSRMLS_DC);
|
||||
size_t (*stream_write)(MYSQLND * const conn, const zend_uchar * const buf, size_t count TSRMLS_DC);
|
||||
|
||||
/* sequence for simple checking of correct packets */
|
||||
zend_uchar packet_no;
|
||||
|
||||
#ifdef MYSQLND_DO_WIRE_CHECK_BEFORE_COMMAND
|
||||
zend_uchar last_command;
|
||||
zend_uchar packet_no;
|
||||
zend_bool compressed;
|
||||
zend_uchar compressed_envelope_packet_no;
|
||||
#ifdef MYSQLND_COMPRESSION_ENABLED
|
||||
MYSQLND_READ_BUFFER * uncompressed_data;
|
||||
#endif
|
||||
#ifdef MYSQLND_DO_WIRE_CHECK_BEFORE_COMMAND
|
||||
zend_uchar last_command;
|
||||
#endif
|
||||
|
||||
/* cmd buffer */
|
||||
MYSQLND_CMD_BUFFER cmd_buffer;
|
||||
} MYSQLND_NET;
|
||||
|
||||
|
||||
|
||||
|
||||
struct st_mysqlnd_conn_methods
|
||||
{
|
||||
enum_func_status (*connect)(MYSQLND *conn, const char *host, const char * user, const char * passwd, unsigned int passwd_len, const char * db, unsigned int db_len, unsigned int port, const char * socket, unsigned int mysql_flags, MYSQLND_THD_ZVAL_PCACHE * zval_cache TSRMLS_DC);
|
||||
ulong (*escape_string)(const MYSQLND * const conn, char *newstr, const char *escapestr, size_t escapestr_len TSRMLS_DC);
|
||||
enum_func_status (*set_charset)(MYSQLND * const conn, const char * const charset TSRMLS_DC);
|
||||
enum_func_status (*query)(MYSQLND *conn, const char *query, unsigned int query_len TSRMLS_DC);
|
||||
|
@ -285,6 +306,8 @@ struct st_mysqlnd_conn_methods
|
|||
enum_func_status (*close)(MYSQLND *conn, enum_connection_close_type close_type TSRMLS_DC);
|
||||
void (*dtor)(MYSQLND *conn TSRMLS_DC); /* private */
|
||||
|
||||
enum_func_status (*query_read_result_set_header)(MYSQLND *conn, MYSQLND_STMT *stmt TSRMLS_DC);
|
||||
|
||||
MYSQLND * (*get_reference)(MYSQLND * const conn TSRMLS_DC);
|
||||
enum_func_status (*free_reference)(MYSQLND * const conn TSRMLS_DC);
|
||||
enum mysqlnd_connection_state (*get_state)(MYSQLND * const conn TSRMLS_DC);
|
||||
|
@ -317,13 +340,25 @@ struct st_mysqlnd_res_methods
|
|||
|
||||
enum_func_status (*read_result_metadata)(MYSQLND_RES *result, MYSQLND *conn TSRMLS_DC);
|
||||
unsigned long * (*fetch_lengths)(MYSQLND_RES * const result);
|
||||
enum_func_status (*store_result_fetch_data)(MYSQLND * const conn, MYSQLND_RES *result, MYSQLND_RES_METADATA *meta, zend_bool binary_protocol, zend_bool to_cache TSRMLS_DC);
|
||||
void (*initialize_result_set_rest)(MYSQLND_RES * const result TSRMLS_DC);
|
||||
|
||||
void (*free_result_buffers)(MYSQLND_RES * result TSRMLS_DC); /* private */
|
||||
enum_func_status (*free_result)(MYSQLND_RES * result, zend_bool implicit TSRMLS_DC);
|
||||
void (*free_result_internal)(MYSQLND_RES *result TSRMLS_DC);
|
||||
void (*free_result_contents)(MYSQLND_RES *result TSRMLS_DC);
|
||||
void (*free_result_internal)(MYSQLND_RES *result TSRMLS_DC);
|
||||
void (*free_result_contents)(MYSQLND_RES *result TSRMLS_DC);
|
||||
void (*free_buffered_data)(MYSQLND_RES *result TSRMLS_DC);
|
||||
void (*unbuffered_free_last_data)(MYSQLND_RES *result TSRMLS_DC);
|
||||
|
||||
/* for decoding - binary or text protocol */
|
||||
void (*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,
|
||||
MYSQLND_THD_ZVAL_PCACHE * zval_cache,
|
||||
MYSQLND_STATS * stats TSRMLS_DC);
|
||||
|
||||
|
||||
/* for decoding - binary or text protocol */
|
||||
void (*row_decoder)(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval ** fields, unsigned int field_count, MYSQLND_FIELD *fields_metadata, MYSQLND *conn TSRMLS_DC);
|
||||
};
|
||||
|
||||
|
||||
|
@ -445,7 +480,7 @@ struct st_mysqlnd_connection
|
|||
|
||||
/* Temporal storage for mysql_query */
|
||||
unsigned int field_count;
|
||||
|
||||
|
||||
/* persistent connection */
|
||||
zend_bool persistent;
|
||||
|
||||
|
@ -458,8 +493,6 @@ struct st_mysqlnd_connection
|
|||
/* qcache */
|
||||
MYSQLND_QCACHE *qcache;
|
||||
|
||||
MYSQLND_MEMORY_POOL * result_set_memory_pool;
|
||||
|
||||
/* stats */
|
||||
MYSQLND_STATS stats;
|
||||
|
||||
|
@ -490,7 +523,7 @@ struct mysqlnd_field_hash_key
|
|||
#if PHP_MAJOR_VERSION >= 6
|
||||
zstr ustr;
|
||||
unsigned int ulen;
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
@ -578,7 +611,7 @@ struct st_mysqlnd_res
|
|||
|
||||
/*
|
||||
Column lengths of current row - both buffered and unbuffered.
|
||||
For buffered results it duplicates the data found in **data
|
||||
For buffered results it duplicates the data found in **data
|
||||
*/
|
||||
unsigned long *lengths;
|
||||
|
||||
|
@ -586,6 +619,8 @@ struct st_mysqlnd_res
|
|||
|
||||
/* zval cache */
|
||||
MYSQLND_THD_ZVAL_PCACHE *zval_cache;
|
||||
|
||||
MYSQLND_MEMORY_POOL * result_set_memory_pool;
|
||||
};
|
||||
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -24,6 +24,7 @@
|
|||
#define MYSQLND_WIREPROTOCOL_H
|
||||
|
||||
#define MYSQLND_HEADER_SIZE 4
|
||||
#define COMPRESSED_HEADER_SIZE 3
|
||||
|
||||
#define MYSQLND_NULL_LENGTH (unsigned long) ~0
|
||||
|
||||
|
@ -261,6 +262,7 @@ struct st_php_mysql_packet_row {
|
|||
uint16_t server_status;
|
||||
|
||||
struct st_mysqlnd_memory_pool_chunk *row_buffer;
|
||||
MYSQLND_MEMORY_POOL * result_set_memory_pool;
|
||||
|
||||
zend_bool skip_extraction;
|
||||
zend_bool binary_protocol;
|
||||
|
@ -303,7 +305,7 @@ typedef struct st_php_mysql_packet_prepare_response {
|
|||
typedef struct st_php_mysql_packet_chg_user_resp {
|
||||
mysqlnd_packet_header header;
|
||||
uint32_t field_count;
|
||||
|
||||
|
||||
/* message_len is not part of the packet*/
|
||||
uint16_t server_capabilities;
|
||||
/* If error packet, we use these */
|
||||
|
@ -311,8 +313,8 @@ typedef struct st_php_mysql_packet_chg_user_resp {
|
|||
} php_mysql_packet_chg_user_resp;
|
||||
|
||||
|
||||
size_t mysqlnd_stream_write(MYSQLND * const conn, char * const buf, size_t count TSRMLS_DC);
|
||||
size_t mysqlnd_stream_write_w_header(MYSQLND * const conn, char * const buf, size_t count TSRMLS_DC);
|
||||
size_t mysqlnd_stream_write(MYSQLND * const conn, const zend_uchar * const buf, size_t count TSRMLS_DC);
|
||||
|
||||
#ifdef MYSQLND_DO_WIRE_CHECK_BEFORE_COMMAND
|
||||
size_t php_mysqlnd_consume_uneaten_data(MYSQLND * const conn, enum php_mysqlnd_server_command cmd TSRMLS_DC);
|
||||
|
@ -327,10 +329,22 @@ extern char * const mysqlnd_empty_string;
|
|||
|
||||
|
||||
void php_mysqlnd_rowp_read_binary_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval ** fields,
|
||||
unsigned int field_count, MYSQLND_FIELD *fields_metadata, MYSQLND *conn TSRMLS_DC);
|
||||
unsigned int field_count, MYSQLND_FIELD *fields_metadata,
|
||||
zend_bool persistent,
|
||||
zend_bool as_unicode, zend_bool as_int_or_float,
|
||||
MYSQLND_THD_ZVAL_PCACHE * zval_cache,
|
||||
MYSQLND_STATS * stats TSRMLS_DC);
|
||||
|
||||
|
||||
void php_mysqlnd_rowp_read_text_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval ** fields,
|
||||
unsigned int field_count, MYSQLND_FIELD *fields_metadata, MYSQLND *conn TSRMLS_DC);
|
||||
unsigned int field_count, MYSQLND_FIELD *fields_metadata,
|
||||
zend_bool persistent,
|
||||
zend_bool as_unicode, zend_bool as_int_or_float,
|
||||
MYSQLND_THD_ZVAL_PCACHE * zval_cache,
|
||||
MYSQLND_STATS * stats TSRMLS_DC);
|
||||
|
||||
enum_func_status mysqlnd_read_from_stream(MYSQLND * conn, zend_uchar * buffer, size_t count TSRMLS_DC);
|
||||
|
||||
|
||||
#endif /* MYSQLND_WIREPROTOCOL_H */
|
||||
|
||||
|
|
|
@ -102,6 +102,12 @@ PHP_MINFO_FUNCTION(mysqlnd)
|
|||
php_info_print_table_start();
|
||||
php_info_print_table_header(2, "mysqlnd", "enabled");
|
||||
php_info_print_table_row(2, "Version", mysqlnd_get_client_info());
|
||||
php_info_print_table_row(2, "Compression",
|
||||
#ifdef MYSQLND_COMPRESSION_ENABLED
|
||||
"supported");
|
||||
#else
|
||||
"not supported");
|
||||
#endif
|
||||
snprintf(buf, sizeof(buf), "%ld", MYSQLND_G(net_cmd_buffer_size));
|
||||
php_info_print_table_row(2, "Command buffer size", buf);
|
||||
snprintf(buf, sizeof(buf), "%ld", MYSQLND_G(net_read_buffer_size));
|
||||
|
@ -234,10 +240,18 @@ static PHP_RSHUTDOWN_FUNCTION(mysqlnd)
|
|||
#endif
|
||||
|
||||
|
||||
|
||||
static const zend_module_dep mysqlnd_deps[] = {
|
||||
ZEND_MOD_REQUIRED("standard")
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
/* {{{ mysqlnd_module_entry
|
||||
*/
|
||||
zend_module_entry mysqlnd_module_entry = {
|
||||
STANDARD_MODULE_HEADER,
|
||||
STANDARD_MODULE_HEADER_EX,
|
||||
NULL,
|
||||
mysqlnd_deps,
|
||||
"mysqlnd",
|
||||
mysqlnd_functions,
|
||||
PHP_MINIT(mysqlnd),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue