Update mysqlnd in HEAD

Updated ext/mysql and ext/mysqli in HEAD
This commit is contained in:
Andrey Hristov 2007-10-02 10:45:27 +00:00
parent f0e5df4544
commit 9ac92cfecb
35 changed files with 4154 additions and 1551 deletions

View File

@ -47,6 +47,7 @@ package.xml added to support installation using pear installer
<file role="src" name="mysql.mak"/>
<file role="src" name="php_mysql.c"/>
<file role="src" name="php_mysql.h"/>
<file role="src" name="mysql_mysqlnd.h"/>
<file role="test" name="tests/001.phpt"/>
<file role="test" name="tests/002.phpt"/>
<file role="test" name="tests/003.phpt"/>

View File

@ -1,6 +1,6 @@
/*
+----------------------------------------------------------------------+
| PHP Version 5 |
| PHP Version 6 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2007 The PHP Group |
+----------------------------------------------------------------------+
@ -132,7 +132,7 @@ static MYSQLND_QCACHE *mysql_mysqlnd_qcache;
/* {{{ mysql_functions[]
*/
const zend_function_entry mysql_functions[] = {
static const zend_function_entry mysql_functions[] = {
PHP_FE(mysql_connect, NULL)
PHP_FE(mysql_pconnect, NULL)
PHP_FE(mysql_close, NULL)
@ -469,8 +469,11 @@ PHP_MSHUTDOWN_FUNCTION(mysql)
#if MYSQL_VERSION_ID >= 40000
#ifdef PHP_WIN32
unsigned long client_ver = mysql_get_client_version();
/* Can't call mysql_server_end() multiple times prior to 5.0.42 on Windows */
if ((client_ver > 50042 && client_ver < 50100) || client_ver > 50122) {
/*
Can't call mysql_server_end() multiple times prior to 5.0.42 on Windows.
PHP bug#41350 MySQL bug#25621
*/
if ((client_ver >= 50042 && client_ver < 50100) || client_ver > 50122) {
mysql_server_end();
}
#else
@ -1764,6 +1767,9 @@ PHP_FUNCTION(mysql_escape_string)
/* Now we kind of realloc() by returning a zval pointing to a buffer with enough size */
RETVAL_UTF8_STRINGL(new_str, new_str_len, ZSTR_DUPLICATE);
efree(new_str);
if (MySG(trace_mode)){
php_error_docref("function.mysql-real-escape-string" TSRMLS_CC, E_WARNING, "This function is deprecated; use mysql_real_escape_string() instead.");
}
}
/* }}} */

View File

@ -72,15 +72,53 @@ typedef struct _mysqli_prop_handler {
static int le_pmysqli;
/* Destructor for Persistent Connections */
static int php_mysqli_persistent_on_rshut(zend_rsrc_list_entry *le TSRMLS_DC)
{
if (le->type == le_pmysqli) {
mysqli_plist_entry *plist = (mysqli_plist_entry *) le->ptr;
HashPosition pos;
MYSQL **mysql;
ulong idx;
dtor_func_t pDestructor = plist->used_links.pDestructor;
plist->used_links.pDestructor = NULL; /* Don't call pDestructor now */
zend_hash_internal_pointer_reset_ex(&plist->used_links, &pos);
while (SUCCESS == zend_hash_get_current_data_ex(&plist->used_links, (void **)&mysql, &pos)) {
zend_hash_get_current_key_ex(&plist->used_links, NULL, NULL, &idx, FALSE, &pos);
/* Make it free */
zend_hash_next_index_insert(&plist->free_links, mysql, sizeof(MYSQL *), NULL);
/* First move forward */
zend_hash_move_forward_ex(&plist->used_links, &pos);
/* The delete, because del will free memory, but we need it's ->nextItem */
zend_hash_index_del(&plist->used_links, idx);
}
/* restore pDestructor, which should be php_mysqli_dtor_p_elements() */
plist->used_links.pDestructor = pDestructor;
}
return ZEND_HASH_APPLY_KEEP;
}
/* Destructor for mysqli entries in free_links/used_links */
void php_mysqli_dtor_p_elements(void *data)
{
MYSQL **mysql = (MYSQL **) data;
TSRMLS_FETCH();
#if defined(HAVE_MYSQLND)
mysqlnd_end_psession(*mysql);
#endif
mysqli_close(*mysql, MYSQLI_CLOSE_IMPLICIT);
}
ZEND_RSRC_DTOR_FUNC(php_mysqli_dtor)
{
if (rsrc->ptr) {
MYSQL *mysql = (MYSQL *)rsrc->ptr;
#if defined(HAVE_MYSQLND)
mysqlnd_end_psession(mysql);
#endif
mysqli_close(mysql, MYSQLI_CLOSE_IMPLICIT);
mysqli_plist_entry *plist = (mysqli_plist_entry *) rsrc->ptr;
zend_hash_destroy(&plist->free_links);
zend_hash_destroy(&plist->used_links);
free(plist);
}
}
@ -162,6 +200,10 @@ void php_clear_stmt_bind(MY_STMT *stmt TSRMLS_DC)
/* {{{ php_clear_mysql */
void php_clear_mysql(MY_MYSQL *mysql) {
if (mysql->hash_key) {
efree(mysql->hash_key);
mysql->hash_key = NULL;
}
if (mysql->li_read) {
efree(Z_STRVAL_P(mysql->li_read));
FREE_ZVAL(mysql->li_read);
@ -508,6 +550,8 @@ ZEND_GET_MODULE(mysqli)
*/
PHP_INI_BEGIN()
STD_PHP_INI_ENTRY_EX("mysqli.max_links", "-1", PHP_INI_SYSTEM, OnUpdateLong, max_links, zend_mysqli_globals, mysqli_globals, display_link_numbers)
STD_PHP_INI_ENTRY_EX("mysqli.max_persistent", "-1", PHP_INI_SYSTEM, OnUpdateLong, max_persistent, zend_mysqli_globals, mysqli_globals, display_link_numbers)
STD_PHP_INI_BOOLEAN("mysqli.allow_persistent", "1", PHP_INI_SYSTEM, OnUpdateLong, allow_persistent, zend_mysqli_globals, mysqli_globals)
STD_PHP_INI_ENTRY("mysqli.default_host", NULL, PHP_INI_ALL, OnUpdateString, default_host, zend_mysqli_globals, mysqli_globals)
STD_PHP_INI_ENTRY("mysqli.default_user", NULL, PHP_INI_ALL, OnUpdateString, default_user, zend_mysqli_globals, mysqli_globals)
STD_PHP_INI_ENTRY("mysqli.default_pw", NULL, PHP_INI_ALL, OnUpdateString, default_pw, zend_mysqli_globals, mysqli_globals)
@ -527,7 +571,11 @@ PHP_INI_END()
static PHP_GINIT_FUNCTION(mysqli)
{
mysqli_globals->num_links = 0;
mysqli_globals->num_active_persistent = 0;
mysqli_globals->num_inactive_persistent = 0;
mysqli_globals->max_links = -1;
mysqli_globals->max_persistent = -1;
mysqli_globals->allow_persistent = 1;
mysqli_globals->default_port = 0;
mysqli_globals->default_host = NULL;
mysqli_globals->default_user = NULL;
@ -559,9 +607,11 @@ PHP_MINIT_FUNCTION(mysqli)
REGISTER_INI_ENTRIES();
#ifndef HAVE_MYSQLND
#if MYSQL_VERSION_ID >= 40000
if (mysql_server_init(0, NULL, NULL)) {
return FAILURE;
}
#endif
#else
mysqli_mysqlnd_zval_cache = mysqlnd_palloc_init_cache(MyG(cache_size));
mysqli_mysqlnd_qcache = mysqlnd_qcache_init_cache();
@ -631,6 +681,8 @@ PHP_MINIT_FUNCTION(mysqli)
REGISTER_LONG_CONSTANT("MYSQLI_INIT_COMMAND", MYSQL_INIT_COMMAND, CONST_CS | CONST_PERSISTENT);
#if defined(HAVE_MYSQLND)
REGISTER_LONG_CONSTANT("MYSQLI_OPT_NUMERIC_AND_DATETIME_AS_UNICODE", MYSQLND_OPT_NUMERIC_AND_DATETIME_AS_UNICODE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("MYSQLI_OPT_NET_CMD_BUFFER_SIZE", MYSQLND_OPT_NET_CMD_BUFFER_SIZE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("MYSQLI_OPT_NET_READ_BUFFER_SIZE", MYSQLND_OPT_NET_READ_BUFFER_SIZE, CONST_CS | CONST_PERSISTENT);
#endif
#ifdef MYSQLND_STRING_TO_INT_CONVERSION
REGISTER_LONG_CONSTANT("MYSQLI_OPT_INT_AND_YEAR_AS_INT", MYSQLND_OPT_INT_AND_YEAR_AS_INT, CONST_CS | CONST_PERSISTENT);
@ -746,15 +798,20 @@ PHP_MINIT_FUNCTION(mysqli)
PHP_MSHUTDOWN_FUNCTION(mysqli)
{
#ifndef HAVE_MYSQLND
#if MYSQL_VERSION_ID >= 40000
#ifdef PHP_WIN32
unsigned long client_ver = mysql_get_client_version;
/* Can't call mysql_server_end() multiple times prior to 5.0.42 on Windows */
if ((client_ver > 50042 && client_ver < 50100) || client_ver > 50122) {
unsigned long client_ver = mysql_get_client_version();
/*
Can't call mysql_server_end() multiple times prior to 5.0.42 on Windows.
PHP bug#41350 MySQL bug#25621
*/
if ((client_ver >= 50042 && client_ver < 50100) || client_ver > 50122) {
mysql_server_end();
}
#else
mysql_server_end();
#endif
#endif
#else
mysqlnd_palloc_free_cache(mysqli_mysqlnd_zval_cache);
mysqlnd_qcache_free_cache_reference(&mysqli_mysqlnd_qcache);
@ -776,7 +833,7 @@ PHP_MSHUTDOWN_FUNCTION(mysqli)
*/
PHP_RINIT_FUNCTION(mysqli)
{
#if !defined(HAVE_MYSQLND) && defined(ZTS)
#if !defined(HAVE_MYSQLND) && defined(ZTS) && MYSQL_VERSION_ID >= 40000
if (mysql_thread_init()) {
return FAILURE;
}
@ -795,7 +852,10 @@ PHP_RINIT_FUNCTION(mysqli)
*/
PHP_RSHUTDOWN_FUNCTION(mysqli)
{
#if !defined(HAVE_MYSQLND) && defined(ZTS)
/* check persistent connections, move used to free */
zend_hash_apply(&EG(persistent_list), (apply_func_t) php_mysqli_persistent_on_rshut TSRMLS_CC);
#if !defined(HAVE_MYSQLND) && defined(ZTS) && MYSQL_VERSION_ID >= 40000
mysql_thread_end();
#endif
if (MyG(error_msg)) {
@ -813,6 +873,10 @@ PHP_RSHUTDOWN_FUNCTION(mysqli)
*/
PHP_MINFO_FUNCTION(mysqli)
{
#if defined(HAVE_MYSQLND)
char buf[32];
#endif
php_info_print_table_start();
php_info_print_table_header(2, "MysqlI Support", "enabled");
php_info_print_table_row(2, "Client API library version", mysql_get_client_info());
@ -820,6 +884,12 @@ PHP_MINFO_FUNCTION(mysqli)
php_info_print_table_row(2, "Client API header version", MYSQL_SERVER_VERSION);
php_info_print_table_row(2, "MYSQLI_SOCKET", MYSQL_UNIX_ADDR);
#else
snprintf(buf, sizeof(buf), "%ld", MyG(num_active_persistent));
php_info_print_table_row(2, "Active Persistent Links", buf);
snprintf(buf, sizeof(buf), "%ld", MyG(num_inactive_persistent));
php_info_print_table_row(2, "Inactive Persistent Links", buf);
snprintf(buf, sizeof(buf), "%ld", MyG(num_links));
php_info_print_table_row(2, "Active Links", buf);
{
zval values;
@ -1151,6 +1221,9 @@ PHP_MYSQLI_API void php_mysqli_set_error(long mysql_errno, char *mysql_err TSRML
}
/* }}} */
#if !defined(HAVE_MYSQLND)
#define ALLOC_CALLBACK_ARGS(a, b, c)\
if (c) {\
a = (zval ***)safe_emalloc(c, sizeof(zval **), 0);\
@ -1171,27 +1244,23 @@ if (a) {\
#define LOCAL_INFILE_ERROR_MSG(source,dest)\
memset(source, 0, LOCAL_INFILE_ERROR_LEN);\
memcpy(source, dest, LOCAL_INFILE_ERROR_LEN-1);\
memcpy(source, dest, MIN(strlen(dest), LOCAL_INFILE_ERROR_LEN-1));\
php_error_docref(NULL TSRMLS_CC, E_WARNING, dest);
/* {{{ void php_set_local_infile_handler_default
*/
void php_set_local_infile_handler_default(MY_MYSQL *mysql) {
/* register internal callback functions */
#if !defined(HAVE_MYSQLND)
mysql_set_local_infile_handler(mysql->mysql, &php_local_infile_init, &php_local_infile_read,
&php_local_infile_end, &php_local_infile_error, (void *)mysql);
if (mysql->li_read) {
zval_ptr_dtor(&mysql->li_read);
mysql->li_read = NULL;
}
#else
mysqlnd_local_infile_default(mysql->mysql, TRUE);
#endif
}
/* }}} */
#if !defined(HAVE_MYSQLND)
/* {{{ php_local_infile_init
*/
int php_local_infile_init(void **ptr, const char *filename, void *userdata)
@ -1304,6 +1373,16 @@ int php_local_infile_read(void *ptr, char *buf, uint buf_len)
LOCAL_INFILE_ERROR_MSG(data->error_msg, "Can't execute load data local init callback function");
rc = -1;
}
/*
If the (ab)user has closed the file handle we should
not try to use it anymore or even close it
*/
if (!zend_rsrc_list_get_rsrc_type(Z_LVAL_P(fp) TSRMLS_CC)) {
LOCAL_INFILE_ERROR_MSG(data->error_msg, "File handle closed");
rc = -1;
/* Thus the end handler won't try to free already freed memory */
mysql->li_stream = NULL;
}
FREE_CALLBACK_ARGS(callback_args, 1, argc);
efree(fp);
@ -1343,8 +1422,9 @@ void php_local_infile_end(void *ptr)
}
return;
}
php_stream_close(mysql->li_stream);
if (mysql->li_stream) {
php_stream_close(mysql->li_stream);
}
free(data);
return;
}

View File

@ -28,6 +28,7 @@
#include "php.h"
#include "php_ini.h"
#include "php_globals.h"
#include "ext/standard/info.h"
#include "php_mysqli_structs.h"
@ -518,6 +519,11 @@ PHP_FUNCTION(mysqli_change_user)
RETURN_FALSE;
}
/* Change user resets the charset in the server, change it back */
if (UG(unicode)) {
mysql_set_character_set(mysql->mysql, "utf8");
}
RETURN_TRUE;
}
/* }}} */
@ -552,12 +558,31 @@ PHP_FUNCTION(mysqli_close)
MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link", MYSQLI_STATUS_INITIALIZED);
php_clear_mysql(mysql);
if (!mysql->persistent) {
mysqli_close(mysql->mysql, MYSQLI_CLOSE_EXPLICIT);
mysql->mysql = NULL;
} else {
zend_rsrc_list_entry *le;
if (zend_hash_find(&EG(persistent_list), mysql->hash_key, strlen(mysql->hash_key) + 1, (void **)&le) == SUCCESS) {
if (Z_TYPE_P(le) == php_le_pmysqli()) {
mysqli_plist_entry *plist = (mysqli_plist_entry *) le->ptr;
dtor_func_t pDestructor = plist->used_links.pDestructor;
plist->used_links.pDestructor = NULL; /* Don't call pDestructor now */
zend_hash_index_del(&plist->used_links, mysql->hash_index);
plist->used_links.pDestructor = pDestructor; /* Restore the destructor */
zend_hash_next_index_insert(&plist->free_links, &mysql->mysql, sizeof(MYSQL *), NULL);
MyG(num_links)--;
MyG(num_active_persistent)--;
MyG(num_inactive_persistent)++;
}
}
}
php_clear_mysql(mysql);
MYSQLI_CLEAR_RESOURCE(&mysql_link);
efree(mysql);
RETURN_TRUE;
@ -1365,6 +1390,7 @@ PHP_FUNCTION(mysqli_kill)
/* {{{ proto void mysqli_set_local_infile_default(object link) U
unsets user defined handler for load local infile command */
#if !defined(HAVE_MYSQLND)
PHP_FUNCTION(mysqli_set_local_infile_default)
{
MY_MYSQL *mysql;
@ -1376,15 +1402,10 @@ PHP_FUNCTION(mysqli_set_local_infile_default)
MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link", MYSQLI_STATUS_VALID);
#if !defined(HAVE_MYSQLND)
if (mysql->li_read) {
efree(Z_STRVAL_P(mysql->li_read));
zval_dtor(mysql->li_read);
mysql->li_read = NULL;
}
#else
mysqlnd_local_infile_default(mysql->mysql, TRUE);
#endif
}
/* }}} */
@ -1417,19 +1438,16 @@ PHP_FUNCTION(mysqli_set_local_infile_handler)
zval_dtor(&callback_name);
/* save callback function */
#if !defined(HAVE_MYSQLND)
if (!mysql->li_read) {
MAKE_STD_ZVAL(mysql->li_read);
} else {
zval_dtor(mysql->li_read);
}
ZVAL_STRINGL(mysql->li_read, Z_STRVAL_P(callback_func), Z_STRLEN_P(callback_func), 1);
#else
mysqlnd_set_local_infile_handler(mysql->mysql, callback_func->value.str.val);
#endif
RETURN_TRUE;
}
#endif
/* }}} */
/* {{{ proto bool mysqli_more_results(object link) U
@ -1778,7 +1796,7 @@ PHP_FUNCTION(mysqli_real_escape_string) {
newstr_len = mysql_real_escape_string(mysql->mysql, newstr, escapestr, escapestr_len);
newstr = erealloc(newstr, newstr_len + 1);
RETURN_UTF8_STRING(newstr, ZSTR_AUTOFREE);
RETURN_UTF8_STRINGL(newstr, newstr_len, ZSTR_AUTOFREE);
}
/* }}} */
@ -2290,7 +2308,10 @@ PHP_FUNCTION(mysqli_stmt_store_result)
int i = 0;
for (i = mysql_stmt_field_count(stmt->stmt) - 1; i >=0; --i) {
if (stmt->stmt->fields && stmt->stmt->fields[i].type == MYSQL_TYPE_BLOB) {
if (stmt->stmt->fields && (stmt->stmt->fields[i].type == MYSQL_TYPE_BLOB ||
stmt->stmt->fields[i].type == MYSQL_TYPE_MEDIUM_BLOB ||
stmt->stmt->fields[i].type == MYSQL_TYPE_LONG_BLOB))
{
my_bool tmp=1;
mysql_stmt_attr_set(stmt->stmt, STMT_ATTR_UPDATE_MAX_LENGTH, &tmp);
break;

View File

@ -142,7 +142,7 @@ ZEND_FUNCTION(mysqli_driver_construct)
((mysqli_object *) zend_object_store_get_object(getThis() TSRMLS_CC))->ptr = mysqli_resource;
}
mysqli_property_entry mysqli_driver_property_entries[] = {
const mysqli_property_entry mysqli_driver_property_entries[] = {
{"client_info", driver_client_info_read, NULL},
{"client_version", driver_client_version_read, NULL},
{"driver_version", driver_driver_version_read, NULL},

View File

@ -119,8 +119,10 @@ const zend_function_entry mysqli_functions[] = {
PHP_FE(mysqli_info, NULL)
PHP_FE(mysqli_insert_id, NULL)
PHP_FE(mysqli_kill, NULL)
#if !defined(HAVE_MYSQLND)
PHP_FE(mysqli_set_local_infile_default, NULL)
PHP_FE(mysqli_set_local_infile_handler, NULL)
#endif
PHP_FE(mysqli_more_results, NULL)
PHP_FE(mysqli_multi_query, NULL)
PHP_FE(mysqli_next_result, NULL)
@ -227,8 +229,10 @@ const zend_function_entry mysqli_link_methods[] = {
PHP_FALIAS(get_warnings, mysqli_get_warnings, NULL)
PHP_FALIAS(init,mysqli_init,NULL)
PHP_FALIAS(kill,mysqli_kill,NULL)
#if !defined(HAVE_MYSQLND)
PHP_FALIAS(set_local_infile_default,mysqli_set_local_infile_default,NULL)
PHP_FALIAS(set_local_infile_handler,mysqli_set_local_infile_handler,NULL)
#endif
PHP_FALIAS(multi_query,mysqli_multi_query,NULL)
PHP_FALIAS(mysqli,mysqli_connect,NULL)
PHP_FALIAS(more_results,mysqli_more_results, NULL)

View File

@ -19,8 +19,8 @@
*/
#ifndef MYSQL_MYSQLND_H
#define MYSQL_MYSQLND_H
#ifndef MYSQLI_MYSQLND_H
#define MYSQLI_MYSQLND_H
#include "ext/mysqlnd/mysqlnd_libmysql_compat.h"

View File

@ -38,17 +38,18 @@
Open a connection to a mysql server */
PHP_FUNCTION(mysqli_connect)
{
MY_MYSQL *mysql;
MYSQLI_RESOURCE *mysqli_resource;
zval *object = getThis();
char *hostname = NULL, *username=NULL, *passwd=NULL, *dbname=NULL, *socket=NULL;
unsigned int hostname_len = 0, username_len = 0, passwd_len = 0, dbname_len = 0, socket_len = 0;
MY_MYSQL *mysql = NULL;
MYSQLI_RESOURCE *mysqli_resource = NULL;
zval *object = getThis();
char *hostname = NULL, *username=NULL, *passwd=NULL, *dbname=NULL, *socket=NULL;
unsigned int hostname_len = 0, username_len = 0, passwd_len = 0, dbname_len = 0, socket_len = 0;
zend_bool persistent = FALSE;
long port=0;
long port = 0;
uint hash_len;
char *hash_key = NULL;
zend_bool new_connection = FALSE;
zend_rsrc_list_entry *le;
mysqli_plist_entry *plist = NULL;
if (getThis() && !ZEND_NUM_ARGS()) {
RETURN_NULL();
@ -77,60 +78,123 @@ PHP_FUNCTION(mysqli_connect)
hostname = MyG(default_host);
}
mysql = (MY_MYSQL *) ecalloc(1, sizeof(MY_MYSQL));
if (object && instanceof_function(Z_OBJCE_P(object), mysqli_link_class_entry TSRMLS_CC)) {
mysqli_resource = ((mysqli_object *) zend_object_store_get_object(object TSRMLS_CC))->ptr;
if (mysqli_resource && mysqli_resource->ptr &&
mysqli_resource->status >= MYSQLI_STATUS_INITIALIZED)
{
mysql = (MY_MYSQL*)mysqli_resource->ptr;
php_clear_mysql(mysql);
if (mysql->mysql) {
mysqli_close(mysql->mysql, MYSQLI_CLOSE_EXPLICIT);
mysql->mysql = NULL;
}
}
}
if (!mysql) {
mysql = (MY_MYSQL *) ecalloc(1, sizeof(MY_MYSQL));
}
if (strlen(SAFE_STR(hostname)) > 2 && !strncasecmp(hostname, "p:", 2)) {
mysql->persistent = persistent = TRUE;
hostname += 2;
if (!MyG(allow_persistent)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Persistent connections are disabled. Downgrading to normal");
} else {
mysql->persistent = persistent = TRUE;
if (!strlen(hostname)) {
hostname = MyG(default_host);
}
if (!strlen(hostname)) {
hostname = MyG(default_host);
}
/* caclulate hash length: mysqli_ + Hostname + 5 (Port) + username + dbname + pw */
hash_len = 7 + strlen(SAFE_STR(hostname)) + 5 + strlen(SAFE_STR(username))
+ strlen(SAFE_STR(dbname)) + strlen(SAFE_STR(passwd)) + 1;
hash_len = spprintf(&hash_key, 0, "mysqli_%s%ld%s%s%s", SAFE_STR(hostname),
port, SAFE_STR(username), SAFE_STR(dbname),
SAFE_STR(passwd));
hash_key = emalloc(hash_len);
hash_len = snprintf(hash_key, hash_len, "mysqli_%s%ld%s%s%s", SAFE_STR(hostname),
port, SAFE_STR(username), SAFE_STR(dbname),
SAFE_STR(passwd));
/* check if we can reuse exisiting connection ... */
if (zend_hash_find(&EG(persistent_list), hash_key, hash_len + 1, (void **)&le) == SUCCESS) {
if (Z_TYPE_P(le) == php_le_pmysqli()) {
plist = (mysqli_plist_entry *) le->ptr;
/* check if we can reuse exisiting connection ... */
if (zend_hash_find(&EG(persistent_list), hash_key, hash_len + 1, (void **)&le) == SUCCESS) {
if (Z_TYPE_P(le) == php_le_pmysqli()) {
mysql->mysql = (MYSQL *)le->ptr;
do {
if (zend_hash_num_elements(&plist->free_links)) {
HashPosition pos;
MYSQL **free_mysql;
ulong idx;
dtor_func_t pDestructor = plist->free_links.pDestructor;
/* reset variables */
/* todo: option for ping or change_user */
zend_hash_internal_pointer_reset_ex(&plist->free_links, &pos);
if (SUCCESS != zend_hash_get_current_data_ex(&plist->free_links,
(void **)&free_mysql, &pos)) {
break;
}
if (HASH_KEY_IS_LONG != zend_hash_get_current_key_ex(&plist->free_links, NULL,
NULL, &idx, FALSE, &pos)) {
break;
}
mysql->mysql = *free_mysql;
plist->free_links.pDestructor = NULL; /* Don't call pDestructor now */
if (SUCCESS != zend_hash_index_del(&plist->free_links, idx)) {
plist->used_links.pDestructor = pDestructor; /* Restore the destructor */
break;
}
plist->used_links.pDestructor = pDestructor; /* Restore the destructor */
MyG(num_inactive_persistent)--;
MyG(num_active_persistent)++;
/* reset variables */
/* todo: option for ping or change_user */
#if G0
if (!mysql_change_user(mysql->mysql, username, passwd, dbname)) {
if (!mysql_change_user(mysql->mysql, username, passwd, dbname)) {
#else
if (!mysql_ping(mysql->mysql)) {
#endif
if (!mysql_ping(mysql->mysql)) {
#ifdef HAVE_MYSQLND
mysqlnd_restart_psession(mysql->mysql);
mysqlnd_restart_psession(mysql->mysql);
#endif
goto end;
idx = zend_hash_next_free_element(&plist->used_links);
if (SUCCESS != zend_hash_next_index_insert(&plist->used_links, &free_mysql,
sizeof(MYSQL *), NULL)) {
php_mysqli_dtor_p_elements(free_mysql);
break;
}
mysql->hash_index = idx;
mysql->hash_key = hash_key;
goto end;
}
}
} while (0);
}
/*
Here we fall if the connection is not ok.
When we update EG(persistent_list) with a new connection, this one will
get destructed. No need to do it explicitly.
*/
}
} else {
zend_rsrc_list_entry le;
le.type = php_le_pmysqli();
le.ptr = plist = calloc(1, sizeof(mysqli_plist_entry));
zend_hash_init(&plist->free_links, MAX(10, MyG(max_persistent)), NULL, php_mysqli_dtor_p_elements, 1);
zend_hash_init(&plist->used_links, MAX(10, MyG(max_persistent)), NULL, php_mysqli_dtor_p_elements, 1);
zend_hash_update(&EG(persistent_list), hash_key, hash_len + 1, (void *)&le, sizeof(le), NULL);
}
}
}
if (MyG(max_links) != -1 && MyG(num_links) >= MyG(max_links)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too many open links (%ld)", MyG(num_links));
goto err;
}
if (persistent && MyG(max_persistent) != -1 &&
(MyG(num_active_persistent) + MyG(num_inactive_persistent))>= MyG(max_persistent))
{
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too many open persistent links (%ld)",
MyG(num_active_persistent) + MyG(num_inactive_persistent));
goto err;
}
#if !defined(HAVE_MYSQLND)
if (!(mysql->mysql = mysql_init(NULL))) {
#else
if (!(mysql->mysql = mysqlnd_init(persistent))) {
#endif
efree(mysql);
if (persistent) {
efree(hash_key);
}
RETURN_FALSE;
goto err;
}
new_connection = TRUE;
@ -138,7 +202,6 @@ PHP_FUNCTION(mysqli_connect)
mysql_options(mysql->mysql, MYSQL_SET_CHARSET_NAME, "utf8");
}
#ifdef HAVE_EMBEDDED_MYSQLI
if (hostname_len) {
unsigned int external=1;
@ -162,11 +225,7 @@ PHP_FUNCTION(mysqli_connect)
/* free mysql structure */
mysqli_close(mysql->mysql, MYSQLI_CLOSE_DISCONNECTED);
efree(mysql);
if (persistent) {
efree(hash_key);
}
RETURN_FALSE;
goto err;
}
/* when PHP runs in unicode, set default character set to utf8 */
@ -187,38 +246,48 @@ PHP_FUNCTION(mysqli_connect)
mysql_options(mysql->mysql, MYSQL_OPT_LOCAL_INFILE, (char *)&MyG(allow_local_infile));
end:
mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
mysqli_resource->ptr = (void *)mysql;
if (!mysqli_resource) {
mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
mysqli_resource->ptr = (void *)mysql;
}
mysqli_resource->status = MYSQLI_STATUS_VALID;
/* store persistent connection */
if (persistent && new_connection) {
zend_rsrc_list_entry le;
le.type = php_le_pmysqli();
le.ptr = mysql->mysql;
ulong hash_index = zend_hash_next_free_element(&plist->used_links);
/* save persistent connection */
if (zend_hash_update(&EG(persistent_list), hash_key, hash_len + 1, (void *)&le,
sizeof(le), NULL) == FAILURE) {
if (SUCCESS != zend_hash_next_index_insert(&plist->used_links, &mysql->mysql,
sizeof(MYSQL *), NULL)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can't store persistent connection");
}
}
if (persistent) {
efree(hash_key);
} else {
mysql->hash_index = hash_index;
}
MyG(num_active_persistent)++;
}
mysql->hash_key = hash_key;
MyG(num_links)++;
#if !defined(HAVE_MYSQLND)
mysql->multi_query = 0;
#else
mysql->multi_query = 1;
#endif
if (!object || !instanceof_function(Z_OBJCE_P(object), mysqli_link_class_entry TSRMLS_CC)) {
MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_link_class_entry);
} else {
((mysqli_object *) zend_object_store_get_object(object TSRMLS_CC))->ptr = mysqli_resource;
}
return;
err:
efree(mysql);
if (persistent) {
efree(hash_key);
}
RETVAL_FALSE;
}
/* }}} */

View File

@ -313,7 +313,7 @@ MYSQLI_MAP_PROPERTY_FUNC_STRING(stmt_error_read, mysql_stmt_error, MYSQLI_GET_ST
MYSQLI_MAP_PROPERTY_FUNC_STRING(stmt_sqlstate_read, mysql_stmt_sqlstate, MYSQLI_GET_STMT(MYSQLI_STATUS_INITIALIZED));
/* }}} */
mysqli_property_entry mysqli_link_property_entries[] = {
const mysqli_property_entry mysqli_link_property_entries[] = {
{"affected_rows", link_affected_rows_read, NULL},
{"client_info", link_client_info_read, NULL},
{"client_version", link_client_version_read, NULL},
@ -334,7 +334,7 @@ mysqli_property_entry mysqli_link_property_entries[] = {
{NULL, NULL, NULL}
};
mysqli_property_entry mysqli_result_property_entries[] = {
const mysqli_property_entry mysqli_result_property_entries[] = {
{"current_field", result_current_field_read, NULL},
{"field_count", result_field_count_read, NULL},
{"lengths", result_lengths_read, NULL},
@ -343,7 +343,7 @@ mysqli_property_entry mysqli_result_property_entries[] = {
{NULL, NULL, NULL}
};
mysqli_property_entry mysqli_stmt_property_entries[] = {
const mysqli_property_entry mysqli_stmt_property_entries[] = {
{"affected_rows", stmt_affected_rows_read, NULL},
{"insert_id", stmt_insert_id_read, NULL},
{"num_rows", stmt_num_rows_read, NULL},

View File

@ -321,7 +321,7 @@ const zend_function_entry mysqli_warning_methods[] = {
/* }}} */
/* {{{ mysqli_warning_property_entries */
mysqli_property_entry mysqli_warning_property_entries[] = {
const mysqli_property_entry mysqli_warning_property_entries[] = {
{"message", mysqli_warning_message, NULL},
{"sqlstate", mysqli_warning_sqlstate, NULL},
{"errno", mysqli_warning_errno, NULL},

View File

@ -1,6 +1,6 @@
/*
+----------------------------------------------------------------------+
| PHP Version 5 |
| PHP Version 6 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2007 The PHP Group |
+----------------------------------------------------------------------+
@ -98,9 +98,11 @@ typedef struct {
typedef struct {
MYSQL *mysql;
char *hash_key;
zval *li_read;
php_stream *li_stream;
zend_bool persistent;
unsigned long hash_index; /* Used when persistent, hold the index in plist->used_links */
unsigned int multi_query;
UConverter *conv;
} MY_MYSQL;
@ -145,6 +147,11 @@ typedef struct {
} mysqli_local_infile;
#endif
typedef struct {
HashTable free_links;
HashTable used_links;
} mysqli_plist_entry;
#ifdef PHP_WIN32
#define PHP_MYSQLI_API __declspec(dllexport)
#define MYSQLI_LLU_SPEC "%I64u"
@ -173,11 +180,11 @@ extern const zend_function_entry mysqli_driver_methods[];
extern const zend_function_entry mysqli_warning_methods[];
extern const zend_function_entry mysqli_exception_methods[];
extern mysqli_property_entry mysqli_link_property_entries[];
extern mysqli_property_entry mysqli_result_property_entries[];
extern mysqli_property_entry mysqli_stmt_property_entries[];
extern mysqli_property_entry mysqli_driver_property_entries[];
extern mysqli_property_entry mysqli_warning_property_entries[];
extern const mysqli_property_entry mysqli_link_property_entries[];
extern const mysqli_property_entry mysqli_result_property_entries[];
extern const mysqli_property_entry mysqli_stmt_property_entries[];
extern const mysqli_property_entry mysqli_driver_property_entries[];
extern const mysqli_property_entry mysqli_warning_property_entries[];
#ifdef HAVE_MYSQLND
extern MYSQLND_ZVAL_PCACHE *mysqli_mysqlnd_zval_cache;
@ -205,6 +212,7 @@ extern zend_class_entry *mysqli_driver_class_entry;
extern zend_class_entry *mysqli_warning_class_entry;
extern zend_class_entry *mysqli_exception_class_entry;
extern int php_le_pmysqli(void);
extern void php_mysqli_dtor_p_elements(void *data);
#ifdef HAVE_SPL
extern PHPAPI zend_class_entry *spl_ce_RuntimeException;
@ -279,9 +287,10 @@ PHP_MYSQLI_EXPORT(zend_object_value) mysqli_objects_new(zend_class_entry * TSRML
#define MYSQLI_RETURN_LONG_LONG(__val) \
{ \
if ((__val) < LONG_MAX) { \
RETURN_LONG((__val)); \
RETURN_LONG((long) (__val)); \
} else { \
char *ret; \
/* always used with my_ulonglong -> %llu */ \
int l = spprintf(&ret, 0, "%llu", (__val)); \
RETURN_STRINGL(ret, l, 0); \
} \
@ -347,6 +356,10 @@ ZEND_BEGIN_MODULE_GLOBALS(mysqli)
long default_link;
long num_links;
long max_links;
long num_active_persistent;
long num_inactive_persistent;
long max_persistent;
long allow_persistent;
long cache_size;
unsigned long default_port;
char *default_host;

View File

@ -41,6 +41,7 @@ if (PHP_MYSQLI != "no") {
mysqlnd_source =
"mysqlnd.c " +
// "mysqlnd_alloc.c " +
"mysqlnd_debug.c " +
"mysqlnd_charset.c " +
"mysqlnd_loaddata.c " +
"mysqlnd_palloc.c " +
@ -51,14 +52,15 @@ if (PHP_MYSQLI != "no") {
"mysqlnd_result_meta.c " +
"mysqlnd_statistics.c " +
"mysqlnd_wireprotocol.c";
EXTENSION("mysqli", mysqli_source);
// Specify that add "mysqlnd" sources, but use same object file
// directory as the "mysqli" sources
// FIXME the hard coded "ext/mysqli/mysqlnd" prevents pointing
// out sources in another directory? Like above: PHP_MYSQLI + "\\include;"
ADD_SOURCES("ext/mysqli/mysqlnd", mysqlnd_source, "mysqli");
AC_DEFINE('HAVE_MYSQLILIB', 1, 'Have MySQLi library');
AC_DEFINE('HAVE_MYSQLND' , 1, 'MySQL native driver support enabled');
if (CHECK_LIB("ws2_32.lib", "mysqlnd")) {
EXTENSION("mysqli", mysqli_source);
// Specify that add "mysqlnd" sources, but use same object file
// directory as the "mysqli" sources
// FIXME the hard coded "ext/mysqli/mysqlnd" prevents pointing
// out sources in another directory? Like above: PHP_MYSQLI + "\\include;"
ADD_SOURCES("ext/mysqli/mysqlnd", mysqlnd_source, "mysqli");
AC_DEFINE('HAVE_MYSQLILIB', 1, 'Have MySQLi library');
AC_DEFINE('HAVE_MYSQLND' , 1, 'MySQL native driver support enabled');
}
}
}

View File

@ -7,7 +7,7 @@ if test "$PHP_MYSQLND_ENABLED" = "yes"; then
mysqlnd_sources="mysqlnd.c mysqlnd_charset.c mysqlnd_wireprotocol.c \
mysqlnd_ps.c mysqlnd_loaddata.c mysqlnd_palloc.c \
mysqlnd_ps_codec.c mysqlnd_statistics.c mysqlnd_qcache.c\
mysqlnd_result.c mysqlnd_result_meta.c"
mysqlnd_result.c mysqlnd_result_meta.c mysqlnd_debug.c"
PHP_NEW_EXTENSION(mysqlnd, $mysqlnd_sources, no)
PHP_ADD_BUILD_DIR([ext/mysqlnd], 1)

File diff suppressed because it is too large Load Diff

View File

@ -23,13 +23,9 @@
#ifndef MYSQLND_H
#define MYSQLND_H
#define MYSQLND_VERSION "mysqlnd 5.0.2-dev - 070702 - $Revision$"
#define MYSQLND_VERSION "mysqlnd 5.0.2-dev - 070928 - $Revision$"
#define MYSQLND_VERSION_ID 50002
#define phpext_mysqlnd_ptr &mysqlnd_module_entry
extern zend_module_entry mysqlnd_module_entry;
/* This forces inlining of some accessor functions */
#define MYSQLND_USE_OPTIMISATIONS 0
@ -49,607 +45,18 @@ extern zend_module_entry mysqlnd_module_entry;
#define MYSQLND_DO_WIRE_CHECK_BEFORE_COMMAND 1
#endif
#include "mysqlnd_portability.h"
#ifdef ZTS
#include "TSRM.h"
#endif
#include "mysqlnd_portability.h"
#include "mysqlnd_enum_n_def.h"
/*
/-----> CONN_CLOSE <---------------\
| ^ \
| | \
CONN_READY -> CONN_QUERY_SENT -> CONN_FETCHING_DATA
^ |
\-------------------------------------/
*/
typedef enum mysqlnd_connection_state
{
CONN_ALLOCED = 0,
CONN_READY,
CONN_QUERY_SENT,
CONN_SENDING_LOAD_DATA,
CONN_FETCHING_DATA,
CONN_NEXT_RESULT_PENDING,
CONN_QUIT_SENT, /* object is "destroyed" at this stage */
} enum_mysqlnd_connection_state;
typedef enum mysqlnd_stmt_state {
MYSQLND_STMT_INITTED = 0,
MYSQLND_STMT_PREPARED,
MYSQLND_STMT_EXECUTED,
MYSQLND_STMT_WAITING_USE_OR_STORE,
MYSQLND_STMT_USE_OR_STORE_CALLED,
MYSQLND_STMT_USER_FETCHING, /* fetch_row_buff or fetch_row_unbuf */
} enum_mysqlnd_stmt_state;
typedef enum param_bind_flags {
MYSQLND_PARAM_BIND_BLOB_USED = 1
} enum_param_bind_flags;
/* PS */
enum mysqlnd_stmt_attr
{
STMT_ATTR_UPDATE_MAX_LENGTH,
STMT_ATTR_CURSOR_TYPE,
STMT_ATTR_PREFETCH_ROWS
};
enum myslqnd_cursor_type
{
CURSOR_TYPE_NO_CURSOR= 0,
CURSOR_TYPE_READ_ONLY= 1,
CURSOR_TYPE_FOR_UPDATE= 2,
CURSOR_TYPE_SCROLLABLE= 4
};
typedef enum mysqlnd_connection_close_type
{
MYSQLND_CLOSE_EXPLICIT = 0,
MYSQLND_CLOSE_IMPLICIT,
MYSQLND_CLOSE_DISCONNECTED,
MYSQLND_CLOSE_LAST /* for checking, should always be last */
} enum_connection_close_type;
typedef enum mysqlnd_collected_stats {
STAT_BYTES_SENT,
STAT_BYTES_RECEIVED,
STAT_PACKETS_SENT,
STAT_PACKETS_RECEIVED,
STAT_PROTOCOL_OVERHEAD_IN,
STAT_PROTOCOL_OVERHEAD_OUT,
STAT_RSET_QUERY,
STAT_NON_RSET_QUERY,
STAT_NO_INDEX_USED,
STAT_BAD_INDEX_USED,
STAT_BUFFERED_SETS,
STAT_UNBUFFERED_SETS,
STAT_PS_BUFFERED_SETS,
STAT_PS_UNBUFFERED_SETS,
STAT_FLUSHED_NORMAL_SETS,
STAT_FLUSHED_PS_SETS,
STAT_ROWS_FETCHED_FROM_SERVER,
STAT_ROWS_FETCHED_FROM_CLIENT,
STAT_ROWS_SKIPPED,
STAT_COPY_ON_WRITE_SAVED,
STAT_COPY_ON_WRITE_PERFORMED,
STAT_CMD_BUFFER_TOO_SMALL,
STAT_CONNECT_SUCCESS,
STAT_CONNECT_FAILURE,
STAT_CONNECT_REUSED,
STAT_CLOSE_EXPLICIT,
STAT_CLOSE_IMPLICIT,
STAT_CLOSE_DISCONNECT,
STAT_CLOSE_IN_MIDDLE,
STAT_FREE_RESULT_EXPLICIT,
STAT_FREE_RESULT_IMPLICIT,
STAT_STMT_CLOSE_EXPLICIT,
STAT_STMT_CLOSE_IMPLICIT,
STAT_LAST /* Should be always the last */
} enum_mysqlnd_collected_stats;
typedef struct st_mysqlnd_cmd_buffer {
zend_uchar *buffer;
size_t length;
} MYSQLND_CMD_BUFFER;
typedef struct st_mysqlnd_field {
char *name; /* Name of column */
char *org_name; /* Original column name, if an alias */
char *table; /* Table of column if column was a field */
char *org_table; /* Org table name, if table was an alias */
char *db; /* Database for table */
char *catalog; /* Catalog for table */
char *def; /* Default value (set by mysql_list_fields) */
unsigned long length; /* Width of column (create length) */
unsigned long max_length; /* Max width for selected set */
unsigned int name_length;
unsigned int org_name_length;
unsigned int table_length;
unsigned int org_table_length;
unsigned int db_length;
unsigned int catalog_length;
unsigned int def_length;
unsigned int flags; /* Diverse flags */
unsigned int decimals; /* Number of decimals in field */
unsigned int charsetnr; /* Character set */
enum mysqlnd_field_types type; /* Type of field. See mysql_com.h for types */
char *root;
size_t root_len;
} MYSQLND_FIELD;
typedef struct st_mysqlnd_upsert_result {
unsigned int warning_count;
unsigned int server_status;
unsigned long long affected_rows;
unsigned long long last_insert_id;
} mysqlnd_upsert_status;
typedef struct st_mysqlnd_error_info {
char error[MYSQLND_ERRMSG_SIZE+1];
char sqlstate[MYSQLND_SQLSTATE_LENGTH + 1];
unsigned int error_no;
} mysqlnd_error_info;
typedef struct st_mysqlnd_zval_pcache MYSQLND_ZVAL_PCACHE;
typedef struct st_mysqlnd_thread_zval_pcache MYSQLND_THD_ZVAL_PCACHE;
typedef struct st_mysqlnd_qcache MYSQLND_QCACHE;
typedef struct st_mysqlnd_infile_info {
php_stream *fd;
int error_no;
char error_msg[MYSQLND_ERRMSG_SIZE + 1];
const char *filename;
zval *callback;
} MYSQLND_INFILE_INFO;
/* character set information */
typedef struct st_mysqlnd_charset
{
uint nr;
char *name;
char *collation;
uint char_minlen;
uint char_maxlen;
uint dangerous_for_escape_backslash;
uint (*mb_charlen)(uint c);
uint (*mb_valid)(const char *start, const char *end);
} MYSQLND_CHARSET;
/* local infile handler */
typedef struct st_mysqlnd_infile
{
int (*local_infile_init)(void **ptr, char *filename, void **userdata TSRMLS_DC);
int (*local_infile_read)(void *ptr, char *buf, uint buf_len TSRMLS_DC);
int (*local_infile_error)(void *ptr, char *error_msg, uint error_msg_len TSRMLS_DC);
void (*local_infile_end)(void *ptr TSRMLS_DC);
zval *callback;
void *userdata;
} MYSQLND_INFILE;
typedef struct st_mysqlnd_option {
/* timeouts */
uint timeout_connect;
uint timeout_read;
uint timeout_write;
ulong flags;
/* init commands - we need to send them to server directly after connect */
uint num_commands;
char **init_commands;
/* configuration file information */
char *cfg_file;
char *cfg_section;
/* SSL information */
char *ssl_key;
char *ssl_cert;
char *ssl_ca;
char *ssl_capath;
char *ssl_cipher;
zend_bool use_ssl;
char *charset_name;
/* maximum allowed packet size for communication */
ulong max_allowed_packet;
zend_bool numeric_and_datetime_as_unicode;
#ifdef MYSQLND_STRING_TO_INT_CONVERSION
zend_bool int_and_year_as_int;
#endif
} MYSQLND_OPTION;
typedef struct st_mysqlnd_connection MYSQLND;
typedef struct st_mysqlnd_res MYSQLND_RES;
typedef char** MYSQLND_ROW; /* return data as array of strings */
typedef struct st_mysqlnd_stmt MYSQLND_STMT;
typedef unsigned int MYSQLND_FIELD_OFFSET;
typedef struct st_mysqlnd_param_bind MYSQLND_PARAM_BIND;
typedef struct st_mysqlnd_result_bind MYSQLND_RESULT_BIND;
typedef struct st_mysqlnd_result_metadata MYSQLND_RES_METADATA;
typedef struct st_mysqlnd_buffered_result MYSQLND_RES_BUFFERED;
typedef struct st_mysqlnd_unbuffered_result MYSQLND_RES_UNBUFFERED;
typedef MYSQLND_RES* (*mysqlnd_stmt_use_or_store_func)(MYSQLND_STMT * const TSRMLS_DC);
typedef enum_func_status (*mysqlnd_fetch_row_func)(MYSQLND_RES *result,
void *param,
unsigned int flags,
zend_bool *fetched_anything
TSRMLS_DC);
typedef struct st_mysqlnd_stats {
my_uint64 values[STAT_LAST];
#ifdef ZTS
MUTEX_T LOCK_access;
#endif
} MYSQLND_STATS;
typedef struct st_mysqlnd_net {
php_stream *stream;
/* sequence for simple checking of correct packets */
zend_uchar packet_no;
#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 {
ulong (*escape_string)(const MYSQLND * const conn, char *newstr, const char *escapestr, int escapestr_len);
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);
MYSQLND_RES * (*use_result)(MYSQLND * const conn TSRMLS_DC);
MYSQLND_RES * (*store_result)(MYSQLND * const conn TSRMLS_DC);
enum_func_status (*next_result)(MYSQLND * const conn TSRMLS_DC);
zend_bool (*more_results)(const MYSQLND * const conn);
MYSQLND_STMT * (*stmt_init)(MYSQLND * const conn);
enum_func_status (*shutdown_server)(MYSQLND * const conn, unsigned long level TSRMLS_DC);
enum_func_status (*refresh_server)(MYSQLND * const conn, unsigned long options TSRMLS_DC);
enum_func_status (*ping)(MYSQLND * const conn TSRMLS_DC);
enum_func_status (*kill_connection)(MYSQLND *conn, unsigned long pid TSRMLS_DC);
enum_func_status (*select_db)(MYSQLND * const conn, const char * const db, unsigned int db_len TSRMLS_DC);
enum_func_status (*server_dump_debug_information)(MYSQLND * const conn TSRMLS_DC);
enum_func_status (*change_user)(MYSQLND * const conn, const char * user, const char * passwd, const char * db TSRMLS_DC);
unsigned int (*get_error_no)(const MYSQLND * const conn);
const char * (*get_error_str)(const MYSQLND * const conn);
const char * (*get_sqlstate)(const MYSQLND * const conn);
mynd_ulonglong (*get_thread_id)(const MYSQLND * const conn);
void (*get_statistics)(const MYSQLND * const conn, zval *return_value TSRMLS_DC ZEND_FILE_LINE_DC);
unsigned long (*get_server_version)(const MYSQLND * const conn);
const char * (*get_server_information)(const MYSQLND * const conn);
enum_func_status (*get_server_statistics)(MYSQLND *conn, char **message, unsigned int * message_len TSRMLS_DC);
const char * (*get_host_information)(const MYSQLND * const conn);
unsigned int (*get_protocol_information)(const MYSQLND * const conn);
const char * (*get_last_message)(const MYSQLND * const conn);
const char * (*charset_name)(const MYSQLND * const conn);
MYSQLND_RES * (*list_method)(MYSQLND *conn, const char *query, char *achtung_wild, char *par1 TSRMLS_DC);
mynd_ulonglong (*get_last_insert_id)(const MYSQLND * const conn);
mynd_ulonglong (*get_affected_rows)(const MYSQLND * const conn);
unsigned int (*get_warning_count)(const MYSQLND * const conn);
unsigned int (*get_field_count)(const MYSQLND * const conn);
enum_func_status (*set_server_option)(MYSQLND * const conn, enum_mysqlnd_server_option option TSRMLS_DC);
enum_func_status (*set_client_option)(MYSQLND * const conn, enum_mysqlnd_option option, const char * const value);
void (*free_contents)(MYSQLND *conn TSRMLS_DC); /* private */
enum_func_status (*close)(MYSQLND *conn, enum_connection_close_type close_type TSRMLS_DC);
void (*dtor)(MYSQLND *conn TSRMLS_DC); /* private */
MYSQLND * (*get_reference)(MYSQLND * const conn);
void (*free_reference)(MYSQLND * const conn TSRMLS_DC);
};
struct st_mysqlnd_res_methods {
mysqlnd_fetch_row_func fetch_row;
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, 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, enum_mysqlnd_extension ext TSRMLS_DC ZEND_FILE_LINE_DC);
void (*fetch_all)(MYSQLND_RES *result, unsigned int flags, zval *return_value TSRMLS_DC ZEND_FILE_LINE_DC);
void (*fetch_field_data)(MYSQLND_RES *result, unsigned int offset, zval *return_value TSRMLS_DC);
mynd_ulonglong (*num_rows)(const MYSQLND_RES * const result);
unsigned int (*num_fields)(const MYSQLND_RES * const result);
enum_func_status (*skip_result)(MYSQLND_RES * const result TSRMLS_DC);
enum_func_status (*seek_data)(MYSQLND_RES * result, mynd_ulonglong row);
MYSQLND_FIELD_OFFSET (*seek_field)(MYSQLND_RES * const result, MYSQLND_FIELD_OFFSET field_offset);
MYSQLND_FIELD_OFFSET (*field_tell)(const MYSQLND_RES * const result);
MYSQLND_FIELD * (*fetch_field)(MYSQLND_RES * const result);
MYSQLND_FIELD * (*fetch_field_direct)(const MYSQLND_RES * const result, MYSQLND_FIELD_OFFSET fieldnr);
enum_func_status (*read_result_metadata)(MYSQLND_RES *result, MYSQLND *conn TSRMLS_DC);
unsigned long * (*fetch_lengths)(MYSQLND_RES * const result);
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);
};
struct st_mysqlnd_res_meta_methods {
MYSQLND_FIELD * (*fetch_field)(MYSQLND_RES_METADATA * const meta);
MYSQLND_FIELD * (*fetch_field_direct)(const MYSQLND_RES_METADATA * const meta, MYSQLND_FIELD_OFFSET fieldnr);
MYSQLND_FIELD_OFFSET (*field_tell)(const MYSQLND_RES_METADATA * const meta);
enum_func_status (*read_metadata)(MYSQLND_RES_METADATA * const meta, MYSQLND *conn TSRMLS_DC);
MYSQLND_RES_METADATA * (*clone_metadata)(const MYSQLND_RES_METADATA * const meta, zend_bool persistent);
void (*free_metadata)(MYSQLND_RES_METADATA *meta, zend_bool persistent TSRMLS_DC);
};
struct st_mysqlnd_stmt_methods {
enum_func_status (*prepare)(MYSQLND_STMT * const stmt, const char * const query, unsigned int query_len TSRMLS_DC);
enum_func_status (*execute)(MYSQLND_STMT * const stmt TSRMLS_DC);
MYSQLND_RES * (*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);
enum_func_status (*close)(MYSQLND_STMT * const stmt, zend_bool implicit TSRMLS_DC); /* private */
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);
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);
enum_func_status (*send_long_data)(MYSQLND_STMT * const stmt, unsigned int param_num,
const char * const data, unsigned long length TSRMLS_DC);
MYSQLND_RES * (*get_parameter_metadata)(MYSQLND_STMT * const stmt);
MYSQLND_RES * (*get_result_metadata)(MYSQLND_STMT * const stmt);
mynd_ulonglong (*get_last_insert_id)(const MYSQLND_STMT * const stmt);
mynd_ulonglong (*get_affected_rows)(const MYSQLND_STMT * const stmt);
mynd_ulonglong (*get_num_rows)(const MYSQLND_STMT * const stmt);
unsigned int (*get_param_count)(const MYSQLND_STMT * const stmt);
unsigned int (*get_field_count)(const MYSQLND_STMT * const stmt);
unsigned int (*get_warning_count)(const MYSQLND_STMT * const stmt);
unsigned int (*get_error_no)(const MYSQLND_STMT * const stmt);
const char * (*get_error_str)(const MYSQLND_STMT * const stmt);
const char * (*get_sqlstate)(const MYSQLND_STMT * const stmt);
enum_func_status (*get_attribute)(MYSQLND_STMT * const stmt, enum mysqlnd_stmt_attr attr_type, void * const value);
enum_func_status (*set_attribute)(MYSQLND_STMT * const stmt, enum mysqlnd_stmt_attr attr_type, const void * const value);
};
struct st_mysqlnd_connection {
/* Operation related */
MYSQLND_NET net;
/* Information related */
char *host;
char *unix_socket;
char *user;
char *passwd;
unsigned int *passwd_len;
char *scheme;
unsigned long long thread_id;
char *server_version;
char *host_info;
unsigned char *scramble;
const MYSQLND_CHARSET *charset;
MYSQLND_INFILE infile;
unsigned int protocol_version;
unsigned long max_packet_size;
unsigned int port;
unsigned long client_flag;
unsigned long server_capabilities;
int tmp_int;
/* For UPSERT queries */
mysqlnd_upsert_status upsert_status;
char *last_message;
unsigned int last_message_len;
/* If error packet, we use these */
mysqlnd_error_info error_info;
/*
To prevent queries during unbuffered fetches. Also to
mark the connection as destroyed for garbage collection.
*/
enum mysqlnd_connection_state state;
enum_mysqlnd_query_type last_query_type;
/* Temporary storage between query and (use|store)_result() call */
MYSQLND_RES *current_result;
/*
How many result sets reference this connection.
It won't be freed until this number reaches 0.
The last one, please close the door! :-)
The result set objects can determine by inspecting
'quit_sent' whether the connection is still valid.
*/
unsigned int refcount;
/* Temporal storage for mysql_query */
unsigned int field_count;
/* persistent connection */
zend_bool persistent;
/* options */
MYSQLND_OPTION options;
/* zval cache */
MYSQLND_THD_ZVAL_PCACHE *zval_cache;
/* qcache */
MYSQLND_QCACHE *qcache;
/* stats */
MYSQLND_STATS stats;
struct st_mysqlnd_conn_methods *m;
};
typedef struct st_php_mysql_packet_row php_mysql_packet_row;
struct mysqlnd_field_hash_key {
zend_bool is_numeric;
unsigned long key;
#if PHP_MAJOR_VERSION >= 6
zstr ustr;
unsigned int ulen;
#endif
};
struct st_mysqlnd_result_metadata {
MYSQLND_FIELD *fields;
struct mysqlnd_field_hash_key *zend_hash_keys;
unsigned int current_field;
unsigned int field_count;
/* We need this to make fast allocs in rowp_read */
unsigned int bit_fields_count;
size_t bit_fields_total_len; /* trailing \0 not counted */
struct st_mysqlnd_res_meta_methods *m;
};
struct st_mysqlnd_buffered_result {
zval ***data;
zval ***data_cursor;
zend_uchar **row_buffers;
mynd_ulonglong row_count;
zend_bool persistent;
MYSQLND_QCACHE *qcache;
unsigned int references;
zend_bool async_invalid;
mysqlnd_error_info error_info;
};
struct st_mysqlnd_unbuffered_result {
/* For unbuffered (both normal and PS) */
zval **last_row_data;
zend_uchar *last_row_buffer;
mynd_ulonglong row_count;
zend_bool eof_reached;
};
struct st_mysqlnd_res {
struct st_mysqlnd_res_methods m;
MYSQLND *conn;
enum_mysqlnd_res_type type;
unsigned int field_count;
/* For metadata functions */
MYSQLND_RES_METADATA *meta;
/* To be used with store_result() - both normal and PS */
MYSQLND_RES_BUFFERED *data;
MYSQLND_RES_UNBUFFERED *unbuf;
/*
Column lengths of current row - both buffered and unbuffered.
For buffered results it duplicates the data found in **data
*/
unsigned long *lengths;
php_mysql_packet_row *row_packet; /* Unused for PS */
/* zval cache */
MYSQLND_THD_ZVAL_PCACHE *zval_cache;
};
#define MYSQLND_DEFAULT_PREFETCH_ROWS (ulong) 1
struct st_mysqlnd_param_bind {
zval *zv;
zend_uchar type;
enum_param_bind_flags flags;
};
struct st_mysqlnd_result_bind {
zval *zv;
zend_uchar original_type;
zend_bool bound;
};
struct st_mysqlnd_stmt {
MYSQLND *conn;
unsigned long stmt_id;
unsigned long flags;/* cursor is set here */
enum_mysqlnd_stmt_state state;
unsigned int warning_count;
MYSQLND_RES *result;
unsigned int field_count;
unsigned int param_count;
unsigned char send_types_to_server;
MYSQLND_PARAM_BIND *param_bind;
MYSQLND_RESULT_BIND *result_bind;
zend_bool result_zvals_separated_once;
mysqlnd_upsert_status upsert_status;
mysqlnd_error_info error_info;
zend_bool update_max_length;
unsigned long prefetch_rows;
zend_bool cursor_exists;
mysqlnd_stmt_use_or_store_func default_rset_handler;
MYSQLND_CMD_BUFFER cmd_buffer;
struct st_mysqlnd_stmt_methods *m;
};
#include "mysqlnd_structs.h"
/* Library related */
PHPAPI void mysqlnd_restart_psession(MYSQLND *conn);
#define mysqlnd_restart_psession(conn) _mysqlnd_restart_psession((conn) TSRMLS_CC)
PHPAPI void _mysqlnd_restart_psession(MYSQLND *conn TSRMLS_DC);
PHPAPI void mysqlnd_end_psession(MYSQLND *conn);
PHPAPI void mysqlnd_minfo_print_hash(zval *values);
#define mysqlnd_thread_safe() TRUE
@ -659,7 +66,8 @@ PHPAPI const MYSQLND_CHARSET * mysqlnd_find_charset_name(const char * const char
/* Connect */
PHPAPI MYSQLND * mysqlnd_init(zend_bool persistent);
#define mysqlnd_init(persistent) _mysqlnd_init((persistent) TSRMLS_CC)
PHPAPI MYSQLND * _mysqlnd_init(zend_bool persistent TSRMLS_DC);
PHPAPI MYSQLND * mysqlnd_connect(MYSQLND *conn,
char *host, char *user,
char *passwd, unsigned int passwd_len,
@ -672,7 +80,8 @@ PHPAPI MYSQLND * mysqlnd_connect(MYSQLND *conn,
#define mysqlnd_change_user(conn, user, passwd, db) (conn)->m->change_user((conn), (user), (passwd), (db) TSRMLS_CC)
#define mysqlnd_debug(x)
#define mysqlnd_debug(x) _mysqlnd_debug((x) TSRMLS_CC)
void _mysqlnd_debug(const char *mode TSRMLS_DC);
/* Query */
#define mysqlnd_fetch_into(result, flags, ret_val, ext) (result)->m.fetch_into((result), (flags), (ret_val), (ext) TSRMLS_CC ZEND_FILE_LINE_CC)
@ -691,7 +100,7 @@ PHPAPI MYSQLND * mysqlnd_connect(MYSQLND *conn,
#define mysqlnd_next_result(conn) (conn)->m->next_result((conn) TSRMLS_CC)
#define mysqlnd_more_results(conn) (conn)->m->more_results((conn))
#define mysqlnd_free_result(r,e_or_i) ((MYSQLND_RES*)r)->m.free_result(((MYSQLND_RES*)(r)), (e_or_i) TSRMLS_CC)
#define mysqlnd_data_seek(result, row) (result)->m.seek_data((result), (row))
#define mysqlnd_data_seek(result, row) (result)->m.seek_data((result), (row) TSRMLS_CC)
/*****************************************************************************************************/
#if defined(MYSQLND_USE_OPTIMISATIONS) && MYSQLND_USE_OPTIMISATIONS == 1
@ -722,7 +131,7 @@ PHPAPI MYSQLND * mysqlnd_connect(MYSQLND *conn,
#define mysqlnd_field_seek(result, ofs) (result)->m.seek_field((result), (ofs))
#define mysqlnd_field_tell(result) (result)->meta? (result)->meta->current_field:0)
#define mysqlnd_fetch_field(result) (result)->m.fetch_field((result))
#define mysqlnd_fetch_field(result) (result)->m.fetch_field((result) TSRMLS_CC)
#define mysqlnd_fetch_field_direct(result,fnr) ((result)->meta? &((result)->meta->fields[(fnr)]):NULL)
/* mysqlnd metadata */
@ -772,8 +181,8 @@ 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))
#define mysqlnd_fetch_field(result) (result)->m.fetch_field((result))
#define mysqlnd_fetch_field_direct(result,fnr) (result)->m.fetch_field_direct((result), (fnr))
#define mysqlnd_fetch_field(result) (result)->m.fetch_field((result) TSRMLS_CC)
#define mysqlnd_fetch_field_direct(result,fnr) (result)->m.fetch_field_direct((result), (fnr) TSRMLS_CC)
/* mysqlnd metadata */
PHPAPI const char * mysqlnd_get_client_info();
@ -797,7 +206,7 @@ PHPAPI unsigned int mysqlnd_get_client_version();
PHPAPI const char * mysqlnd_field_type_name(enum mysqlnd_field_types field_type);
/* LOAD DATA LOCAL */
PHPAPI void mysqlnd_local_infile_default(MYSQLND *conn, zend_bool free_callback);
PHPAPI void mysqlnd_local_infile_default(MYSQLND *conn);
PHPAPI void mysqlnd_set_local_infile_handler(MYSQLND * const conn, const char * const funcname);
/* Simple commands */
@ -805,7 +214,7 @@ PHPAPI void mysqlnd_set_local_infile_handler(MYSQLND * const conn, const char *
#define mysqlnd_commit(conn) (conn)->m->query((conn), "COMMIT", sizeof("COMMIT")-1 TSRMLS_CC)
#define mysqlnd_rollback(conn) (conn)->m->query((conn), "ROLLBACK", sizeof("ROLLBACK")-1 TSRMLS_CC)
#define mysqlnd_list_dbs(conn, wild) (conn)->m->list_method((conn), wild? "SHOW DATABASES LIKE %s":"SHOW DATABASES", (wild), NULL TSRMLS_CC)
#define mysqlnd_list_fields(conn, tab,wild) (conn)->m->list_method((conn), wild? "SHOW FIELDS FROM %s LIKE %s":"SHOW FIELDS FROM %s", wild, tab TSRMLS_CC)
#define mysqlnd_list_fields(conn, tab,wild) (conn)->m->list_fields((conn), (tab), (wild) TSRMLS_CC)
#define mysqlnd_list_processes(conn) (conn)->m->list_method((conn), "SHOW PROCESSLIST", NULL, NULL TSRMLS_CC)
#define mysqlnd_list_tables(conn, wild) (conn)->m->list_method((conn), wild? "SHOW TABLES LIKE %s":"SHOW TABLES", (wild), NULL TSRMLS_CC)
#define mysqlnd_dump_debug_info(conn) (conn)->m->server_dump_debug_information((conn) TSRMLS_CC)
@ -817,38 +226,38 @@ PHPAPI void mysqlnd_set_local_infile_handler(MYSQLND * const conn, const char *
#define mysqlnd_get_server_version(conn) (conn)->m->get_server_version((conn))
#define mysqlnd_set_character_set(conn, cs) (conn)->m->set_charset((conn), (cs) TSRMLS_CC)
#define mysqlnd_stat(conn, msg, msg_len) (conn)->m->get_server_statistics((conn), (msg), (msg_len) TSRMLS_CC)
#define mysqlnd_options(conn, opt, value) (conn)->m->set_client_option((conn), (opt), (value))
#define mysqlnd_options(conn, opt, value) (conn)->m->set_client_option((conn), (opt), (value) TSRMLS_CC)
#define mysqlnd_set_server_option(conn, op) (conn)->m->set_server_option((conn), (op) TSRMLS_CC)
/* Escaping */
#define mysqlnd_real_escape_string(conn, newstr, escapestr, escapestr_len) \
(conn)->m->escape_string((conn), (newstr), (escapestr), (escapestr_len))
(conn)->m->escape_string((conn), (newstr), (escapestr), (escapestr_len) TSRMLS_CC)
#define mysqlnd_escape_string(newstr, escapestr, escapestr_len) \
mysqlnd_old_escape_string((newstr), (escapestr), (escapestr_len))
mysqlnd_old_escape_string((newstr), (escapestr), (escapestr_len) TSRMLS_CC)
PHPAPI ulong mysqlnd_old_escape_string(char *newstr, const char *escapestr, int escapestr_len);
PHPAPI ulong mysqlnd_old_escape_string(char *newstr, const char *escapestr, int escapestr_len TSRMLS_DC);
/* PS */
#define mysqlnd_stmt_init(conn) (conn)->m->stmt_init((conn))
#define mysqlnd_stmt_init(conn) (conn)->m->stmt_init((conn) TSRMLS_CC)
#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_data_seek(stmt, row) (stmt)->m->seek_data((stmt), (row) TSRMLS_CC)
#define mysqlnd_stmt_prepare(stmt, q, qlen) (stmt)->m->prepare((stmt), (q), (qlen) TSRMLS_CC)
#define mysqlnd_stmt_execute(stmt) (stmt)->m->execute((stmt) TSRMLS_CC)
#define mysqlnd_stmt_send_long_data(s,p,d,l) (s)->m->send_long_data((s), (p), (d), (l) TSRMLS_CC)
#define mysqlnd_stmt_bind_param(stmt,bind) (stmt)->m->bind_param((stmt), (bind))
#define mysqlnd_stmt_bind_result(stmt,bind) (stmt)->m->bind_result((stmt), (bind))
#define mysqlnd_stmt_bind_param(stmt,bind) (stmt)->m->bind_param((stmt), (bind) TSRMLS_CC)
#define mysqlnd_stmt_bind_result(stmt,bind) (stmt)->m->bind_result((stmt), (bind) TSRMLS_CC)
#define mysqlnd_stmt_param_metadata(stmt) (stmt)->m->get_parameter_metadata((stmt))
#define mysqlnd_stmt_result_metadata(stmt) (stmt)->m->get_result_metadata((stmt))
#define mysqlnd_stmt_result_metadata(stmt) (stmt)->m->get_result_metadata((stmt) TSRMLS_CC)
#define mysqlnd_stmt_free_result(stmt) (stmt)->m->free_result((stmt) TSRMLS_CC)
#define mysqlnd_stmt_close(stmt, implicit) (stmt)->m->dtor((stmt), (implicit) TSRMLS_CC)
#define mysqlnd_stmt_reset(stmt) (stmt)->m->reset((stmt) TSRMLS_CC)
#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_attr_get(stmt, attr, value) (stmt)->m->get_attribute((stmt), (attr), (value) TSRMLS_CC)
#define mysqlnd_stmt_attr_set(stmt, attr, value) (stmt)->m->set_attribute((stmt), (attr), (value) TSRMLS_CC)
#define mysqlnd_stmt_fetch(stmt, fetched) (stmt)->m->fetch((stmt), (fetched) TSRMLS_CC)
@ -857,21 +266,29 @@ PHPAPI ulong mysqlnd_old_escape_string(char *newstr, const char *escapestr, int
PHPAPI void _mysqlnd_get_client_stats(zval *return_value TSRMLS_DC ZEND_FILE_LINE_DC);
/* Persistent caching zval allocator */
PHPAPI MYSQLND_ZVAL_PCACHE* mysqlnd_palloc_init_cache(unsigned int cache_size);
PHPAPI void mysqlnd_palloc_free_cache(MYSQLND_ZVAL_PCACHE *cache);
PHPAPI void mysqlnd_palloc_stats(const MYSQLND_ZVAL_PCACHE * const cache, zval *return_value);
#define mysqlnd_palloc_init_cache(size) _mysqlnd_palloc_init_cache((size) TSRMLS_CC)
#define mysqlnd_palloc_free_cache(cache) _mysqlnd_palloc_free_cache((cache) TSRMLS_CC)
PHPAPI MYSQLND_ZVAL_PCACHE* _mysqlnd_palloc_init_cache(unsigned int cache_size TSRMLS_DC);
PHPAPI void _mysqlnd_palloc_free_cache(MYSQLND_ZVAL_PCACHE *cache TSRMLS_DC);
PHPAPI void mysqlnd_palloc_stats(const MYSQLND_ZVAL_PCACHE * const cache,
zval *return_value);
PHPAPI MYSQLND_THD_ZVAL_PCACHE * mysqlnd_palloc_rinit(MYSQLND_ZVAL_PCACHE * cache);
PHPAPI void mysqlnd_palloc_rshutdown(MYSQLND_THD_ZVAL_PCACHE * cache);
#define mysqlnd_palloc_rinit(cache) _mysqlnd_palloc_rinit((cache) TSRMLS_CC)
#define mysqlnd_palloc_rshutdown(cache) _mysqlnd_palloc_rshutdown((cache) TSRMLS_CC)
PHPAPI MYSQLND_THD_ZVAL_PCACHE * _mysqlnd_palloc_rinit(MYSQLND_ZVAL_PCACHE * cache TSRMLS_DC);
PHPAPI void _mysqlnd_palloc_rshutdown(MYSQLND_THD_ZVAL_PCACHE * cache TSRMLS_DC);
PHPAPI MYSQLND_THD_ZVAL_PCACHE* mysqlnd_palloc_init_thd_cache(MYSQLND_ZVAL_PCACHE * const cache);
MYSQLND_THD_ZVAL_PCACHE* mysqlnd_palloc_get_thd_cache_reference(MYSQLND_THD_ZVAL_PCACHE * const cache);
PHPAPI void mysqlnd_palloc_free_thd_cache_reference(MYSQLND_THD_ZVAL_PCACHE **cache);
#define mysqlnd_palloc_init_thd_cache(cache) _mysqlnd_palloc_init_thd_cache((cache) TSRMLS_CC)
#define mysqlnd_palloc_free_thd_cache_reference(cache) _mysqlnd_palloc_free_thd_cache_reference((cache) TSRMLS_CC)
PHPAPI MYSQLND_THD_ZVAL_PCACHE* _mysqlnd_palloc_init_thd_cache(MYSQLND_ZVAL_PCACHE * const cache TSRMLS_DC);
MYSQLND_THD_ZVAL_PCACHE* mysqlnd_palloc_get_thd_cache_reference(MYSQLND_THD_ZVAL_PCACHE * const cache);
PHPAPI void _mysqlnd_palloc_free_thd_cache_reference(MYSQLND_THD_ZVAL_PCACHE **cache TSRMLS_DC);
/* There two should not be used from outside */
void * mysqlnd_palloc_get_zval(MYSQLND_THD_ZVAL_PCACHE * const cache, zend_bool *allocated);
void * mysqlnd_palloc_get_zval(MYSQLND_THD_ZVAL_PCACHE * const cache, zend_bool *allocated TSRMLS_DC);
void mysqlnd_palloc_zval_ptr_dtor(zval **zv, MYSQLND_THD_ZVAL_PCACHE * const cache,
enum_mysqlnd_res_type type, zend_bool *copy_ctor_called TSRMLS_DC);
@ -908,8 +325,15 @@ void mysqlnd_qcache_put(MYSQLND_QCACHE * const cache, char * query, size_t qu
ZEND_BEGIN_MODULE_GLOBALS(mysqlnd)
zend_bool collect_statistics;
zend_bool collect_memory_statistics;
char* debug; /* The actual string */
MYSQLND_DEBUG *dbg; /* The DBG object */
long net_cmd_buffer_size;
long net_read_buffer_size;
ZEND_END_MODULE_GLOBALS(mysqlnd)
ZEND_EXTERN_MODULE_GLOBALS(mysqlnd);
#ifdef ZTS
#define MYSQLND_G(v) TSRMG(mysqlnd_globals_id, zend_mysqlnd_globals *, v)
#else

View File

@ -21,10 +21,11 @@
#include "php_globals.h"
#include "mysqlnd.h"
#include "mysqlnd_priv.h"
#include "mysqlnd_debug.h"
/* {{{ utf8 functions */
static uint check_mb_utf8(const char *start, const char *end)
static uint check_mb_utf8_sequence(const char *start, const char *end)
{
zend_uchar c;
@ -62,6 +63,11 @@ static uint check_mb_utf8(const char *start, const char *end)
return 0;
}
static uint check_mb_utf8_valid(const char *start, const char *end)
{
uint len = check_mb_utf8_sequence(start, end);
return (len > 1)? len:0;
}
static uint mysqlnd_mbcharlen_utf8(uint utf8)
{
@ -93,7 +99,7 @@ static uint mysqlnd_mbcharlen_utf8(uint utf8)
static uint check_mb_big5(const char *start, const char *end)
{
return ((end - start) > 1 && valid_big5head(*(start)) && valid_big5tail(*(start + 1)) ? 2 : 0);
return (valid_big5head(*(start)) && (end - start) > 1 && valid_big5tail(*(start + 1)) ? 2 : 0);
}
@ -111,14 +117,14 @@ static uint mysqlnd_mbcharlen_big5(uint big5)
static uint check_mb_cp932(const char *start, const char *end)
{
return (((end > start) + 1) && valid_cp932head((uint)start[0]) &&
valid_cp932tail((uint)start[1])) ? 2 : 0;
return (valid_cp932head((zend_uchar)start[0]) && (end - start > 1) &&
valid_cp932tail((zend_uchar)start[1])) ? 2 : 0;
}
static uint mysqlnd_mbcharlen_cp932(uint cp932)
{
return (valid_cp932head(cp932)) ? 2 : 1;
return (valid_cp932head((zend_uchar)cp932)) ? 2 : 1;
}
/* }}} */
@ -156,7 +162,7 @@ static uint mysqlnd_mbcharlen_euckr(uint kr)
static uint check_mb_eucjpms(const char *start, const char *end)
{
if (*((uint *)start) < 0x80) {
if (*((zend_uchar *)start) < 0x80) {
return 0; /* invalid eucjpms character */
}
if (valid_eucjpms(start[0]) && (end - start) > 1 && valid_eucjpms(start[1])) {
@ -187,13 +193,13 @@ static uint mysqlnd_mbcharlen_eucjpms(uint jpms)
/* {{{ gb2312 functions */
#define valid_gb2312_head(c) (0xA1 <= (c) && (c) <= 0xF7)
#define valid_gb2312_tail(c) (0xA1 <= (c) && (c) <= 0xFE)
#define valid_gb2312_head(c) (0xA1 <= (zend_uchar)(c) && (zend_uchar)(c) <= 0xF7)
#define valid_gb2312_tail(c) (0xA1 <= (zend_uchar)(c) && (zend_uchar)(c) <= 0xFE)
static uint check_mb_gb2312(const char *start, const char *end)
{
return (end - start > 1 || valid_gb2312_head((uint)start[0]) ||
return (valid_gb2312_head((uint)start[0]) && end - start > 1 &&
valid_gb2312_tail((uint)start[1])) ? 2 : 0;
}
@ -206,15 +212,12 @@ static uint mysqlnd_mbcharlen_gb2312(uint gb)
/* {{{ gbk functions */
#define valid_gbk_head(c) ((uint)(c) >> 8)
#define valid_gbk_tail(c) ((uint)(c) & 0xFF)
#define valid_gbk_head(c) (0x81<=(zend_uchar)(c) && (zend_uchar)(c)<=0xFE)
#define valid_gbk_tail(c) ((0x40<=(zend_uchar)(c) && (zend_uchar)(c)<=0x7E) || (0x80<=(zend_uchar)(c) && (zend_uchar)(c)<=0xFE))
static uint check_mb_gbk(const char *start, const char *end)
{
if (end - start <= 1) {
return 0; /* invalid length */
}
return (valid_gbk_head(start[0]) && valid_gbk_tail(start[1])) ? 2 : 0;
return (valid_gbk_head(start[0]) && (end) - (start) > 1 && valid_gbk_tail(start[1])) ? 2 : 0;
}
static uint mysqlnd_mbcharlen_gbk(uint gbk)
@ -223,6 +226,7 @@ static uint mysqlnd_mbcharlen_gbk(uint gbk)
}
/* }}} */
/* {{{ sjis functions */
#define valid_sjis_head(c) ((0x81 <= (c) && (c) <= 0x9F) && \
(0xE0 <= (c) && (c) <= 0xFC))
@ -232,16 +236,13 @@ static uint mysqlnd_mbcharlen_gbk(uint gbk)
static uint check_mb_sjis(const char *start, const char *end)
{
if (end - start <= 1) {
return 0;
}
return (valid_sjis_head((uint)start[0]) && valid_sjis_tail((uint)start[1])) ? 2 : 0;
return (valid_sjis_head((zend_uchar)start[0]) && (end - start) > 1 && valid_sjis_tail((zend_uchar)start[1])) ? 2 : 0;
}
static uint mysqlnd_mbcharlen_sjis(uint sjis)
{
return (valid_sjis_head((uint)sjis)) ? 2 : 1;
return (valid_sjis_head((zend_uchar)sjis)) ? 2 : 1;
}
/* }}} */
@ -267,7 +268,7 @@ static uint mysqlnd_mbcharlen_ucs2(uint ucs2 __attribute((unused)))
static uint check_mb_ujis(const char *start, const char *end)
{
if ((uint)start[0] < 0x80) {
if (*(uchar*)start < 0x80) {
return 0; /* invalid ujis character */
}
if (valid_ujis(*(start)) && valid_ujis(*((start)+1))) {
@ -276,8 +277,7 @@ static uint check_mb_ujis(const char *start, const char *end)
if (valid_ujis_ss2(*(start)) && valid_ujis_kata(*((start)+1))) {
return 2;
}
if (valid_ujis_ss3(*(start)) && (end-start) > 2 && valid_ujis(*((start)+1))
&& valid_ujis(*((start)+2))) {
if (valid_ujis_ss3(*(start)) && (end-start) > 2 && valid_ujis(*((start)+1)) && valid_ujis(*((start)+2))) {
return 3;
}
return 0;
@ -286,14 +286,7 @@ static uint check_mb_ujis(const char *start, const char *end)
static uint mysqlnd_mbcharlen_ujis(uint ujis)
{
if (((ujis & 0xFF) >= 0xA1 && (ujis & 0xFF) <= 0xFE) ||
((ujis & 0xFF) == 0x8E)) {
return 2;
}
if ((ujis & 0xFF) == 0x8F) {
return 3;
}
return 1;
return (valid_ujis(ujis)? 2: valid_ujis_ss2(ujis)? 2: valid_ujis_ss3(ujis)? 3: 1);
}
/* }}} */
@ -315,7 +308,7 @@ const MYSQLND_CHARSET mysqlnd_charsets[] =
{ 13, "sjis", "sjis_japanese_ci", 1, 2, 0, mysqlnd_mbcharlen_sjis, check_mb_sjis},
{ 16, "hebrew", "hebrew_general_ci", 1, 1, 0, NULL, NULL},
{ 18, "tis620", "tis620_thai_ci", 1, 1, 0, NULL, NULL},
{ 19, "euckr", "euckr_korean_ci", 1, 2, 0, mysqlnd_mbcharlen_euckr, check_mb_eucjpms},
{ 19, "euckr", "euckr_korean_ci", 1, 2, 0, mysqlnd_mbcharlen_euckr, check_mb_euckr},
{ 22, "koi8u", "koi8u_general_ci", 1, 1, 0, NULL, NULL},
{ 24, "gb2312", "gb2312_chinese_ci", 1, 2, 0, mysqlnd_mbcharlen_gb2312, check_mb_gb2312},
{ 25, "greek", "greek_general_ci", 1, 1, 0, NULL, NULL},
@ -323,7 +316,7 @@ const MYSQLND_CHARSET mysqlnd_charsets[] =
{ 28, "gbk", "gbk_chinese_ci", 1, 2, 0, mysqlnd_mbcharlen_gbk, check_mb_gbk},
{ 30, "latin5", "latin5_turkish_ci", 1, 1, 0, NULL, NULL},
{ 32, "armscii8", "armscii8_general_ci", 1, 1, 0, NULL, NULL},
{ 33, "utf8", "utf8_general_ci", 1, 2, 0, mysqlnd_mbcharlen_utf8, check_mb_utf8},
{ 33, "utf8", "utf8_general_ci", 1, 2, 0, mysqlnd_mbcharlen_utf8, check_mb_utf8_valid},
{ 35, "ucs2", "ucs2_general_ci", 2, 2, 0, mysqlnd_mbcharlen_ucs2, check_mb_ucs2},
{ 36, "cp866", "cp866_general_ci", 1, 1, 0, NULL, NULL},
{ 37, "keybcs2", "keybcs2_general_ci", 1, 1, 0, NULL, NULL},
@ -337,7 +330,7 @@ const MYSQLND_CHARSET mysqlnd_charsets[] =
{ 63, "binary", "binary", 1, 1, 0, NULL, NULL},
{ 92, "geostd8", "geostd8_general_ci", 1, 1, 0, NULL, NULL},
{ 95, "cp932", "cp932_japanese_ci", 1, 2, 1, mysqlnd_mbcharlen_cp932, check_mb_cp932},
{ 97, "eucjpms", "eucjpms_japanese_ci", 1, 3, 0, mysqlnd_mbcharlen_eucjpms, },
{ 97, "eucjpms", "eucjpms_japanese_ci", 1, 3, 0, mysqlnd_mbcharlen_eucjpms, check_mb_eucjpms},
{ 2, "latin2", "latin2_czech_cs", 1, 1, 0, NULL, NULL},
{ 5, "latin1", "latin1_german_ci", 1, 1, 0, NULL, NULL},
{ 14, "cp1251", "cp1251_bulgarian_ci", 1, 1, 0, NULL, NULL},
@ -379,7 +372,7 @@ const MYSQLND_CHARSET mysqlnd_charsets[] =
{ 81, "cp852", "cp852_bin", 1, 1, 0, NULL, NULL},
{ 82, "swe7", "swe7_bin", 1, 1, 0, NULL, NULL},
{ 93, "geostd8", "geostd8_bin", 1, 1, 0, NULL, NULL},
{ 83, "utf8", "utf8_bin", 1, 2, 0, mysqlnd_mbcharlen_utf8, check_mb_utf8},
{ 83, "utf8", "utf8_bin", 1, 2, 0, mysqlnd_mbcharlen_utf8, check_mb_utf8_valid},
{ 84, "big5", "big5_bin", 1, 2, 0, mysqlnd_mbcharlen_big5, check_mb_big5},
{ 85, "euckr", "euckr_bin", 1, 2, 0, mysqlnd_mbcharlen_euckr, check_mb_euckr},
{ 86, "gb2312", "gb2312_bin", 1, 2, 0, mysqlnd_mbcharlen_gb2312, check_mb_gb2312},
@ -411,26 +404,26 @@ const MYSQLND_CHARSET mysqlnd_charsets[] =
{ 144, "ucs2", "ucs2_persian_ci", 2, 2, 0, mysqlnd_mbcharlen_ucs2, check_mb_ucs2},
{ 145, "ucs2", "ucs2_esperanto_ci", 2, 2, 0, mysqlnd_mbcharlen_ucs2, check_mb_ucs2},
{ 146, "ucs2", "ucs2_hungarian_ci", 2, 2, 0, mysqlnd_mbcharlen_ucs2, check_mb_ucs2},
{ 192, "utf8", "utf8_general_ci", 1, 3, 0, mysqlnd_mbcharlen_utf8, check_mb_utf8},
{ 193, "utf8", "utf8_icelandic_ci", 1, 3, 0, mysqlnd_mbcharlen_utf8, check_mb_utf8},
{ 194, "utf8", "utf8_latvian_ci", 1, 3, 0, mysqlnd_mbcharlen_utf8, check_mb_utf8},
{ 195, "utf8", "utf8_romanian_ci", 1, 3, 0, mysqlnd_mbcharlen_utf8, check_mb_utf8},
{ 196, "utf8", "utf8_slovenian_ci", 1, 3, 0, mysqlnd_mbcharlen_utf8, check_mb_utf8},
{ 197, "utf8", "utf8_polish_ci", 1, 3, 0, mysqlnd_mbcharlen_utf8, check_mb_utf8},
{ 198, "utf8", "utf8_estonian_ci", 1, 3, 0, mysqlnd_mbcharlen_utf8, check_mb_utf8},
{ 119, "utf8", "utf8_spanish_ci", 1, 3, 0, mysqlnd_mbcharlen_utf8, check_mb_utf8},
{ 200, "utf8", "utf8_swedish_ci", 1, 3, 0, mysqlnd_mbcharlen_utf8, check_mb_utf8},
{ 201, "utf8", "utf8_turkish_ci", 1, 3, 0, mysqlnd_mbcharlen_utf8, check_mb_utf8},
{ 202, "utf8", "utf8_czech_ci", 1, 3, 0, mysqlnd_mbcharlen_utf8, check_mb_utf8},
{ 203, "utf8", "utf8_danish_ci", 1, 3, 0, mysqlnd_mbcharlen_utf8, check_mb_utf8 },
{ 204, "utf8", "utf8_lithunian_ci", 1, 3, 0, mysqlnd_mbcharlen_utf8, check_mb_utf8 },
{ 205, "utf8", "utf8_slovak_ci", 1, 3, 0, mysqlnd_mbcharlen_utf8, check_mb_utf8},
{ 206, "utf8", "utf8_spanish2_ci", 1, 3, 0, mysqlnd_mbcharlen_utf8, check_mb_utf8},
{ 207, "utf8", "utf8_roman_ci", 1, 3, 0, mysqlnd_mbcharlen_utf8, check_mb_utf8},
{ 208, "utf8", "utf8_persian_ci", 1, 3, 0, mysqlnd_mbcharlen_utf8, check_mb_utf8},
{ 209, "utf8", "utf8_esperanto_ci", 1, 3, 0, mysqlnd_mbcharlen_utf8, check_mb_utf8},
{ 210, "utf8", "utf8_hungarian_ci", 1, 3, 0, mysqlnd_mbcharlen_utf8, check_mb_utf8},
{ 254, "utf8", "utf8_general_cs", 1, 2, 0, mysqlnd_mbcharlen_utf8, check_mb_utf8 },
{ 192, "utf8", "utf8_general_ci", 1, 3, 0, mysqlnd_mbcharlen_utf8, check_mb_utf8_valid},
{ 193, "utf8", "utf8_icelandic_ci", 1, 3, 0, mysqlnd_mbcharlen_utf8, check_mb_utf8_valid},
{ 194, "utf8", "utf8_latvian_ci", 1, 3, 0, mysqlnd_mbcharlen_utf8, check_mb_utf8_valid},
{ 195, "utf8", "utf8_romanian_ci", 1, 3, 0, mysqlnd_mbcharlen_utf8, check_mb_utf8_valid},
{ 196, "utf8", "utf8_slovenian_ci", 1, 3, 0, mysqlnd_mbcharlen_utf8, check_mb_utf8_valid},
{ 197, "utf8", "utf8_polish_ci", 1, 3, 0, mysqlnd_mbcharlen_utf8, check_mb_utf8_valid},
{ 198, "utf8", "utf8_estonian_ci", 1, 3, 0, mysqlnd_mbcharlen_utf8, check_mb_utf8_valid},
{ 119, "utf8", "utf8_spanish_ci", 1, 3, 0, mysqlnd_mbcharlen_utf8, check_mb_utf8_valid},
{ 200, "utf8", "utf8_swedish_ci", 1, 3, 0, mysqlnd_mbcharlen_utf8, check_mb_utf8_valid},
{ 201, "utf8", "utf8_turkish_ci", 1, 3, 0, mysqlnd_mbcharlen_utf8, check_mb_utf8_valid},
{ 202, "utf8", "utf8_czech_ci", 1, 3, 0, mysqlnd_mbcharlen_utf8, check_mb_utf8_valid},
{ 203, "utf8", "utf8_danish_ci", 1, 3, 0, mysqlnd_mbcharlen_utf8, check_mb_utf8_valid },
{ 204, "utf8", "utf8_lithunian_ci", 1, 3, 0, mysqlnd_mbcharlen_utf8, check_mb_utf8_valid },
{ 205, "utf8", "utf8_slovak_ci", 1, 3, 0, mysqlnd_mbcharlen_utf8, check_mb_utf8_valid},
{ 206, "utf8", "utf8_spanish2_ci", 1, 3, 0, mysqlnd_mbcharlen_utf8, check_mb_utf8_valid},
{ 207, "utf8", "utf8_roman_ci", 1, 3, 0, mysqlnd_mbcharlen_utf8, check_mb_utf8_valid},
{ 208, "utf8", "utf8_persian_ci", 1, 3, 0, mysqlnd_mbcharlen_utf8, check_mb_utf8_valid},
{ 209, "utf8", "utf8_esperanto_ci", 1, 3, 0, mysqlnd_mbcharlen_utf8, check_mb_utf8_valid},
{ 210, "utf8", "utf8_hungarian_ci", 1, 3, 0, mysqlnd_mbcharlen_utf8, check_mb_utf8_valid},
{ 254, "utf8", "utf8_general_cs", 1, 2, 0, mysqlnd_mbcharlen_utf8, check_mb_utf8_valid },
{ 0, NULL, NULL, 0, 0, 0, NULL, NULL}
};
/* }}} */
@ -469,19 +462,21 @@ PHPAPI const MYSQLND_CHARSET * mysqlnd_find_charset_name(const char * const name
/* {{{ mysqlnd_cset_escape_quotes */
PHPAPI ulong mysqlnd_cset_escape_quotes(const MYSQLND_CHARSET * const cset, char *newstr, const char *escapestr, int escapestr_len)
PHPAPI ulong mysqlnd_cset_escape_quotes(const MYSQLND_CHARSET * const cset, char *newstr,
const char *escapestr, int escapestr_len TSRMLS_DC)
{
const char *newstr_s = newstr;
const char *newstr_e = newstr + 2 * escapestr_len;
const char *end = escapestr + escapestr_len;
zend_bool escape_overflow = FALSE;
DBG_ENTER("mysqlnd_cset_escape_quotes");
for (;escapestr < end; escapestr++) {
uint len = 0;
/* check unicode characters */
if (cset->char_maxlen > 1 && cset->mb_charlen(*escapestr) > 1 &&
(len = cset->mb_valid(escapestr, end))) {
if (cset->char_maxlen > 1 && (len = cset->mb_valid(escapestr, end))) {
/* check possible overflow */
if ((newstr + len) > newstr_e) {
@ -495,7 +490,7 @@ PHPAPI ulong mysqlnd_cset_escape_quotes(const MYSQLND_CHARSET * const cset, char
escapestr--;
continue;
}
if (*newstr == '\'') {
if (*escapestr == '\'') {
if (newstr + 2 > newstr_e) {
escape_overflow = TRUE;
break;
@ -507,35 +502,36 @@ PHPAPI ulong mysqlnd_cset_escape_quotes(const MYSQLND_CHARSET * const cset, char
escape_overflow = TRUE;
break;
}
*newstr++= *escapestr;
*newstr++ = *escapestr;
}
}
*newstr = '\0';
if (escape_overflow) {
return (ulong)~0;
DBG_RETURN((ulong)~0);
}
return (ulong)(newstr - newstr_s);
DBG_RETURN((ulong)(newstr - newstr_s));
}
/* }}} */
/* {{{ mysqlnd_cset_escape_slashes */
PHPAPI ulong mysqlnd_cset_escape_slashes(const MYSQLND_CHARSET * const cset, char *newstr, const char *escapestr, int escapestr_len)
PHPAPI ulong mysqlnd_cset_escape_slashes(const MYSQLND_CHARSET * const cset, char *newstr,
const char *escapestr, int escapestr_len TSRMLS_DC)
{
const char *newstr_s = newstr;
const char *newstr_e = newstr + 2 * escapestr_len;
const char *end = escapestr + escapestr_len;
zend_bool escape_overflow = FALSE;
DBG_ENTER("mysqlnd_cset_escape_slashes");
for (;escapestr < end; escapestr++) {
char esc = '\0';
uint len = 0;
/* check unicode characters */
if (cset->char_maxlen > 1 && cset->mb_charlen(*escapestr) > 1 &&
(len = cset->mb_valid(escapestr, end))) {
if (cset->char_maxlen > 1 && (len = cset->mb_valid(escapestr, end))) {
/* check possible overflow */
if ((newstr + len) > newstr_e) {
escape_overflow = TRUE;
@ -548,8 +544,7 @@ PHPAPI ulong mysqlnd_cset_escape_slashes(const MYSQLND_CHARSET * const cset, cha
escapestr--;
continue;
}
if (cset->char_maxlen > 1 && cset->mb_charlen(*escapestr) > 1 &&
(len = cset->mb_valid(escapestr, end))) {
if (cset->char_maxlen > 1 && cset->mb_charlen(*escapestr) > 1) {
esc = *escapestr;
} else {
switch (*escapestr) {
@ -592,9 +587,9 @@ PHPAPI ulong mysqlnd_cset_escape_slashes(const MYSQLND_CHARSET * const cset, cha
*newstr = '\0';
if (escape_overflow) {
return (ulong)~0;
DBG_RETURN((ulong)~0);
}
return (ulong)(newstr - newstr_s);
DBG_RETURN((ulong)(newstr - newstr_s));
}
/* }}} */

View File

@ -19,10 +19,10 @@
*/
PHPAPI ulong mysqlnd_cset_escape_quotes(const MYSQLND_CHARSET * const charset, char *newstr,
const char *escapestr, int escapestr_len);
const char *escapestr, int escapestr_len TSRMLS_DC);
PHPAPI ulong mysqlnd_cset_escape_slashes(const MYSQLND_CHARSET * const cset, char *newstr,
const char *escapestr, int escapestr_len);
const char *escapestr, int escapestr_len TSRMLS_DC);
/*

1338
ext/mysqlnd/mysqlnd_debug.c Normal file

File diff suppressed because it is too large Load Diff

147
ext/mysqlnd/mysqlnd_debug.h Normal file
View File

@ -0,0 +1,147 @@
/*
+----------------------------------------------------------------------+
| PHP Version 6 |
+----------------------------------------------------------------------+
| Copyright (c) 2006-2007 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: Georg Richter <georg@mysql.com> |
| Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
+----------------------------------------------------------------------+
*/
/* $Id$ */
#ifndef MYSQLND_DEBUG_H
#define MYSQLND_DEBUG_H
#include "zend_stack.h"
#define MYSQLND_DEBUG_MEMORY 1
struct st_mysqlnd_debug_methods
{
enum_func_status (*open)(MYSQLND_DEBUG *self, zend_bool reopen);
void (*set_mode)(MYSQLND_DEBUG *self, const char * const mode);
enum_func_status (*log)(MYSQLND_DEBUG *self, unsigned int line, const char * const file,
unsigned int level, const char * type, const char *message);
enum_func_status (*log_va)(MYSQLND_DEBUG *self, unsigned int line, const char * const file,
unsigned int level, const char * type, const char *format, ...);
zend_bool (*func_enter)(MYSQLND_DEBUG *self, unsigned int line, const char * const file,
char * func_name, size_t func_name_len);
enum_func_status (*func_leave)(MYSQLND_DEBUG *self, unsigned int line, const char * const file);
enum_func_status (*close)(MYSQLND_DEBUG *self);
enum_func_status (*free)(MYSQLND_DEBUG *self);
};
struct st_mysqlnd_debug
{
php_stream *stream;
#ifdef ZTS
TSRMLS_D;
#endif
unsigned int flags;
unsigned int nest_level_limit;
int pid;
char * file_name;
zend_stack call_stack;
HashTable not_filtered_functions;
struct st_mysqlnd_debug_methods *m;
};
MYSQLND_DEBUG *mysqlnd_debug_init(TSRMLS_D);
#define MYSQLND_MEM_D TSRMLS_DC ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC
void * _mysqlnd_emalloc(size_t size MYSQLND_MEM_D);
void * _mysqlnd_pemalloc(size_t size, zend_bool persistent MYSQLND_MEM_D);
void * _mysqlnd_ecalloc(uint nmemb, size_t size MYSQLND_MEM_D);
void * _mysqlnd_pecalloc(uint nmemb, size_t size, zend_bool persistent MYSQLND_MEM_D);
void * _mysqlnd_erealloc(void *ptr, size_t new_size MYSQLND_MEM_D);
void * _mysqlnd_perealloc(void *ptr, size_t new_size, zend_bool persistent MYSQLND_MEM_D);
void _mysqlnd_efree(void *ptr MYSQLND_MEM_D);
void _mysqlnd_pefree(void *ptr, zend_bool persistent MYSQLND_MEM_D);
void * _mysqlnd_malloc(size_t size MYSQLND_MEM_D);
void * _mysqlnd_calloc(uint nmemb, size_t size MYSQLND_MEM_D);
void * _mysqlnd_realloc(void *ptr, size_t new_size MYSQLND_MEM_D);
void _mysqlnd_free(void *ptr MYSQLND_MEM_D);
char * mysqlnd_get_backtrace(TSRMLS_D);
#if PHP_DEBUG && !defined(PHP_WIN32)
#define DBG_INF(msg) do { if (dbg_skip_trace == FALSE) MYSQLND_G(dbg)->m->log(MYSQLND_G(dbg), __LINE__, __FILE__, -1, "info : ", (msg)); } while (0)
#define DBG_ERR(msg) do { if (dbg_skip_trace == FALSE) MYSQLND_G(dbg)->m->log(MYSQLND_G(dbg), __LINE__, __FILE__, -1, "error: ", (msg)); } while (0)
#define DBG_INF_FMT(...) do { if (dbg_skip_trace == FALSE) MYSQLND_G(dbg)->m->log_va(MYSQLND_G(dbg), __LINE__, __FILE__, -1, "info : ", __VA_ARGS__); } while (0)
#define DBG_ERR_FMT(...) do { if (dbg_skip_trace == FALSE) MYSQLND_G(dbg)->m->log_va(MYSQLND_G(dbg), __LINE__, __FILE__, -1, "error: ", __VA_ARGS__); } while (0)
#define DBG_ENTER(func_name) zend_bool dbg_skip_trace = TRUE; if (MYSQLND_G(dbg)) dbg_skip_trace = !MYSQLND_G(dbg)->m->func_enter(MYSQLND_G(dbg), __LINE__, __FILE__, func_name, strlen(func_name));
#define DBG_RETURN(value) do { if (MYSQLND_G(dbg)) MYSQLND_G(dbg)->m->func_leave(MYSQLND_G(dbg), __LINE__, __FILE__); return (value); } while (0)
#define DBG_VOID_RETURN do { if (MYSQLND_G(dbg)) MYSQLND_G(dbg)->m->func_leave(MYSQLND_G(dbg), __LINE__, __FILE__); return; } while (0)
#else
#define DBG_INF(msg)
#define DBG_ERR(msg)
#define DBG_INF_FMT(...)
#define DBG_ERR_FMT(...)
#define DBG_ENTER(func_name)
#define DBG_RETURN(value) return (value)
#define DBG_VOID_RETURN return;
#endif
#if MYSQLND_DEBUG_MEMORY
#define mnd_emalloc(size) _mysqlnd_emalloc((size) TSRMLS_CC ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
#define mnd_pemalloc(size, pers) _mysqlnd_pemalloc((size), (pers) TSRMLS_CC ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
#define mnd_ecalloc(nmemb, size) _mysqlnd_ecalloc((nmemb), (size) TSRMLS_CC ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
#define mnd_pecalloc(nmemb, size, p) _mysqlnd_pecalloc((nmemb), (size), (p) TSRMLS_CC ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
#define mnd_erealloc(ptr, new_size) _mysqlnd_erealloc((ptr), (new_size) TSRMLS_CC ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
#define mnd_perealloc(ptr, new_size, p) _mysqlnd_perealloc((ptr), (new_size), (p) TSRMLS_CC ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
#define mnd_efree(ptr) _mysqlnd_efree((ptr) TSRMLS_CC ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
#define mnd_pefree(ptr, pers) _mysqlnd_pefree((ptr), (pers) TSRMLS_CC ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
#define mnd_malloc(size) _mysqlnd_malloc((size) TSRMLS_CC ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
#define mnd_calloc(nmemb, size) _mysqlnd_calloc((nmemb), (size) TSRMLS_CC ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
#define mnd_realloc(ptr, new_size) _mysqlnd_realloc((ptr), (new_size) TSRMLS_CC ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
#define mnd_free(ptr) _mysqlnd_free((ptr) TSRMLS_CC ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
#else
#define mnd_emalloc(size) emalloc((size))
#define mnd_pemalloc(size, pers) pemalloc((size), (pers))
#define mnd_ecalloc(nmemb, size) ecalloc((nmemb), (size))
#define mnd_pecalloc(nmemb, size, p) pecalloc((nmemb), (size), (p))
#define mnd_erealloc(ptr, new_size) erealloc((ptr), (new_size))
#define mnd_perealloc(ptr, new_size, p) perealloc((ptr), (new_size), (p))
#define mnd_efree(ptr) efree((ptr))
#define mnd_pefree(ptr, pers) pefree((ptr), (pers))
#define mnd_malloc(size) malloc((size))
#define mnd_calloc(nmemb, size) calloc((nmemb), (size))
#define mnd_realloc(ptr, new_size) realloc((ptr), (new_size))
#define mnd_free(ptr) free((ptr))
#endif
#endif /* MYSQLND_DEBUG_H */
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
*/

View File

@ -114,10 +114,14 @@ typedef enum mysqlnd_option
MYSQL_REPORT_DATA_TRUNCATION,
MYSQL_OPT_RECONNECT,
MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
#if PHP_MAJOR_VERSION >= 6
MYSQLND_OPT_NUMERIC_AND_DATETIME_AS_UNICODE = 200,
#endif
#ifdef MYSQLND_STRING_TO_INT_CONVERSION
MYSQLND_OPT_INT_AND_YEAR_AS_INT = 201,
#endif
MYSQLND_OPT_NET_CMD_BUFFER_SIZE = 202,
MYSQLND_OPT_NET_READ_BUFFER_SIZE = 203,
} enum_mysqlnd_option;
@ -218,6 +222,138 @@ typedef enum mysqlnd_server_option
/* see mysqlnd_charset.c for more information */
#define MYSQLND_BINARY_CHARSET_NR 63
/*
/-----> CONN_CLOSE <---------------\
| ^ \
| | \
CONN_READY -> CONN_QUERY_SENT -> CONN_FETCHING_DATA
^ |
\-------------------------------------/
*/
typedef enum mysqlnd_connection_state
{
CONN_ALLOCED = 0,
CONN_READY,
CONN_QUERY_SENT,
CONN_SENDING_LOAD_DATA,
CONN_FETCHING_DATA,
CONN_NEXT_RESULT_PENDING,
CONN_QUIT_SENT, /* object is "destroyed" at this stage */
} enum_mysqlnd_connection_state;
typedef enum mysqlnd_stmt_state
{
MYSQLND_STMT_INITTED = 0,
MYSQLND_STMT_PREPARED,
MYSQLND_STMT_EXECUTED,
MYSQLND_STMT_WAITING_USE_OR_STORE,
MYSQLND_STMT_USE_OR_STORE_CALLED,
MYSQLND_STMT_USER_FETCHING, /* fetch_row_buff or fetch_row_unbuf */
} enum_mysqlnd_stmt_state;
typedef enum param_bind_flags
{
MYSQLND_PARAM_BIND_BLOB_USED = 1
} enum_param_bind_flags;
/* PS */
enum mysqlnd_stmt_attr
{
STMT_ATTR_UPDATE_MAX_LENGTH,
STMT_ATTR_CURSOR_TYPE,
STMT_ATTR_PREFETCH_ROWS
};
enum myslqnd_cursor_type
{
CURSOR_TYPE_NO_CURSOR= 0,
CURSOR_TYPE_READ_ONLY= 1,
CURSOR_TYPE_FOR_UPDATE= 2,
CURSOR_TYPE_SCROLLABLE= 4
};
typedef enum mysqlnd_connection_close_type
{
MYSQLND_CLOSE_EXPLICIT = 0,
MYSQLND_CLOSE_IMPLICIT,
MYSQLND_CLOSE_DISCONNECTED,
MYSQLND_CLOSE_LAST /* for checking, should always be last */
} enum_connection_close_type;
typedef enum mysqlnd_collected_stats
{
STAT_BYTES_SENT,
STAT_BYTES_RECEIVED,
STAT_PACKETS_SENT,
STAT_PACKETS_RECEIVED,
STAT_PROTOCOL_OVERHEAD_IN,
STAT_PROTOCOL_OVERHEAD_OUT,
STAT_RSET_QUERY,
STAT_NON_RSET_QUERY,
STAT_NO_INDEX_USED,
STAT_BAD_INDEX_USED,
STAT_BUFFERED_SETS,
STAT_UNBUFFERED_SETS,
STAT_PS_BUFFERED_SETS,
STAT_PS_UNBUFFERED_SETS,
STAT_FLUSHED_NORMAL_SETS,
STAT_FLUSHED_PS_SETS,
STAT_PS_PREPARED_NEVER_EXECUTED,
STAT_PS_PREPARED_ONCE_USED,
STAT_ROWS_FETCHED_FROM_SERVER_NORMAL,
STAT_ROWS_FETCHED_FROM_SERVER_PS,
STAT_ROWS_BUFFERED_FROM_CLIENT_NORMAL,
STAT_ROWS_BUFFERED_FROM_CLIENT_PS,
STAT_ROWS_FETCHED_FROM_CLIENT_NORMAL_BUF,
STAT_ROWS_FETCHED_FROM_CLIENT_NORMAL_UNBUF,
STAT_ROWS_FETCHED_FROM_CLIENT_PS_BUF,
STAT_ROWS_FETCHED_FROM_CLIENT_PS_UNBUF,
STAT_ROWS_FETCHED_FROM_CLIENT_PS_CURSOR,
STAT_ROWS_SKIPPED_NORMAL,
STAT_ROWS_SKIPPED_PS,
STAT_COPY_ON_WRITE_SAVED,
STAT_COPY_ON_WRITE_PERFORMED,
STAT_CMD_BUFFER_TOO_SMALL,
STAT_CONNECT_SUCCESS,
STAT_CONNECT_FAILURE,
STAT_CONNECT_REUSED,
STAT_RECONNECT,
STAT_PCONNECT_SUCCESS,
STAT_OPENED_CONNECTIONS,
STAT_OPENED_PERSISTENT_CONNECTIONS,
STAT_CLOSE_EXPLICIT,
STAT_CLOSE_IMPLICIT,
STAT_CLOSE_DISCONNECT,
STAT_CLOSE_IN_MIDDLE,
STAT_FREE_RESULT_EXPLICIT,
STAT_FREE_RESULT_IMPLICIT,
STAT_STMT_CLOSE_EXPLICIT,
STAT_STMT_CLOSE_IMPLICIT,
STAT_MEM_EMALLOC_COUNT,
STAT_MEM_EMALLOC_AMMOUNT,
STAT_MEM_ECALLOC_COUNT,
STAT_MEM_ECALLOC_AMMOUNT,
STAT_MEM_EREALLOC_COUNT,
STAT_MEM_EREALLOC_AMMOUNT,
STAT_MEM_EFREE_COUNT,
STAT_MEM_MALLOC_COUNT,
STAT_MEM_MALLOC_AMMOUNT,
STAT_MEM_CALLOC_COUNT,
STAT_MEM_CALLOC_AMMOUNT,
STAT_MEM_REALLOC_COUNT,
STAT_MEM_REALLOC_AMMOUNT,
STAT_MEM_FREE_COUNT,
STAT_LAST /* Should be always the last */
} enum_mysqlnd_collected_stats;
#define MYSQLND_DEFAULT_PREFETCH_ROWS (ulong) 1
#endif /* MYSQLND_ENUM_N_DEF_H */

View File

@ -23,6 +23,7 @@
#include "mysqlnd.h"
#include "mysqlnd_wireprotocol.h"
#include "mysqlnd_priv.h"
#include "mysqlnd_debug.h"
enum_func_status mysqlnd_simple_command_handle_response(MYSQLND *conn,
enum php_mysql_packet_type ok_packet,
@ -34,7 +35,7 @@ enum_func_status mysqlnd_simple_command_handle_response(MYSQLND *conn,
if (c) {\
a = (zval ***)safe_emalloc(c, sizeof(zval **), 0);\
for (i = b; i < c; i++) {\
a[i] = emalloc(sizeof(zval *));\
a[i] = mnd_emalloc(sizeof(zval *));\
MAKE_STD_ZVAL(*a[i]);\
}\
}
@ -43,9 +44,9 @@ if (c) {\
if (a) {\
for (i=b; i < c; i++) {\
zval_ptr_dtor(a[i]);\
efree(a[i]);\
mnd_efree(a[i]);\
}\
efree(a);\
mnd_efree(a);\
}
/* {{{ mysqlnd_local_infile_init */
@ -55,14 +56,16 @@ int mysqlnd_local_infile_init(void **ptr, char *filename, void **userdata TSRMLS
MYSQLND_INFILE_INFO *info;
php_stream_context *context = NULL;
*ptr= info= ((MYSQLND_INFILE_INFO *)ecalloc(1, sizeof(MYSQLND_INFILE_INFO)));
DBG_ENTER("mysqlnd_local_infile_init");
*ptr= info= ((MYSQLND_INFILE_INFO *)mnd_ecalloc(1, sizeof(MYSQLND_INFILE_INFO)));
/* check open_basedir */
if (PG(open_basedir)) {
if (php_check_open_basedir_ex(filename, 0 TSRMLS_CC) == -1) {
strcpy(info->error_msg, "open_basedir restriction in effect. Unable to open file");
info->error_no = CR_UNKNOWN_ERROR;
return 1;
DBG_RETURN(1);
}
}
@ -72,10 +75,10 @@ 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;
return 1;
DBG_RETURN(1);
}
return 0;
DBG_RETURN(0);
}
/* }}} */
@ -87,81 +90,16 @@ int mysqlnd_local_infile_read(void *ptr, char *buf, uint buf_len TSRMLS_DC)
MYSQLND_INFILE_INFO *info = (MYSQLND_INFILE_INFO *)ptr;
int count;
/* default processing */
if (!info->callback) {
count = (int)php_stream_read(info->fd, buf, buf_len);
DBG_ENTER("mysqlnd_local_infile_read");
if (count < 0) {
strcpy(info->error_msg, "Error reading file");
info->error_no = MYSQLND_EE_READ;
}
return count;
} else {
zval ***callback_args;
zval *retval;
zval *fp;
int argc = 4;
int i;
long rc;
ALLOC_CALLBACK_ARGS(callback_args, 1, argc);
/* set parameters: filepointer, buffer, buffer_len, errormsg */
MAKE_STD_ZVAL(fp);
php_stream_to_zval(info->fd, fp);
callback_args[0] = &fp;
ZVAL_STRING(*callback_args[1], "", 1);
ZVAL_LONG(*callback_args[2], buf_len);
ZVAL_STRING(*callback_args[3], "", 1);
if (call_user_function_ex(EG(function_table),
NULL,
info->callback,
&retval,
argc,
callback_args,
0,
NULL TSRMLS_CC) == SUCCESS) {
rc = Z_LVAL_P(retval);
zval_ptr_dtor(&retval);
if (rc > 0) {
const char * msg = NULL;
if (rc >= 0 && rc != Z_STRLEN_P(*callback_args[1])) {
msg = "Mismatch between the return value of the callback and the content "
"length of the buffer.";
php_error_docref(NULL TSRMLS_CC, E_WARNING, msg);
rc = -1;
} else if (Z_STRLEN_P(*callback_args[1]) > buf_len) {
/* check buffer overflow */
msg = "Too much data returned";
rc = -1;
} else {
memcpy(buf, Z_STRVAL_P(*callback_args[1]), MIN(rc, Z_STRLEN_P(*callback_args[1])));
}
if (rc == -1) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, msg);
strcpy(info->error_msg, msg);
info->error_no = MYSQLND_EE_READ;
}
} else if (rc < 0) {
strncpy(info->error_msg, Z_STRVAL_P(*callback_args[3]), MYSQLND_ERRMSG_SIZE);
info->error_no = MYSQLND_EE_READ;
}
} else {
strcpy(info->error_msg, "Can't execute load data local init callback function");
info->error_no = MYSQLND_EE_READ;
rc = -1;
}
efree(fp);
FREE_CALLBACK_ARGS(callback_args, 1, argc);
return rc;
count = (int)php_stream_read(info->fd, buf, buf_len);
if (count < 0) {
strcpy(info->error_msg, "Error reading file");
info->error_no = CR_UNKNOWN_ERROR;
}
DBG_RETURN(count);
}
/* }}} */
@ -172,14 +110,17 @@ int mysqlnd_local_infile_error(void *ptr, char *error_buf, uint error_buf_len TS
{
MYSQLND_INFILE_INFO *info = (MYSQLND_INFILE_INFO *)ptr;
DBG_ENTER("mysqlnd_local_infile_error");
if (info) {
strncpy(error_buf, info->error_msg, error_buf_len);
return info->error_no;
DBG_INF_FMT("have info, %d", info->error_no);
DBG_RETURN(info->error_no);
}
strncpy(error_buf, "Unknown error", error_buf_len);
return CR_UNKNOWN_ERROR;
DBG_INF_FMT("no info, %d", CR_UNKNOWN_ERROR);
DBG_RETURN(CR_UNKNOWN_ERROR);
}
/* }}} */
@ -194,25 +135,21 @@ void mysqlnd_local_infile_end(void *ptr TSRMLS_DC)
/* php_stream_close segfaults on NULL */
if (info->fd) {
php_stream_close(info->fd);
info->fd = NULL;
}
efree(info);
mnd_efree(info);
}
}
/* }}} */
/* {{{ mysqlnd_local_infile_default */
PHPAPI void mysqlnd_local_infile_default(MYSQLND *conn, zend_bool free_callback)
PHPAPI void mysqlnd_local_infile_default(MYSQLND *conn)
{
conn->infile.local_infile_init = mysqlnd_local_infile_init;
conn->infile.local_infile_read = mysqlnd_local_infile_read;
conn->infile.local_infile_error = mysqlnd_local_infile_error;
conn->infile.local_infile_end = mysqlnd_local_infile_end;
conn->infile.userdata = NULL;
if (free_callback == TRUE && conn->infile.callback) {
zval_ptr_dtor(&conn->infile.callback);
conn->infile.callback = NULL;
}
}
/* }}} */
@ -245,6 +182,8 @@ mysqlnd_handle_local_infile(MYSQLND *conn, const char *filename, zend_bool *is_w
size_t ret;
MYSQLND_INFILE infile;
DBG_ENTER("mysqlnd_handle_local_infile");
if (!(conn->options.flags & CLIENT_LOCAL_FILES)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "LOAD DATA LOCAL INFILE forbidden");
/* write empty packet to server */
@ -253,15 +192,9 @@ mysqlnd_handle_local_infile(MYSQLND *conn, const char *filename, zend_bool *is_w
goto infile_error;
}
/* check if we have valid functions */
if (!conn->infile.local_infile_init || !conn->infile.local_infile_read ||
!conn->infile.local_infile_error || !conn->infile.local_infile_end) {
mysqlnd_local_infile_default(conn, FALSE);
}
infile = conn->infile;
/* allocate buffer for reading data */
buf = (char *)ecalloc(1, buflen);
buf = (char *)mnd_ecalloc(1, buflen);
*is_warning = FALSE;
@ -278,17 +211,11 @@ mysqlnd_handle_local_infile(MYSQLND *conn, const char *filename, zend_bool *is_w
goto infile_error;
}
/* pass callback handler */
if (infile.callback) {
MYSQLND_INFILE_INFO *ptr = (MYSQLND_INFILE_INFO *)info;
ptr->callback = infile.callback;
}
/* read data */
while ((bufsize = infile.local_infile_read (info, buf + MYSQLND_HEADER_SIZE,
buflen - MYSQLND_HEADER_SIZE TSRMLS_CC)) > 0) {
if ((ret = mysqlnd_stream_write_w_header(conn, buf, bufsize TSRMLS_CC)) < 0) {
DBG_ERR_FMT("Error during read : %d %s %s", CR_SERVER_LOST, UNKNOWN_SQLSTATE, lost_conn);
SET_CLIENT_ERROR(conn->error_info, CR_SERVER_LOST, UNKNOWN_SQLSTATE, lost_conn);
goto infile_error;
}
@ -303,6 +230,7 @@ mysqlnd_handle_local_infile(MYSQLND *conn, const char *filename, zend_bool *is_w
/* error during read occured */
if (bufsize < 0) {
*is_warning = TRUE;
DBG_ERR_FMT("Bufsize < 0, warning, %d %s %s", CR_SERVER_LOST, UNKNOWN_SQLSTATE, lost_conn);
strcpy(conn->error_info.sqlstate, UNKNOWN_SQLSTATE);
conn->error_info.error_no = infile.local_infile_error(info, conn->error_info.error,
sizeof(conn->error_info.error) TSRMLS_CC);
@ -319,8 +247,9 @@ infile_error:
}
(*conn->infile.local_infile_end)(info TSRMLS_CC);
efree(buf);
return result;
mnd_efree(buf);
DBG_INF_FMT("%s", result == PASS? "PASS":"FAIL");
DBG_RETURN(result);
}
/* }}} */

View File

@ -23,8 +23,11 @@
#include "mysqlnd.h"
#include "mysqlnd_priv.h"
#include "mysqlnd_palloc.h"
#include "mysqlnd_debug.h"
#define MYSQLND_SILENT
/* Used in mysqlnd_debug.c */
char * mysqlnd_palloc_zval_ptr_dtor_name = "mysqlnd_palloc_zval_ptr_dtor";
char * mysqlnd_palloc_get_zval_name = "mysqlnd_palloc_get_zval";
#ifdef ZTS
@ -43,14 +46,14 @@
#endif
/* {{{ mysqlnd_palloc_init_cache */
PHPAPI MYSQLND_ZVAL_PCACHE* mysqlnd_palloc_init_cache(unsigned int cache_size)
/* {{{ _mysqlnd_palloc_init_cache */
PHPAPI MYSQLND_ZVAL_PCACHE* _mysqlnd_palloc_init_cache(unsigned int cache_size TSRMLS_DC)
{
MYSQLND_ZVAL_PCACHE *ret = calloc(1, sizeof(MYSQLND_ZVAL_PCACHE));
unsigned int i;
#ifndef MYSQLND_SILENT
php_printf("[mysqlnd_palloc_init_cache %p]\n", ret);
#endif
DBG_ENTER("_mysqlnd_palloc_init_cache");
DBG_INF_FMT("cache=%p size=%u", ret, cache_size);
#ifdef ZTS
ret->LOCK_access = tsrm_mutex_alloc();
@ -77,9 +80,8 @@ PHPAPI MYSQLND_ZVAL_PCACHE* mysqlnd_palloc_init_cache(unsigned int cache_size)
/* 2. Add to the free list */
*(--ret->free_list.last_added) = &(ret->block[i]);
}
return ret;
DBG_RETURN(ret);
}
/* }}} */
@ -105,31 +107,32 @@ MYSQLND_ZVAL_PCACHE* mysqlnd_palloc_get_cache_reference(MYSQLND_ZVAL_PCACHE * co
to the free list after usage. We ZVAL_NULL() them when we allocate them in the
constructor of the cache.
*/
void mysqlnd_palloc_free_cache(MYSQLND_ZVAL_PCACHE *cache)
void _mysqlnd_palloc_free_cache(MYSQLND_ZVAL_PCACHE *cache TSRMLS_DC)
{
#ifndef MYSQLND_SILENT
php_printf("[mysqlnd_palloc_free_cache %p]\n", cache);
#endif
DBG_ENTER("_mysqlnd_palloc_free_cache");
DBG_INF_FMT("cache=%p", cache);
#ifdef ZTS
tsrm_mutex_free(cache->LOCK_access);
#endif
/* Data in pointed by 'block' was cleaned in RSHUTDOWN */
free(cache->block);
free(cache->free_list.ptr_line);
free(cache);
mnd_free(cache->block);
mnd_free(cache->free_list.ptr_line);
mnd_free(cache);
DBG_VOID_RETURN;
}
/* }}} */
/* {{{ mysqlnd_palloc_init_thd_cache */
PHPAPI MYSQLND_THD_ZVAL_PCACHE* mysqlnd_palloc_init_thd_cache(MYSQLND_ZVAL_PCACHE * const cache)
/* {{{ _mysqlnd_palloc_init_thd_cache */
PHPAPI MYSQLND_THD_ZVAL_PCACHE* _mysqlnd_palloc_init_thd_cache(MYSQLND_ZVAL_PCACHE * const cache TSRMLS_DC)
{
MYSQLND_THD_ZVAL_PCACHE *ret = calloc(1, sizeof(MYSQLND_THD_ZVAL_PCACHE));
#ifndef MYSQLND_SILENT
php_printf("[mysqlnd_palloc_init_thd_cache %p]\n", ret);
#endif
DBG_ENTER("_mysqlnd_palloc_init_thd_cache");
DBG_INF_FMT("ret = %p", ret);
ret->parent = mysqlnd_palloc_get_cache_reference(cache);
#ifdef ZTS
@ -143,7 +146,7 @@ PHPAPI MYSQLND_THD_ZVAL_PCACHE* mysqlnd_palloc_init_thd_cache(MYSQLND_ZVAL_PCACH
/* Backward and forward looping is possible */
ret->gc_list.last_added = ret->gc_list.ptr_line;
return ret;
DBG_RETURN(ret);
}
/* }}} */
@ -169,32 +172,33 @@ MYSQLND_THD_ZVAL_PCACHE* mysqlnd_palloc_get_thd_cache_reference(MYSQLND_THD_ZVAL
constructor of the cache.
*/
static
void mysqlnd_palloc_free_thd_cache(MYSQLND_THD_ZVAL_PCACHE *cache)
void mysqlnd_palloc_free_thd_cache(MYSQLND_THD_ZVAL_PCACHE *cache TSRMLS_DC)
{
#ifndef MYSQLND_SILENT
php_printf("[mysqlnd_palloc_free_thd_cache %p]\n", cache);
#endif
DBG_ENTER("mysqlnd_palloc_free_thd_cache");
DBG_INF_FMT("cache=%p", cache);
free(cache->gc_list.ptr_line);
free(cache);
mnd_free(cache->gc_list.ptr_line);
mnd_free(cache);
DBG_VOID_RETURN;
}
/* }}} */
/* {{{ mysqlnd_palloc_free_thd_cache_reference */
PHPAPI void mysqlnd_palloc_free_thd_cache_reference(MYSQLND_THD_ZVAL_PCACHE **cache)
/* {{{ _mysqlnd_palloc_free_thd_cache_reference */
PHPAPI void _mysqlnd_palloc_free_thd_cache_reference(MYSQLND_THD_ZVAL_PCACHE **cache TSRMLS_DC)
{
DBG_ENTER("_mysqlnd_palloc_free_thd_cache_reference");
if (*cache) {
#ifndef MYSQLND_SILENT
php_printf("[mysqlnd_palloc_free_thd_cache_reference %p] refs=%d\n", *cache, (*cache)->references);
#endif
DBG_INF_FMT("cache=%p refs=%d", *cache, (*cache)->references);
--(*cache)->parent->references;
if (--(*cache)->references == 0) {
mysqlnd_palloc_free_thd_cache(*cache);
mysqlnd_palloc_free_thd_cache(*cache TSRMLS_CC);
}
*cache = NULL;
}
DBG_VOID_RETURN;
}
/* }}} */
@ -285,15 +289,14 @@ PHPAPI void mysqlnd_palloc_free_thd_cache_reference(MYSQLND_THD_ZVAL_PCACHE **ca
/* {{{ mysqlnd_palloc_get_zval */
void *mysqlnd_palloc_get_zval(MYSQLND_THD_ZVAL_PCACHE * const thd_cache, zend_bool *allocated)
void *mysqlnd_palloc_get_zval(MYSQLND_THD_ZVAL_PCACHE * const thd_cache, zend_bool *allocated TSRMLS_DC)
{
void *ret = NULL;
#ifndef MYSQLND_SILENT
php_printf("[mysqlnd_palloc_get_zval %p] *last_added=%p free_items=%d\n",
DBG_ENTER("mysqlnd_palloc_get_zval");
DBG_INF_FMT("cache=%p *last_added=%p free_items=%d",
thd_cache, thd_cache? thd_cache->parent->free_list.last_added:NULL,
thd_cache->parent->free_items);
#endif
if (thd_cache) {
MYSQLND_ZVAL_PCACHE *cache = thd_cache->parent;
@ -328,7 +331,8 @@ void *mysqlnd_palloc_get_zval(MYSQLND_THD_ZVAL_PCACHE * const thd_cache, zend_bo
ZVAL_ADDREF(&(((mysqlnd_zval *)ret)->zv));
}
return ret;
DBG_INF_FMT("allocated=%d ret=%p", *allocated, ret);
DBG_RETURN(ret);
}
/* }}} */
@ -338,13 +342,12 @@ void mysqlnd_palloc_zval_ptr_dtor(zval **zv, MYSQLND_THD_ZVAL_PCACHE * const thd
enum_mysqlnd_res_type type, zend_bool *copy_ctor_called TSRMLS_DC)
{
MYSQLND_ZVAL_PCACHE *cache;
#ifndef MYSQLND_SILENT
php_printf("[mysqlnd_palloc_zval_ptr_dtor %p] parent_block=%p last_in_block=%p *zv=%p type=%d refc=%d\n",
DBG_ENTER("mysqlnd_palloc_zval_ptr_dtor");
DBG_INF_FMT("cache=%p parent_block=%p last_in_block=%p *zv=%p refc=%d type=%d ",
thd_cache,
thd_cache->parent? thd_cache->parent->block:NULL,
thd_cache->parent? thd_cache->parent->last_in_block:NULL,
*zv, type, ZVAL_REFCOUNT(*zv));
#endif
*zv, ZVAL_REFCOUNT(*zv), type);
*copy_ctor_called = FALSE;
/* Check whether cache is used and the zval is from the cache */
if (!thd_cache || !(cache = thd_cache->parent) || ((char *)*zv < (char *)thd_cache->parent->block ||
@ -381,7 +384,7 @@ void mysqlnd_palloc_zval_ptr_dtor(zval **zv, MYSQLND_THD_ZVAL_PCACHE * const thd
}
}
zval_ptr_dtor(zv);
return;
DBG_VOID_RETURN;
}
/* The zval is from our cache */
@ -441,26 +444,28 @@ void mysqlnd_palloc_zval_ptr_dtor(zval **zv, MYSQLND_THD_ZVAL_PCACHE * const thd
UNLOCK_PCACHE(cache);
}
DBG_VOID_RETURN;
}
/* }}} */
/* {{{ mysqlnd_palloc_rinit */
PHPAPI MYSQLND_THD_ZVAL_PCACHE * mysqlnd_palloc_rinit(MYSQLND_ZVAL_PCACHE * cache)
/* {{{ _mysqlnd_palloc_rinit */
PHPAPI MYSQLND_THD_ZVAL_PCACHE * _mysqlnd_palloc_rinit(MYSQLND_ZVAL_PCACHE * cache TSRMLS_DC)
{
return mysqlnd_palloc_init_thd_cache(cache);
}
/* }}} */
/* {{{ mysqlnd_palloc_rshutdown */
PHPAPI void mysqlnd_palloc_rshutdown(MYSQLND_THD_ZVAL_PCACHE * thd_cache)
/* {{{ _mysqlnd_palloc_rshutdown */
PHPAPI void _mysqlnd_palloc_rshutdown(MYSQLND_THD_ZVAL_PCACHE * thd_cache TSRMLS_DC)
{
MYSQLND_ZVAL_PCACHE *cache;
mysqlnd_zval **p;
#ifndef MYSQLND_SILENT
php_printf("[mysqlnd_palloc_rshutdown %p]\n", thd_cache);
#endif
DBG_ENTER("_mysqlnd_palloc_rshutdown");
DBG_INF_FMT("cache=%p", thd_cache);
if (!thd_cache || !(cache = thd_cache->parent)) {
return;
}
@ -490,6 +495,8 @@ PHPAPI void mysqlnd_palloc_rshutdown(MYSQLND_THD_ZVAL_PCACHE * thd_cache)
UNLOCK_PCACHE(cache);
mysqlnd_palloc_free_thd_cache_reference(&thd_cache);
DBG_VOID_RETURN;
}
/* }}} */

View File

@ -22,6 +22,11 @@
#ifndef MYSQLND_PALLOC_H
#define MYSQLND_PALLOC_H
/* Used in mysqlnd_debug.c */
extern char * mysqlnd_palloc_zval_ptr_dtor_name;
extern char * mysqlnd_palloc_get_zval_name;
/* Session caching allocator */
struct st_mysqlnd_zval_list {
zval **ptr_line;

View File

@ -98,8 +98,7 @@
#define CR_INVALID_PARAMETER_NO 2034
#define CR_INVALID_BUFFER_USE 2035
#define MYSQLND_EE_READ 2
#define MYSQLND_EE_FILENOTFOUND 29
#define MYSQLND_EE_FILENOTFOUND 7890
#define UNKNOWN_SQLSTATE "HY000"
@ -164,6 +163,7 @@ struct st_mysqlnd_perm_bind {
extern struct st_mysqlnd_perm_bind mysqlnd_ps_fetch_functions[MYSQL_TYPE_LAST + 1];
extern const char * mysqlnd_out_of_sync;
extern const char * mysqlnd_server_gone;
enum_func_status mysqlnd_handle_local_infile(MYSQLND *conn, const char *filename, zend_bool *is_warning TSRMLS_DC);
@ -171,9 +171,6 @@ enum_func_status mysqlnd_handle_local_infile(MYSQLND *conn, const char *filename
void _mysqlnd_init_ps_subsystem();/* This one is private, mysqlnd_library_init() will call it */
void mysqlnd_stmt_execute_store_params(MYSQLND_STMT *stmt, zend_uchar **buf, zend_uchar **p,
size_t *buf_len, unsigned int null_byte_offset);
void ps_fetch_from_1_to_8_bytes(zval *zv, const MYSQLND_FIELD * const field,
uint pack_len, zend_uchar **row, zend_bool as_unicode,
unsigned int byte_count TSRMLS_DC);

File diff suppressed because it is too large Load Diff

View File

@ -23,7 +23,7 @@
#include "mysqlnd.h"
#include "mysqlnd_wireprotocol.h"
#include "mysqlnd_priv.h"
#include "mysqlnd_debug.h"
#define MYSQLND_SILENT
@ -205,7 +205,7 @@ void ps_fetch_int32(zval *zv, const MYSQLND_FIELD * const field,
if (uval > INT_MAX) {
char *tmp, *p;
int j=10;
tmp= emalloc(11);
tmp= mnd_emalloc(11);
p= &tmp[9];
do {
*p-- = (uval % 10) + 48;
@ -354,7 +354,7 @@ void ps_fetch_time(zval *zv, const MYSQLND_FIELD * const field,
if (!as_unicode) {
#endif
ZVAL_STRINGL(zv, to, length, 1);
efree(to);
mnd_efree(to);
#if PHP_MAJOR_VERSION >= 6
} else {
ZVAL_UTF8_STRINGL(zv, to, length, ZSTR_AUTOFREE);
@ -402,7 +402,7 @@ void ps_fetch_date(zval *zv, const MYSQLND_FIELD * const field,
if (!as_unicode) {
#endif
ZVAL_STRINGL(zv, to, length, 1);
efree(to);
mnd_efree(to);
#if PHP_MAJOR_VERSION >= 6
} else {
ZVAL_UTF8_STRINGL(zv, to, length, ZSTR_AUTOFREE);
@ -458,7 +458,7 @@ void ps_fetch_datetime(zval *zv, const MYSQLND_FIELD * const field,
if (!as_unicode) {
#endif
ZVAL_STRINGL(zv, to, length, 1);
efree(to);
mnd_efree(to);
#if PHP_MAJOR_VERSION >= 6
} else {
ZVAL_UTF8_STRINGL(zv, to, length, ZSTR_AUTOFREE);
@ -653,7 +653,7 @@ void _mysqlnd_init_ps_subsystem()
/* {{{ mysqlnd_stmt_execute_store_params */
void
mysqlnd_stmt_execute_store_params(MYSQLND_STMT *stmt, zend_uchar **buf, zend_uchar **p,
size_t *buf_len, unsigned int null_byte_offset)
size_t *buf_len, unsigned int null_byte_offset TSRMLS_DC)
{
unsigned int i = 0;
unsigned left = (*buf_len - (*p - *buf));
@ -667,7 +667,7 @@ mysqlnd_stmt_execute_store_params(MYSQLND_STMT *stmt, zend_uchar **buf, zend_uch
unsigned int offset = *p - *buf;
zend_uchar *tmp_buf;
*buf_len = offset + stmt->param_count * 2 + 20;
tmp_buf = emalloc(*buf_len);
tmp_buf = mnd_emalloc(*buf_len);
memcpy(tmp_buf, *buf, offset);
*buf = tmp_buf;
@ -734,7 +734,7 @@ mysqlnd_stmt_execute_store_params(MYSQLND_STMT *stmt, zend_uchar **buf, zend_uch
unsigned int offset = *p - *buf;
zend_uchar *tmp_buf;
*buf_len = offset + data_size + 10; /* Allocate + 10 for safety */
tmp_buf = emalloc(*buf_len);
tmp_buf = mnd_emalloc(*buf_len);
memcpy(tmp_buf, *buf, offset);
*buf = tmp_buf;
/* Update our pos pointer */
@ -805,7 +805,8 @@ mysqlnd_stmt_execute_store_params(MYSQLND_STMT *stmt, zend_uchar **buf, zend_uch
/* {{{ mysqlnd_stmt_execute_generate_request */
zend_uchar* mysqlnd_stmt_execute_generate_request(MYSQLND_STMT *stmt, size_t *request_len, zend_bool *free_buffer)
zend_uchar* mysqlnd_stmt_execute_generate_request(MYSQLND_STMT *stmt, size_t *request_len,
zend_bool *free_buffer TSRMLS_DC)
{
zend_uchar *p = stmt->cmd_buffer.buffer,
*cmd_buffer = stmt->cmd_buffer.buffer;
@ -835,7 +836,7 @@ zend_uchar* mysqlnd_stmt_execute_generate_request(MYSQLND_STMT *stmt, size_t *re
int1store(p, stmt->send_types_to_server);
p++;
mysqlnd_stmt_execute_store_params(stmt, &cmd_buffer, &p, &cmd_buffer_length, null_byte_offset);
mysqlnd_stmt_execute_store_params(stmt, &cmd_buffer, &p, &cmd_buffer_length, null_byte_offset TSRMLS_CC);
*free_buffer = (cmd_buffer != stmt->cmd_buffer.buffer);
*request_len = (p - cmd_buffer);

View File

@ -27,6 +27,7 @@
#include "mysqlnd_result_meta.h"
#include "mysqlnd_statistics.h"
#include "mysqlnd_charset.h"
#include "mysqlnd_debug.h"
#include "ext/standard/basic_functions.h"
#define MYSQLND_SILENT
@ -36,8 +37,11 @@
void mysqlnd_unbuffered_free_last_data(MYSQLND_RES *result TSRMLS_DC)
{
MYSQLND_RES_UNBUFFERED *unbuf = result->unbuf;
DBG_ENTER("mysqlnd_unbuffered_free_last_data");
if (!unbuf) {
return;
DBG_VOID_RETURN;
}
if (unbuf->last_row_data) {
@ -69,6 +73,8 @@ void mysqlnd_unbuffered_free_last_data(MYSQLND_RES *result TSRMLS_DC)
efree(unbuf->last_row_buffer);
unbuf->last_row_buffer = NULL;
}
DBG_VOID_RETURN;
}
/* }}} */
@ -80,6 +86,10 @@ void mysqlnd_free_buffered_data(MYSQLND_RES *result TSRMLS_DC)
unsigned int field_count = result->field_count;
unsigned int row;
DBG_ENTER("mysqlnd_free_buffered_data");
DBG_INF_FMT("Freeing "MYSQLND_LLU_SPEC" row(s)", result->data->row_count);
DBG_INF_FMT("before: real_usage=%lu usage=%lu", zend_memory_usage(TRUE TSRMLS_CC), zend_memory_usage(FALSE TSRMLS_CC));
for (row = 0; row < result->data->row_count; row++) {
unsigned int col;
zval **current_row = current_row = set->data[row];
@ -89,12 +99,19 @@ void mysqlnd_free_buffered_data(MYSQLND_RES *result TSRMLS_DC)
zend_bool copy_ctor_called;
mysqlnd_palloc_zval_ptr_dtor(&(current_row[col]), zval_cache,
result->type, &copy_ctor_called TSRMLS_CC);
MYSQLND_INC_CONN_STATISTIC(NULL, copy_ctor_called? STAT_COPY_ON_WRITE_PERFORMED:
STAT_COPY_ON_WRITE_SAVED);
#if MYSQLND_DEBUG_MEMORY
DBG_INF_FMT("Copy_ctor_called=%d", copy_ctor_called);
#endif
MYSQLND_INC_GLOBAL_STATISTIC(copy_ctor_called? STAT_COPY_ON_WRITE_PERFORMED:
STAT_COPY_ON_WRITE_SAVED);
}
#if MYSQLND_DEBUG_MEMORY
DBG_INF("Freeing current_row & current_buffer");
#endif
pefree(current_row, set->persistent);
pefree(current_buffer, set->persistent);
}
DBG_INF("Freeing data & row_buffer");
pefree(set->data, set->persistent);
pefree(set->row_buffers, set->persistent);
set->data = NULL;
@ -104,7 +121,11 @@ void mysqlnd_free_buffered_data(MYSQLND_RES *result TSRMLS_DC)
if (set->qcache) {
mysqlnd_qcache_free_cache_reference(&set->qcache);
}
DBG_INF("Freeing set");
pefree(set, set->persistent);
DBG_INF_FMT("after: real_usage=%lu usage=%lu", zend_memory_usage(TRUE TSRMLS_CC), zend_memory_usage(FALSE TSRMLS_CC));
DBG_VOID_RETURN;
}
/* }}} */
@ -113,6 +134,8 @@ void mysqlnd_free_buffered_data(MYSQLND_RES *result TSRMLS_DC)
void
MYSQLND_METHOD(mysqlnd_res, free_result_buffers)(MYSQLND_RES *result TSRMLS_DC)
{
DBG_ENTER("mysqlnd_res::free_result_buffers");
DBG_INF_FMT("%s", result->unbuf? "unbuffered":(result->data? "buffered":"unknown"));
if (result->unbuf) {
mysqlnd_unbuffered_free_last_data(result TSRMLS_CC);
@ -127,6 +150,8 @@ MYSQLND_METHOD(mysqlnd_res, free_result_buffers)(MYSQLND_RES *result TSRMLS_DC)
efree(result->lengths);
result->lengths = NULL;
}
DBG_VOID_RETURN;
}
/* }}} */
@ -135,9 +160,12 @@ MYSQLND_METHOD(mysqlnd_res, free_result_buffers)(MYSQLND_RES *result TSRMLS_DC)
static
void mysqlnd_internal_free_result_contents(MYSQLND_RES *result TSRMLS_DC)
{
DBG_ENTER("mysqlnd_internal_free_result_contents");
result->m.free_result_buffers(result TSRMLS_CC);
if (result->row_packet) {
DBG_INF("Freeing packet");
PACKET_FREE(result->row_packet);
result->row_packet = NULL;
}
@ -150,9 +178,12 @@ void mysqlnd_internal_free_result_contents(MYSQLND_RES *result TSRMLS_DC)
}
if (result->zval_cache) {
DBG_INF("Freeing zval cache reference");
mysqlnd_palloc_free_thd_cache_reference(&result->zval_cache);
result->zval_cache = NULL;
}
DBG_VOID_RETURN;
}
/* }}} */
@ -161,6 +192,7 @@ void mysqlnd_internal_free_result_contents(MYSQLND_RES *result TSRMLS_DC)
static
void mysqlnd_internal_free_result(MYSQLND_RES *result TSRMLS_DC)
{
DBG_ENTER("mysqlnd_internal_free_result");
/*
result->conn is an address if this is an unbuffered query.
In this case, decrement the reference counter in the connection
@ -173,6 +205,8 @@ void mysqlnd_internal_free_result(MYSQLND_RES *result TSRMLS_DC)
result->m.free_result_contents(result TSRMLS_CC);
efree(result);
DBG_VOID_RETURN;
}
/* }}} */
@ -181,6 +215,8 @@ void mysqlnd_internal_free_result(MYSQLND_RES *result TSRMLS_DC)
static enum_func_status
MYSQLND_METHOD(mysqlnd_res, read_result_metadata)(MYSQLND_RES *result, MYSQLND *conn TSRMLS_DC)
{
DBG_ENTER("mysqlnd_res::read_result_metadata");
/*
Make it safe to call it repeatedly for PS -
better free and allocate a new because the number of field might change
@ -192,14 +228,14 @@ MYSQLND_METHOD(mysqlnd_res, read_result_metadata)(MYSQLND_RES *result, MYSQLND *
result->meta = NULL;
}
result->meta = mysqlnd_result_meta_init(result->field_count);
result->meta = mysqlnd_result_meta_init(result->field_count TSRMLS_CC);
/* 1. Read all fields metadata */
/* It's safe to reread without freeing */
if (FAIL == result->meta->m->read_metadata(result->meta, conn TSRMLS_CC)) {
result->m.free_result_contents(result TSRMLS_CC);
return FAIL;
DBG_RETURN(FAIL);
}
/*
@ -209,7 +245,7 @@ MYSQLND_METHOD(mysqlnd_res, read_result_metadata)(MYSQLND_RES *result, MYSQLND *
If PS, then no result set follows.
*/
return PASS;
DBG_RETURN(PASS);
}
/* }}} */
@ -221,6 +257,9 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT *stmt TSRMLS_DC
enum_func_status ret;
php_mysql_packet_rset_header rset_header;
DBG_ENTER("mysqlnd_query_read_result_set_header");
DBG_INF_FMT("stmt=%d", stmt? stmt->stmt_id:0);
ret = FAIL;
PACKET_INIT_ALLOCA(rset_header, PROT_RSET_HEADER_PACKET);
do {
@ -254,6 +293,7 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT *stmt TSRMLS_DC
switch (rset_header.field_count) {
case MYSQLND_NULL_LENGTH: { /* LOAD DATA LOCAL INFILE */
zend_bool is_warning;
DBG_INF("LOAD DATA");
conn->last_query_type = QUERY_LOAD_LOCAL;
conn->state = CONN_SENDING_LOAD_DATA;
ret = mysqlnd_handle_local_infile(conn, rset_header.info_or_local_file, &is_warning TSRMLS_CC);
@ -262,6 +302,7 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT *stmt TSRMLS_DC
break;
}
case 0: /* UPSERT */
DBG_INF("UPSERT");
conn->last_query_type = QUERY_UPSERT;
conn->field_count = rset_header.field_count;
conn->upsert_status.warning_count = rset_header.warning_count;
@ -283,8 +324,9 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT *stmt TSRMLS_DC
default:{ /* Result set */
php_mysql_packet_eof fields_eof;
MYSQLND_RES *result;
uint stat = -1;
enum_mysqlnd_collected_stats stat = STAT_LAST;
DBG_INF("Result set pending");
SET_EMPTY_MESSAGE(conn->last_message, conn->last_message_len, conn->persistent);
MYSQLND_INC_CONN_STATISTIC(&conn->stats, STAT_RSET_QUERY);
@ -297,9 +339,11 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT *stmt TSRMLS_DC
result =
conn->current_result=
mysqlnd_result_init(rset_header.field_count,
mysqlnd_palloc_get_thd_cache_reference(conn->zval_cache));
mysqlnd_palloc_get_thd_cache_reference(conn->zval_cache)
TSRMLS_CC);
} else {
if (!stmt->result) {
DBG_INF("This is 'SHOW'/'EXPLAIN'-like query.");
/*
This is 'SHOW'/'EXPLAIN'-like query. Current implementation of
prepared statements can't send result set metadata for these queries
@ -309,7 +353,8 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT *stmt TSRMLS_DC
result =
stmt->result =
mysqlnd_result_init(rset_header.field_count,
mysqlnd_palloc_get_thd_cache_reference(conn->zval_cache));
mysqlnd_palloc_get_thd_cache_reference(conn->zval_cache)
TSRMLS_CC);
} else {
/*
Update result set metadata if it for some reason changed between
@ -333,12 +378,14 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT *stmt TSRMLS_DC
efree(conn->current_result);
conn->current_result = NULL;
}
DBG_ERR("Error ocurred while reading metadata");
break;
}
/* Check for SERVER_STATUS_MORE_RESULTS if needed */
PACKET_INIT_ALLOCA(fields_eof, PROT_EOF_PACKET);
if (FAIL == (ret = PACKET_READ_ALLOCA(fields_eof, conn))) {
DBG_ERR("Error ocurred while reading the EOF packet");
result->m.free_result_contents(result TSRMLS_CC);
efree(result);
if (!stmt) {
@ -349,6 +396,7 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT *stmt TSRMLS_DC
stmt->state = MYSQLND_STMT_INITTED;
}
} else {
DBG_INF_FMT("warns=%u status=%u", fields_eof.warning_count, fields_eof.server_status);
conn->upsert_status.warning_count = fields_eof.warning_count;
conn->upsert_status.server_status = fields_eof.server_status;
if (fields_eof.server_status & MYSQLND_SERVER_QUERY_NO_GOOD_INDEX_USED) {
@ -356,7 +404,12 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT *stmt TSRMLS_DC
} else if (fields_eof.server_status & MYSQLND_SERVER_QUERY_NO_INDEX_USED) {
stat = STAT_NO_INDEX_USED;
}
if (stat != -1) {
if (stat != STAT_LAST) {
char *backtrace = mysqlnd_get_backtrace(TSRMLS_C);
#if A0
php_log_err(backtrace TSRMLS_CC);
#endif
efree(backtrace);
MYSQLND_INC_CONN_STATISTIC(&conn->stats, stat);
}
}
@ -368,7 +421,9 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT *stmt TSRMLS_DC
}
} while (0);
PACKET_FREE_ALLOCA(rset_header);
return ret;
DBG_INF(ret == PASS? "PASS":"FAIL");
DBG_RETURN(ret);
}
/* }}} */
@ -438,17 +493,20 @@ mysqlnd_fetch_row_unbuffered(MYSQLND_RES *result, void *param, unsigned int flag
php_mysql_packet_row *row_packet = result->row_packet;
unsigned long *lengths = result->lengths;
DBG_ENTER("mysqlnd_fetch_row_unbuffered");
DBG_INF_FMT("flags=%d", flags);
if (result->unbuf->eof_reached) {
/* No more rows obviously */
*fetched_anything = FALSE;
return PASS;
DBG_RETURN(PASS);
}
if (result->conn->state != CONN_FETCHING_DATA) {
SET_CLIENT_ERROR(result->conn->error_info, CR_COMMANDS_OUT_OF_SYNC,
UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
return FAIL;
DBG_RETURN(FAIL);
}
/* Let the row packet fill our buffer and skip additional malloc + memcpy */
/* Let the row packet fill our buffer and skip additional mnd_malloc + memcpy */
row_packet->skip_extraction = row? FALSE:TRUE;
/*
@ -466,7 +524,7 @@ mysqlnd_fetch_row_unbuffered(MYSQLND_RES *result, void *param, unsigned int flag
row_packet->fields = NULL;
row_packet->row_buffer = NULL;
MYSQLND_INC_CONN_STATISTIC(&result->conn->stats, STAT_ROWS_FETCHED_FROM_CLIENT);
MYSQLND_INC_CONN_STATISTIC(&result->conn->stats, STAT_ROWS_FETCHED_FROM_CLIENT_NORMAL_UNBUF);
if (!row_packet->skip_extraction) {
HashTable *row_ht = Z_ARRVAL_P(row);
@ -527,14 +585,15 @@ mysqlnd_fetch_row_unbuffered(MYSQLND_RES *result, void *param, unsigned int flag
}
} else if (ret == FAIL) {
if (row_packet->error_info.error_no) {
result->conn->error_info = row_packet->error_info;
result->conn->error_info = row_packet->error_info;
DBG_ERR_FMT("errorno=%d error=%s", row_packet->error_info.error_no, row_packet->error_info.error);
}
*fetched_anything = FALSE;
result->conn->state = CONN_READY;
result->unbuf->eof_reached = TRUE; /* so next time we won't get an error */
} else if (row_packet->eof) {
/* Mark the connection as usable again */
DBG_INF_FMT("warns=%u status=%u", row_packet->warning_count, row_packet->server_status);
result->unbuf->eof_reached = TRUE;
result->conn->upsert_status.warning_count = row_packet->warning_count;
result->conn->upsert_status.server_status = row_packet->server_status;
@ -551,7 +610,8 @@ mysqlnd_fetch_row_unbuffered(MYSQLND_RES *result, void *param, unsigned int flag
*fetched_anything = FALSE;
}
return PASS;
DBG_INF_FMT("ret=%s fetched=%d", ret == PASS? "PASS":"FAIL", *fetched_anything);
DBG_RETURN(PASS);
}
/* }}} */
@ -560,10 +620,13 @@ mysqlnd_fetch_row_unbuffered(MYSQLND_RES *result, void *param, unsigned int flag
MYSQLND_RES *
MYSQLND_METHOD(mysqlnd_res, use_result)(MYSQLND_RES * const result, zend_bool ps TSRMLS_DC)
{
DBG_ENTER("mysqlnd_res::use_result");
DBG_INF_FMT("ps=%d", ps);
result->type = MYSQLND_RES_NORMAL;
result->m.fetch_row = result->m.fetch_row_normal_unbuffered;
result->m.fetch_lengths = mysqlnd_fetch_lengths_unbuffered;
result->unbuf = ecalloc(1, sizeof(MYSQLND_RES_UNBUFFERED));
result->unbuf = mnd_ecalloc(1, sizeof(MYSQLND_RES_UNBUFFERED));
/*
Will be freed in the mysqlnd_internal_free_result_contents() called
@ -576,11 +639,11 @@ MYSQLND_METHOD(mysqlnd_res, use_result)(MYSQLND_RES * const result, zend_bool ps
result->row_packet->fields_metadata = result->meta->fields;
result->row_packet->bit_fields_count = result->meta->bit_fields_count;
result->row_packet->bit_fields_total_len = result->meta->bit_fields_total_len;
result->lengths = ecalloc(result->field_count, sizeof(unsigned long));
result->lengths = mnd_ecalloc(result->field_count, sizeof(unsigned long));
/* No multithreading issues as we don't share the connection :) */
return result;
DBG_RETURN(result);
}
/* }}} */
@ -593,6 +656,9 @@ mysqlnd_fetch_row_buffered(MYSQLND_RES *result, void *param, unsigned int flags,
unsigned int i;
zval *row = (zval *) param;
DBG_ENTER("mysqlnd_fetch_row_buffered");
DBG_INF_FMT("flags=%u row=%p", flags, row);
/* If we haven't read everything */
if (result->data->data_cursor &&
(result->data->data_cursor - result->data->data) < result->data->row_count)
@ -647,14 +713,14 @@ mysqlnd_fetch_row_buffered(MYSQLND_RES *result, void *param, unsigned int flags,
}
result->data->data_cursor++;
*fetched_anything = TRUE;
MYSQLND_INC_GLOBAL_STATISTIC(STAT_ROWS_FETCHED_FROM_CLIENT_NORMAL_BUF);
} else {
result->data->data_cursor = NULL;
*fetched_anything = FALSE;
#ifndef MYSQLND_SILENT
php_printf("NO MORE DATA\n ");
#endif
DBG_INF("EOF reached");
}
return PASS;
DBG_INF_FMT("ret=PASS fetched=%d", *fetched_anything);
DBG_RETURN(PASS);
}
/* }}} */
@ -674,11 +740,15 @@ mysqlnd_store_result_fetch_data(MYSQLND * const conn, MYSQLND_RES *result,
unsigned int next_extend = STORE_RESULT_PREALLOCATED_SET, free_rows;
MYSQLND_RES_BUFFERED *set;
DBG_ENTER("mysqlnd_store_result_fetch_data");
DBG_INF_FMT("conn=%llu binary_proto=%d update_max_len=%d to_cache=%d",
conn->thread_id, binary_protocol, update_max_length, to_cache);
free_rows = next_extend;
result->data = set = pecalloc(1, sizeof(MYSQLND_RES_BUFFERED), to_cache);
set->data = pemalloc(STORE_RESULT_PREALLOCATED_SET * sizeof(zval **), to_cache);
set->row_buffers= pemalloc(STORE_RESULT_PREALLOCATED_SET * sizeof(zend_uchar *), to_cache);
result->data = set = mnd_pecalloc(1, sizeof(MYSQLND_RES_BUFFERED), to_cache);
set->data = mnd_pemalloc(STORE_RESULT_PREALLOCATED_SET * sizeof(zval **), to_cache);
set->row_buffers= mnd_pemalloc(STORE_RESULT_PREALLOCATED_SET * sizeof(zend_uchar *), to_cache);
set->persistent = to_cache;
set->qcache = to_cache? mysqlnd_qcache_get_cache_reference(conn->qcache):NULL;
set->references = 1;
@ -697,9 +767,9 @@ mysqlnd_store_result_fetch_data(MYSQLND * const conn, MYSQLND_RES *result,
if (!free_rows) {
mynd_ulonglong total_rows = free_rows = next_extend = next_extend * 5 / 3; /* extend with 33% */
total_rows += set->row_count;
set->data = perealloc(set->data, total_rows * sizeof(zval **), set->persistent);
set->data = mnd_perealloc(set->data, total_rows * sizeof(zval **), set->persistent);
set->row_buffers = perealloc(set->row_buffers,
set->row_buffers = mnd_perealloc(set->row_buffers,
total_rows * sizeof(zend_uchar *), set->persistent);
}
free_rows--;
@ -734,7 +804,9 @@ mysqlnd_store_result_fetch_data(MYSQLND * const conn, MYSQLND_RES *result,
transfered above.
*/
}
MYSQLND_INC_CONN_STATISTIC_W_VALUE(&conn->stats, STAT_ROWS_FETCHED_FROM_CLIENT,
MYSQLND_INC_CONN_STATISTIC_W_VALUE(&conn->stats,
binary_protocol? STAT_ROWS_BUFFERED_FROM_CLIENT_PS:
STAT_ROWS_BUFFERED_FROM_CLIENT_NORMAL,
set->row_count);
/* Finally clean */
@ -744,10 +816,10 @@ mysqlnd_store_result_fetch_data(MYSQLND * const conn, MYSQLND_RES *result,
}
/* save some memory */
if (free_rows) {
set->data = perealloc(set->data,
set->data = mnd_perealloc(set->data,
(size_t) set->row_count * sizeof(zval **),
set->persistent);
set->row_buffers = perealloc(set->row_buffers,
set->row_buffers = mnd_perealloc(set->row_buffers,
(size_t) set->row_count * sizeof(zend_uchar *),
set->persistent);
}
@ -769,7 +841,9 @@ mysqlnd_store_result_fetch_data(MYSQLND * const conn, MYSQLND_RES *result,
}
PACKET_FREE_ALLOCA(row_packet);
return ret;
DBG_INF_FMT("ret=%s row_count=%u warns=%u status=%u", ret == PASS? "PASS":"FAIL",
set->row_count, conn->upsert_status.warning_count, conn->upsert_status.server_status);
DBG_RETURN(ret);
}
/* }}} */
@ -783,6 +857,9 @@ MYSQLND_METHOD(mysqlnd_res, store_result)(MYSQLND_RES * result,
enum_func_status ret;
zend_bool to_cache = FALSE;
DBG_ENTER("mysqlnd_res::store_result");
DBG_INF_FMT("conn=%d ps_protocol=%d", conn->thread_id, ps_protocol);
result->conn = NULL; /* store result does not reference the connection */
result->type = MYSQLND_RES_NORMAL;
result->m.fetch_row = result->m.fetch_row_normal_buffered;
@ -790,7 +867,7 @@ MYSQLND_METHOD(mysqlnd_res, store_result)(MYSQLND_RES * result,
conn->state = CONN_FETCHING_DATA;
result->lengths = ecalloc(result->field_count, sizeof(unsigned long));
result->lengths = mnd_ecalloc(result->field_count, sizeof(unsigned long));
ret = mysqlnd_store_result_fetch_data(conn, result, result->meta,
ps_protocol, TRUE, to_cache TSRMLS_CC);
@ -803,7 +880,7 @@ MYSQLND_METHOD(mysqlnd_res, store_result)(MYSQLND_RES * result,
result = NULL;
}
return result;
DBG_RETURN(result);
}
/* }}} */
@ -814,6 +891,7 @@ MYSQLND_METHOD(mysqlnd_res, skip_result)(MYSQLND_RES * const result TSRMLS_DC)
{
zend_bool fetched_anything;
DBG_ENTER("mysqlnd_res::skip_result");
/*
Unbuffered sets
A PS could be prepared - there is metadata and thus a stmt->result but the
@ -822,6 +900,7 @@ MYSQLND_METHOD(mysqlnd_res, skip_result)(MYSQLND_RES * const result TSRMLS_DC)
if (!result->data && result->conn && result->unbuf &&
!result->unbuf->eof_reached && result->m.fetch_row)
{
DBG_INF("skipping result");
/* We have to fetch all data to clean the line */
MYSQLND_INC_CONN_STATISTIC(&result->conn->stats,
result->type == MYSQLND_RES_NORMAL? STAT_FLUSHED_NORMAL_SETS:
@ -833,7 +912,7 @@ MYSQLND_METHOD(mysqlnd_res, skip_result)(MYSQLND_RES * const result TSRMLS_DC)
/* do nothing */;
}
}
return PASS;
DBG_RETURN(PASS);
}
/* }}} */
@ -842,21 +921,27 @@ MYSQLND_METHOD(mysqlnd_res, skip_result)(MYSQLND_RES * const result TSRMLS_DC)
static enum_func_status
MYSQLND_METHOD(mysqlnd_res, free_result)(MYSQLND_RES *result, zend_bool implicit TSRMLS_DC)
{
DBG_ENTER("mysqlnd_res::free_result");
DBG_INF_FMT("implicit=%d", implicit);
result->m.skip_result(result TSRMLS_CC);
MYSQLND_INC_CONN_STATISTIC(result->conn? &result->conn->stats : NULL,
implicit == TRUE? STAT_FREE_RESULT_EXPLICIT:
STAT_FREE_RESULT_IMPLICIT);
implicit == TRUE? STAT_FREE_RESULT_IMPLICIT:
STAT_FREE_RESULT_EXPLICIT);
result->m.free_result_internal(result TSRMLS_CC);
return PASS;
DBG_RETURN(PASS);
}
/* }}} */
/* {{{ _mysqlnd_data_seek */
/* {{{ mysqlnd_res::data_seek */
static enum_func_status
MYSQLND_METHOD(mysqlnd_res, data_seek)(MYSQLND_RES *result, mynd_ulonglong row)
MYSQLND_METHOD(mysqlnd_res, data_seek)(MYSQLND_RES *result, mynd_ulonglong row TSRMLS_DC)
{
DBG_ENTER("mysqlnd_res::data_seek");
DBG_INF_FMT("row=%lu", row);
if (!result->data) {
return FAIL;
}
@ -868,7 +953,7 @@ MYSQLND_METHOD(mysqlnd_res, data_seek)(MYSQLND_RES *result, mynd_ulonglong row)
result->data->data_cursor = result->data->data + row;
}
return PASS;
DBG_RETURN(PASS);
}
/* }}} */
@ -894,9 +979,10 @@ MYSQLND_METHOD(mysqlnd_res, num_fields)(const MYSQLND_RES * const res)
/* {{{ mysqlnd_res::fetch_field */
static MYSQLND_FIELD *
MYSQLND_METHOD(mysqlnd_res, fetch_field)(MYSQLND_RES * const result)
MYSQLND_METHOD(mysqlnd_res, fetch_field)(MYSQLND_RES * const result TSRMLS_DC)
{
return result->meta? result->meta->m->fetch_field(result->meta):NULL;
DBG_ENTER("mysqlnd_res::fetch_field");
DBG_RETURN(result->meta? result->meta->m->fetch_field(result->meta TSRMLS_CC):NULL);
}
/* }}} */
@ -904,9 +990,10 @@ MYSQLND_METHOD(mysqlnd_res, fetch_field)(MYSQLND_RES * const result)
/* {{{ mysqlnd_res::fetch_field_direct */
static MYSQLND_FIELD *
MYSQLND_METHOD(mysqlnd_res, fetch_field_direct)(const MYSQLND_RES * const result,
MYSQLND_FIELD_OFFSET fieldnr)
MYSQLND_FIELD_OFFSET fieldnr TSRMLS_DC)
{
return result->meta? result->meta->m->fetch_field_direct(result->meta, fieldnr):NULL;
DBG_ENTER("mysqlnd_res::fetch_field_direct");
DBG_RETURN(result->meta? result->meta->m->fetch_field_direct(result->meta, fieldnr TSRMLS_CC):NULL);
}
/* }}} */
@ -943,8 +1030,12 @@ MYSQLND_METHOD(mysqlnd_res, fetch_into)(MYSQLND_RES *result, unsigned int flags,
{
zend_bool fetched_anything;
DBG_ENTER("mysqlnd_res::fetch_into");
DBG_INF_FMT("flags=%u mysqlnd_extension=%d", flags, extension);
if (!result->m.fetch_row) {
RETURN_NULL();
RETVAL_NULL();
DBG_VOID_RETURN;
}
/*
Hint Zend how many elements we will have in the hash. Thus it won't
@ -953,15 +1044,15 @@ MYSQLND_METHOD(mysqlnd_res, fetch_into)(MYSQLND_RES *result, unsigned int flags,
mysqlnd_array_init(return_value, mysqlnd_num_fields(result) * 2);
if (FAIL == result->m.fetch_row(result, (void *)return_value, flags, &fetched_anything TSRMLS_CC)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error while reading a row");
RETURN_FALSE;
RETVAL_FALSE;
} else if (fetched_anything == FALSE) {
zval_dtor(return_value);
switch (extension) {
case MYSQLND_MYSQLI:
RETURN_NULL();
RETVAL_NULL();
break;
case MYSQLND_MYSQL:
RETURN_FALSE;
RETVAL_FALSE;
break;
default:exit(0);
}
@ -970,6 +1061,7 @@ MYSQLND_METHOD(mysqlnd_res, fetch_into)(MYSQLND_RES *result, unsigned int flags,
return_value is IS_NULL for no more data and an array for data. Thus it's ok
to return here.
*/
DBG_VOID_RETURN;
}
/* }}} */
@ -982,12 +1074,16 @@ MYSQLND_METHOD(mysqlnd_res, fetch_all)(MYSQLND_RES *result, unsigned int flags,
zval *row;
ulong i = 0;
DBG_ENTER("mysqlnd_res::fetch_all");
DBG_INF_FMT("flags=%u", flags);
/* mysqlnd_res::fetch_all works with buffered resultsets only */
if (result->conn || !result->data ||
!result->data->row_count || !result->data->data_cursor ||
result->data->data_cursor >= result->data->data + result->data->row_count)
{
RETURN_NULL();
RETVAL_NULL();
DBG_VOID_RETURN;
}
mysqlnd_array_init(return_value, (uint) result->data->row_count);
@ -999,6 +1095,8 @@ MYSQLND_METHOD(mysqlnd_res, fetch_all)(MYSQLND_RES *result, unsigned int flags,
mysqlnd_fetch_into(result, flags, row, MYSQLND_MYSQLI);
add_index_zval(return_value, i++, row);
}
DBG_VOID_RETURN;
}
/* }}} */
@ -1012,8 +1110,12 @@ MYSQLND_METHOD(mysqlnd_res, fetch_field_data)(MYSQLND_RES *result, unsigned int
zval **entry;
uint i = 0;
DBG_ENTER("mysqlnd_res::fetch_field_data");
DBG_INF_FMT("offset=%u", offset);
if (!result->m.fetch_row) {
RETURN_NULL();
RETVAL_NULL();
DBG_VOID_RETURN;
}
/*
Hint Zend how many elements we will have in the hash. Thus it won't
@ -1023,7 +1125,8 @@ MYSQLND_METHOD(mysqlnd_res, fetch_field_data)(MYSQLND_RES *result, unsigned int
mysqlnd_fetch_into(result, MYSQLND_FETCH_NUM, &row, MYSQLND_MYSQL);
if (Z_TYPE(row) != IS_ARRAY) {
zval_dtor(&row);
RETURN_NULL();
RETVAL_NULL();
DBG_VOID_RETURN;
}
zend_hash_internal_pointer_reset(Z_ARRVAL(row));
while (i++ < offset) {
@ -1037,14 +1140,19 @@ MYSQLND_METHOD(mysqlnd_res, fetch_field_data)(MYSQLND_RES *result, unsigned int
zval_copy_ctor(return_value);
ZVAL_REFCOUNT(return_value) = 1;
zval_dtor(&row);
DBG_VOID_RETURN;
}
/* }}} */
/* {{{ mysqlnd_result_init */
MYSQLND_RES *mysqlnd_result_init(unsigned int field_count, MYSQLND_THD_ZVAL_PCACHE *cache)
MYSQLND_RES *mysqlnd_result_init(unsigned int field_count, MYSQLND_THD_ZVAL_PCACHE *cache TSRMLS_DC)
{
MYSQLND_RES *ret = ecalloc(1, sizeof(MYSQLND_RES));
MYSQLND_RES *ret = mnd_ecalloc(1, sizeof(MYSQLND_RES));
DBG_ENTER("mysqlnd_result_init");
DBG_INF_FMT("field_count=%u cache=%p", field_count, cache);
ret->field_count = field_count;
ret->zval_cache = cache;
@ -1072,7 +1180,7 @@ MYSQLND_RES *mysqlnd_result_init(unsigned int field_count, MYSQLND_THD_ZVAL_PCAC
ret->m.fetch_row_normal_buffered = mysqlnd_fetch_row_buffered;
ret->m.fetch_row_normal_unbuffered = mysqlnd_fetch_row_unbuffered;
return ret;
DBG_RETURN(ret);
}
/* }}} */

View File

@ -23,7 +23,7 @@
#ifndef MYSQLND_RESULT_H
#define MYSQLND_RESULT_H
MYSQLND_RES *mysqlnd_result_init(unsigned int field_count, MYSQLND_THD_ZVAL_PCACHE *cache);
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);

View File

@ -24,20 +24,21 @@
#include "mysqlnd_priv.h"
#include "mysqlnd_result.h"
#include "mysqlnd_wireprotocol.h"
#include "mysqlnd_debug.h"
#include "ext/standard/basic_functions.h"
/* {{{ php_mysqlnd_free_field_metadata */
static
void php_mysqlnd_free_field_metadata(MYSQLND_FIELD *meta, zend_bool persistent)
void php_mysqlnd_free_field_metadata(MYSQLND_FIELD *meta, zend_bool persistent TSRMLS_DC)
{
if (meta) {
if (meta->root) {
pefree(meta->root, persistent);
mnd_pefree(meta->root, persistent);
meta->root = NULL;
}
if (meta->def) {
pefree(meta->def, persistent);
mnd_pefree(meta->def, persistent);
meta->def = NULL;
}
}
@ -143,32 +144,40 @@ MYSQLND_METHOD(mysqlnd_res_meta, read_metadata)(MYSQLND_RES_METADATA * const met
int i = 0;
php_mysql_packet_res_field field_packet;
DBG_ENTER("mysqlnd_res_meta::read_metadata");
PACKET_INIT_ALLOCA(field_packet, PROT_RSET_FLD_PACKET);
for (;i < meta->field_count; i++) {
long idx;
if (meta->fields[i].root) {
/* We re-read metadata for PS */
efree(meta->fields[i].root);
mnd_efree(meta->fields[i].root);
meta->fields[i].root = NULL;
}
field_packet.metadata = &(meta->fields[i]);
if (FAIL == PACKET_READ_ALLOCA(field_packet, conn)) {
PACKET_FREE_ALLOCA(field_packet);
return FAIL;
DBG_RETURN(FAIL);
}
if (field_packet.stupid_list_fields_eof == TRUE) {
break;
}
if (mysqlnd_ps_fetch_functions[meta->fields[i].type].func == NULL) {
DBG_ERR_FMT("Unknown type %d sent by the server. Please send a report to the developers",
meta->fields[i].type);
php_error_docref(NULL TSRMLS_CC, E_WARNING,
"Unknown type %d sent by the server. "
"Please send a report to the developers",
meta->fields[i].type);
PACKET_FREE_ALLOCA(field_packet);
return FAIL;
DBG_RETURN(FAIL);
}
if (meta->fields[i].type == MYSQL_TYPE_BIT) {
size_t field_len;
DBG_INF("BIT");
++meta->bit_fields_count;
/* .length is in bits */
field_len = meta->fields[i].length / 8;
@ -213,7 +222,7 @@ MYSQLND_METHOD(mysqlnd_res_meta, read_metadata)(MYSQLND_RES_METADATA * const met
mysqlnd_unicode_is_key_numeric(ustr, ulen + 1, &idx)))
{
meta->zend_hash_keys[i].key = idx;
efree(ustr);
mnd_efree(ustr);
} else {
meta->zend_hash_keys[i].ustr.u = ustr;
meta->zend_hash_keys[i].ulen = ulen;
@ -239,7 +248,7 @@ MYSQLND_METHOD(mysqlnd_res_meta, read_metadata)(MYSQLND_RES_METADATA * const met
}
PACKET_FREE_ALLOCA(field_packet);
return PASS;
DBG_RETURN(PASS);
}
/* }}} */
@ -251,29 +260,37 @@ MYSQLND_METHOD(mysqlnd_res_meta, free)(MYSQLND_RES_METADATA *meta, zend_bool per
int i;
MYSQLND_FIELD *fields;
DBG_ENTER("mysqlnd_res_meta::free");
DBG_INF_FMT("persistent=%d", persistent);
if ((fields = meta->fields)) {
DBG_INF("Freeing fields metadata");
i = meta->field_count;
while (i--) {
php_mysqlnd_free_field_metadata(fields++, persistent);
php_mysqlnd_free_field_metadata(fields++, persistent TSRMLS_CC);
}
pefree(meta->fields, persistent);
mnd_pefree(meta->fields, persistent);
meta->fields = NULL;
}
if (meta->zend_hash_keys) {
DBG_INF("Freeing zend_hash_keys");
#if PHP_MAJOR_VERSION >= 6
if (UG(unicode)) {
for (i = 0; i < meta->field_count; i++) {
if (meta->zend_hash_keys[i].ustr.v) {
pefree(meta->zend_hash_keys[i].ustr.v, persistent);
mnd_pefree(meta->zend_hash_keys[i].ustr.v, persistent);
}
}
}
#endif
pefree(meta->zend_hash_keys, persistent);
mnd_pefree(meta->zend_hash_keys, persistent);
meta->zend_hash_keys = NULL;
}
pefree(meta, persistent);
DBG_INF("Freeing metadata structure");
mnd_pefree(meta, persistent);
DBG_VOID_RETURN;
}
/* }}} */
@ -281,16 +298,19 @@ MYSQLND_METHOD(mysqlnd_res_meta, free)(MYSQLND_RES_METADATA *meta, zend_bool per
/* {{{ mysqlnd_res::clone_metadata */
static MYSQLND_RES_METADATA *
MYSQLND_METHOD(mysqlnd_res_meta, clone_metadata)(const MYSQLND_RES_METADATA * const meta,
zend_bool persistent)
zend_bool persistent TSRMLS_DC)
{
unsigned int i;
/* +1 is to have empty marker at the end */
MYSQLND_RES_METADATA *new_meta = pemalloc(sizeof(MYSQLND_RES_METADATA), persistent);
MYSQLND_FIELD *new_fields = pecalloc(meta->field_count + 1, sizeof(MYSQLND_FIELD), persistent);
MYSQLND_RES_METADATA *new_meta = mnd_pemalloc(sizeof(MYSQLND_RES_METADATA), persistent);
MYSQLND_FIELD *new_fields = mnd_pecalloc(meta->field_count + 1, sizeof(MYSQLND_FIELD), persistent);
MYSQLND_FIELD *orig_fields = meta->fields;
size_t len = meta->field_count * sizeof(struct mysqlnd_field_hash_key);
new_meta->zend_hash_keys = pemalloc(len, persistent);
DBG_ENTER("mysqlnd_res_meta::clone_metadata");
DBG_INF_FMT("persistent=%d", persistent);
new_meta->zend_hash_keys = mnd_pemalloc(len, persistent);
memcpy(new_meta->zend_hash_keys, meta->zend_hash_keys, len);
new_meta->m = meta->m;
@ -301,7 +321,7 @@ MYSQLND_METHOD(mysqlnd_res_meta, clone_metadata)(const MYSQLND_RES_METADATA * co
memcpy(new_fields, orig_fields, (meta->field_count) * sizeof(MYSQLND_FIELD));
for (i = 0; i < meta->field_count; i++) {
/* First copy the root, then field by field adjust the pointers */
new_fields[i].root = pemalloc(orig_fields[i].root_len, persistent);
new_fields[i].root = mnd_pemalloc(orig_fields[i].root_len, persistent);
memcpy(new_fields[i].root, orig_fields[i].root, new_fields[i].root_len);
if (orig_fields[i].name && orig_fields[i].name != mysqlnd_empty_string) {
@ -328,7 +348,7 @@ MYSQLND_METHOD(mysqlnd_res_meta, clone_metadata)(const MYSQLND_RES_METADATA * co
}
/* def is not on the root, if allocated at all */
if (orig_fields[i].def) {
new_fields[i].def = pemalloc(orig_fields[i].def_length + 1, persistent);
new_fields[i].def = mnd_pemalloc(orig_fields[i].def_length + 1, persistent);
/* copy the trailing \0 too */
memcpy(new_fields[i].def, orig_fields[i].def, orig_fields[i].def_length + 1);
}
@ -344,17 +364,19 @@ MYSQLND_METHOD(mysqlnd_res_meta, clone_metadata)(const MYSQLND_RES_METADATA * co
new_meta->fields = new_fields;
return new_meta;
DBG_RETURN(new_meta);
}
/* }}} */
/* {{{ mysqlnd_res_meta::fetch_field */
static MYSQLND_FIELD *
MYSQLND_METHOD(mysqlnd_res_meta, fetch_field)(MYSQLND_RES_METADATA * const meta)
MYSQLND_METHOD(mysqlnd_res_meta, fetch_field)(MYSQLND_RES_METADATA * const meta TSRMLS_DC)
{
if (meta->current_field >= meta->field_count)
return NULL;
return &meta->fields[meta->current_field++];
DBG_ENTER("mysqlnd_res_meta::fetch_field");
if (meta->current_field >= meta->field_count) {
DBG_RETURN(NULL);
}
DBG_RETURN(&meta->fields[meta->current_field++]);
}
/* }}} */
@ -362,9 +384,11 @@ MYSQLND_METHOD(mysqlnd_res_meta, fetch_field)(MYSQLND_RES_METADATA * const meta)
/* {{{ mysqlnd_res_meta::fetch_field_direct */
static MYSQLND_FIELD *
MYSQLND_METHOD(mysqlnd_res_meta, fetch_field_direct)(const MYSQLND_RES_METADATA * const meta,
MYSQLND_FIELD_OFFSET fieldnr)
MYSQLND_FIELD_OFFSET fieldnr TSRMLS_DC)
{
return &meta->fields[fieldnr];
DBG_ENTER("mysqlnd_res_meta::fetch_field_direct");
DBG_INF_FMT("fieldnr=%d", fieldnr);
DBG_RETURN(&meta->fields[fieldnr]);
}
/* }}} */
@ -389,17 +413,20 @@ MYSQLND_CLASS_METHODS_END;
/* {{{ mysqlnd_result_meta_init */
MYSQLND_RES_METADATA *mysqlnd_result_meta_init(unsigned int field_count)
MYSQLND_RES_METADATA *mysqlnd_result_meta_init(unsigned int field_count TSRMLS_DC)
{
MYSQLND_RES_METADATA *ret;
DBG_ENTER("mysqlnd_result_meta_init");
/* +1 is to have empty marker at the end */
ret = ecalloc(1, sizeof(MYSQLND_RES_METADATA));
ret = mnd_ecalloc(1, sizeof(MYSQLND_RES_METADATA));
ret->field_count = field_count;
ret->fields = ecalloc(field_count + 1, sizeof(MYSQLND_FIELD));
ret->zend_hash_keys = ecalloc(field_count, sizeof(struct mysqlnd_field_hash_key));
ret->m = & mysqlnd_mysqlnd_res_meta_methods;
return ret;
DBG_INF_FMT("meta=%p", ret);
DBG_RETURN(ret);
}

View File

@ -24,7 +24,7 @@
#define MYSQLND_RESULT_META_H
MYSQLND_RES_METADATA *mysqlnd_result_meta_init(unsigned int field_count);
MYSQLND_RES_METADATA *mysqlnd_result_meta_init(unsigned int field_count TSRMLS_DC);

View File

@ -23,20 +23,13 @@
#include "mysqlnd.h"
#include "mysqlnd_priv.h"
#include "mysqlnd_statistics.h"
typedef struct st_mysqlnd_string
{
char *s;
size_t l;
} MYSQLND_STRING;
#include "mysqlnd_debug.h"
#define STR_W_LEN(str) str, (sizeof(str) - 1)
/* {{{ mysqlnd_stats_values_names
*/
static
const MYSQLND_STRING mysqlnd_stats_values_names[STAT_LAST] =
{
{ STR_W_LEN("bytes_sent") },
@ -55,15 +48,29 @@ const MYSQLND_STRING mysqlnd_stats_values_names[STAT_LAST] =
{ STR_W_LEN("ps_unbuffered_sets") },
{ STR_W_LEN("flushed_normal_sets") },
{ STR_W_LEN("flushed_ps_sets") },
{ STR_W_LEN("rows_fetched_from_server") },
{ STR_W_LEN("rows_fetched_from_client") },
{ STR_W_LEN("rows_skipped") },
{ STR_W_LEN("ps_prepared_never_executed") },
{ STR_W_LEN("ps_prepared_once_executed") },
{ STR_W_LEN("rows_fetched_from_server_normal") },
{ STR_W_LEN("rows_fetched_from_server_ps") },
{ STR_W_LEN("rows_buffered_from_client_normal") },
{ STR_W_LEN("rows_buffered_from_client_ps") },
{ STR_W_LEN("rows_fetched_from_client_normal_buffered") },
{ STR_W_LEN("rows_fetched_from_client_normal_unbuffered") },
{ STR_W_LEN("rows_fetched_from_client_ps_buffered") },
{ STR_W_LEN("rows_fetched_from_client_ps_unbuffered") },
{ STR_W_LEN("rows_fetched_from_client_ps_cursor") },
{ STR_W_LEN("rows_skipped_normal") },
{ STR_W_LEN("rows_skipped_ps") },
{ STR_W_LEN("copy_on_write_saved") },
{ STR_W_LEN("copy_on_write_performed") },
{ STR_W_LEN("command_buffer_too_small") },
{ STR_W_LEN("connect_success") },
{ STR_W_LEN("connect_failure") },
{ STR_W_LEN("connection_reused") },
{ STR_W_LEN("reconnect") },
{ STR_W_LEN("pconnect_success") },
{ STR_W_LEN("active_connections") },
{ STR_W_LEN("active_persistent_connections") },
{ STR_W_LEN("explicit_close") },
{ STR_W_LEN("implicit_close") },
{ STR_W_LEN("disconnect_close") },
@ -72,10 +79,25 @@ const MYSQLND_STRING mysqlnd_stats_values_names[STAT_LAST] =
{ STR_W_LEN("implicit_free_result") },
{ STR_W_LEN("explicit_stmt_close") },
{ STR_W_LEN("implicit_stmt_close") },
{ STR_W_LEN("mem_emalloc_count") },
{ STR_W_LEN("mem_emalloc_ammount") },
{ STR_W_LEN("mem_ecalloc_count") },
{ STR_W_LEN("mem_ecalloc_ammount") },
{ STR_W_LEN("mem_erealloc_count") },
{ STR_W_LEN("mem_erealloc_ammount") },
{ STR_W_LEN("mem_efree_count") },
{ STR_W_LEN("mem_malloc_count") },
{ STR_W_LEN("mem_malloc_ammount") },
{ STR_W_LEN("mem_calloc_count") },
{ STR_W_LEN("mem_calloc_ammount") },
{ STR_W_LEN("mem_realloc_calloc") },
{ STR_W_LEN("mem_realloc_ammount") },
{ STR_W_LEN("mem_free_count") }
};
/* }}} */
/* {{{ mysqlnd_fill_stats_hash */
void
mysqlnd_fill_stats_hash(const MYSQLND_STATS * const stats, zval *return_value TSRMLS_DC ZEND_FILE_LINE_DC)
{
@ -105,19 +127,22 @@ mysqlnd_fill_stats_hash(const MYSQLND_STATS * const stats, zval *return_value TS
}
}
}
/* }}} */
/* {{{ _mysqlnd_get_client_stats */
PHPAPI void _mysqlnd_get_client_stats(zval *return_value TSRMLS_DC ZEND_FILE_LINE_DC)
{
MYSQLND_STATS stats, *stats_ptr = mysqlnd_global_stats;
DBG_ENTER("_mysqlnd_get_client_stats");
if (!stats_ptr) {
memset(&stats, 0, sizeof(stats));
stats_ptr = &stats;
}
mysqlnd_fill_stats_hash(stats_ptr, return_value TSRMLS_CC ZEND_FILE_LINE_CC);
DBG_VOID_RETURN;
}
/* }}} */
/*

View File

@ -26,50 +26,93 @@
extern MYSQLND_STATS *mysqlnd_global_stats;
typedef struct st_mysqlnd_string
{
char *s;
size_t l;
} MYSQLND_STRING;
extern const MYSQLND_STRING mysqlnd_stats_values_names[];
#ifdef ZTS
#define MYSQLND_INC_GLOBAL_STATISTIC(statistic) \
{ \
if (MYSQLND_G(collect_statistics)) { \
DBG_INF_FMT("Global stat increase [%s]", mysqlnd_stats_values_names[statistic]); \
tsrm_mutex_lock(mysqlnd_global_stats->LOCK_access); \
mysqlnd_global_stats->values[(statistic)]++; \
tsrm_mutex_unlock(mysqlnd_global_stats->LOCK_access); \
}\
}
#define MYSQLND_INC_GLOBAL_STATISTIC2_W_VALUE(statistic1, value1, statistic2, value2) \
{ \
if (MYSQLND_G(collect_statistics)) { \
DBG_INF_FMT("Global stats increase w value [%s] [%s]", mysqlnd_stats_values_names[statistic1], mysqlnd_stats_values_names[statistic2]); \
tsrm_mutex_lock(mysqlnd_global_stats->LOCK_access); \
mysqlnd_global_stats->values[(statistic1)] += (value1); \
mysqlnd_global_stats->values[(statistic2)] += (value2); \
tsrm_mutex_unlock(mysqlnd_global_stats->LOCK_access); \
}\
}
#define MYSQLND_DEC_CONN_STATISTIC(conn_stats, statistic) \
{ \
if (MYSQLND_G(collect_statistics)) { \
DBG_INF_FMT("Global&conn stat decrease [%s]", mysqlnd_stats_values_names[statistic]); \
tsrm_mutex_lock(mysqlnd_global_stats->LOCK_access); \
mysqlnd_global_stats->values[(statistic)]--; \
tsrm_mutex_unlock(mysqlnd_global_stats->LOCK_access); \
if ((conn_stats)) { \
((MYSQLND_STATS *) conn_stats)->values[(statistic)]--; \
} \
}\
}
#define MYSQLND_INC_CONN_STATISTIC(conn_stats, statistic) \
{ \
if (mysqlnd_global_stats) { \
if (MYSQLND_G(collect_statistics)) { \
DBG_INF_FMT("Global&Conn stat increase [%s]", mysqlnd_stats_values_names[statistic]); \
tsrm_mutex_lock(mysqlnd_global_stats->LOCK_access); \
mysqlnd_global_stats->values[statistic]++; \
mysqlnd_global_stats->values[(statistic)]++; \
tsrm_mutex_unlock(mysqlnd_global_stats->LOCK_access); \
if ((conn_stats)) { \
((MYSQLND_STATS *) conn_stats)->values[statistic]++; \
((MYSQLND_STATS *) conn_stats)->values[(statistic)]++; \
} \
}\
}
#define MYSQLND_INC_CONN_STATISTIC_W_VALUE(conn_stats, statistic, value) \
{ \
if (mysqlnd_global_stats) {\
my_uint64 v = (value); \
\
if (MYSQLND_G(collect_statistics)) { \
my_uint64 v = (my_uint64) (value); \
DBG_INF_FMT("Global&Conn stat increase w value [%s]", mysqlnd_stats_values_names[statistic]); \
tsrm_mutex_lock(mysqlnd_global_stats->LOCK_access); \
mysqlnd_global_stats->values[statistic] += v; \
mysqlnd_global_stats->values[(statistic)] += v; \
tsrm_mutex_unlock(mysqlnd_global_stats->LOCK_access); \
if ((conn_stats)) { \
((MYSQLND_STATS *) conn_stats)->values[statistic]+= v; \
((MYSQLND_STATS *) conn_stats)->values[(statistic)]+= v; \
} \
}\
}
#define MYSQLND_INC_CONN_STATISTIC_W_VALUE3(conn_stats, statistic1, value1, statistic2, value2, statistic3, value3) \
{ \
if (mysqlnd_global_stats) { \
my_uint64 v1 = (value1); \
my_uint64 v2 = (value2); \
my_uint64 v3 = (value3); \
if (MYSQLND_G(collect_statistics)) { \
my_uint64 v1 = (my_uint64) (value1); \
my_uint64 v2 = (my_uint64) (value2); \
my_uint64 v3 = (my_uint64) (value3); \
\
tsrm_mutex_lock(mysqlnd_global_stats->LOCK_access); \
mysqlnd_global_stats->values[statistic1]+= v1; \
mysqlnd_global_stats->values[statistic2]+= v2; \
mysqlnd_global_stats->values[statistic3]+= v3; \
mysqlnd_global_stats->values[(statistic1)]+= v1; \
mysqlnd_global_stats->values[(statistic2)]+= v2; \
mysqlnd_global_stats->values[(statistic3)]+= v3; \
tsrm_mutex_unlock(mysqlnd_global_stats->LOCK_access); \
if ((conn_stats)) { \
((MYSQLND_STATS *) conn_stats)->values[statistic1]+= v1; \
((MYSQLND_STATS *) conn_stats)->values[statistic2]+= v2; \
((MYSQLND_STATS *) conn_stats)->values[statistic3]+= v3; \
((MYSQLND_STATS *) conn_stats)->values[(statistic1)]+= v1; \
((MYSQLND_STATS *) conn_stats)->values[(statistic2)]+= v2; \
((MYSQLND_STATS *) conn_stats)->values[(statistic3)]+= v3; \
} \
} \
}
@ -77,42 +120,73 @@ extern MYSQLND_STATS *mysqlnd_global_stats;
#else /* NON-ZTS */
#define MYSQLND_INC_GLOBAL_STATISTIC(statistic) \
{ \
if (MYSQLND_G(collect_statistics)) { \
DBG_INF_FMT("Global stat increase [%s]", mysqlnd_stats_values_names[statistic]); \
mysqlnd_global_stats->values[(statistic)]++; \
} \
}
#define MYSQLND_INC_GLOBAL_STATISTIC2_W_VALUE(statistic1, value1, statistic2, value2) \
{ \
if (MYSQLND_G(collect_statistics)) { \
DBG_INF_FMT("Global stats increase w value [%s] [%s]", \
mysqlnd_stats_values_names[statistic1], mysqlnd_stats_values_names[statistic2]); \
mysqlnd_global_stats->values[(statistic1)] += (value1); \
mysqlnd_global_stats->values[(statistic2)] += (value2); \
}\
}
#define MYSQLND_DEC_CONN_STATISTIC(conn_stats, statistic) \
{ \
if (MYSQLND_G(collect_statistics)) { \
DBG_INF_FMT("Global&Conn stat decrease [%s]", mysqlnd_stats_values_names[statistic]); \
mysqlnd_global_stats->values[(statistic)]--; \
if ((conn_stats)) { \
((MYSQLND_STATS *) conn_stats)->values[(statistic)]--; \
} \
} \
}
#define MYSQLND_INC_CONN_STATISTIC(conn_stats, statistic) \
{ \
if (mysqlnd_global_stats) { \
mysqlnd_global_stats->values[statistic]++; \
if (MYSQLND_G(collect_statistics)) { \
DBG_INF_FMT("Global&Conn stat increase [%s]", mysqlnd_stats_values_names[statistic]); \
mysqlnd_global_stats->values[(statistic)]++; \
if ((conn_stats)) { \
((MYSQLND_STATS *) conn_stats)->values[statistic]++; \
((MYSQLND_STATS *) conn_stats)->values[(statistic)]++; \
} \
} \
}
#define MYSQLND_INC_CONN_STATISTIC_W_VALUE(conn_stats, statistic, value) \
{ \
my_uint64 v = (value); \
\
if (mysqlnd_global_stats) { \
mysqlnd_global_stats->values[statistic]+= v; \
my_uint64 v = (my_uint64) (value); \
DBG_INF_FMT("Global&Conn stats increase w value [%s]", mysqlnd_stats_values_names[statistic]); \
if (MYSQLND_G(collect_statistics)) { \
mysqlnd_global_stats->values[(statistic)] += v; \
if ((conn_stats)) { \
((MYSQLND_STATS *) conn_stats)->values[statistic]+= v; \
((MYSQLND_STATS *) conn_stats)->values[(statistic)] += v; \
} \
} \
}
#define MYSQLND_INC_CONN_STATISTIC_W_VALUE3(conn_stats, statistic1, value1, statistic2, value2, statistic3, value3) \
{ \
if (mysqlnd_global_stats) { \
my_uint64 v1 = (value1); \
my_uint64 v2 = (value2); \
my_uint64 v3 = (value3); \
if (MYSQLND_G(collect_statistics)) { \
my_uint64 v1 = (my_uint64) (value1); \
my_uint64 v2 = (my_uint64) (value2); \
my_uint64 v3 = (my_uint64) (value3); \
\
mysqlnd_global_stats->values[statistic1]+= v1; \
mysqlnd_global_stats->values[statistic2]+= v2; \
mysqlnd_global_stats->values[statistic3]+= v3; \
mysqlnd_global_stats->values[(statistic1)]+= v1; \
mysqlnd_global_stats->values[(statistic2)]+= v2; \
mysqlnd_global_stats->values[(statistic3)]+= v3; \
if ((conn_stats)) { \
((MYSQLND_STATS *) conn_stats)->values[statistic1]+= v1; \
((MYSQLND_STATS *) conn_stats)->values[statistic2]+= v2; \
((MYSQLND_STATS *) conn_stats)->values[statistic3]+= v3; \
((MYSQLND_STATS *) conn_stats)->values[(statistic1)]+= v1; \
((MYSQLND_STATS *) conn_stats)->values[(statistic2)]+= v2; \
((MYSQLND_STATS *) conn_stats)->values[(statistic3)]+= v3; \
} \
} \
}

View File

@ -0,0 +1,540 @@
/*
+----------------------------------------------------------------------+
| PHP Version 6 |
+----------------------------------------------------------------------+
| Copyright (c) 2006-2007 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: Georg Richter <georg@mysql.com> |
| Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
+----------------------------------------------------------------------+
*/
/* $Id$ */
#ifndef MYSQLND_STRUCTS_H
#define MYSQLND_STRUCTS_H
typedef struct st_mysqlnd_cmd_buffer
{
zend_uchar *buffer;
size_t length;
} MYSQLND_CMD_BUFFER;
typedef struct st_mysqlnd_field
{
char *name; /* Name of column */
char *org_name; /* Original column name, if an alias */
char *table; /* Table of column if column was a field */
char *org_table; /* Org table name, if table was an alias */
char *db; /* Database for table */
char *catalog; /* Catalog for table */
char *def; /* Default value (set by mysql_list_fields) */
unsigned long length; /* Width of column (create length) */
unsigned long max_length; /* Max width for selected set */
unsigned int name_length;
unsigned int org_name_length;
unsigned int table_length;
unsigned int org_table_length;
unsigned int db_length;
unsigned int catalog_length;
unsigned int def_length;
unsigned int flags; /* Diverse flags */
unsigned int decimals; /* Number of decimals in field */
unsigned int charsetnr; /* Character set */
enum mysqlnd_field_types type; /* Type of field. See mysql_com.h for types */
char *root;
size_t root_len;
} MYSQLND_FIELD;
typedef struct st_mysqlnd_upsert_result
{
unsigned int warning_count;
unsigned int server_status;
unsigned long long affected_rows;
unsigned long long last_insert_id;
} mysqlnd_upsert_status;
typedef struct st_mysqlnd_error_info
{
char error[MYSQLND_ERRMSG_SIZE+1];
char sqlstate[MYSQLND_SQLSTATE_LENGTH + 1];
unsigned int error_no;
} mysqlnd_error_info;
typedef struct st_mysqlnd_zval_pcache MYSQLND_ZVAL_PCACHE;
typedef struct st_mysqlnd_thread_zval_pcache MYSQLND_THD_ZVAL_PCACHE;
typedef struct st_mysqlnd_qcache MYSQLND_QCACHE;
typedef struct st_mysqlnd_infile_info
{
php_stream *fd;
int error_no;
char error_msg[MYSQLND_ERRMSG_SIZE + 1];
const char *filename;
} MYSQLND_INFILE_INFO;
/* character set information */
typedef struct st_mysqlnd_charset
{
uint nr;
char *name;
char *collation;
uint char_minlen;
uint char_maxlen;
uint dangerous_for_escape_backslash;
uint (*mb_charlen)(uint c);
uint (*mb_valid)(const char *start, const char *end);
} MYSQLND_CHARSET;
/* local infile handler */
typedef struct st_mysqlnd_infile
{
int (*local_infile_init)(void **ptr, char *filename, void **userdata TSRMLS_DC);
int (*local_infile_read)(void *ptr, char *buf, uint buf_len TSRMLS_DC);
int (*local_infile_error)(void *ptr, char *error_msg, uint error_msg_len TSRMLS_DC);
void (*local_infile_end)(void *ptr TSRMLS_DC);
zval *callback;
void *userdata;
} MYSQLND_INFILE;
typedef struct st_mysqlnd_option
{
/* timeouts */
uint timeout_connect;
uint timeout_read;
uint timeout_write;
ulong flags;
/* init commands - we need to send them to server directly after connect */
uint num_commands;
char **init_commands;
/* configuration file information */
char *cfg_file;
char *cfg_section;
/* SSL information */
char *ssl_key;
char *ssl_cert;
char *ssl_ca;
char *ssl_capath;
char *ssl_cipher;
zend_bool use_ssl;
char *charset_name;
/* maximum allowed packet size for communication */
ulong max_allowed_packet;
zend_bool numeric_and_datetime_as_unicode;
#ifdef MYSQLND_STRING_TO_INT_CONVERSION
zend_bool int_and_year_as_int;
#endif
unsigned int net_read_buffer_size;
} MYSQLND_OPTION;
typedef struct st_mysqlnd_connection MYSQLND;
typedef struct st_mysqlnd_res MYSQLND_RES;
typedef char** MYSQLND_ROW; /* return data as array of strings */
typedef struct st_mysqlnd_stmt MYSQLND_STMT;
typedef unsigned int MYSQLND_FIELD_OFFSET;
typedef struct st_mysqlnd_param_bind MYSQLND_PARAM_BIND;
typedef struct st_mysqlnd_result_bind MYSQLND_RESULT_BIND;
typedef struct st_mysqlnd_result_metadata MYSQLND_RES_METADATA;
typedef struct st_mysqlnd_buffered_result MYSQLND_RES_BUFFERED;
typedef struct st_mysqlnd_unbuffered_result MYSQLND_RES_UNBUFFERED;
typedef struct st_mysqlnd_debug MYSQLND_DEBUG;
typedef MYSQLND_RES* (*mysqlnd_stmt_use_or_store_func)(MYSQLND_STMT * const TSRMLS_DC);
typedef enum_func_status (*mysqlnd_fetch_row_func)(MYSQLND_RES *result,
void *param,
unsigned int flags,
zend_bool *fetched_anything
TSRMLS_DC);
typedef struct st_mysqlnd_stats
{
my_uint64 values[STAT_LAST];
#ifdef ZTS
MUTEX_T LOCK_access;
#endif
} MYSQLND_STATS;
typedef struct st_mysqlnd_net
{
php_stream *stream;
/* sequence for simple checking of correct packets */
zend_uchar packet_no;
#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
{
ulong (*escape_string)(const MYSQLND * const conn, char *newstr, const char *escapestr, int 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);
MYSQLND_RES * (*use_result)(MYSQLND * const conn TSRMLS_DC);
MYSQLND_RES * (*store_result)(MYSQLND * const conn TSRMLS_DC);
enum_func_status (*next_result)(MYSQLND * const conn TSRMLS_DC);
zend_bool (*more_results)(const MYSQLND * const conn);
MYSQLND_STMT * (*stmt_init)(MYSQLND * const conn TSRMLS_DC);
enum_func_status (*shutdown_server)(MYSQLND * const conn, unsigned long level TSRMLS_DC);
enum_func_status (*refresh_server)(MYSQLND * const conn, unsigned long options TSRMLS_DC);
enum_func_status (*ping)(MYSQLND * const conn TSRMLS_DC);
enum_func_status (*kill_connection)(MYSQLND *conn, unsigned int pid TSRMLS_DC);
enum_func_status (*select_db)(MYSQLND * const conn, const char * const db, unsigned int db_len TSRMLS_DC);
enum_func_status (*server_dump_debug_information)(MYSQLND * const conn TSRMLS_DC);
enum_func_status (*change_user)(MYSQLND * const conn, const char * user, const char * passwd, const char * db TSRMLS_DC);
unsigned int (*get_error_no)(const MYSQLND * const conn);
const char * (*get_error_str)(const MYSQLND * const conn);
const char * (*get_sqlstate)(const MYSQLND * const conn);
mynd_ulonglong (*get_thread_id)(const MYSQLND * const conn);
void (*get_statistics)(const MYSQLND * const conn, zval *return_value TSRMLS_DC ZEND_FILE_LINE_DC);
unsigned long (*get_server_version)(const MYSQLND * const conn);
const char * (*get_server_information)(const MYSQLND * const conn);
enum_func_status (*get_server_statistics)(MYSQLND *conn, char **message, unsigned int * message_len TSRMLS_DC);
const char * (*get_host_information)(const MYSQLND * const conn);
unsigned int (*get_protocol_information)(const MYSQLND * const conn);
const char * (*get_last_message)(const MYSQLND * const conn);
const char * (*charset_name)(const MYSQLND * const conn);
MYSQLND_RES * (*list_fields)(MYSQLND *conn, const char *table, const char *achtung_wild TSRMLS_DC);
MYSQLND_RES * (*list_method)(MYSQLND *conn, const char *query, const char *achtung_wild, char *par1 TSRMLS_DC);
mynd_ulonglong (*get_last_insert_id)(const MYSQLND * const conn);
mynd_ulonglong (*get_affected_rows)(const MYSQLND * const conn);
unsigned int (*get_warning_count)(const MYSQLND * const conn);
unsigned int (*get_field_count)(const MYSQLND * const conn);
enum_func_status (*set_server_option)(MYSQLND * const conn, enum_mysqlnd_server_option option TSRMLS_DC);
enum_func_status (*set_client_option)(MYSQLND * const conn, enum_mysqlnd_option option, const char * const value TSRMLS_DC);
void (*free_contents)(MYSQLND *conn TSRMLS_DC); /* private */
enum_func_status (*close)(MYSQLND *conn, enum_connection_close_type close_type TSRMLS_DC);
void (*dtor)(MYSQLND *conn TSRMLS_DC); /* private */
MYSQLND * (*get_reference)(MYSQLND * const conn);
enum_func_status (*free_reference)(MYSQLND * const conn TSRMLS_DC);
};
struct st_mysqlnd_res_methods
{
mysqlnd_fetch_row_func fetch_row;
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, 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, enum_mysqlnd_extension ext TSRMLS_DC ZEND_FILE_LINE_DC);
void (*fetch_all)(MYSQLND_RES *result, unsigned int flags, zval *return_value TSRMLS_DC ZEND_FILE_LINE_DC);
void (*fetch_field_data)(MYSQLND_RES *result, unsigned int offset, zval *return_value TSRMLS_DC);
mynd_ulonglong (*num_rows)(const MYSQLND_RES * const result);
unsigned int (*num_fields)(const MYSQLND_RES * const result);
enum_func_status (*skip_result)(MYSQLND_RES * const result TSRMLS_DC);
enum_func_status (*seek_data)(MYSQLND_RES * result, mynd_ulonglong row TSRMLS_DC);
MYSQLND_FIELD_OFFSET (*seek_field)(MYSQLND_RES * const result, MYSQLND_FIELD_OFFSET field_offset);
MYSQLND_FIELD_OFFSET (*field_tell)(const MYSQLND_RES * const result);
MYSQLND_FIELD * (*fetch_field)(MYSQLND_RES * const result TSRMLS_DC);
MYSQLND_FIELD * (*fetch_field_direct)(const MYSQLND_RES * const result, MYSQLND_FIELD_OFFSET fieldnr TSRMLS_DC);
enum_func_status (*read_result_metadata)(MYSQLND_RES *result, MYSQLND *conn TSRMLS_DC);
unsigned long * (*fetch_lengths)(MYSQLND_RES * const result);
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);
};
struct st_mysqlnd_res_meta_methods
{
MYSQLND_FIELD * (*fetch_field)(MYSQLND_RES_METADATA * const meta TSRMLS_DC);
MYSQLND_FIELD * (*fetch_field_direct)(const MYSQLND_RES_METADATA * const meta, MYSQLND_FIELD_OFFSET fieldnr TSRMLS_DC);
MYSQLND_FIELD_OFFSET (*field_tell)(const MYSQLND_RES_METADATA * const meta);
enum_func_status (*read_metadata)(MYSQLND_RES_METADATA * const meta, MYSQLND *conn TSRMLS_DC);
MYSQLND_RES_METADATA * (*clone_metadata)(const MYSQLND_RES_METADATA * const meta, zend_bool persistent TSRMLS_DC);
void (*free_metadata)(MYSQLND_RES_METADATA *meta, zend_bool persistent TSRMLS_DC);
};
struct st_mysqlnd_stmt_methods
{
enum_func_status (*prepare)(MYSQLND_STMT * const stmt, const char * const query, unsigned int query_len TSRMLS_DC);
enum_func_status (*execute)(MYSQLND_STMT * const stmt TSRMLS_DC);
MYSQLND_RES * (*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 TSRMLS_DC);
enum_func_status (*reset)(MYSQLND_STMT * const stmt TSRMLS_DC);
enum_func_status (*close)(MYSQLND_STMT * const stmt, zend_bool implicit TSRMLS_DC); /* private */
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);
enum_func_status (*bind_param)(MYSQLND_STMT * const stmt, MYSQLND_PARAM_BIND * const param_bind TSRMLS_DC);
enum_func_status (*bind_result)(MYSQLND_STMT * const stmt, MYSQLND_RESULT_BIND * const result_bind TSRMLS_DC);
enum_func_status (*send_long_data)(MYSQLND_STMT * const stmt, unsigned int param_num,
const char * const data, unsigned long length TSRMLS_DC);
MYSQLND_RES * (*get_parameter_metadata)(MYSQLND_STMT * const stmt);
MYSQLND_RES * (*get_result_metadata)(MYSQLND_STMT * const stmt TSRMLS_DC);
mynd_ulonglong (*get_last_insert_id)(const MYSQLND_STMT * const stmt);
mynd_ulonglong (*get_affected_rows)(const MYSQLND_STMT * const stmt);
mynd_ulonglong (*get_num_rows)(const MYSQLND_STMT * const stmt);
unsigned int (*get_param_count)(const MYSQLND_STMT * const stmt);
unsigned int (*get_field_count)(const MYSQLND_STMT * const stmt);
unsigned int (*get_warning_count)(const MYSQLND_STMT * const stmt);
unsigned int (*get_error_no)(const MYSQLND_STMT * const stmt);
const char * (*get_error_str)(const MYSQLND_STMT * const stmt);
const char * (*get_sqlstate)(const MYSQLND_STMT * const stmt);
enum_func_status (*get_attribute)(MYSQLND_STMT * const stmt, enum mysqlnd_stmt_attr attr_type, void * const value TSRMLS_DC);
enum_func_status (*set_attribute)(MYSQLND_STMT * const stmt, enum mysqlnd_stmt_attr attr_type, const void * const value TSRMLS_DC);
};
struct st_mysqlnd_connection
{
/* Operation related */
MYSQLND_NET net;
/* Information related */
char *host;
char *unix_socket;
char *user;
char *passwd;
unsigned int *passwd_len;
char *scheme;
unsigned long long thread_id;
char *server_version;
char *host_info;
unsigned char *scramble;
const MYSQLND_CHARSET *charset;
const MYSQLND_CHARSET *greet_charset;
MYSQLND_INFILE infile;
unsigned int protocol_version;
unsigned long max_packet_size;
unsigned int port;
unsigned long client_flag;
unsigned long server_capabilities;
int tmp_int;
/* For UPSERT queries */
mysqlnd_upsert_status upsert_status;
char *last_message;
unsigned int last_message_len;
/* If error packet, we use these */
mysqlnd_error_info error_info;
/*
To prevent queries during unbuffered fetches. Also to
mark the connection as destroyed for garbage collection.
*/
enum mysqlnd_connection_state state;
enum_mysqlnd_query_type last_query_type;
/* Temporary storage between query and (use|store)_result() call */
MYSQLND_RES *current_result;
/*
How many result sets reference this connection.
It won't be freed until this number reaches 0.
The last one, please close the door! :-)
The result set objects can determine by inspecting
'quit_sent' whether the connection is still valid.
*/
unsigned int refcount;
/* Temporal storage for mysql_query */
unsigned int field_count;
/* persistent connection */
zend_bool persistent;
/* options */
MYSQLND_OPTION options;
/* zval cache */
MYSQLND_THD_ZVAL_PCACHE *zval_cache;
/* qcache */
MYSQLND_QCACHE *qcache;
/* stats */
MYSQLND_STATS stats;
struct st_mysqlnd_conn_methods *m;
};
typedef struct st_php_mysql_packet_row php_mysql_packet_row;
struct mysqlnd_field_hash_key
{
zend_bool is_numeric;
unsigned long key;
#if PHP_MAJOR_VERSION >= 6
zstr ustr;
unsigned int ulen;
#endif
};
struct st_mysqlnd_result_metadata
{
MYSQLND_FIELD *fields;
struct mysqlnd_field_hash_key *zend_hash_keys;
unsigned int current_field;
unsigned int field_count;
/* We need this to make fast allocs in rowp_read */
unsigned int bit_fields_count;
size_t bit_fields_total_len; /* trailing \0 not counted */
struct st_mysqlnd_res_meta_methods *m;
};
struct st_mysqlnd_buffered_result
{
zval ***data;
zval ***data_cursor;
zend_uchar **row_buffers;
mynd_ulonglong row_count;
zend_bool persistent;
MYSQLND_QCACHE *qcache;
unsigned int references;
zend_bool async_invalid;
mysqlnd_error_info error_info;
};
struct st_mysqlnd_unbuffered_result
{
/* For unbuffered (both normal and PS) */
zval **last_row_data;
zend_uchar *last_row_buffer;
mynd_ulonglong row_count;
zend_bool eof_reached;
};
struct st_mysqlnd_res
{
struct st_mysqlnd_res_methods m;
MYSQLND *conn;
enum_mysqlnd_res_type type;
unsigned int field_count;
/* For metadata functions */
MYSQLND_RES_METADATA *meta;
/* To be used with store_result() - both normal and PS */
MYSQLND_RES_BUFFERED *data;
MYSQLND_RES_UNBUFFERED *unbuf;
/*
Column lengths of current row - both buffered and unbuffered.
For buffered results it duplicates the data found in **data
*/
unsigned long *lengths;
php_mysql_packet_row *row_packet; /* Unused for PS */
/* zval cache */
MYSQLND_THD_ZVAL_PCACHE *zval_cache;
};
struct st_mysqlnd_param_bind
{
zval *zv;
zend_uchar type;
enum_param_bind_flags flags;
};
struct st_mysqlnd_result_bind
{
zval *zv;
zend_uchar original_type;
zend_bool bound;
};
struct st_mysqlnd_stmt
{
MYSQLND *conn;
unsigned long stmt_id;
unsigned long flags;/* cursor is set here */
enum_mysqlnd_stmt_state state;
unsigned int warning_count;
MYSQLND_RES *result;
unsigned int field_count;
unsigned int param_count;
unsigned char send_types_to_server;
MYSQLND_PARAM_BIND *param_bind;
MYSQLND_RESULT_BIND *result_bind;
zend_bool result_zvals_separated_once;
mysqlnd_upsert_status upsert_status;
mysqlnd_error_info error_info;
zend_bool update_max_length;
unsigned long prefetch_rows;
zend_bool cursor_exists;
mysqlnd_stmt_use_or_store_func default_rset_handler;
MYSQLND_CMD_BUFFER cmd_buffer;
unsigned int execute_count;/* count how many times the stmt was executed */
struct st_mysqlnd_stmt_methods *m;
};
#endif /* MYSQLND_STRUCTS_H */

File diff suppressed because it is too large Load Diff

View File

@ -31,6 +31,10 @@ typedef zend_uchar mysqlnd_1b;
typedef zend_ushort mysqlnd_2b;
typedef zend_uint mysqlnd_4b;
/* Used in mysqlnd_debug.c */
extern char * mysqlnd_read_header_name;
extern char * mysqlnd_read_body_name;
/* Packet handling */
#define PACKET_INIT(packet, enum_type, c_type) \
@ -42,7 +46,7 @@ typedef zend_uint mysqlnd_4b;
#define PACKET_READ(packet, conn) ((packet)->header.m->read_from_net((packet), (conn) TSRMLS_CC))
#define PACKET_FREE(packet) \
do { \
((packet)->header.m->free_mem((packet), FALSE)); \
((packet)->header.m->free_mem((packet), FALSE TSRMLS_CC)); \
} while (0);
#define PACKET_INIT_ALLOCA(packet, enum_type) \
@ -52,7 +56,7 @@ typedef zend_uint mysqlnd_4b;
}
#define PACKET_WRITE_ALLOCA(packet, conn) PACKET_WRITE(&(packet), (conn))
#define PACKET_READ_ALLOCA(packet, conn) PACKET_READ(&(packet), (conn))
#define PACKET_FREE_ALLOCA(packet) (packet.header.m->free_mem(&(packet), TRUE))
#define PACKET_FREE_ALLOCA(packet) (packet.header.m->free_mem(&(packet), TRUE TSRMLS_CC))
/* Enums */
enum php_mysql_packet_type
@ -114,7 +118,7 @@ typedef struct st_mysqlnd_packet_methods {
size_t struct_size;
enum_func_status (*read_from_net)(void *packet, MYSQLND *conn TSRMLS_DC);
size_t (*write_to_net)(void *packet, MYSQLND *conn TSRMLS_DC);
void (*free_mem)(void *packet, zend_bool alloca);
void (*free_mem)(void *packet, zend_bool alloca TSRMLS_DC);
} mysqlnd_packet_methods;
extern mysqlnd_packet_methods packet_methods[];
@ -237,6 +241,7 @@ typedef struct st_php_mysql_packet_res_field {
MYSQLND_FIELD *metadata;
/* For table definitions, empty for result sets */
zend_bool skip_parsing;
zend_bool stupid_list_fields_eof;
} php_mysql_packet_res_field;