mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00

This is a larger overhaul of the mysqlnd result set infrastructure: * Drop support for two different types of buffered results sets ("c" and "zval"). Possibly these made sense at some earlier time, but now (with minor adjustments) one option is strictly worse than the other. Buffered result sets already buffer the full row packets, from which zvals can be decoded. The "zval" style additionally also buffered the decoded zvals. As result sets, even buffered ones, are generally only traversed once, this just ends up wasting memory. Now, a potentially useful variation here would be to buffer the decoded zvals instead of the row packets, but that's not what the code was doing. * To make it really strictly better, pre-allocate the zval row buffer and reuse it for all rows. Previously the "c" style always allocated a new buffer for each row. * The fetch_row API now provides a populated zval[]. The task of populating an array is deferred to fetch_row_into, which also avoids duplicating this code in multiple places. The fetch_row_c API is also implemented on top of fetch_row now, rather than duplicating large parts of the code. * The row fetching code for prepared statements and normal result sets has been mostly merged. These already used the same infrastructure, but prepared statements used separate row fetching functions that were nearly the same as the normal ones. This requires passing the stmt into the result set, rather than just a flag. The only part that remains separate is reading of unbuffered results in the presence of PS cursors.
309 lines
9.6 KiB
C
309 lines
9.6 KiB
C
/*
|
|
+----------------------------------------------------------------------+
|
|
| Copyright (c) The PHP Group |
|
|
+----------------------------------------------------------------------+
|
|
| This source file is subject to version 3.01 of the PHP license, |
|
|
| that is bundled with this package in the file LICENSE, and is |
|
|
| available through the world-wide-web at the following url: |
|
|
| http://www.php.net/license/3_01.txt |
|
|
| If you did not receive a copy of the PHP license and are unable to |
|
|
| obtain it through the world-wide-web, please send a note to |
|
|
| license@php.net so we can mail you a copy immediately. |
|
|
+----------------------------------------------------------------------+
|
|
| Authors: Andrey Hristov <andrey@php.net> |
|
|
| Ulf Wendel <uw@php.net> |
|
|
+----------------------------------------------------------------------+
|
|
*/
|
|
|
|
#include "php.h"
|
|
#include "mysqlnd.h"
|
|
#include "mysqlnd_priv.h"
|
|
#include "mysqlnd_debug.h"
|
|
#include "mysqlnd_statistics.h"
|
|
#include "mysqlnd_reverse_api.h"
|
|
#include "ext/standard/info.h"
|
|
#include "zend_smart_str.h"
|
|
|
|
/* {{{ mysqlnd_minfo_print_hash */
|
|
PHPAPI void
|
|
mysqlnd_minfo_print_hash(zval *values)
|
|
{
|
|
zval *values_entry;
|
|
zend_string *string_key;
|
|
|
|
ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(values), string_key, values_entry) {
|
|
convert_to_string(values_entry);
|
|
php_info_print_table_row(2, ZSTR_VAL(string_key), Z_STRVAL_P(values_entry));
|
|
} ZEND_HASH_FOREACH_END();
|
|
}
|
|
/* }}} */
|
|
|
|
|
|
/* {{{ mysqlnd_minfo_dump_loaded_plugins */
|
|
static int
|
|
mysqlnd_minfo_dump_loaded_plugins(zval *el, void * buf)
|
|
{
|
|
smart_str * buffer = (smart_str *) buf;
|
|
struct st_mysqlnd_plugin_header * plugin_header = (struct st_mysqlnd_plugin_header *)Z_PTR_P(el);
|
|
if (plugin_header->plugin_name) {
|
|
if (buffer->s) {
|
|
smart_str_appendc(buffer, ',');
|
|
}
|
|
smart_str_appends(buffer, plugin_header->plugin_name);
|
|
}
|
|
return ZEND_HASH_APPLY_KEEP;
|
|
}
|
|
/* }}} */
|
|
|
|
|
|
/* {{{ mysqlnd_minfo_dump_api_plugins */
|
|
static void
|
|
mysqlnd_minfo_dump_api_plugins(smart_str * buffer)
|
|
{
|
|
HashTable *ht = mysqlnd_reverse_api_get_api_list();
|
|
MYSQLND_REVERSE_API *ext;
|
|
|
|
ZEND_HASH_FOREACH_PTR(ht, ext) {
|
|
if (buffer->s) {
|
|
smart_str_appendc(buffer, ',');
|
|
}
|
|
smart_str_appends(buffer, ext->module->name);
|
|
} ZEND_HASH_FOREACH_END();
|
|
}
|
|
/* }}} */
|
|
|
|
|
|
/* {{{ PHP_MINFO_FUNCTION */
|
|
PHP_MINFO_FUNCTION(mysqlnd)
|
|
{
|
|
char buf[32];
|
|
|
|
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
|
|
php_info_print_table_row(2, "core SSL",
|
|
#ifdef MYSQLND_SSL_SUPPORTED
|
|
"supported");
|
|
#else
|
|
"not supported");
|
|
#endif
|
|
php_info_print_table_row(2, "extended SSL",
|
|
#ifdef MYSQLND_HAVE_SSL
|
|
"supported");
|
|
#else
|
|
"not supported");
|
|
#endif
|
|
snprintf(buf, sizeof(buf), ZEND_LONG_FMT, MYSQLND_G(net_cmd_buffer_size));
|
|
php_info_print_table_row(2, "Command buffer size", buf);
|
|
snprintf(buf, sizeof(buf), ZEND_LONG_FMT, MYSQLND_G(net_read_buffer_size));
|
|
php_info_print_table_row(2, "Read buffer size", buf);
|
|
snprintf(buf, sizeof(buf), ZEND_LONG_FMT, MYSQLND_G(net_read_timeout));
|
|
php_info_print_table_row(2, "Read timeout", buf);
|
|
php_info_print_table_row(2, "Collecting statistics", MYSQLND_G(collect_statistics)? "Yes":"No");
|
|
php_info_print_table_row(2, "Collecting memory statistics", MYSQLND_G(collect_memory_statistics)? "Yes":"No");
|
|
|
|
php_info_print_table_row(2, "Tracing", MYSQLND_G(debug)? MYSQLND_G(debug):"n/a");
|
|
|
|
/* loaded plugins */
|
|
{
|
|
smart_str tmp_str = {0};
|
|
mysqlnd_plugin_apply_with_argument(mysqlnd_minfo_dump_loaded_plugins, &tmp_str);
|
|
smart_str_0(&tmp_str);
|
|
php_info_print_table_row(2, "Loaded plugins", tmp_str.s? ZSTR_VAL(tmp_str.s) : "");
|
|
smart_str_free(&tmp_str);
|
|
|
|
mysqlnd_minfo_dump_api_plugins(&tmp_str);
|
|
smart_str_0(&tmp_str);
|
|
php_info_print_table_row(2, "API Extensions", tmp_str.s? ZSTR_VAL(tmp_str.s) : "");
|
|
smart_str_free(&tmp_str);
|
|
}
|
|
|
|
php_info_print_table_end();
|
|
}
|
|
/* }}} */
|
|
|
|
|
|
PHPAPI ZEND_DECLARE_MODULE_GLOBALS(mysqlnd)
|
|
|
|
|
|
/* {{{ PHP_GINIT_FUNCTION */
|
|
static PHP_GINIT_FUNCTION(mysqlnd)
|
|
{
|
|
#if defined(COMPILE_DL_MYSQLND) && defined(ZTS)
|
|
ZEND_TSRMLS_CACHE_UPDATE();
|
|
#endif
|
|
mysqlnd_globals->collect_statistics = TRUE;
|
|
mysqlnd_globals->collect_memory_statistics = FALSE;
|
|
mysqlnd_globals->debug = NULL; /* The actual string */
|
|
mysqlnd_globals->dbg = NULL; /* The DBG object*/
|
|
mysqlnd_globals->trace_alloc_settings = NULL;
|
|
mysqlnd_globals->trace_alloc = NULL;
|
|
mysqlnd_globals->net_cmd_buffer_size = MYSQLND_NET_CMD_BUFFER_MIN_SIZE;
|
|
mysqlnd_globals->net_read_buffer_size = 32768;
|
|
mysqlnd_globals->net_read_timeout = 31536000;
|
|
mysqlnd_globals->log_mask = 0;
|
|
mysqlnd_globals->mempool_default_size = 16000;
|
|
mysqlnd_globals->debug_malloc_fail_threshold = -1;
|
|
mysqlnd_globals->debug_calloc_fail_threshold = -1;
|
|
mysqlnd_globals->debug_realloc_fail_threshold = -1;
|
|
mysqlnd_globals->sha256_server_public_key = NULL;
|
|
}
|
|
/* }}} */
|
|
|
|
|
|
/* {{{ PHP_INI_MH */
|
|
static PHP_INI_MH(OnUpdateNetCmdBufferSize)
|
|
{
|
|
zend_long long_value;
|
|
|
|
ZEND_ATOL(long_value, ZSTR_VAL(new_value));
|
|
if (long_value < MYSQLND_NET_CMD_BUFFER_MIN_SIZE) {
|
|
return FAILURE;
|
|
}
|
|
MYSQLND_G(net_cmd_buffer_size) = long_value;
|
|
|
|
return SUCCESS;
|
|
}
|
|
/* }}} */
|
|
|
|
|
|
/* {{{ PHP_INI_BEGIN */
|
|
PHP_INI_BEGIN()
|
|
STD_PHP_INI_BOOLEAN("mysqlnd.collect_statistics", "1", PHP_INI_ALL, OnUpdateBool, collect_statistics, zend_mysqlnd_globals, mysqlnd_globals)
|
|
STD_PHP_INI_BOOLEAN("mysqlnd.collect_memory_statistics","0",PHP_INI_SYSTEM, OnUpdateBool, collect_memory_statistics, zend_mysqlnd_globals, mysqlnd_globals)
|
|
STD_PHP_INI_ENTRY("mysqlnd.debug", NULL, PHP_INI_SYSTEM, OnUpdateString, debug, zend_mysqlnd_globals, mysqlnd_globals)
|
|
STD_PHP_INI_ENTRY("mysqlnd.trace_alloc", NULL, PHP_INI_SYSTEM, OnUpdateString, trace_alloc_settings, zend_mysqlnd_globals, mysqlnd_globals)
|
|
STD_PHP_INI_ENTRY("mysqlnd.net_cmd_buffer_size", MYSQLND_NET_CMD_BUFFER_MIN_SIZE_STR, PHP_INI_ALL, OnUpdateNetCmdBufferSize, net_cmd_buffer_size, zend_mysqlnd_globals, mysqlnd_globals)
|
|
STD_PHP_INI_ENTRY("mysqlnd.net_read_buffer_size", "32768",PHP_INI_ALL, OnUpdateLong, net_read_buffer_size, zend_mysqlnd_globals, mysqlnd_globals)
|
|
STD_PHP_INI_ENTRY("mysqlnd.net_read_timeout", "86400",PHP_INI_ALL, OnUpdateLong, net_read_timeout, zend_mysqlnd_globals, mysqlnd_globals)
|
|
STD_PHP_INI_ENTRY("mysqlnd.log_mask", "0", PHP_INI_ALL, OnUpdateLong, log_mask, zend_mysqlnd_globals, mysqlnd_globals)
|
|
STD_PHP_INI_ENTRY("mysqlnd.mempool_default_size","16000", PHP_INI_ALL, OnUpdateLong, mempool_default_size, zend_mysqlnd_globals, mysqlnd_globals)
|
|
STD_PHP_INI_ENTRY("mysqlnd.sha256_server_public_key",NULL, PHP_INI_PERDIR, OnUpdateString, sha256_server_public_key, zend_mysqlnd_globals, mysqlnd_globals)
|
|
#if PHP_DEBUG
|
|
|
|
STD_PHP_INI_ENTRY("mysqlnd.debug_malloc_fail_threshold","-1", PHP_INI_SYSTEM, OnUpdateLong, debug_malloc_fail_threshold, zend_mysqlnd_globals, mysqlnd_globals)
|
|
STD_PHP_INI_ENTRY("mysqlnd.debug_calloc_fail_threshold","-1", PHP_INI_SYSTEM, OnUpdateLong, debug_calloc_fail_threshold, zend_mysqlnd_globals, mysqlnd_globals)
|
|
STD_PHP_INI_ENTRY("mysqlnd.debug_realloc_fail_threshold","-1", PHP_INI_SYSTEM, OnUpdateLong, debug_realloc_fail_threshold, zend_mysqlnd_globals, mysqlnd_globals)
|
|
#endif
|
|
PHP_INI_END()
|
|
/* }}} */
|
|
|
|
|
|
/* {{{ PHP_MINIT_FUNCTION */
|
|
static PHP_MINIT_FUNCTION(mysqlnd)
|
|
{
|
|
REGISTER_INI_ENTRIES();
|
|
|
|
mysqlnd_library_init();
|
|
return SUCCESS;
|
|
}
|
|
/* }}} */
|
|
|
|
|
|
/* {{{ PHP_MSHUTDOWN_FUNCTION */
|
|
static PHP_MSHUTDOWN_FUNCTION(mysqlnd)
|
|
{
|
|
mysqlnd_library_end();
|
|
|
|
UNREGISTER_INI_ENTRIES();
|
|
return SUCCESS;
|
|
}
|
|
/* }}} */
|
|
|
|
|
|
#if PHP_DEBUG
|
|
/* {{{ PHP_RINIT_FUNCTION */
|
|
static PHP_RINIT_FUNCTION(mysqlnd)
|
|
{
|
|
if (MYSQLND_G(debug)) {
|
|
struct st_mysqlnd_plugin_trace_log * trace_log_plugin = mysqlnd_plugin_find("debug_trace");
|
|
MYSQLND_G(dbg) = NULL;
|
|
if (trace_log_plugin) {
|
|
MYSQLND_DEBUG * dbg = trace_log_plugin->methods.trace_instance_init(mysqlnd_debug_std_no_trace_funcs);
|
|
MYSQLND_DEBUG * trace_alloc = trace_log_plugin->methods.trace_instance_init(NULL);
|
|
if (!dbg || !trace_alloc) {
|
|
return FAILURE;
|
|
}
|
|
dbg->m->set_mode(dbg, MYSQLND_G(debug));
|
|
trace_alloc->m->set_mode(trace_alloc, MYSQLND_G(trace_alloc_settings));
|
|
MYSQLND_G(dbg) = dbg;
|
|
MYSQLND_G(trace_alloc) = trace_alloc;
|
|
}
|
|
}
|
|
return SUCCESS;
|
|
}
|
|
/* }}} */
|
|
#endif
|
|
|
|
|
|
#if PHP_DEBUG
|
|
/* {{{ PHP_RSHUTDOWN_FUNCTION */
|
|
static PHP_RSHUTDOWN_FUNCTION(mysqlnd)
|
|
{
|
|
MYSQLND_DEBUG * dbg = MYSQLND_G(dbg);
|
|
MYSQLND_DEBUG * trace_alloc = MYSQLND_G(trace_alloc);
|
|
DBG_ENTER("RSHUTDOWN");
|
|
if (dbg) {
|
|
dbg->m->close(dbg);
|
|
dbg->m->free_handle(dbg);
|
|
MYSQLND_G(dbg) = NULL;
|
|
}
|
|
if (trace_alloc) {
|
|
trace_alloc->m->close(trace_alloc);
|
|
trace_alloc->m->free_handle(trace_alloc);
|
|
MYSQLND_G(trace_alloc) = NULL;
|
|
}
|
|
return SUCCESS;
|
|
}
|
|
/* }}} */
|
|
#endif
|
|
|
|
|
|
static const zend_module_dep mysqlnd_deps[] = {
|
|
ZEND_MOD_REQUIRED("standard")
|
|
ZEND_MOD_END
|
|
};
|
|
|
|
/* {{{ mysqlnd_module_entry */
|
|
zend_module_entry mysqlnd_module_entry = {
|
|
STANDARD_MODULE_HEADER_EX,
|
|
NULL,
|
|
mysqlnd_deps,
|
|
"mysqlnd",
|
|
NULL,
|
|
PHP_MINIT(mysqlnd),
|
|
PHP_MSHUTDOWN(mysqlnd),
|
|
#if PHP_DEBUG
|
|
PHP_RINIT(mysqlnd),
|
|
#else
|
|
NULL,
|
|
#endif
|
|
#if PHP_DEBUG
|
|
PHP_RSHUTDOWN(mysqlnd),
|
|
#else
|
|
NULL,
|
|
#endif
|
|
PHP_MINFO(mysqlnd),
|
|
PHP_MYSQLND_VERSION,
|
|
PHP_MODULE_GLOBALS(mysqlnd),
|
|
PHP_GINIT(mysqlnd),
|
|
NULL,
|
|
NULL,
|
|
STANDARD_MODULE_PROPERTIES_EX
|
|
};
|
|
/* }}} */
|
|
|
|
/* {{{ COMPILE_DL_MYSQLND */
|
|
#ifdef COMPILE_DL_MYSQLND
|
|
#ifdef ZTS
|
|
ZEND_TSRMLS_CACHE_DEFINE()
|
|
#endif
|
|
ZEND_GET_MODULE(mysqlnd)
|
|
#endif
|
|
/* }}} */
|