summaryrefslogtreecommitdiff
path: root/ext/mysqli/mysqli.c
diff options
context:
space:
mode:
authorAndrey Hristov <andrey@php.net>2007-07-24 16:13:26 +0000
committerAndrey Hristov <andrey@php.net>2007-07-24 16:13:26 +0000
commit222174e23fe2e5583ecf9bf3f002190fd5b19120 (patch)
treee3f84d2b146f50276444987c08d2ef6fa163f770 /ext/mysqli/mysqli.c
parent9343c54040883483b20824ad50252e64b348a1cd (diff)
downloadphp-git-222174e23fe2e5583ecf9bf3f002190fd5b19120.tar.gz
Import of mysqlnd and ext/mysql + ext/mysqli patched to be built either
with libmysql or mysqld. Use --with-mysql=mysqlnd --with-mysqli=mysqlnd to build with mysqlnd.
Diffstat (limited to 'ext/mysqli/mysqli.c')
-rw-r--r--ext/mysqli/mysqli.c306
1 files changed, 220 insertions, 86 deletions
diff --git a/ext/mysqli/mysqli.c b/ext/mysqli/mysqli.c
index cb3de3388a..ce7f7eebd1 100644
--- a/ext/mysqli/mysqli.c
+++ b/ext/mysqli/mysqli.c
@@ -1,6 +1,6 @@
/*
+----------------------------------------------------------------------+
- | PHP Version 5 |
+ | PHP Version 6 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2007 The PHP Group |
+----------------------------------------------------------------------+
@@ -12,7 +12,9 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Author: Georg Richter <georg@php.net> |
+ | Authors: Georg Richter <georg@php.net> |
+ | Andrey Hristov <andrey@php.net> |
+ | Ulf Wendel <uw@php.net> |
+----------------------------------------------------------------------+
$Id$
@@ -28,7 +30,7 @@
#include "php_ini.h"
#include "ext/standard/info.h"
#include "ext/standard/php_string.h"
-#include "php_mysqli.h"
+#include "php_mysqli_structs.h"
#include "zend_exceptions.h"
#define MYSQLI_STORE_RESULT 0
@@ -52,6 +54,12 @@ zend_class_entry *mysqli_driver_class_entry;
zend_class_entry *mysqli_warning_class_entry;
zend_class_entry *mysqli_exception_class_entry;
+#ifdef HAVE_MYSQLND
+MYSQLND_ZVAL_PCACHE *mysqli_mysqlnd_zval_cache;
+MYSQLND_QCACHE *mysqli_mysqlnd_qcache;
+#endif
+
+
extern void php_mysqli_connect(INTERNAL_FUNCTION_PARAMETERS);
typedef int (*mysqli_read_t)(mysqli_object *obj, zval **retval TSRMLS_DC);
@@ -62,6 +70,26 @@ typedef struct _mysqli_prop_handler {
mysqli_write_t write_func;
} mysqli_prop_handler;
+static int le_pmysqli;
+
+/* Destructor for Persistent Connections */
+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);
+ }
+}
+
+int php_le_pmysqli(void)
+{
+ return le_pmysqli;
+}
+
+#ifndef HAVE_MYSQLND
/* {{{ php_free_stmt_bind_buffer */
void php_free_stmt_bind_buffer(BIND_BUFFER bbuf, int type)
{
@@ -100,25 +128,35 @@ void php_free_stmt_bind_buffer(BIND_BUFFER bbuf, int type)
}
bbuf.var_cnt = 0;
- return;
}
/* }}} */
+#endif
/* {{{ php_clear_stmt_bind */
-void php_clear_stmt_bind(MY_STMT *stmt)
+void php_clear_stmt_bind(MY_STMT *stmt TSRMLS_DC)
{
if (stmt->stmt) {
- mysql_stmt_close(stmt->stmt);
+ if (mysqli_stmt_close(stmt->stmt, TRUE)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error occured while closing statement");
+ return;
+ }
}
+ /*
+ mysqlnd keeps track of the binding and has freed its
+ structures in stmt_close() above
+ */
+#ifndef HAVE_MYSQLND
+ /* Clean param bind */
php_free_stmt_bind_buffer(stmt->param, FETCH_SIMPLE);
+ /* Clean output bind */
php_free_stmt_bind_buffer(stmt->result, FETCH_RESULT);
+#endif
if (stmt->query) {
efree(stmt->query);
}
efree(stmt);
- return;
}
/* }}} */
@@ -157,7 +195,9 @@ static void mysqli_link_free_storage(void *object TSRMLS_DC)
if (my_res && my_res->ptr) {
MY_MYSQL *mysql = (MY_MYSQL *)my_res->ptr;
if (mysql->mysql) {
- mysql_close(mysql->mysql);
+ if (!mysql->persistent) {
+ mysqli_close(mysql->mysql, MYSQLI_CLOSE_IMPLICIT);
+ }
}
php_clear_mysql(mysql);
efree(mysql);
@@ -183,7 +223,7 @@ static void mysqli_stmt_free_storage(void *object TSRMLS_DC)
if (my_res && my_res->ptr) {
MY_STMT *stmt = (MY_STMT *)my_res->ptr;
- php_clear_stmt_bind(stmt);
+ php_clear_stmt_bind(stmt TSRMLS_CC);
}
mysqli_objects_free_storage(object TSRMLS_CC);
}
@@ -262,8 +302,8 @@ zval *mysqli_read_property(zval *object, zval *member, int type TSRMLS_DC)
}
if (ret == SUCCESS) {
-
- if ((!obj->ptr || ((MYSQLI_RESOURCE *)(obj->ptr))->status < MYSQLI_STATUS_INITIALIZED)) {
+ if ((!obj->ptr || ((MYSQLI_RESOURCE *)(obj->ptr))->status < MYSQLI_STATUS_INITIALIZED))
+ {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Couldn't fetch %v", obj->zo.ce->name );
retval = EG(uninitialized_zval_ptr);
return(retval);
@@ -340,7 +380,6 @@ void mysqli_add_property(HashTable *h, char *pname, mysqli_read_t r_func, mysqli
static union _zend_function *php_mysqli_constructor_get(zval *object TSRMLS_DC)
{
- mysqli_object *obj = (mysqli_object *)zend_objects_get_address(object TSRMLS_CC);
zend_class_entry * ce = Z_OBJCE_P(object);
if (ce != mysqli_link_class_entry && ce != mysqli_stmt_class_entry &&
@@ -349,6 +388,7 @@ static union _zend_function *php_mysqli_constructor_get(zval *object TSRMLS_DC)
return zend_std_get_constructor(object TSRMLS_CC);
} else {
static zend_internal_function f;
+ mysqli_object *obj = (mysqli_object *)zend_objects_get_address(object TSRMLS_CC);
f.function_name = obj->zo.ce->name;
f.scope = obj->zo.ce;
@@ -366,7 +406,7 @@ static union _zend_function *php_mysqli_constructor_get(zval *object TSRMLS_DC)
} else if (obj->zo.ce == mysqli_driver_class_entry) {
f.handler = ZEND_FN(mysqli_driver_construct);
} else if (obj->zo.ce == mysqli_warning_class_entry) {
- f.handler = ZEND_FN(mysqli_warning_construct);
+ f.handler = ZEND_MN(mysqli_warning___construct);
}
return (union _zend_function*)&f;
@@ -404,7 +444,7 @@ PHP_MYSQLI_EXPORT(zend_object_value) mysqli_objects_new(zend_class_entry *class_
/* link object */
if (instanceof_function(class_type, mysqli_link_class_entry TSRMLS_CC)) {
free_storage = mysqli_link_free_storage;
- } else if (instanceof_function(class_type, mysqli_driver_class_entry TSRMLS_CC)) { /* stmt object */
+ } else if (instanceof_function(class_type, mysqli_driver_class_entry TSRMLS_CC)) { /* driver object */
free_storage = mysqli_driver_free_storage;
} else if (instanceof_function(class_type, mysqli_stmt_class_entry TSRMLS_CC)) { /* stmt object */
free_storage = mysqli_stmt_free_storage;
@@ -422,16 +462,21 @@ PHP_MYSQLI_EXPORT(zend_object_value) mysqli_objects_new(zend_class_entry *class_
return retval;
}
/* }}} */
-
-/* {{{ mysqli_module_entry
- */
+
+
+/* Dependancies */
static zend_module_dep mysqli_deps[] = {
#if defined(HAVE_SPL) && ((PHP_MAJOR_VERSION > 5) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 1))
ZEND_MOD_REQUIRED("spl")
#endif
+#if defined(HAVE_MYSQLND)
+ ZEND_MOD_REQUIRED("mysqlnd")
+#endif
{NULL, NULL, NULL}
};
+/* {{{ mysqli_module_entry
+ */
zend_module_entry mysqli_module_entry = {
#if ZEND_MODULE_API_NO >= 20050922
STANDARD_MODULE_HEADER_EX, NULL,
@@ -469,22 +514,27 @@ PHP_INI_BEGIN()
STD_PHP_INI_ENTRY("mysqli.default_port", "3306", PHP_INI_ALL, OnUpdateLong, default_port, zend_mysqli_globals, mysqli_globals)
STD_PHP_INI_ENTRY("mysqli.default_socket", NULL, PHP_INI_ALL, OnUpdateStringUnempty, default_socket, zend_mysqli_globals, mysqli_globals)
STD_PHP_INI_BOOLEAN("mysqli.reconnect", "0", PHP_INI_SYSTEM, OnUpdateLong, reconnect, zend_mysqli_globals, mysqli_globals)
+ STD_PHP_INI_BOOLEAN("mysqli.allow_local_infile", "1", PHP_INI_SYSTEM, OnUpdateLong, allow_local_infile, zend_mysqli_globals, mysqli_globals)
+#ifdef HAVE_MYSQLND
+ STD_PHP_INI_ENTRY("mysqli.cache_size", "2000", PHP_INI_SYSTEM, OnUpdateLong, cache_size, zend_mysqli_globals, mysqli_globals)
+#endif
PHP_INI_END()
-
/* }}} */
+
/* {{{ PHP_GINIT_FUNCTION
*/
static PHP_GINIT_FUNCTION(mysqli)
{
mysqli_globals->num_links = 0;
- mysqli_globals->max_links = 0;
+ mysqli_globals->max_links = -1;
mysqli_globals->default_port = 0;
mysqli_globals->default_host = NULL;
mysqli_globals->default_user = NULL;
mysqli_globals->default_pw = NULL;
mysqli_globals->default_socket = NULL;
mysqli_globals->reconnect = 0;
+ mysqli_globals->allow_local_infile = 1;
mysqli_globals->report_mode = 0;
mysqli_globals->report_ht = 0;
#ifdef HAVE_EMBEDDED_MYSQLI
@@ -492,6 +542,10 @@ static PHP_GINIT_FUNCTION(mysqli)
#else
mysqli_globals->embedded = 0;
#endif
+#ifdef HAVE_MYSQLND
+ mysqli_globals->cache_size = 0;
+ mysqli_globals->mysqlnd_thd_zval_cache = NULL;
+#endif
}
/* }}} */
@@ -504,6 +558,15 @@ PHP_MINIT_FUNCTION(mysqli)
REGISTER_INI_ENTRIES();
+#ifndef HAVE_MYSQLND
+ if (mysql_server_init(0, NULL, NULL)) {
+ return FAILURE;
+ }
+#else
+ mysqli_mysqlnd_zval_cache = mysqlnd_palloc_init_cache(MyG(cache_size));
+ mysqli_mysqlnd_qcache = mysqlnd_qcache_init_cache();
+#endif
+
memcpy(&mysqli_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
mysqli_object_handlers.clone_obj = NULL;
mysqli_object_handlers.read_property = mysqli_read_property;
@@ -513,6 +576,10 @@ PHP_MINIT_FUNCTION(mysqli)
zend_u_hash_init(&classes, 0, NULL, NULL, 1, 1);
+ /* persistent connections */
+ le_pmysqli = zend_register_list_destructors_ex(NULL, php_mysqli_dtor,
+ "MySqli persistent connection", module_number);
+
INIT_CLASS_ENTRY(cex, "mysqli_sql_exception", mysqli_exception_methods);
#ifdef HAVE_SPL
mysqli_exception_class_entry = zend_register_internal_class_ex(&cex, spl_ce_RuntimeException, NULL TSRMLS_CC);
@@ -527,33 +594,33 @@ PHP_MINIT_FUNCTION(mysqli)
ce = mysqli_driver_class_entry;
zend_u_hash_init(&mysqli_driver_properties, 0, NULL, NULL, 1, 1);
MYSQLI_ADD_PROPERTIES(&mysqli_driver_properties, mysqli_driver_property_entries);
- zend_hash_add(&classes, ce->name.s, ce->name_length+1, &mysqli_driver_properties, sizeof(mysqli_driver_properties), NULL);
+ zend_u_hash_add(&classes, ZEND_STR_TYPE, ce->name, ce->name_length+1, &mysqli_driver_properties, sizeof(mysqli_driver_properties), NULL);
ce->ce_flags |= ZEND_ACC_FINAL_CLASS;
REGISTER_MYSQLI_CLASS_ENTRY("mysqli", mysqli_link_class_entry, mysqli_link_methods);
ce = mysqli_link_class_entry;
zend_u_hash_init(&mysqli_link_properties, 0, NULL, NULL, 1, 1);
MYSQLI_ADD_PROPERTIES(&mysqli_link_properties, mysqli_link_property_entries);
- zend_hash_add(&classes, ce->name.s, ce->name_length+1, &mysqli_link_properties, sizeof(mysqli_link_properties), NULL);
+ zend_u_hash_add(&classes, ZEND_STR_TYPE, ce->name, ce->name_length+1, &mysqli_link_properties, sizeof(mysqli_link_properties), NULL);
REGISTER_MYSQLI_CLASS_ENTRY("mysqli_warning", mysqli_warning_class_entry, mysqli_warning_methods);
ce = mysqli_warning_class_entry;
ce->ce_flags |= ZEND_ACC_FINAL_CLASS | ZEND_ACC_PROTECTED;
zend_u_hash_init(&mysqli_warning_properties, 0, NULL, NULL, 1, 1);
MYSQLI_ADD_PROPERTIES(&mysqli_warning_properties, mysqli_warning_property_entries);
- zend_hash_add(&classes, ce->name.s, ce->name_length+1, &mysqli_warning_properties, sizeof(mysqli_warning_properties), NULL);
+ zend_u_hash_add(&classes, ZEND_STR_TYPE, ce->name, ce->name_length+1, &mysqli_warning_properties, sizeof(mysqli_warning_properties), NULL);
REGISTER_MYSQLI_CLASS_ENTRY("mysqli_result", mysqli_result_class_entry, mysqli_result_methods);
ce = mysqli_result_class_entry;
zend_u_hash_init(&mysqli_result_properties, 0, NULL, NULL, 1, 1);
MYSQLI_ADD_PROPERTIES(&mysqli_result_properties, mysqli_result_property_entries);
- zend_hash_add(&classes, ce->name.s, ce->name_length+1, &mysqli_result_properties, sizeof(mysqli_result_properties), NULL);
+ zend_u_hash_add(&classes, ZEND_STR_TYPE, ce->name, ce->name_length+1, &mysqli_result_properties, sizeof(mysqli_result_properties), NULL);
REGISTER_MYSQLI_CLASS_ENTRY("mysqli_stmt", mysqli_stmt_class_entry, mysqli_stmt_methods);
ce = mysqli_stmt_class_entry;
zend_u_hash_init(&mysqli_stmt_properties, 0, NULL, NULL, 1, 1);
MYSQLI_ADD_PROPERTIES(&mysqli_stmt_properties, mysqli_stmt_property_entries);
- zend_hash_add(&classes, ce->name.s, ce->name_length+1, &mysqli_stmt_properties, sizeof(mysqli_stmt_properties), NULL);
+ zend_u_hash_add(&classes, ZEND_STR_TYPE, ce->name, ce->name_length+1, &mysqli_stmt_properties, sizeof(mysqli_stmt_properties), NULL);
/* mysqli_options */
@@ -562,6 +629,12 @@ PHP_MINIT_FUNCTION(mysqli)
REGISTER_LONG_CONSTANT("MYSQLI_OPT_CONNECT_TIMEOUT", MYSQL_OPT_CONNECT_TIMEOUT, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("MYSQLI_OPT_LOCAL_INFILE", MYSQL_OPT_LOCAL_INFILE, CONST_CS | CONST_PERSISTENT);
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);
+#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);
+#endif
/* mysqli_real_connect flags */
REGISTER_LONG_CONSTANT("MYSQLI_CLIENT_SSL", CLIENT_SSL, CONST_CS | CONST_PERSISTENT);
@@ -583,7 +656,7 @@ PHP_MINIT_FUNCTION(mysqli)
/* for mysqli_stmt_set_attr */
REGISTER_LONG_CONSTANT("MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH", STMT_ATTR_UPDATE_MAX_LENGTH, CONST_CS | CONST_PERSISTENT);
-#if MYSQL_VERSION_ID > 50003
+#if MYSQL_VERSION_ID > 50003 || defined(HAVE_MYSQLND)
REGISTER_LONG_CONSTANT("MYSQLI_STMT_ATTR_CURSOR_TYPE", STMT_ATTR_CURSOR_TYPE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("MYSQLI_CURSOR_TYPE_NO_CURSOR", CURSOR_TYPE_NO_CURSOR, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("MYSQLI_CURSOR_TYPE_READ_ONLY", CURSOR_TYPE_READ_ONLY, CONST_CS | CONST_PERSISTENT);
@@ -591,7 +664,7 @@ PHP_MINIT_FUNCTION(mysqli)
REGISTER_LONG_CONSTANT("MYSQLI_CURSOR_TYPE_SCROLLABLE", CURSOR_TYPE_SCROLLABLE, CONST_CS | CONST_PERSISTENT);
#endif
-#if MYSQL_VERSION_ID > 50007
+#if MYSQL_VERSION_ID > 50007 || defined(HAVE_MYSQLND)
REGISTER_LONG_CONSTANT("MYSQLI_STMT_ATTR_PREFETCH_ROWS", STMT_ATTR_PREFETCH_ROWS, CONST_CS | CONST_PERSISTENT);
#endif
@@ -637,17 +710,19 @@ PHP_MINIT_FUNCTION(mysqli)
REGISTER_LONG_CONSTANT("MYSQLI_TYPE_INTERVAL", FIELD_TYPE_INTERVAL, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("MYSQLI_TYPE_GEOMETRY", FIELD_TYPE_GEOMETRY, CONST_CS | CONST_PERSISTENT);
-#if MYSQL_VERSION_ID > 50002
+#if MYSQL_VERSION_ID > 50002 || defined(HAVE_MYSQLND)
REGISTER_LONG_CONSTANT("MYSQLI_TYPE_NEWDECIMAL", FIELD_TYPE_NEWDECIMAL, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("MYSQLI_TYPE_BIT", FIELD_TYPE_BIT, CONST_CS | CONST_PERSISTENT);
#endif
-
+ REGISTER_LONG_CONSTANT("MYSQLI_SET_CHARSET_NAME", MYSQL_SET_CHARSET_NAME, CONST_CS | CONST_PERSISTENT);
/* replication */
+#if !defined(HAVE_MYSQLND)
REGISTER_LONG_CONSTANT("MYSQLI_RPL_MASTER", MYSQL_RPL_MASTER, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("MYSQLI_RPL_SLAVE", MYSQL_RPL_SLAVE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("MYSQLI_RPL_ADMIN", MYSQL_RPL_ADMIN, CONST_CS | CONST_PERSISTENT);
+#endif
/* bind support */
REGISTER_LONG_CONSTANT("MYSQLI_NO_DATA", MYSQL_NO_DATA, CONST_CS | CONST_PERSISTENT);
@@ -662,10 +737,6 @@ PHP_MINIT_FUNCTION(mysqli)
REGISTER_LONG_CONSTANT("MYSQLI_REPORT_ALL", MYSQLI_REPORT_ALL, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("MYSQLI_REPORT_OFF", 0, CONST_CS | CONST_PERSISTENT);
- if (mysql_server_init(0, NULL, NULL)) {
- return FAILURE;
- }
-
return SUCCESS;
}
/* }}} */
@@ -674,6 +745,7 @@ PHP_MINIT_FUNCTION(mysqli)
*/
PHP_MSHUTDOWN_FUNCTION(mysqli)
{
+#ifndef HAVE_MYSQLND
#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 */
@@ -683,6 +755,10 @@ PHP_MSHUTDOWN_FUNCTION(mysqli)
#else
mysql_server_end();
#endif
+#else
+ mysqlnd_palloc_free_cache(mysqli_mysqlnd_zval_cache);
+ mysqlnd_qcache_free_cache_reference(&mysqli_mysqlnd_qcache);
+#endif
zend_hash_destroy(&mysqli_driver_properties);
zend_hash_destroy(&mysqli_result_properties);
@@ -700,13 +776,16 @@ PHP_MSHUTDOWN_FUNCTION(mysqli)
*/
PHP_RINIT_FUNCTION(mysqli)
{
-#ifdef ZTS
+#if !defined(HAVE_MYSQLND) && defined(ZTS)
if (mysql_thread_init()) {
return FAILURE;
}
#endif
MyG(error_msg) = NULL;
MyG(error_no) = 0;
+#ifdef HAVE_MYSQLND
+ MyG(mysqlnd_thd_zval_cache) = mysqlnd_palloc_rinit(mysqli_mysqlnd_zval_cache);
+#endif
return SUCCESS;
}
@@ -716,16 +795,20 @@ PHP_RINIT_FUNCTION(mysqli)
*/
PHP_RSHUTDOWN_FUNCTION(mysqli)
{
-#ifdef ZTS
+#if !defined(HAVE_MYSQLND) && defined(ZTS)
mysql_thread_end();
#endif
if (MyG(error_msg)) {
efree(MyG(error_msg));
}
+#ifdef HAVE_MYSQLND
+ mysqlnd_palloc_rshutdown(MyG(mysqlnd_thd_zval_cache));
+#endif
return SUCCESS;
}
/* }}} */
+
/* {{{ PHP_MINFO_FUNCTION
*/
PHP_MINFO_FUNCTION(mysqli)
@@ -733,9 +816,23 @@ PHP_MINFO_FUNCTION(mysqli)
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());
+#if !defined(HAVE_MYSQLND)
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
+ {
+ zval values;
+
+ php_info_print_table_header(2, "Persistent cache", mysqli_mysqlnd_zval_cache? "enabled":"disabled");
+
+ if (mysqli_mysqlnd_zval_cache) {
+ /* Now report cache status */
+ mysqlnd_palloc_stats(mysqli_mysqlnd_zval_cache, &values);
+ mysqlnd_minfo_print_hash(&values);
+ zval_dtor(&values);
+ }
+ }
+#endif
php_info_print_table_end();
DISPLAY_INI_ENTRIES();
@@ -760,7 +857,7 @@ ZEND_FUNCTION(mysqli_stmt_construct)
switch (ZEND_NUM_ARGS())
{
case 1: /* mysql_stmt_init */
- if (zend_parse_parameters(1 TSRMLS_CC, "O", &mysql_link, mysqli_link_class_entry)==FAILURE) {
+ if (zend_parse_parameters(1 TSRMLS_CC, "O", &mysql_link, mysqli_link_class_entry)==FAILURE) {
return;
}
MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link", MYSQLI_STATUS_VALID);
@@ -814,15 +911,19 @@ ZEND_FUNCTION(mysqli_result_construct)
switch (ZEND_NUM_ARGS()) {
case 1:
- if (zend_parse_parameters(1 TSRMLS_CC, "O", &mysql_link, mysqli_link_class_entry)==FAILURE) {
+ if (zend_parse_parameters(1 TSRMLS_CC, "O", &mysql_link, mysqli_link_class_entry)==FAILURE) {
return;
}
- break;
+ break;
case 2:
- if (zend_parse_parameters(2 TSRMLS_CC, "Ol", &mysql_link, mysqli_link_class_entry, &resmode)==FAILURE) {
+ if (zend_parse_parameters(2 TSRMLS_CC, "Ol", &mysql_link, mysqli_link_class_entry, &resmode)==FAILURE) {
return;
}
- break;
+ if (resmode != MYSQLI_USE_RESULT && resmode != MYSQLI_STORE_RESULT) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid value for resultmode");
+ RETURN_FALSE;
+ }
+ break;
default:
WRONG_PARAM_COUNT;
}
@@ -839,11 +940,19 @@ ZEND_FUNCTION(mysqli_result_construct)
mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
mysqli_resource->ptr = (void *)result;
mysqli_resource->status = MYSQLI_STATUS_VALID;
-
+
((mysqli_object *) zend_object_store_get_object(getThis() TSRMLS_CC))->ptr = mysqli_resource;
}
/* }}} */
+#define MYSQL_BINARY_CHARSET_NR 63
+
+#define IS_BINARY_DATA(f) (((f).type == MYSQL_TYPE_TINY_BLOB || (f).type == MYSQL_TYPE_BLOB || \
+ (f).type == MYSQL_TYPE_MEDIUM_BLOB || (f).type == MYSQL_TYPE_LONG_BLOB || \
+ (f).type == MYSQL_TYPE_BIT || (f).type == MYSQL_TYPE_VAR_STRING || (f).type == MYSQL_TYPE_VARCHAR ||\
+ (f).type == MYSQL_TYPE_STRING) && (f).charsetnr == MYSQL_BINARY_CHARSET_NR)
+
+
/* {{{ php_mysqli_fetch_into_hash
*/
void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flags, int into_object)
@@ -851,17 +960,20 @@ void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flags
MYSQL_RES *result;
zval *mysql_result;
long fetchtype;
+ zval *ctor_params = NULL;
+ zend_class_entry *ce = NULL;
+#if !defined(HAVE_MYSQLND)
unsigned int i;
MYSQL_FIELD *fields;
MYSQL_ROW row;
unsigned long *field_len;
- zval *ctor_params = NULL;
- zend_class_entry *ce = NULL;
- void *classname;
- int classname_len;
- zend_uchar classname_type;
+#endif
if (into_object) {
+ void *classname;
+ int classname_len;
+ zend_uchar classname_type;
+
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O|Tz", &mysql_result, mysqli_result_class_entry,
&classname, &classname_len, &classname_type, &ctor_params) == FAILURE) {
return;
@@ -891,18 +1003,17 @@ void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flags
}
MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, &mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
- if ((fetchtype & MYSQLI_BOTH) == 0) {
+ if (fetchtype < MYSQLI_ASSOC || fetchtype > MYSQLI_BOTH) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "The result type should be either MYSQLI_NUM, MYSQLI_ASSOC or MYSQLI_BOTH");
RETURN_FALSE;
}
+#if !defined(HAVE_MYSQLND)
if (!(row = mysql_fetch_row(result))) {
RETURN_NULL();
}
- if (fetchtype & MYSQLI_ASSOC) {
- fields = mysql_fetch_fields(result);
- }
+ fields = mysql_fetch_fields(result);
array_init(return_value);
field_len = mysql_fetch_lengths(result);
@@ -912,8 +1023,7 @@ void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flags
zval *res;
MAKE_STD_ZVAL(res);
-
- if (UG(unicode)) {
+ if (UG(unicode) && !IS_BINARY_DATA(fields[i])) {
UChar *ustr;
int ulen;
@@ -946,20 +1056,32 @@ void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flags
add_index_null(return_value, i);
}
if (fetchtype & MYSQLI_ASSOC) {
- add_assoc_null(return_value, fields[i].name);
+ if (UG(unicode)) {
+ UChar *ustr;
+ int ulen;
+
+ zend_string_to_unicode(UG(utf8_conv), &ustr, &ulen, fields[i].name, strlen(fields[i].name) TSRMLS_CC);
+ add_u_assoc_null(return_value, IS_UNICODE, ZSTR(ustr));
+ efree(ustr);
+ } else {
+ add_assoc_null(return_value, fields[i].name);
+ }
}
}
}
+#else
+ mysqlnd_fetch_into(result, MYSQLND_FETCH_ASSOC, return_value, MYSQLND_MYSQLI);
+#endif
- if (into_object) {
+ if (into_object && Z_TYPE_P(return_value) != IS_NULL) {
zval dataset = *return_value;
zend_fcall_info fci;
zend_fcall_info_cache fcc;
zval *retval_ptr;
-
+
object_and_properties_init(return_value, ce, NULL);
zend_merge_properties(return_value, Z_ARRVAL(dataset), 1 TSRMLS_CC);
-
+
if (ce->constructor) {
fci.size = sizeof(fci);
fci.function_table = &ce->function_table;
@@ -971,7 +1093,7 @@ void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flags
if (Z_TYPE_P(ctor_params) == IS_ARRAY) {
HashTable *ht = Z_ARRVAL_P(ctor_params);
Bucket *p;
-
+
fci.param_count = 0;
fci.params = safe_emalloc(sizeof(zval*), ht->nNumOfElements, 0);
p = ht->pListHead;
@@ -999,9 +1121,9 @@ void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flags
fcc.function_handler = ce->constructor;
fcc.calling_scope = EG(scope);
fcc.object_pp = &return_value;
-
+
if (zend_call_function(&fci, &fcc TSRMLS_CC) == FAILURE) {
- zend_throw_exception_ex(zend_exception_get_default(TSRMLS_C), 0 TSRMLS_CC, "Could not execute %s::%s()", ce->name, ce->constructor->common.function_name);
+ zend_throw_exception_ex(zend_exception_get_default(TSRMLS_C), 0 TSRMLS_CC, "Could not execute %v::%v()", ce->name, ce->constructor->common.function_name);
} else {
if (retval_ptr) {
zval_ptr_dtor(&retval_ptr);
@@ -1011,7 +1133,7 @@ void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flags
efree(fci.params);
}
} else if (ctor_params) {
- zend_throw_exception_ex(zend_exception_get_default(TSRMLS_C), 0 TSRMLS_CC, "Class %s does not have a constructor hence you cannot use ctor_params", ce->name);
+ zend_throw_exception_ex(zend_exception_get_default(TSRMLS_C), 0 TSRMLS_CC, "Class %v does not have a constructor hence you cannot use ctor_params", ce->name);
}
}
}
@@ -1049,25 +1171,34 @@ 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, 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);
- mysql->li_read = NULL;
+ 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)
{
mysqli_local_infile *data;
- MY_MYSQL *mysql;
- php_stream_context *context = NULL;
+ MY_MYSQL *mysql;
+ php_stream_context *context = NULL;
TSRMLS_FETCH();
@@ -1092,7 +1223,7 @@ int php_local_infile_init(void **ptr, const char *filename, void *userdata)
mysql->li_stream = php_stream_open_wrapper_ex((char *)filename, "r", 0, NULL, context);
if (mysql->li_stream == NULL) {
- snprintf((char *)data->error_msg, sizeof(data->error_msg), "Can't find file '%-.64s'.", filename);
+ snprintf((char *)data->error_msg, sizeof(data->error_msg), "Can't find file '%-.64s'.", filename);
return 1;
}
@@ -1105,8 +1236,8 @@ int php_local_infile_init(void **ptr, const char *filename, void *userdata)
/* {{{ int php_local_infile_read */
int php_local_infile_read(void *ptr, char *buf, uint buf_len)
{
- mysqli_local_infile *data;
- MY_MYSQL *mysql;
+ mysqli_local_infile *data;
+ MY_MYSQL *mysql;
zval ***callback_args;
zval *retval;
zval *fp;
@@ -1121,9 +1252,7 @@ int php_local_infile_read(void *ptr, char *buf, uint buf_len)
/* default processing */
if (!mysql->li_read) {
- int count;
-
- count = (int)php_stream_read(mysql->li_stream, buf, buf_len);
+ int count= (int)php_stream_read(mysql->li_stream, buf, buf_len);
if (count < 0) {
LOCAL_INFILE_ERROR_MSG(data->error_msg, ER(2));
@@ -1139,15 +1268,15 @@ int php_local_infile_read(void *ptr, char *buf, uint buf_len)
MAKE_STD_ZVAL(fp);
php_stream_to_zval(mysql->li_stream, fp);
callback_args[0] = &fp;
- ZVAL_STRING(*callback_args[1], "", 1);
- ZVAL_LONG(*callback_args[2], buf_len);
- ZVAL_STRING(*callback_args[3], "", 1);
-
+ 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,
mysql->li_read,
&retval,
- argc,
+ argc,
callback_args,
0,
NULL TSRMLS_CC) == SUCCESS) {
@@ -1156,22 +1285,26 @@ int php_local_infile_read(void *ptr, char *buf, uint buf_len)
zval_ptr_dtor(&retval);
if (rc > 0) {
- if (rc > buf_len) {
+ if (rc >= 0 && rc != Z_STRLEN_P(*callback_args[1])) {
+ LOCAL_INFILE_ERROR_MSG(data->error_msg,
+ "Mismatch between the return value of the callback and the content "
+ "length of the buffer.");
+ rc = -1;
+ } else if (rc > buf_len) {
/* check buffer overflow */
- LOCAL_INFILE_ERROR_MSG(data->error_msg, "Read buffer too large");
+ LOCAL_INFILE_ERROR_MSG(data->error_msg, "Too much data returned");
rc = -1;
} else {
- memcpy(buf, Z_STRVAL_P(*callback_args[1]), rc);
+ memcpy(buf, Z_STRVAL_P(*callback_args[1]), MIN(rc, Z_STRLEN_P(*callback_args[1])));
}
- }
- if (rc < 0) {
+ } else if (rc < 0) {
LOCAL_INFILE_ERROR_MSG(data->error_msg, Z_STRVAL_P(*callback_args[3]));
}
} else {
LOCAL_INFILE_ERROR_MSG(data->error_msg, "Can't execute load data local init callback function");
rc = -1;
}
-
+
FREE_CALLBACK_ARGS(callback_args, 1, argc);
efree(fp);
return rc;
@@ -1187,7 +1320,7 @@ int php_local_infile_error(void *ptr, char *error_msg, uint error_msg_len)
if (data) {
strlcpy(error_msg, data->error_msg, error_msg_len);
return 2000;
- }
+ }
strlcpy(error_msg, ER(CR_OUT_OF_MEMORY), error_msg_len);
return CR_OUT_OF_MEMORY;
}
@@ -1195,10 +1328,10 @@ int php_local_infile_error(void *ptr, char *error_msg, uint error_msg_len)
/* {{{ php_local_infile_end
*/
-void php_local_infile_end(void *ptr)
+void php_local_infile_end(void *ptr)
{
- mysqli_local_infile *data;
- MY_MYSQL *mysql;
+ mysqli_local_infile *data;
+ MY_MYSQL *mysql;
TSRMLS_FETCH();
@@ -1213,9 +1346,10 @@ void php_local_infile_end(void *ptr)
php_stream_close(mysql->li_stream);
free(data);
- return;
+ return;
}
/* }}} */
+#endif
/*
* Local variables: