mirror of
https://github.com/php/php-src.git
synced 2024-11-25 02:44:58 +08:00
Import mysqlnd
Patch ext/mysql and ext/mysqli to support mysqlnd
This commit is contained in:
parent
9f9495a484
commit
8b9b553aa2
@ -40,7 +40,8 @@ AC_DEFUN([PHP_MYSQL_SOCKET_SEARCH], [
|
||||
|
||||
|
||||
PHP_ARG_WITH(mysql, for MySQL support,
|
||||
[ --with-mysql[=DIR] Include MySQL support. DIR is the MySQL base directory])
|
||||
[ --with-mysql[=DIR] Include MySQL support. DIR is the MySQL base directory.
|
||||
If mysqlnd is passed as DIR, the MySQL native driver will be used])
|
||||
|
||||
PHP_ARG_WITH(mysql-sock, for specified location of the MySQL UNIX socket,
|
||||
[ --with-mysql-sock[=DIR] MySQL: Location of the MySQL unix socket pointer.
|
||||
@ -51,9 +52,11 @@ if test -z "$PHP_ZLIB_DIR"; then
|
||||
[ --with-zlib-dir[=DIR] MySQL: Set the path to libz install prefix], no, no)
|
||||
fi
|
||||
|
||||
if test "$PHP_MYSQL" = "mysqlnd"; then
|
||||
dnl enables build of mysqnd library
|
||||
PHP_MYSQLND_ENABLED=yes
|
||||
|
||||
if test "$PHP_MYSQL" != "no"; then
|
||||
AC_DEFINE(HAVE_MYSQL, 1, [Whether you have MySQL])
|
||||
elif test "$PHP_MYSQL" != "no"; then
|
||||
|
||||
AC_MSG_CHECKING([for MySQL UNIX socket location])
|
||||
if test "$PHP_MYSQL_SOCK" != "no" && test "$PHP_MYSQL_SOCK" != "yes"; then
|
||||
@ -137,14 +140,22 @@ Note that the MySQL client library is not bundled anymore!])
|
||||
PHP_ADD_LIBRARY_WITH_PATH($MYSQL_LIBNAME, $MYSQL_LIB_DIR, MYSQL_SHARED_LIBADD)
|
||||
PHP_ADD_INCLUDE($MYSQL_INC_DIR)
|
||||
|
||||
PHP_NEW_EXTENSION(mysql, php_mysql.c, $ext_shared)
|
||||
|
||||
MYSQL_MODULE_TYPE=external
|
||||
MYSQL_LIBS="-L$MYSQL_LIB_DIR -l$MYSQL_LIBNAME $MYSQL_LIBS"
|
||||
MYSQL_INCLUDE=-I$MYSQL_INC_DIR
|
||||
|
||||
PHP_SUBST(MYSQL_SHARED_LIBADD)
|
||||
PHP_SUBST_OLD(MYSQL_MODULE_TYPE)
|
||||
PHP_SUBST_OLD(MYSQL_LIBS)
|
||||
PHP_SUBST_OLD(MYSQL_INCLUDE)
|
||||
fi
|
||||
|
||||
dnl Enable extension
|
||||
if test "$PHP_MYSQL" != "no"; then
|
||||
AC_DEFINE(HAVE_MYSQL, 1, [Whether you have MySQL])
|
||||
PHP_NEW_EXTENSION(mysql, php_mysql.c, $ext_shared)
|
||||
PHP_SUBST(MYSQL_SHARED_LIBADD)
|
||||
|
||||
if test "$PHP_MYSQLI" = "mysqlnd"; then
|
||||
PHP_ADD_EXTENSION_DEP(mysqli, mysqlnd)
|
||||
fi
|
||||
fi
|
||||
|
@ -4,12 +4,17 @@
|
||||
ARG_WITH("mysql", "MySQL support", "no");
|
||||
|
||||
if (PHP_MYSQL != "no") {
|
||||
if (CHECK_LIB("libmysql.lib", "mysql", PHP_MYSQL) &&
|
||||
if (PHP_MYSQLI != "mysqlnd") {
|
||||
if (CHECK_LIB("libmysql.lib", "mysql", PHP_MYSQL) &&
|
||||
CHECK_HEADER_ADD_INCLUDE("mysql.h", "CFLAGS_MYSQL",
|
||||
PHP_MYSQL + "\\include;" + PHP_PHP_BUILD + "\\include\\mysql;" + PHP_MYSQL)) {
|
||||
EXTENSION("mysql", "php_mysql.c");
|
||||
AC_DEFINE('HAVE_MYSQL', 1, 'Have MySQL library');
|
||||
PHP_MYSQL + "\\include;" + PHP_PHP_BUILD + "\\include\\mysql;" + PHP_MYSQL)) {
|
||||
} else {
|
||||
WARNING("mysql not enabled; libraries and headers not found");
|
||||
}
|
||||
} else {
|
||||
WARNING("mysql not enabled; libraries and headers not found");
|
||||
AC_DEFINE('HAVE_MYSQLND', 1, 'MySQL native driver support enabled');
|
||||
ADD_EXTENSION_DEP('mysql', 'mysqlnd', true);
|
||||
}
|
||||
EXTENSION("mysql", "php_mysql.c");
|
||||
AC_DEFINE('HAVE_MYSQL', 1, 'Have MySQL library');
|
||||
}
|
||||
|
41
ext/mysql/mysql_mysqlnd.h
Normal file
41
ext/mysql/mysql_mysqlnd.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| PHP Version 5 |
|
||||
+----------------------------------------------------------------------+
|
||||
| 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> |
|
||||
+----------------------------------------------------------------------+
|
||||
|
||||
*/
|
||||
|
||||
#ifndef MYSQL_MYSQLND_H
|
||||
#define MYSQL_MYSQLND_H
|
||||
|
||||
#include "ext/mysqlnd/mysqlnd_libmysql_compat.h"
|
||||
|
||||
/* Here comes non-libmysql API to have less ifdefs in mysqli*/
|
||||
#define MYSQLI_CLOSE_EXPLICIT MYSQLND_CLOSE_EXPLICIT
|
||||
#define MYSQLI_CLOSE_IMPLICIT MYSQLND_CLOSE_IMPLICIT
|
||||
#define MYSQLI_CLOSE_DISCONNECTED MYSQLND_CLOSE_DISCONNECTED
|
||||
|
||||
#define mysqli_result_is_unbuffered(r) ((r)->unbuf)
|
||||
#define mysqli_server_status(c) (c)->upsert_status.server_status
|
||||
#define mysqli_stmt_warning_count(s) mysqlnd_stmt_warning_count((s))
|
||||
#define mysqli_stmt_server_status(s) (s)->upsert_status.server_status
|
||||
#define mysqli_stmt_get_connection(s) (s)->conn
|
||||
#define mysqli_close(c, how) mysqlnd_close((c), (how))
|
||||
#define mysqli_stmt_close(c, implicit) mysqlnd_stmt_close((c), (implicit))
|
||||
#define mysqli_free_result(r, implicit) mysqlnd_free_result((r), (implicit))
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -34,6 +34,25 @@
|
||||
#include "TSRM.h"
|
||||
#endif
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_MYSQLND)
|
||||
#include "ext/mysqlnd/mysqlnd.h"
|
||||
#include "ext/mysql/mysql_mysqlnd.h"
|
||||
#else
|
||||
#include <mysql.h>
|
||||
#endif
|
||||
|
||||
#if (MYSQL_VERSION_ID >= 40113 && MYSQL_VERSION_ID < 50000) || MYSQL_VERSION_ID >= 50007 || HAVE_MYSQLND
|
||||
#define MYSQL_HAS_SET_CHARSET
|
||||
#endif
|
||||
|
||||
extern zend_module_entry mysql_module_entry;
|
||||
|
||||
#define mysql_module_ptr &mysql_module_entry
|
||||
@ -91,9 +110,6 @@ PHP_FUNCTION(mysql_stat);
|
||||
PHP_FUNCTION(mysql_thread_id);
|
||||
PHP_FUNCTION(mysql_client_encoding);
|
||||
PHP_FUNCTION(mysql_ping);
|
||||
#if (MYSQL_VERSION_ID >= 40113 && MYSQL_VERSION_ID < 50000) || MYSQL_VERSION_ID >= 50007
|
||||
PHP_FUNCTION(mysql_set_charset);
|
||||
#endif
|
||||
|
||||
ZEND_BEGIN_MODULE_GLOBALS(mysql)
|
||||
long default_link;
|
||||
@ -108,6 +124,12 @@ ZEND_BEGIN_MODULE_GLOBALS(mysql)
|
||||
long connect_timeout;
|
||||
long result_allocated;
|
||||
long trace_mode;
|
||||
long allow_local_infile;
|
||||
#ifdef HAVE_MYSQLND
|
||||
MYSQLND_THD_ZVAL_PCACHE *mysqlnd_thd_zval_cache;
|
||||
MYSQLND_QCACHE *mysqlnd_qcache;
|
||||
long cache_size;
|
||||
#endif
|
||||
ZEND_END_MODULE_GLOBALS(mysql)
|
||||
|
||||
#ifdef ZTS
|
||||
|
@ -3,18 +3,17 @@ dnl $Id$
|
||||
dnl config.m4 for extension mysqli
|
||||
|
||||
PHP_ARG_WITH(mysqli, for MySQLi support,
|
||||
[ --with-mysqli[=FILE] Include MySQLi support. FILE is the optional pathname
|
||||
to mysql_config [mysql_config]])
|
||||
[ --with-mysqli[=FILE] Include MySQLi support. FILE is the optional pathname to mysql_config [mysql_config].
|
||||
If mysqlnd is passed as FILE, the MySQL native driver will be used])
|
||||
|
||||
PHP_ARG_ENABLE(embedded_mysqli, whether to enable embedded MySQLi support,
|
||||
[ --enable-embedded-mysqli MYSQLi: Enable embedded support], no, no)
|
||||
|
||||
if test "$PHP_MYSQLI" != "no"; then
|
||||
if test "$PHP_MYSQLI" = "mysqlnd"; then
|
||||
dnl This needs to be set in any extension which wishes to use mysqlnd
|
||||
PHP_MYSQLND_ENABLED=yes
|
||||
|
||||
dnl there are no mysql libs currently bundled with PHP.. --Jani
|
||||
dnl if test "$PHP_MYSQL" = "yes"; then
|
||||
dnl AC_MSG_ERROR([--with-mysql (using bundled libs) can not be used together with --with-mysqli.])
|
||||
dnl fi
|
||||
elif test "$PHP_MYSQLI" != "no"; then
|
||||
|
||||
if test "$PHP_MYSQLI" = "yes"; then
|
||||
MYSQL_CONFIG=`$php_shtool path mysql_config`
|
||||
@ -26,6 +25,8 @@ dnl fi
|
||||
if test "$PHP_EMBEDDED_MYSQLI" = "yes"; then
|
||||
AC_DEFINE(HAVE_EMBEDDED_MYSQLI, 1, [embedded MySQL support enabled])
|
||||
MYSQL_LIB_CFG='--libmysqld-libs'
|
||||
dnl mysqlnd doesn't support embedded, so we have to add some extra stuff
|
||||
mysqli_extra_sources="mysqli_embedded.c"
|
||||
elif test "$enable_maintainer_zts" = "yes"; then
|
||||
MYSQL_LIB_CFG='--libs_r'
|
||||
MYSQL_LIB_NAME='mysqlclient_r'
|
||||
@ -48,17 +49,29 @@ dnl fi
|
||||
[
|
||||
PHP_EVAL_INCLINE($MYSQLI_INCLINE)
|
||||
PHP_EVAL_LIBLINE($MYSQLI_LIBLINE, MYSQLI_SHARED_LIBADD)
|
||||
AC_DEFINE(HAVE_MYSQLILIB,1,[ ])
|
||||
PHP_CHECK_LIBRARY($MYSQL_LIB_NAME, mysql_stmt_field_count,
|
||||
AC_DEFINE(HAVE_MYSQLILIB, 1, [ ])
|
||||
PHP_CHECK_LIBRARY($MYSQL_LIB_NAME, mysql_set_character_set,
|
||||
[ ],[
|
||||
AC_MSG_ERROR([MySQLI doesn't support versions < 4.1.3 (for MySQL 4.1.x) and < 5.0.1 for (MySQL 5.0.x) anymore. Please update your libraries.])
|
||||
],[$MYSQLI_LIBLINE])
|
||||
AC_MSG_ERROR([MySQLI doesn't support versions < 4.1.13 (for MySQL 4.1.x) and < 5.0.7 for (MySQL 5.0.x) anymore. Please update your libraries.])
|
||||
],[$MYSQLI_LIBLINE])
|
||||
],[
|
||||
AC_MSG_ERROR([wrong mysql library version or lib not found. Check config.log for more information.])
|
||||
],[
|
||||
$MYSQLI_LIBLINE
|
||||
])
|
||||
|
||||
PHP_NEW_EXTENSION(mysqli, mysqli.c mysqli_api.c mysqli_prop.c mysqli_nonapi.c mysqli_fe.c mysqli_report.c mysqli_repl.c mysqli_driver.c mysqli_warning.c mysqli_exception.c mysqli_embedded.c, $ext_shared)
|
||||
PHP_SUBST(MYSQLI_SHARED_LIBADD)
|
||||
mysqli_extra_sources="$mysqli_extra_sources mysqli_repl.c"
|
||||
fi
|
||||
|
||||
dnl Build extension
|
||||
if test "$PHP_MYSQLI" != "no"; then
|
||||
mysqli_sources="mysqli.c mysqli_api.c mysqli_prop.c mysqli_nonapi.c \
|
||||
mysqli_fe.c mysqli_report.c mysqli_driver.c mysqli_warning.c \
|
||||
mysqli_exception.c $mysqli_extra_sources"
|
||||
PHP_NEW_EXTENSION(mysqli, $mysqli_sources, $ext_shared)
|
||||
PHP_SUBST(MYSQLI_SHARED_LIBADD)
|
||||
|
||||
if test "$PHP_MYSQLI" = "mysqlnd"; then
|
||||
PHP_ADD_EXTENSION_DEP(mysqli, mysqlnd)
|
||||
fi
|
||||
fi
|
||||
|
@ -1,14 +1,42 @@
|
||||
// $Id$
|
||||
// vim:ft=javascript
|
||||
|
||||
// Note: The extension name is "mysqli", you enable it with "--with-mysqli".
|
||||
// Passing value "mysqlnd" to it enables the bundled
|
||||
// client library to connect to the MySQL server, i.e. no external MySQL
|
||||
// client library is needed to perform the build.
|
||||
|
||||
ARG_WITH("mysqli", "MySQLi support", "no");
|
||||
|
||||
if (PHP_MYSQLI != "no") {
|
||||
if (CHECK_LIB("libmysql.lib", "mysqli", PHP_MYSQLI) &&
|
||||
CHECK_HEADER_ADD_INCLUDE("mysql.h", "CFLAGS_MYSQLI", PHP_MYSQLI + "\\include;" + PHP_PHP_BUILD + "\\include\\mysql;" + PHP_MYSQLI)) {
|
||||
EXTENSION("mysqli", "mysqli.c mysqli_api.c mysqli_prop.c mysqli_nonapi.c mysqli_fe.c mysqli_report.c mysqli_repl.c mysqli_driver.c mysqli_warning.c mysqli_exception.c mysqli_embedded.c");
|
||||
AC_DEFINE('HAVE_MYSQLILIB', 1, 'Have MySQLi library');
|
||||
mysqli_source =
|
||||
"mysqli.c " +
|
||||
"mysqli_api.c " +
|
||||
"mysqli_driver.c " +
|
||||
"mysqli_embedded.c " +
|
||||
"mysqli_exception.c " +
|
||||
"mysqli_fe.c " +
|
||||
"mysqli_nonapi.c " +
|
||||
"mysqli_prop.c " +
|
||||
"mysqli_report.c " +
|
||||
"mysqli_warning.c";
|
||||
|
||||
if (PHP_MYSQLI != "mysqlnd") {
|
||||
if (CHECK_LIB("libmysql.lib", "mysqli", PHP_MYSQLI) &&
|
||||
CHECK_HEADER_ADD_INCLUDE("mysql.h", "CFLAGS_MYSQLI", PHP_MYSQLI +
|
||||
"\\include;" + PHP_PHP_BUILD +
|
||||
"\\include\\mysql;" + PHP_MYSQLI)) {
|
||||
// No "mysqli_repl.c" when using "mysqlnd"
|
||||
mysqli_extra_sources = "mysqli_repl.c";
|
||||
EXTENSION("mysqli", mysqli_source + " " + mysqli_extra_sources);
|
||||
AC_DEFINE('HAVE_MYSQLILIB', 1, 'Have MySQLi library');
|
||||
} else {
|
||||
WARNING("mysqli not enabled; libraries and headers not found");
|
||||
}
|
||||
} else {
|
||||
WARNING("mysqli not enabled; libraries and headers not found");
|
||||
EXTENSION("mysqli", mysqli_source);
|
||||
AC_DEFINE('HAVE_MYSQLND', 1, 'MySQLi with native driver support enabled');
|
||||
AC_DEFINE('HAVE_MYSQLILIB', 1, 'Have MySQLi library');
|
||||
ADD_EXTENSION_DEP('mysqli', 'mysqlnd', true);
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,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 +52,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 +68,63 @@ typedef struct _mysqli_prop_handler {
|
||||
mysqli_write_t write_func;
|
||||
} mysqli_prop_handler;
|
||||
|
||||
static int le_pmysqli;
|
||||
|
||||
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) {
|
||||
mysqli_plist_entry *plist = (mysqli_plist_entry *) rsrc->ptr;
|
||||
zend_hash_destroy(&plist->free_links);
|
||||
zend_hash_destroy(&plist->used_links);
|
||||
free(plist);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
@ -80,7 +143,7 @@ void php_free_stmt_bind_buffer(BIND_BUFFER bbuf, int type)
|
||||
|
||||
if (bbuf.vars[i]) {
|
||||
zval_ptr_dtor(&bbuf.vars[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bbuf.vars) {
|
||||
@ -100,30 +163,44 @@ 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;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ 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);
|
||||
@ -140,7 +217,7 @@ static void mysqli_objects_free_storage(void *object TSRMLS_DC)
|
||||
mysqli_object *intern = (mysqli_object *)zo;
|
||||
MYSQLI_RESOURCE *my_res = (MYSQLI_RESOURCE *)intern->ptr;
|
||||
|
||||
my_efree(my_res);
|
||||
my_efree(my_res);
|
||||
zend_object_std_dtor(&intern->zo TSRMLS_CC);
|
||||
efree(intern);
|
||||
}
|
||||
@ -157,7 +234,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);
|
||||
@ -166,6 +245,13 @@ static void mysqli_link_free_storage(void *object TSRMLS_DC)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ mysql_driver_free_storage */
|
||||
static void mysqli_driver_free_storage(void *object TSRMLS_DC)
|
||||
{
|
||||
mysqli_objects_free_storage(object TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ mysqli_stmt_free_storage
|
||||
*/
|
||||
static void mysqli_stmt_free_storage(void *object TSRMLS_DC)
|
||||
@ -176,7 +262,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);
|
||||
}
|
||||
@ -243,7 +329,7 @@ zval *mysqli_read_property(zval *object, zval *member, int type TSRMLS_DC)
|
||||
ret = FAILURE;
|
||||
obj = (mysqli_object *)zend_objects_get_address(object TSRMLS_CC);
|
||||
|
||||
if (member->type != IS_STRING) {
|
||||
if (member->type != IS_STRING) {
|
||||
tmp_member = *member;
|
||||
zval_copy_ctor(&tmp_member);
|
||||
convert_to_string(&tmp_member);
|
||||
@ -256,7 +342,8 @@ zval *mysqli_read_property(zval *object, zval *member, int type TSRMLS_DC)
|
||||
|
||||
if (ret == SUCCESS) {
|
||||
if (strcmp(obj->zo.ce->name, "mysqli_driver") &&
|
||||
(!obj->ptr || ((MYSQLI_RESOURCE *)(obj->ptr))->status < MYSQLI_STATUS_INITIALIZED)) {
|
||||
(!obj->ptr || ((MYSQLI_RESOURCE *)(obj->ptr))->status < MYSQLI_STATUS_INITIALIZED))
|
||||
{
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Couldn't fetch %s", obj->zo.ce->name );
|
||||
retval = EG(uninitialized_zval_ptr);
|
||||
return(retval);
|
||||
@ -290,7 +377,7 @@ void mysqli_write_property(zval *object, zval *member, zval *value TSRMLS_DC)
|
||||
zend_object_handlers *std_hnd;
|
||||
int ret;
|
||||
|
||||
if (member->type != IS_STRING) {
|
||||
if (member->type != IS_STRING) {
|
||||
tmp_member = *member;
|
||||
zval_copy_ctor(&tmp_member);
|
||||
convert_to_string(&tmp_member);
|
||||
@ -333,7 +420,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 &&
|
||||
@ -342,6 +428,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;
|
||||
@ -361,7 +448,7 @@ static union _zend_function *php_mysqli_constructor_get(zval *object TSRMLS_DC)
|
||||
} else if (obj->zo.ce == mysqli_warning_class_entry) {
|
||||
f.handler = ZEND_MN(mysqli_warning___construct);
|
||||
}
|
||||
|
||||
|
||||
return (union _zend_function*)&f;
|
||||
}
|
||||
}
|
||||
@ -382,8 +469,7 @@ PHP_MYSQLI_EXPORT(zend_object_value) mysqli_objects_new(zend_class_entry *class_
|
||||
intern->prop_handler = NULL;
|
||||
|
||||
mysqli_base_class = class_type;
|
||||
while (mysqli_base_class->type != ZEND_INTERNAL_CLASS && mysqli_base_class->parent != NULL)
|
||||
{
|
||||
while (mysqli_base_class->type != ZEND_INTERNAL_CLASS && mysqli_base_class->parent != NULL) {
|
||||
mysqli_base_class = mysqli_base_class->parent;
|
||||
}
|
||||
zend_hash_find(&classes, mysqli_base_class->name, mysqli_base_class->name_length + 1,
|
||||
@ -396,6 +482,8 @@ 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)) { /* 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;
|
||||
} else if (instanceof_function(class_type, mysqli_result_class_entry TSRMLS_CC)) { /* result object */
|
||||
@ -412,17 +500,21 @@ PHP_MYSQLI_EXPORT(zend_object_value) mysqli_objects_new(zend_class_entry *class_
|
||||
return retval;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ mysqli_module_entry
|
||||
*/
|
||||
|
||||
|
||||
/* Dependancies */
|
||||
static const zend_module_dep mysqli_deps[] = {
|
||||
const 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,
|
||||
@ -454,22 +546,33 @@ 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)
|
||||
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->num_active_persistent = 0;
|
||||
mysqli_globals->num_inactive_persistent = 0;
|
||||
mysqli_globals->max_links = -1;
|
||||
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;
|
||||
@ -478,11 +581,16 @@ static PHP_GINIT_FUNCTION(mysqli)
|
||||
mysqli_globals->reconnect = 0;
|
||||
mysqli_globals->report_mode = 0;
|
||||
mysqli_globals->report_ht = 0;
|
||||
mysqli_globals->allow_local_infile = 1;
|
||||
#ifdef HAVE_EMBEDDED_MYSQLI
|
||||
mysqli_globals->embedded = 1;
|
||||
#else
|
||||
mysqli_globals->embedded = 0;
|
||||
#endif
|
||||
#ifdef HAVE_MYSQLND
|
||||
mysqli_globals->cache_size = 0;
|
||||
mysqli_globals->mysqlnd_thd_zval_cache = NULL;
|
||||
#endif
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@ -494,6 +602,16 @@ PHP_MINIT_FUNCTION(mysqli)
|
||||
zend_object_handlers *std_hnd = zend_get_std_object_handlers();
|
||||
|
||||
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();
|
||||
#endif
|
||||
|
||||
memcpy(&mysqli_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
|
||||
mysqli_object_handlers.clone_obj = NULL;
|
||||
@ -504,6 +622,10 @@ PHP_MINIT_FUNCTION(mysqli)
|
||||
|
||||
zend_hash_init(&classes, 0, NULL, NULL, 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);
|
||||
@ -552,6 +674,13 @@ 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_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);
|
||||
#endif
|
||||
|
||||
/* mysqli_real_connect flags */
|
||||
REGISTER_LONG_CONSTANT("MYSQLI_CLIENT_SSL", CLIENT_SSL, CONST_CS | CONST_PERSISTENT);
|
||||
@ -573,7 +702,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);
|
||||
@ -581,7 +710,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
|
||||
|
||||
@ -627,17 +756,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);
|
||||
@ -652,10 +783,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;
|
||||
}
|
||||
/* }}} */
|
||||
@ -664,15 +791,25 @@ 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) {
|
||||
/*
|
||||
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);
|
||||
#endif
|
||||
|
||||
zend_hash_destroy(&mysqli_driver_properties);
|
||||
zend_hash_destroy(&mysqli_result_properties);
|
||||
@ -690,13 +827,16 @@ PHP_MSHUTDOWN_FUNCTION(mysqli)
|
||||
*/
|
||||
PHP_RINIT_FUNCTION(mysqli)
|
||||
{
|
||||
#ifdef ZTS
|
||||
#if !defined(HAVE_MYSQLND) && defined(ZTS) && MYSQL_VERSION_ID >= 40000
|
||||
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;
|
||||
}
|
||||
@ -706,27 +846,55 @@ PHP_RINIT_FUNCTION(mysqli)
|
||||
*/
|
||||
PHP_RSHUTDOWN_FUNCTION(mysqli)
|
||||
{
|
||||
#ifdef 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)) {
|
||||
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)
|
||||
{
|
||||
char buf[32];
|
||||
|
||||
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());
|
||||
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);
|
||||
#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();
|
||||
@ -742,16 +910,16 @@ Parameters:
|
||||
ZEND_FUNCTION(mysqli_stmt_construct)
|
||||
{
|
||||
MY_MYSQL *mysql;
|
||||
zval *mysql_link;
|
||||
zval *mysql_link;
|
||||
MY_STMT *stmt;
|
||||
MYSQLI_RESOURCE *mysqli_resource;
|
||||
MYSQLI_RESOURCE *mysqli_resource;
|
||||
char *statement;
|
||||
int stmt_len;
|
||||
int statement_len;
|
||||
|
||||
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);
|
||||
@ -761,15 +929,15 @@ ZEND_FUNCTION(mysqli_stmt_construct)
|
||||
stmt->stmt = mysql_stmt_init(mysql->mysql);
|
||||
break;
|
||||
case 2:
|
||||
if (zend_parse_parameters(2 TSRMLS_CC, "Os", &mysql_link, mysqli_link_class_entry, &statement, &stmt_len)==FAILURE) {
|
||||
if (zend_parse_parameters(2 TSRMLS_CC, "Os", &mysql_link, mysqli_link_class_entry, &statement, &statement_len)==FAILURE) {
|
||||
return;
|
||||
}
|
||||
MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link", MYSQLI_STATUS_VALID);
|
||||
|
||||
stmt = (MY_STMT *)ecalloc(1,sizeof(MY_STMT));
|
||||
|
||||
|
||||
if ((stmt->stmt = mysql_stmt_init(mysql->mysql))) {
|
||||
mysql_stmt_prepare(stmt->stmt, statement, stmt_len);
|
||||
mysql_stmt_prepare(stmt->stmt, statement, statement_len);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -800,20 +968,24 @@ ZEND_FUNCTION(mysqli_result_construct)
|
||||
MY_MYSQL *mysql;
|
||||
MYSQL_RES *result;
|
||||
zval *mysql_link;
|
||||
MYSQLI_RESOURCE *mysqli_resource;
|
||||
MYSQLI_RESOURCE *mysqli_resource;
|
||||
long resmode = MYSQLI_STORE_RESULT;
|
||||
|
||||
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;
|
||||
}
|
||||
@ -830,7 +1002,7 @@ 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;
|
||||
|
||||
}
|
||||
@ -843,12 +1015,14 @@ 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;
|
||||
#endif
|
||||
|
||||
if (into_object) {
|
||||
char *class_name;
|
||||
@ -882,11 +1056,12 @@ 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();
|
||||
}
|
||||
@ -930,16 +1105,19 @@ void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flags
|
||||
}
|
||||
}
|
||||
}
|
||||
#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;
|
||||
@ -951,7 +1129,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;
|
||||
@ -979,7 +1157,7 @@ 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);
|
||||
} else {
|
||||
@ -1009,6 +1187,8 @@ 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);\
|
||||
@ -1029,7 +1209,7 @@ 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));
|
||||
|
||||
/* {{{ void php_set_local_infile_handler_default
|
||||
*/
|
||||
@ -1037,7 +1217,10 @@ void php_set_local_infile_handler_default(MY_MYSQL *mysql) {
|
||||
/* register internal callback functions */
|
||||
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;
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@ -1047,7 +1230,7 @@ int php_local_infile_init(void **ptr, const char *filename, void *userdata)
|
||||
{
|
||||
mysqli_local_infile *data;
|
||||
MY_MYSQL *mysql;
|
||||
php_stream_context *context = NULL;
|
||||
php_stream_context *context = NULL;
|
||||
|
||||
TSRMLS_FETCH();
|
||||
|
||||
@ -1086,7 +1269,7 @@ int php_local_infile_init(void **ptr, const char *filename, void *userdata)
|
||||
int php_local_infile_read(void *ptr, char *buf, uint buf_len)
|
||||
{
|
||||
mysqli_local_infile *data;
|
||||
MY_MYSQL *mysql;
|
||||
MY_MYSQL *mysql;
|
||||
zval ***callback_args;
|
||||
zval *retval;
|
||||
zval *fp;
|
||||
@ -1101,9 +1284,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));
|
||||
@ -1113,21 +1294,21 @@ int php_local_infile_read(void *ptr, char *buf, uint buf_len)
|
||||
}
|
||||
|
||||
ALLOC_CALLBACK_ARGS(callback_args, 1, argc);
|
||||
|
||||
|
||||
/* set parameters: filepointer, buffer, buffer_len, errormsg */
|
||||
|
||||
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) {
|
||||
@ -1136,22 +1317,36 @@ 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;
|
||||
}
|
||||
|
||||
/*
|
||||
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);
|
||||
return rc;
|
||||
@ -1167,7 +1362,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;
|
||||
}
|
||||
@ -1175,10 +1370,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();
|
||||
|
||||
@ -1193,9 +1388,10 @@ void php_local_infile_end(void *ptr)
|
||||
|
||||
php_stream_close(mysql->li_stream);
|
||||
free(data);
|
||||
return;
|
||||
return;
|
||||
}
|
||||
/* }}} */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -25,7 +25,7 @@
|
||||
#include "php.h"
|
||||
#include "php_ini.h"
|
||||
#include "ext/standard/info.h"
|
||||
#include "php_mysqli.h"
|
||||
#include "php_mysqli_structs.h"
|
||||
#include "zend_exceptions.h"
|
||||
|
||||
|
||||
@ -110,7 +110,7 @@ static int driver_client_version_read(mysqli_object *obj, zval **retval TSRMLS_D
|
||||
static int driver_client_info_read(mysqli_object *obj, zval **retval TSRMLS_DC)
|
||||
{
|
||||
ALLOC_ZVAL(*retval);
|
||||
ZVAL_STRING(*retval, MYSQL_SERVER_VERSION, 1);
|
||||
ZVAL_STRING(*retval, (char *)mysql_get_client_info(), 1);
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
@ -130,9 +130,17 @@ MAP_PROPERTY_MYG_LONG_READ(driver_report_read, report_mode);
|
||||
|
||||
ZEND_FUNCTION(mysqli_driver_construct)
|
||||
{
|
||||
#if G0
|
||||
MYSQLI_RESOURCE *mysqli_resource;
|
||||
|
||||
mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
|
||||
mysqli_resource->ptr = 1;
|
||||
mysqli_resource->status = (ZEND_NUM_ARGS() == 1) ? MYSQLI_STATUS_INITIALIZED : MYSQLI_STATUS_VALID;
|
||||
((mysqli_object *) zend_object_store_get_object(getThis() TSRMLS_CC))->ptr = mysqli_resource;
|
||||
#endif
|
||||
}
|
||||
|
||||
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},
|
||||
@ -145,8 +153,10 @@ mysqli_property_entry mysqli_driver_property_entries[] = {
|
||||
/* {{{ mysqli_driver_methods[]
|
||||
*/
|
||||
const zend_function_entry mysqli_driver_methods[] = {
|
||||
#if defined(HAVE_EMBEDDED_MYSQLI)
|
||||
PHP_FALIAS(embedded_server_start, mysqli_embedded_server_start, NULL)
|
||||
PHP_FALIAS(embedded_server_end, mysqli_embedded_server_end, NULL)
|
||||
#endif
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
/* }}} */
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include "php.h"
|
||||
#include "php_ini.h"
|
||||
#include "ext/standard/info.h"
|
||||
#include "php_mysqli.h"
|
||||
#include "php_mysqli_structs.h"
|
||||
|
||||
/* {{{ proto bool mysqli_embedded_server_start(bool start, array arguments, array groups)
|
||||
initialize and start embedded server */
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include "php.h"
|
||||
#include "php_ini.h"
|
||||
#include "ext/standard/info.h"
|
||||
#include "php_mysqli.h"
|
||||
#include "php_mysqli_structs.h"
|
||||
#include "zend_exceptions.h"
|
||||
|
||||
/* {{{ mysqli_exception_methods[]
|
||||
|
@ -27,7 +27,7 @@
|
||||
#include "php.h"
|
||||
#include "php_ini.h"
|
||||
#include "ext/standard/info.h"
|
||||
#include "php_mysqli.h"
|
||||
#include "php_mysqli_structs.h"
|
||||
|
||||
|
||||
static
|
||||
@ -61,14 +61,24 @@ const zend_function_entry mysqli_functions[] = {
|
||||
PHP_FE(mysqli_connect_errno, NULL)
|
||||
PHP_FE(mysqli_connect_error, NULL)
|
||||
PHP_FE(mysqli_data_seek, NULL)
|
||||
PHP_FE(mysqli_dump_debug_info, NULL)
|
||||
PHP_FE(mysqli_debug, NULL)
|
||||
#if !defined(HAVE_MYSQLND)
|
||||
PHP_FE(mysqli_disable_reads_from_master, NULL)
|
||||
PHP_FE(mysqli_disable_rpl_parse, NULL)
|
||||
PHP_FE(mysqli_dump_debug_info, NULL)
|
||||
PHP_FE(mysqli_enable_reads_from_master, NULL)
|
||||
PHP_FE(mysqli_enable_rpl_parse, NULL)
|
||||
PHP_FE(mysqli_send_query, NULL)
|
||||
PHP_FE(mysqli_slave_query, NULL)
|
||||
PHP_FE(mysqli_master_query, NULL)
|
||||
PHP_FE(mysqli_rpl_parse_enabled, NULL)
|
||||
PHP_FE(mysqli_rpl_probe, NULL)
|
||||
PHP_FE(mysqli_rpl_query_type, NULL)
|
||||
#endif
|
||||
#if defined(HAVE_EMBEDDED_MYSQLI)
|
||||
PHP_FE(mysqli_embedded_server_end, NULL)
|
||||
PHP_FE(mysqli_embedded_server_start, NULL)
|
||||
#endif
|
||||
PHP_FE(mysqli_errno, NULL)
|
||||
PHP_FE(mysqli_error, NULL)
|
||||
PHP_FE(mysqli_stmt_execute, NULL)
|
||||
@ -77,14 +87,22 @@ const zend_function_entry mysqli_functions[] = {
|
||||
PHP_FE(mysqli_fetch_fields, NULL)
|
||||
PHP_FE(mysqli_fetch_field_direct, NULL)
|
||||
PHP_FE(mysqli_fetch_lengths, NULL)
|
||||
#ifdef HAVE_MYSQLND
|
||||
PHP_FE(mysqli_fetch_all, NULL)
|
||||
#endif
|
||||
PHP_FE(mysqli_fetch_array, NULL)
|
||||
PHP_FE(mysqli_fetch_assoc, NULL)
|
||||
PHP_FE(mysqli_fetch_object, NULL)
|
||||
PHP_FE(mysqli_fetch_object, NULL)
|
||||
PHP_FE(mysqli_fetch_row, NULL)
|
||||
PHP_FE(mysqli_field_count, NULL)
|
||||
PHP_FE(mysqli_field_seek, NULL)
|
||||
PHP_FE(mysqli_field_tell, NULL)
|
||||
PHP_FE(mysqli_free_result, NULL)
|
||||
#if defined(HAVE_MYSQLND)
|
||||
PHP_FE(mysqli_get_cache_stats, NULL)
|
||||
PHP_FE(mysqli_get_connection_stats, NULL)
|
||||
PHP_FE(mysqli_get_client_stats, NULL)
|
||||
#endif
|
||||
#ifdef HAVE_MYSQLI_GET_CHARSET
|
||||
PHP_FE(mysqli_get_charset, NULL)
|
||||
#endif
|
||||
@ -99,9 +117,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)
|
||||
PHP_FE(mysqli_master_query, NULL)
|
||||
#endif
|
||||
PHP_FE(mysqli_more_results, NULL)
|
||||
PHP_FE(mysqli_multi_query, NULL)
|
||||
PHP_FE(mysqli_next_result, NULL)
|
||||
@ -116,9 +135,6 @@ const zend_function_entry mysqli_functions[] = {
|
||||
PHP_FE(mysqli_real_escape_string, NULL)
|
||||
PHP_FE(mysqli_real_query, NULL)
|
||||
PHP_FE(mysqli_rollback, NULL)
|
||||
PHP_FE(mysqli_rpl_parse_enabled, NULL)
|
||||
PHP_FE(mysqli_rpl_probe, NULL)
|
||||
PHP_FE(mysqli_rpl_query_type, NULL)
|
||||
PHP_FE(mysqli_select_db, NULL)
|
||||
#ifdef HAVE_MYSQLI_SET_CHARSET
|
||||
PHP_FE(mysqli_set_charset, NULL)
|
||||
@ -134,14 +150,17 @@ const zend_function_entry mysqli_functions[] = {
|
||||
PHP_FE(mysqli_stmt_bind_result, second_arg_force_by_ref_rest)
|
||||
PHP_FE(mysqli_stmt_fetch, NULL)
|
||||
PHP_FE(mysqli_stmt_free_result, NULL)
|
||||
#if defined(HAVE_MYSQLND)
|
||||
PHP_FE(mysqli_stmt_get_result, NULL)
|
||||
#endif
|
||||
PHP_FE(mysqli_stmt_get_warnings, NULL)
|
||||
PHP_FE(mysqli_stmt_insert_id, NULL)
|
||||
PHP_FE(mysqli_stmt_reset, NULL)
|
||||
PHP_FE(mysqli_stmt_param_count, NULL)
|
||||
PHP_FE(mysqli_send_query, NULL)
|
||||
PHP_FE(mysqli_slave_query, NULL)
|
||||
PHP_FE(mysqli_sqlstate, NULL)
|
||||
#if !defined(HAVE_MYSQLND)
|
||||
PHP_FE(mysqli_ssl_set, NULL)
|
||||
#endif
|
||||
PHP_FE(mysqli_stat, NULL)
|
||||
PHP_FE(mysqli_stmt_affected_rows, NULL)
|
||||
PHP_FE(mysqli_stmt_close, NULL)
|
||||
@ -150,8 +169,8 @@ const zend_function_entry mysqli_functions[] = {
|
||||
PHP_FE(mysqli_stmt_error, NULL)
|
||||
PHP_FE(mysqli_stmt_num_rows, NULL)
|
||||
PHP_FE(mysqli_stmt_sqlstate, NULL)
|
||||
PHP_FE(mysqli_store_result, NULL)
|
||||
PHP_FE(mysqli_stmt_store_result, NULL)
|
||||
PHP_FE(mysqli_store_result, NULL)
|
||||
PHP_FE(mysqli_thread_id, NULL)
|
||||
PHP_FE(mysqli_thread_safe, NULL)
|
||||
PHP_FE(mysqli_use_result, NULL)
|
||||
@ -184,23 +203,34 @@ const zend_function_entry mysqli_link_methods[] = {
|
||||
PHP_FALIAS(close,mysqli_close,NULL)
|
||||
PHP_FALIAS(commit,mysqli_commit,NULL)
|
||||
PHP_FALIAS(connect,mysqli_connect,NULL)
|
||||
PHP_FALIAS(dump_debug_info,mysqli_dump_debug_info,NULL)
|
||||
PHP_FALIAS(debug,mysqli_debug,NULL)
|
||||
#if !defined(HAVE_MYSQLND)
|
||||
PHP_FALIAS(disable_reads_from_master,mysqli_disable_reads_from_master,NULL)
|
||||
PHP_FALIAS(disable_rpl_parse,mysqli_disable_rpl_parse,NULL)
|
||||
PHP_FALIAS(dump_debug_info,mysqli_dump_debug_info,NULL)
|
||||
PHP_FALIAS(enable_reads_from_master,mysqli_enable_reads_from_master,NULL)
|
||||
PHP_FALIAS(enable_rpl_parse,mysqli_enable_rpl_parse,NULL)
|
||||
PHP_FALIAS(rpl_parse_enabled,mysqli_rpl_parse_enabled,NULL)
|
||||
PHP_FALIAS(rpl_probe,mysqli_rpl_probe,NULL)
|
||||
PHP_FALIAS(rpl_query_type,mysqli_rpl_query_type,NULL)
|
||||
PHP_FALIAS(master_query,mysqli_master_query,NULL)
|
||||
PHP_FALIAS(slave_query,mysqli_slave_query,NULL)
|
||||
#endif
|
||||
#ifdef HAVE_MYSQLI_GET_CHARSET
|
||||
PHP_FALIAS(get_charset,mysqli_get_charset,NULL)
|
||||
#endif
|
||||
PHP_FALIAS(get_client_info,mysqli_get_client_info,NULL)
|
||||
#if defined(HAVE_MYSQLND)
|
||||
PHP_FALIAS(get_connection_stats,mysqli_get_connection_stats,NULL)
|
||||
#endif
|
||||
PHP_FALIAS(get_server_info,mysqli_get_server_info,NULL)
|
||||
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)
|
||||
PHP_FALIAS(master_query,mysqli_master_query,NULL)
|
||||
#endif
|
||||
PHP_FALIAS(multi_query,mysqli_multi_query,NULL)
|
||||
PHP_FALIAS(mysqli,mysqli_connect,NULL)
|
||||
PHP_FALIAS(more_results,mysqli_more_results, NULL)
|
||||
@ -214,16 +244,14 @@ const zend_function_entry mysqli_link_methods[] = {
|
||||
PHP_FALIAS(escape_string, mysqli_real_escape_string,NULL)
|
||||
PHP_FALIAS(real_query,mysqli_real_query,NULL)
|
||||
PHP_FALIAS(rollback,mysqli_rollback,NULL)
|
||||
PHP_FALIAS(rpl_parse_enabled,mysqli_rpl_parse_enabled,NULL)
|
||||
PHP_FALIAS(rpl_probe,mysqli_rpl_probe,NULL)
|
||||
PHP_FALIAS(rpl_query_type,mysqli_rpl_query_type,NULL)
|
||||
PHP_FALIAS(select_db,mysqli_select_db,NULL)
|
||||
#ifdef HAVE_MYSQLI_SET_CHARSET
|
||||
PHP_FALIAS(set_charset,mysqli_set_charset,NULL)
|
||||
#endif
|
||||
PHP_FALIAS(set_opt, mysqli_options,NULL)
|
||||
PHP_FALIAS(slave_query,mysqli_slave_query,NULL)
|
||||
#if !defined(HAVE_MYSQLND)
|
||||
PHP_FALIAS(ssl_set,mysqli_ssl_set,NULL)
|
||||
#endif
|
||||
PHP_FALIAS(stat,mysqli_stat,NULL)
|
||||
PHP_FALIAS(stmt_init,mysqli_stmt_init, NULL)
|
||||
PHP_FALIAS(store_result,mysqli_store_result,NULL)
|
||||
@ -238,18 +266,20 @@ const zend_function_entry mysqli_link_methods[] = {
|
||||
* Every user visible function must have an entry in mysqli_result_functions[].
|
||||
*/
|
||||
const zend_function_entry mysqli_result_methods[] = {
|
||||
PHP_FALIAS(mysqli_result, mysqli_result_construct, NULL)
|
||||
PHP_FALIAS(__construct, mysqli_result_construct, NULL)
|
||||
PHP_FALIAS(close,mysqli_free_result,NULL)
|
||||
PHP_FALIAS(free,mysqli_free_result,NULL)
|
||||
PHP_FALIAS(data_seek,mysqli_data_seek,NULL)
|
||||
PHP_FALIAS(fetch_field,mysqli_fetch_field,NULL)
|
||||
PHP_FALIAS(fetch_fields,mysqli_fetch_fields,NULL)
|
||||
PHP_FALIAS(fetch_field_direct,mysqli_fetch_field_direct,NULL)
|
||||
#if defined(HAVE_MYSQLND)
|
||||
PHP_FALIAS(fetch_all,mysqli_fetch_all,NULL)
|
||||
#endif
|
||||
PHP_FALIAS(fetch_array,mysqli_fetch_array,NULL)
|
||||
PHP_FALIAS(fetch_assoc,mysqli_fetch_assoc,NULL)
|
||||
PHP_FALIAS(fetch_object,mysqli_fetch_object,NULL)
|
||||
PHP_FALIAS(fetch_row,mysqli_fetch_row,NULL)
|
||||
PHP_FALIAS(field_count,mysqli_field_count,NULL)
|
||||
PHP_FALIAS(field_seek,mysqli_field_seek,NULL)
|
||||
PHP_FALIAS(free_result,mysqli_free_result,NULL)
|
||||
{NULL, NULL, NULL}
|
||||
@ -261,7 +291,7 @@ const zend_function_entry mysqli_result_methods[] = {
|
||||
* Every user visible function must have an entry in mysqli_stmt_functions[].
|
||||
*/
|
||||
const zend_function_entry mysqli_stmt_methods[] = {
|
||||
PHP_FALIAS(mysqli_stmt, mysqli_stmt_construct, NULL)
|
||||
PHP_FALIAS(__construct, mysqli_stmt_construct, NULL)
|
||||
PHP_FALIAS(attr_get,mysqli_stmt_attr_get,NULL)
|
||||
PHP_FALIAS(attr_set,mysqli_stmt_attr_set,NULL)
|
||||
PHP_FALIAS(bind_param,mysqli_stmt_bind_param,second_arg_force_by_ref_rest)
|
||||
@ -279,6 +309,9 @@ const zend_function_entry mysqli_stmt_methods[] = {
|
||||
PHP_FALIAS(reset,mysqli_stmt_reset,NULL)
|
||||
PHP_FALIAS(prepare,mysqli_stmt_prepare, NULL)
|
||||
PHP_FALIAS(store_result,mysqli_stmt_store_result,NULL)
|
||||
#if defined(HAVE_MYSQLND)
|
||||
PHP_FALIAS(get_result,mysqli_stmt_get_result,NULL)
|
||||
#endif
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
/* }}} */
|
||||
|
36
ext/mysqli/mysqli_libmysql.h
Normal file
36
ext/mysqli/mysqli_libmysql.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| PHP Version 6 |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 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> |
|
||||
+----------------------------------------------------------------------+
|
||||
|
||||
*/
|
||||
|
||||
/* These are unused */
|
||||
#define MYSQLI_CLOSE_EXPLICIT
|
||||
#define MYSQLI_CLOSE_IMPLICIT
|
||||
#define MYSQLI_CLOSE_DISCONNECTED
|
||||
#define MYSQLND_OPT_NUMERIC_AND_DATETIME_AS_UNICODE 200
|
||||
#define MYSQLND_OPT_INT_AND_YEAR_AS_INT 201
|
||||
|
||||
#define mysqli_result_is_unbuffered(r) ((r)->handle && (r)->handle->status == MYSQL_STATUS_USE_RESULT)
|
||||
#define mysqli_server_status(c) (c)->server_status
|
||||
#define mysqli_stmt_warning_count(s) mysql_warning_count((s)->mysql)
|
||||
#define mysqli_stmt_server_status(s) (s)->mysql->server_status
|
||||
#define mysqli_stmt_get_connection(s) (s)->mysql
|
||||
#define mysqli_close(c, is_forced) mysql_close((c))
|
||||
#define mysqli_stmt_close(c, implicit) mysql_stmt_close((c))
|
||||
#define mysqli_free_result(r, is_forced) mysql_free_result((r))
|
41
ext/mysqli/mysqli_mysqlnd.h
Normal file
41
ext/mysqli/mysqli_mysqlnd.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| PHP Version 5 |
|
||||
+----------------------------------------------------------------------+
|
||||
| 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> |
|
||||
+----------------------------------------------------------------------+
|
||||
|
||||
*/
|
||||
|
||||
#ifndef MYSQLI_MYSQLND_H
|
||||
#define MYSQLI_MYSQLND_H
|
||||
|
||||
#include "ext/mysqlnd/mysqlnd_libmysql_compat.h"
|
||||
|
||||
/* Here comes non-libmysql API to have less ifdefs in mysqli*/
|
||||
#define MYSQLI_CLOSE_EXPLICIT MYSQLND_CLOSE_EXPLICIT
|
||||
#define MYSQLI_CLOSE_IMPLICIT MYSQLND_CLOSE_IMPLICIT
|
||||
#define MYSQLI_CLOSE_DISCONNECTED MYSQLND_CLOSE_DISCONNECTED
|
||||
|
||||
#define mysqli_result_is_unbuffered(r) ((r)->unbuf)
|
||||
#define mysqli_server_status(c) (c)->upsert_status.server_status
|
||||
#define mysqli_stmt_warning_count(s) mysqlnd_stmt_warning_count((s))
|
||||
#define mysqli_stmt_server_status(s) (s)->upsert_status.server_status
|
||||
#define mysqli_stmt_get_connection(s) (s)->conn
|
||||
#define mysqli_close(c, how) mysqlnd_close((c), (how))
|
||||
#define mysqli_stmt_close(c, implicit) mysqlnd_stmt_close((c), (implicit))
|
||||
#define mysqli_free_result(r, implicit) mysqlnd_free_result((r), (implicit))
|
||||
|
||||
#endif
|
@ -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$
|
||||
@ -27,45 +29,53 @@
|
||||
#include "php.h"
|
||||
#include "php_ini.h"
|
||||
#include "ext/standard/info.h"
|
||||
#include "php_mysqli.h"
|
||||
#include "php_mysqli_structs.h"
|
||||
|
||||
#define SAFE_STR(a) ((a)?a:"")
|
||||
|
||||
|
||||
/* {{{ proto object mysqli_connect([string hostname [,string username [,string passwd [,string dbname [,int port [,string socket]]]]]])
|
||||
Open a connection to a mysql server */
|
||||
PHP_FUNCTION(mysqli_connect)
|
||||
{
|
||||
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;
|
||||
long port=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;
|
||||
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();
|
||||
}
|
||||
hostname = username = dbname = passwd = socket = NULL;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ssssls", &hostname, &hostname_len, &username, &username_len,
|
||||
&passwd, &passwd_len, &dbname, &dbname_len, &port, &socket, &socket_len) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!socket_len) {
|
||||
socket = NULL;
|
||||
if (!socket_len || !socket) {
|
||||
socket = MyG(default_socket);
|
||||
}
|
||||
|
||||
/* TODO: safe mode handling */
|
||||
if (PG(sql_safe_mode)){
|
||||
} else {
|
||||
if (!passwd) {
|
||||
passwd = MyG(default_pw);
|
||||
if (!username){
|
||||
username = MyG(default_user);
|
||||
if (!hostname) {
|
||||
hostname = MyG(default_host);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!passwd) {
|
||||
passwd = MyG(default_pw);
|
||||
passwd_len = strlen(SAFE_STR(passwd));
|
||||
}
|
||||
if (!username){
|
||||
username = MyG(default_user);
|
||||
}
|
||||
if (!hostname || !hostname_len) {
|
||||
hostname = MyG(default_host);
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
@ -75,7 +85,7 @@ PHP_FUNCTION(mysqli_connect)
|
||||
mysql = (MY_MYSQL*)mysqli_resource->ptr;
|
||||
php_clear_mysql(mysql);
|
||||
if (mysql->mysql) {
|
||||
mysql_close(mysql->mysql);
|
||||
mysqli_close(mysql->mysql, MYSQLI_CLOSE_EXPLICIT);
|
||||
mysql->mysql = NULL;
|
||||
}
|
||||
}
|
||||
@ -84,61 +94,194 @@ PHP_FUNCTION(mysqli_connect)
|
||||
mysql = (MY_MYSQL *) ecalloc(1, sizeof(MY_MYSQL));
|
||||
}
|
||||
|
||||
if (!(mysql->mysql = mysql_init(NULL))) {
|
||||
efree(mysql);
|
||||
RETURN_FALSE;
|
||||
if (strlen(SAFE_STR(hostname)) > 2 && !strncasecmp(hostname, "p:", 2)) {
|
||||
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);
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
/* 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;
|
||||
|
||||
do {
|
||||
if (zend_hash_num_elements(&plist->free_links)) {
|
||||
HashPosition pos;
|
||||
MYSQL **free_mysql;
|
||||
ulong idx;
|
||||
dtor_func_t pDestructor = plist->free_links.pDestructor;
|
||||
|
||||
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;
|
||||
}
|
||||
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->free_links.pDestructor = pDestructor; /* Restore the destructor */
|
||||
mysql->mysql = *free_mysql;
|
||||
|
||||
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)) {
|
||||
#else
|
||||
if (!mysql_ping(mysql->mysql)) {
|
||||
#endif
|
||||
#ifdef HAVE_MYSQLND
|
||||
mysqlnd_restart_psession(mysql->mysql);
|
||||
#endif
|
||||
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);
|
||||
MyG(num_links)--;
|
||||
break;
|
||||
}
|
||||
mysql->hash_index = idx;
|
||||
mysql->hash_key = hash_key;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
} while (0);
|
||||
}
|
||||
} 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(2, MyG(max_persistent)), NULL, php_mysqli_dtor_p_elements, 1);
|
||||
zend_hash_init(&plist->used_links, MAX(2, 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
|
||||
goto err;
|
||||
}
|
||||
new_connection = TRUE;
|
||||
|
||||
#ifdef HAVE_EMBEDDED_MYSQLI
|
||||
if (strcmp(hostname, ":embedded")) {
|
||||
if (hostname_len) {
|
||||
unsigned int external=1;
|
||||
mysql_options(mysql->mysql, MYSQL_OPT_USE_REMOTE_CONNECTION, (char *)&external);
|
||||
} else {
|
||||
hostname[0] = '\0';
|
||||
mysql_options(mysql->mysql, MYSQL_OPT_USE_EMBEDDED_CONNECTION, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!socket) {
|
||||
socket = MyG(default_socket);
|
||||
}
|
||||
|
||||
if (mysql_real_connect(mysql->mysql,hostname,username,passwd,dbname,port,socket,CLIENT_MULTI_RESULTS) == NULL) {
|
||||
#if !defined(HAVE_MYSQLND)
|
||||
if (mysql_real_connect(mysql->mysql, hostname, username, passwd, dbname, port, socket, CLIENT_MULTI_RESULTS) == NULL)
|
||||
#else
|
||||
if (mysqlnd_connect(mysql->mysql, hostname, username, passwd, passwd_len, dbname, dbname_len,
|
||||
port, socket, CLIENT_MULTI_RESULTS, MyG(mysqlnd_thd_zval_cache) TSRMLS_CC) == NULL)
|
||||
#endif
|
||||
{
|
||||
/* Save error messages */
|
||||
|
||||
php_mysqli_throw_sql_exception( mysql->mysql->net.sqlstate, mysql->mysql->net.last_errno TSRMLS_CC,
|
||||
"%s", mysql->mysql->net.last_error);
|
||||
|
||||
php_mysqli_set_error(mysql_errno(mysql->mysql), (char *) mysql_error(mysql->mysql) TSRMLS_CC);
|
||||
php_mysqli_throw_sql_exception((char *)mysql_sqlstate(mysql->mysql), mysql_errno(mysql->mysql) TSRMLS_CC,
|
||||
"%s", mysql_error(mysql->mysql));
|
||||
|
||||
/* free mysql structure */
|
||||
mysql_close(mysql->mysql);
|
||||
efree(mysql);
|
||||
RETURN_FALSE;
|
||||
mysqli_close(mysql->mysql, MYSQLI_CLOSE_DISCONNECTED);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* clear error */
|
||||
php_mysqli_set_error(mysql_errno(mysql->mysql), (char *) mysql_error(mysql->mysql) TSRMLS_CC);
|
||||
|
||||
#if !defined(HAVE_MYSQLND)
|
||||
mysql->mysql->reconnect = MyG(reconnect);
|
||||
|
||||
/* set our own local_infile handler */
|
||||
php_set_local_infile_handler_default(mysql);
|
||||
#endif
|
||||
|
||||
mysql_options(mysql->mysql, MYSQL_OPT_LOCAL_INFILE, (char *)&MyG(allow_local_infile));
|
||||
|
||||
end:
|
||||
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) {
|
||||
/* save persistent connection */
|
||||
ulong hash_index = zend_hash_next_free_element(&plist->used_links);
|
||||
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");
|
||||
} 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;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ proto int mysqli_connect_errno(void)
|
||||
Returns the numerical value of the error message from last connect command */
|
||||
PHP_FUNCTION(mysqli_connect_errno)
|
||||
@ -159,11 +302,30 @@ PHP_FUNCTION(mysqli_connect_error)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ proto mixed mysqli_fetch_array (object result [,int resulttype])
|
||||
Fetch a result row as an associative array, a numeric array, or both */
|
||||
PHP_FUNCTION(mysqli_fetch_array)
|
||||
{
|
||||
#if !defined(HAVE_MYSQLND)
|
||||
php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 0);
|
||||
#else
|
||||
MYSQL_RES *result;
|
||||
zval *mysql_result;
|
||||
long mode = MYSQLND_FETCH_BOTH;
|
||||
|
||||
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O|l", &mysql_result, mysqli_result_class_entry, &mode) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, &mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
|
||||
|
||||
if (mode < MYSQLI_ASSOC || mode > 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;
|
||||
}
|
||||
|
||||
mysqlnd_fetch_into(result, mode, return_value, MYSQLND_MYSQLI);
|
||||
#endif
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@ -171,20 +333,102 @@ PHP_FUNCTION(mysqli_fetch_array)
|
||||
Fetch a result row as an associative array */
|
||||
PHP_FUNCTION(mysqli_fetch_assoc)
|
||||
{
|
||||
#if !defined(HAVE_MYSQLND)
|
||||
php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, MYSQLI_ASSOC, 0);
|
||||
#else
|
||||
MYSQL_RES *result;
|
||||
zval *mysql_result;
|
||||
|
||||
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, &mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
|
||||
mysqlnd_fetch_into(result, MYSQLND_FETCH_ASSOC, return_value, MYSQLND_MYSQLI);
|
||||
|
||||
#endif
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ proto mixed mysqli_fetch_all (object result [,int resulttype])
|
||||
Fetches all result rows as an associative array, a numeric array, or both */
|
||||
#if defined(HAVE_MYSQLND)
|
||||
PHP_FUNCTION(mysqli_fetch_all)
|
||||
{
|
||||
MYSQL_RES *result;
|
||||
zval *mysql_result;
|
||||
long mode = MYSQLND_FETCH_NUM;
|
||||
|
||||
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O|l", &mysql_result, mysqli_result_class_entry, &mode) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, &mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
|
||||
|
||||
if (!mode || (mode & ~MYSQLND_FETCH_BOTH)) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Mode can be only MYSQLI_FETCH_NUM, "
|
||||
"MYSQLI_FETCH_ASSOC or MYSQLI_FETCH_BOTH");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
mysqlnd_fetch_all(result, mode, return_value);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ proto array mysqli_cache_stats(void) U
|
||||
Returns statistics about the zval cache */
|
||||
PHP_FUNCTION(mysqli_get_cache_stats)
|
||||
{
|
||||
if (ZEND_NUM_ARGS()) {
|
||||
WRONG_PARAM_COUNT;
|
||||
}
|
||||
mysqlnd_palloc_stats(mysqli_mysqlnd_zval_cache, return_value);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ proto array mysqli_get_client_stats(void)
|
||||
Returns statistics about the zval cache */
|
||||
PHP_FUNCTION(mysqli_get_client_stats)
|
||||
{
|
||||
if (ZEND_NUM_ARGS()) {
|
||||
WRONG_PARAM_COUNT;
|
||||
}
|
||||
mysqlnd_get_client_stats(return_value);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ proto array mysqli_get_connection_stats(void)
|
||||
Returns statistics about the zval cache */
|
||||
PHP_FUNCTION(mysqli_get_connection_stats)
|
||||
{
|
||||
MY_MYSQL *mysql;
|
||||
zval *mysql_link;
|
||||
|
||||
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O",
|
||||
&mysql_link, mysqli_link_class_entry) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link", MYSQLI_STATUS_VALID);
|
||||
|
||||
mysqlnd_get_connection_stats(mysql->mysql, return_value);
|
||||
}
|
||||
#endif
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ proto mixed mysqli_fetch_object (object result [, string class_name [, NULL|array ctor_params]])
|
||||
Fetch a result row as an object */
|
||||
PHP_FUNCTION(mysqli_fetch_object)
|
||||
{
|
||||
php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, MYSQLI_ASSOC, 1);
|
||||
/* todo: mysqlnd support */
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto bool mysqli_multi_query(object link, string query)
|
||||
Binary-safe version of mysql_query() */
|
||||
allows to execute multiple queries */
|
||||
PHP_FUNCTION(mysqli_multi_query)
|
||||
{
|
||||
MY_MYSQL *mysql;
|
||||
@ -199,25 +443,30 @@ PHP_FUNCTION(mysqli_multi_query)
|
||||
|
||||
MYSQLI_ENABLE_MQ;
|
||||
if (mysql_real_query(mysql->mysql, query, query_len)) {
|
||||
#ifndef HAVE_MYSQLND
|
||||
char s_error[MYSQL_ERRMSG_SIZE], s_sqlstate[SQLSTATE_LENGTH+1];
|
||||
unsigned int s_errno;
|
||||
MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
|
||||
|
||||
/* we have to save error information, cause
|
||||
MYSQLI_DISABLE_MQ will reset error information */
|
||||
strcpy(s_error, mysql_error(mysql->mysql));
|
||||
strcpy(s_sqlstate, mysql_sqlstate(mysql->mysql));
|
||||
s_errno = mysql_errno(mysql->mysql);
|
||||
|
||||
#else
|
||||
mysqlnd_error_info error_info = mysql->mysql->error_info;
|
||||
#endif
|
||||
MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
|
||||
MYSQLI_DISABLE_MQ;
|
||||
|
||||
#ifndef HAVE_MYSQLND
|
||||
/* restore error information */
|
||||
strcpy(mysql->mysql->net.last_error, s_error);
|
||||
strcpy(mysql->mysql->net.sqlstate, s_sqlstate);
|
||||
mysql->mysql->net.last_errno = s_errno;
|
||||
|
||||
#else
|
||||
mysql->mysql->error_info = error_info;
|
||||
#endif
|
||||
RETURN_FALSE;
|
||||
}
|
||||
}
|
||||
RETURN_TRUE;
|
||||
}
|
||||
/* }}} */
|
||||
@ -258,7 +507,7 @@ PHP_FUNCTION(mysqli_query)
|
||||
if (!mysql_field_count(mysql->mysql)) {
|
||||
/* no result set - not a SELECT */
|
||||
if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
|
||||
php_mysqli_report_index(query, mysql->mysql->server_status TSRMLS_CC);
|
||||
php_mysqli_report_index(query, mysqli_server_status(mysql->mysql) TSRMLS_CC);
|
||||
}
|
||||
RETURN_TRUE;
|
||||
}
|
||||
@ -266,13 +515,13 @@ PHP_FUNCTION(mysqli_query)
|
||||
result = (resultmode == MYSQLI_USE_RESULT) ? mysql_use_result(mysql->mysql) : mysql_store_result(mysql->mysql);
|
||||
|
||||
if (!result) {
|
||||
php_mysqli_throw_sql_exception(mysql->mysql->net.sqlstate, mysql->mysql->net.last_errno TSRMLS_CC,
|
||||
"%s", mysql->mysql->net.last_error);
|
||||
php_mysqli_throw_sql_exception((char *)mysql_sqlstate(mysql->mysql), mysql_errno(mysql->mysql) TSRMLS_CC,
|
||||
"%s", mysql_error(mysql->mysql));
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
|
||||
php_mysqli_report_index(query, mysql->mysql->server_status TSRMLS_CC);
|
||||
php_mysqli_report_index(query, mysqli_server_status(mysql->mysql) TSRMLS_CC);
|
||||
}
|
||||
|
||||
mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
|
||||
@ -282,6 +531,36 @@ PHP_FUNCTION(mysqli_query)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
#if defined(HAVE_MYSQLND)
|
||||
/* {{{ proto object mysqli_stmt_get_result(object link) U
|
||||
Buffer result set on client */
|
||||
PHP_FUNCTION(mysqli_stmt_get_result)
|
||||
{
|
||||
MYSQL_RES *result;
|
||||
MYSQLI_RESOURCE *mysqli_resource;
|
||||
MY_STMT *stmt;
|
||||
zval *mysql_stmt;
|
||||
|
||||
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
MYSQLI_FETCH_RESOURCE(stmt, MY_STMT *, &mysql_stmt, "mysqli_stmt", MYSQLI_STATUS_VALID);
|
||||
|
||||
if (!(result = mysqlnd_stmt_get_result(stmt->stmt))) {
|
||||
MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
|
||||
mysqli_resource->ptr = (void *)result;
|
||||
mysqli_resource->status = MYSQLI_STATUS_VALID;
|
||||
MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_result_class_entry);
|
||||
}
|
||||
/* }}} */
|
||||
#endif
|
||||
|
||||
|
||||
/* {{{ proto object mysqli_get_warnings(object link) */
|
||||
PHP_FUNCTION(mysqli_get_warnings)
|
||||
{
|
||||
@ -296,12 +575,13 @@ PHP_FUNCTION(mysqli_get_warnings)
|
||||
MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL*, &mysql_link, "mysqli_link", MYSQLI_STATUS_VALID);
|
||||
|
||||
if (mysql_warning_count(mysql->mysql)) {
|
||||
w = php_get_warnings(mysql->mysql);
|
||||
w = php_get_warnings(mysql->mysql TSRMLS_CC);
|
||||
} else {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
|
||||
mysqli_resource->ptr = mysqli_resource->info = (void *)w;
|
||||
mysqli_resource->status = MYSQLI_STATUS_VALID;
|
||||
MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_warning_class_entry);
|
||||
}
|
||||
/* }}} */
|
||||
@ -317,15 +597,16 @@ PHP_FUNCTION(mysqli_stmt_get_warnings)
|
||||
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &stmt_link, mysqli_stmt_class_entry) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
MYSQLI_FETCH_RESOURCE(stmt, MY_STMT*, &stmt_link, "mysqli_stmt", 1);
|
||||
MYSQLI_FETCH_RESOURCE(stmt, MY_STMT*, &stmt_link, "mysqli_stmt", MYSQLI_STATUS_VALID);
|
||||
|
||||
if (mysql_warning_count(stmt->stmt->mysql)) {
|
||||
w = php_get_warnings(stmt->stmt->mysql);
|
||||
if (mysqli_stmt_warning_count(stmt->stmt)) {
|
||||
w = php_get_warnings(mysqli_stmt_get_connection(stmt->stmt) TSRMLS_CC);
|
||||
} else {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
|
||||
mysqli_resource->ptr = mysqli_resource->info = (void *)w;
|
||||
mysqli_resource->status = MYSQLI_STATUS_VALID;
|
||||
MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_warning_class_entry);
|
||||
}
|
||||
/* }}} */
|
||||
@ -354,13 +635,19 @@ PHP_FUNCTION(mysqli_set_charset)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MYSQLI_GET_CHARSET
|
||||
/* {{{ proto object mysqli_get_charset(object link)
|
||||
/* {{{ proto object mysqli_get_charset(object link) U
|
||||
returns a character set object */
|
||||
PHP_FUNCTION(mysqli_get_charset)
|
||||
{
|
||||
MY_MYSQL *mysql;
|
||||
zval *mysql_link;
|
||||
char *name = NULL, *collation = NULL, *dir = NULL;
|
||||
uint minlength, maxlength, number, state;
|
||||
#if !defined(HAVE_MYSQLND)
|
||||
MY_CHARSET_INFO cs;
|
||||
#else
|
||||
const MYSQLND_CHARSET *cs;
|
||||
#endif
|
||||
|
||||
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
|
||||
return;
|
||||
@ -369,16 +656,32 @@ PHP_FUNCTION(mysqli_get_charset)
|
||||
|
||||
object_init(return_value);
|
||||
|
||||
#if !defined(HAVE_MYSQLND)
|
||||
mysql_get_character_set_info(mysql->mysql, &cs);
|
||||
name = (char *)cs.csname;
|
||||
collation = (char *)cs.name;
|
||||
dir = (char *)cs.dir;
|
||||
minlength = cs.mbminlen;
|
||||
maxlength = cs.mbmaxlen;
|
||||
number = cs.number;
|
||||
state = cs.state;
|
||||
#else
|
||||
cs = mysql->mysql->charset;
|
||||
name = cs->name;
|
||||
collation = cs->collation;
|
||||
minlength = cs->char_minlen;
|
||||
maxlength = cs->char_maxlen;
|
||||
number = cs->nr;
|
||||
state = 1; /* all charsets are compiled in */
|
||||
#endif
|
||||
|
||||
add_property_string(return_value, "charset", (cs.name) ? (char *)cs.csname : "", 1);
|
||||
add_property_string(return_value, "collation",(cs.name) ? (char *)cs.name : "", 1);
|
||||
add_property_string(return_value, "comment", (cs.comment) ? (char *)cs.comment : "", 1);
|
||||
add_property_string(return_value, "dir", (cs.dir) ? (char *)cs.dir : "", 1);
|
||||
add_property_long(return_value, "min_length", cs.mbminlen);
|
||||
add_property_long(return_value, "max_length", cs.mbmaxlen);
|
||||
add_property_long(return_value, "number", cs.number);
|
||||
add_property_long(return_value, "state", cs.state);
|
||||
add_property_string(return_value, "charset", (name) ? (char *)name : "", 1);
|
||||
add_property_string(return_value, "collation",(collation) ? (char *)collation : "", 1);
|
||||
add_property_string(return_value, "dir", (dir) ? (char *)dir : "", 1);
|
||||
add_property_long(return_value, "min_length", minlength);
|
||||
add_property_long(return_value, "max_length", maxlength);
|
||||
add_property_long(return_value, "number", number);
|
||||
add_property_long(return_value, "state", state);
|
||||
}
|
||||
/* }}} */
|
||||
#endif
|
||||
|
@ -27,7 +27,7 @@
|
||||
#include "php.h"
|
||||
#include "php_ini.h"
|
||||
#include "ext/standard/info.h"
|
||||
#include "php_mysqli.h"
|
||||
#include "php_mysqli_structs.h"
|
||||
|
||||
#define CHECK_STATUS(value) \
|
||||
if (((MYSQLI_RESOURCE *)obj->ptr)->status < value ) { \
|
||||
@ -221,24 +221,23 @@ static int result_type_read(mysqli_object *obj, zval **retval TSRMLS_DC)
|
||||
static int result_lengths_read(mysqli_object *obj, zval **retval TSRMLS_DC)
|
||||
{
|
||||
MYSQL_RES *p;
|
||||
ulong *ret;
|
||||
|
||||
ALLOC_ZVAL(*retval);
|
||||
|
||||
CHECK_STATUS(MYSQLI_STATUS_VALID);
|
||||
p = (MYSQL_RES *)((MYSQLI_RESOURCE *)(obj->ptr))->ptr;
|
||||
if (!p || !p->field_count) {
|
||||
if (!p || !p->field_count || !(ret = mysql_fetch_lengths(p)))
|
||||
{
|
||||
ZVAL_NULL(*retval);
|
||||
} else {
|
||||
ulong i;
|
||||
zval *l;
|
||||
|
||||
array_init(*retval);
|
||||
|
||||
for (i=0; i < p->field_count; i++) {
|
||||
MAKE_STD_ZVAL(l);
|
||||
ZVAL_LONG(l, p->lengths[i]);
|
||||
add_index_zval(*retval, i, l);
|
||||
}
|
||||
add_index_long(*retval, i, ret[i]);
|
||||
}
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
@ -312,7 +311,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},
|
||||
@ -333,7 +332,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},
|
||||
@ -342,7 +341,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},
|
||||
|
@ -27,7 +27,7 @@
|
||||
#include "php.h"
|
||||
#include "php_ini.h"
|
||||
#include "ext/standard/info.h"
|
||||
#include "php_mysqli.h"
|
||||
#include "php_mysqli_structs.h"
|
||||
|
||||
/* {{{ proto void mysqli_disable_reads_from_master(object link)
|
||||
*/
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include "php.h"
|
||||
#include "php_ini.h"
|
||||
#include "ext/standard/info.h"
|
||||
#include "php_mysqli.h"
|
||||
#include "php_mysqli_structs.h"
|
||||
|
||||
/* {{{ proto bool mysqli_report(int flags)
|
||||
sets report level */
|
||||
@ -45,13 +45,14 @@ PHP_FUNCTION(mysqli_report)
|
||||
/* }}} */
|
||||
|
||||
/* {{{ void php_mysqli_report_error(char *sqlstate, int errorno, char *error) */
|
||||
void php_mysqli_report_error(char *sqlstate, int errorno, char *error TSRMLS_DC) {
|
||||
php_mysqli_throw_sql_exception(sqlstate, errorno TSRMLS_CC, "%s", error);
|
||||
void php_mysqli_report_error(const char *sqlstate, int errorno, const char *error TSRMLS_DC)
|
||||
{
|
||||
php_mysqli_throw_sql_exception((char *)sqlstate, errorno TSRMLS_CC, "%s", error);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ void php_mysqli_report_index() */
|
||||
void php_mysqli_report_index(char *query, unsigned int status TSRMLS_DC) {
|
||||
void php_mysqli_report_index(const char *query, unsigned int status TSRMLS_DC) {
|
||||
char index[15];
|
||||
|
||||
if (status & SERVER_QUERY_NO_GOOD_INDEX_USED) {
|
||||
|
@ -25,60 +25,72 @@
|
||||
#include "php.h"
|
||||
#include "php_ini.h"
|
||||
#include "ext/standard/info.h"
|
||||
#include "php_mysqli.h"
|
||||
#include "php_mysqli_structs.h"
|
||||
|
||||
/* Define these in the PHP5 tree to make merging easy process */
|
||||
#define ZSTR_DUPLICATE (1<<0)
|
||||
#define ZSTR_AUTOFREE (1<<1)
|
||||
|
||||
#define ZVAL_UTF8_STRING(z, s, flags) ZVAL_STRING((z), (char*)(s), ((flags) & ZSTR_DUPLICATE))
|
||||
#define ZVAL_UTF8_STRINGL(z, s, l, flags) ZVAL_STRINGL((z), (char*)(s), (l), ((flags) & ZSTR_DUPLICATE))
|
||||
|
||||
|
||||
/* {{{ void php_clear_warnings() */
|
||||
void php_clear_warnings(MYSQLI_WARNING *w)
|
||||
{
|
||||
MYSQLI_WARNING *n;
|
||||
MYSQLI_WARNING *n;
|
||||
|
||||
while (w) {
|
||||
n = w;
|
||||
efree(w->reason);
|
||||
zval_dtor(&(w->reason));
|
||||
zval_dtor(&(w->sqlstate));
|
||||
w = w->next;
|
||||
efree(n);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
#ifndef HAVE_MYSQLND
|
||||
/* {{{ MYSQLI_WARNING *php_new_warning */
|
||||
MYSQLI_WARNING *php_new_warning(char *reason, char *sqlstate, int errorno)
|
||||
static
|
||||
MYSQLI_WARNING *php_new_warning(const char *reason, int errorno TSRMLS_DC)
|
||||
{
|
||||
MYSQLI_WARNING *w;
|
||||
MYSQLI_WARNING *w;
|
||||
|
||||
w = (MYSQLI_WARNING *)ecalloc(1, sizeof(MYSQLI_WARNING));
|
||||
|
||||
w->reason = safe_estrdup(reason);
|
||||
if (sqlstate) {
|
||||
strcpy(w->sqlstate, sqlstate);
|
||||
} else {
|
||||
strcpy(w->sqlstate, "00000");
|
||||
}
|
||||
ZVAL_UTF8_STRING(&(w->reason), reason, ZSTR_DUPLICATE);
|
||||
|
||||
ZVAL_UTF8_STRINGL(&(w->sqlstate), "HY000", sizeof("HY000") - 1, ZSTR_DUPLICATE);
|
||||
|
||||
w->errorno = errorno;
|
||||
|
||||
return w;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ MYSQLI_WARNING *php_get_warnings(MYSQL *mysql) */
|
||||
MYSQLI_WARNING *php_get_warnings(MYSQL *mysql)
|
||||
|
||||
/* {{{ MYSQLI_WARNING *php_get_warnings(MYSQL *mysql TSRMLS_DC) */
|
||||
MYSQLI_WARNING *php_get_warnings(MYSQL *mysql TSRMLS_DC)
|
||||
{
|
||||
MYSQLI_WARNING *w, *first = NULL, *prev = NULL;
|
||||
MYSQLI_WARNING *w, *first = NULL, *prev = NULL;
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
|
||||
if (mysql_query(mysql, "SHOW WARNINGS")) {
|
||||
if (mysql_real_query(mysql, "SHOW WARNINGS", 13)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result = mysql_store_result(mysql);
|
||||
|
||||
while ((row = mysql_fetch_row(result))) {
|
||||
w = php_new_warning(row[2], "HY000", atoi(row[1]));
|
||||
w = php_new_warning(row[2], atoi(row[1]) TSRMLS_CC);
|
||||
if (!first) {
|
||||
first = w;
|
||||
}
|
||||
if (prev) {
|
||||
prev->next = (void *)w;
|
||||
prev->next = w;
|
||||
}
|
||||
prev = w;
|
||||
}
|
||||
@ -86,6 +98,88 @@ MYSQLI_WARNING *php_get_warnings(MYSQL *mysql)
|
||||
return first;
|
||||
}
|
||||
/* }}} */
|
||||
#else
|
||||
/* {{{ MYSQLI_WARNING *php_new_warning */
|
||||
static
|
||||
MYSQLI_WARNING *php_new_warning(const zval *reason, int errorno TSRMLS_DC)
|
||||
{
|
||||
MYSQLI_WARNING *w;
|
||||
|
||||
w = (MYSQLI_WARNING *)ecalloc(1, sizeof(MYSQLI_WARNING));
|
||||
|
||||
w->reason = *reason;
|
||||
zval_copy_ctor(&(w->reason));
|
||||
|
||||
ZVAL_UTF8_STRINGL(&(w->reason), Z_STRVAL(w->reason), Z_STRLEN(w->reason), ZSTR_AUTOFREE);
|
||||
|
||||
ZVAL_UTF8_STRINGL(&(w->sqlstate), "HY000", sizeof("HY000") - 1, ZSTR_DUPLICATE);
|
||||
|
||||
w->errorno = errorno;
|
||||
|
||||
return w;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ MYSQLI_WARNING *php_get_warnings(MYSQL *mysql TSRMLS_DC) */
|
||||
MYSQLI_WARNING *php_get_warnings(MYSQL *mysql TSRMLS_DC)
|
||||
{
|
||||
MYSQLI_WARNING *w, *first = NULL, *prev = NULL;
|
||||
MYSQL_RES *result;
|
||||
zval *row;
|
||||
|
||||
if (mysql_real_query(mysql, "SHOW WARNINGS", 13)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result = mysql_use_result(mysql);
|
||||
|
||||
for (;;) {
|
||||
zval **entry;
|
||||
int errno;
|
||||
|
||||
MAKE_STD_ZVAL(row);
|
||||
mysqlnd_fetch_into(result, MYSQLND_FETCH_NUM, row, MYSQLND_MYSQLI);
|
||||
if (Z_TYPE_P(row) != IS_ARRAY) {
|
||||
zval_ptr_dtor(&row);
|
||||
break;
|
||||
}
|
||||
zend_hash_internal_pointer_reset(Z_ARRVAL_P(row));
|
||||
/* 0. we don't care about the first */
|
||||
zend_hash_move_forward(Z_ARRVAL_P(row));
|
||||
|
||||
/* 1. Here comes the error no */
|
||||
zend_hash_get_current_data(Z_ARRVAL_P(row), (void **)&entry);
|
||||
convert_to_long_ex(entry);
|
||||
errno = Z_LVAL_PP(entry);
|
||||
zend_hash_move_forward(Z_ARRVAL_P(row));
|
||||
|
||||
/* 2. Here comes the reason */
|
||||
zend_hash_get_current_data(Z_ARRVAL_P(row), (void **)&entry);
|
||||
|
||||
w = php_new_warning(*entry, errno TSRMLS_CC);
|
||||
/*
|
||||
Don't destroy entry, because the row destroy will decrease
|
||||
the refcounter. Decreased twice then mysqlnd_free_result()
|
||||
will crash, because it will try to access already freed memory.
|
||||
*/
|
||||
if (!first) {
|
||||
first = w;
|
||||
}
|
||||
if (prev) {
|
||||
prev->next = (void *)w;
|
||||
}
|
||||
prev = w;
|
||||
|
||||
zval_ptr_dtor(&row);
|
||||
}
|
||||
|
||||
mysql_free_result(result);
|
||||
return first;
|
||||
}
|
||||
/* }}} */
|
||||
#endif
|
||||
|
||||
|
||||
/* {{{ bool mysqli_warning::next() */
|
||||
PHP_METHOD(mysqli_warning, next)
|
||||
@ -112,7 +206,9 @@ PHP_METHOD(mysqli_warning, next)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ property mysqli_warning_message */
|
||||
static
|
||||
int mysqli_warning_message(mysqli_object *obj, zval **retval TSRMLS_DC)
|
||||
{
|
||||
MYSQLI_WARNING *w;
|
||||
@ -122,17 +218,16 @@ int mysqli_warning_message(mysqli_object *obj, zval **retval TSRMLS_DC)
|
||||
}
|
||||
|
||||
w = (MYSQLI_WARNING *)((MYSQLI_RESOURCE *)(obj->ptr))->ptr;
|
||||
ALLOC_ZVAL(*retval);
|
||||
if (w->reason) {
|
||||
ZVAL_STRING(*retval, w->reason, 1);
|
||||
} else {
|
||||
ZVAL_NULL(*retval);
|
||||
}
|
||||
MAKE_STD_ZVAL(*retval);
|
||||
**retval = w->reason;
|
||||
zval_copy_ctor(*retval);
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ property mysqli_warning_sqlstate */
|
||||
static
|
||||
int mysqli_warning_sqlstate(mysqli_object *obj, zval **retval TSRMLS_DC)
|
||||
{
|
||||
MYSQLI_WARNING *w;
|
||||
@ -142,13 +237,16 @@ int mysqli_warning_sqlstate(mysqli_object *obj, zval **retval TSRMLS_DC)
|
||||
}
|
||||
|
||||
w = (MYSQLI_WARNING *)((MYSQLI_RESOURCE *)(obj->ptr))->ptr;
|
||||
ALLOC_ZVAL(*retval);
|
||||
ZVAL_STRING(*retval, w->sqlstate, 1);
|
||||
MAKE_STD_ZVAL(*retval);
|
||||
**retval = w->sqlstate;
|
||||
zval_copy_ctor(*retval);
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ property mysqli_warning_error */
|
||||
static
|
||||
int mysqli_warning_errno(mysqli_object *obj, zval **retval TSRMLS_DC)
|
||||
{
|
||||
MYSQLI_WARNING *w;
|
||||
@ -157,7 +255,7 @@ int mysqli_warning_errno(mysqli_object *obj, zval **retval TSRMLS_DC)
|
||||
return FAILURE;
|
||||
}
|
||||
w = (MYSQLI_WARNING *)((MYSQLI_RESOURCE *)(obj->ptr))->ptr;
|
||||
ALLOC_ZVAL(*retval);
|
||||
MAKE_STD_ZVAL(*retval);
|
||||
ZVAL_LONG(*retval, w->errorno);
|
||||
return SUCCESS;
|
||||
}
|
||||
@ -187,20 +285,22 @@ PHP_METHOD(mysqli_warning, __construct)
|
||||
} else if (obj->zo.ce == mysqli_stmt_class_entry) {
|
||||
MY_STMT *stmt;
|
||||
MYSQLI_FETCH_RESOURCE(stmt, MY_STMT *, &z, "mysqli_stmt", MYSQLI_STATUS_VALID);
|
||||
hdl = stmt->stmt->mysql;
|
||||
hdl = mysqli_stmt_get_connection(stmt->stmt);
|
||||
} else {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid class argument");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if (mysql_warning_count(hdl)) {
|
||||
w = php_get_warnings(hdl);
|
||||
w = php_get_warnings(hdl TSRMLS_CC);
|
||||
} else {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "No warnings found");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
|
||||
mysqli_resource->status = MYSQLI_STATUS_VALID;
|
||||
mysqli_resource->ptr = mysqli_resource->info = (void *)w;
|
||||
mysqli_resource->status = MYSQLI_STATUS_VALID;
|
||||
|
||||
if (!getThis() || !instanceof_function(Z_OBJCE_P(getThis()), mysqli_warning_class_entry TSRMLS_CC)) {
|
||||
MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_warning_class_entry);
|
||||
@ -211,18 +311,22 @@ PHP_METHOD(mysqli_warning, __construct)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ mysqli_warning_methods */
|
||||
const zend_function_entry mysqli_warning_methods[] = {
|
||||
PHP_ME(mysqli_warning, __construct, NULL, ZEND_ACC_PROTECTED)
|
||||
PHP_ME(mysqli_warning, next, NULL, ZEND_ACC_PUBLIC)
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
/* }}} */
|
||||
|
||||
mysqli_property_entry mysqli_warning_property_entries[] = {
|
||||
/* {{{ 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},
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
/* }}} */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
|
@ -12,299 +12,17 @@
|
||||
| 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$
|
||||
*/
|
||||
|
||||
/* A little hack to prevent build break, when mysql is used together with
|
||||
* c-client, which also defines LIST.
|
||||
*/
|
||||
#ifdef LIST
|
||||
#undef LIST
|
||||
#endif
|
||||
|
||||
#include <mysql.h>
|
||||
|
||||
/* character set support */
|
||||
#if MYSQL_VERSION_ID > 50009
|
||||
#define HAVE_MYSQLI_GET_CHARSET
|
||||
#endif
|
||||
|
||||
#if (MYSQL_VERSION_ID > 40112 && MYSQL_VERSION_ID < 50000) || MYSQL_VERSION_ID > 50005
|
||||
#define HAVE_MYSQLI_SET_CHARSET
|
||||
#endif
|
||||
|
||||
|
||||
#include <errmsg.h>
|
||||
|
||||
#ifndef PHP_MYSQLI_H
|
||||
#define PHP_MYSQLI_H
|
||||
|
||||
#define MYSQLI_VERSION_ID 101009
|
||||
|
||||
enum mysqli_status {
|
||||
MYSQLI_STATUS_UNKNOWN=0,
|
||||
MYSQLI_STATUS_CLEARED,
|
||||
MYSQLI_STATUS_INITIALIZED,
|
||||
MYSQLI_STATUS_VALID
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
ulong buflen;
|
||||
char *val;
|
||||
ulong type;
|
||||
} VAR_BUFFER;
|
||||
|
||||
typedef struct {
|
||||
unsigned int var_cnt;
|
||||
VAR_BUFFER *buf;
|
||||
zval **vars;
|
||||
char *is_null;
|
||||
} BIND_BUFFER;
|
||||
|
||||
typedef struct {
|
||||
MYSQL_STMT *stmt;
|
||||
BIND_BUFFER param;
|
||||
BIND_BUFFER result;
|
||||
char *query;
|
||||
} MY_STMT;
|
||||
|
||||
typedef struct {
|
||||
MYSQL *mysql;
|
||||
zval *li_read;
|
||||
php_stream *li_stream;
|
||||
unsigned int multi_query;
|
||||
} MY_MYSQL;
|
||||
|
||||
typedef struct {
|
||||
int mode;
|
||||
int socket;
|
||||
FILE *fp;
|
||||
} PROFILER;
|
||||
|
||||
typedef struct {
|
||||
void *ptr; /* resource: (mysql, result, stmt) */
|
||||
void *info; /* additional buffer */
|
||||
enum mysqli_status status;
|
||||
} MYSQLI_RESOURCE;
|
||||
|
||||
typedef struct _mysqli_object {
|
||||
zend_object zo;
|
||||
void *ptr;
|
||||
HashTable *prop_handler;
|
||||
} mysqli_object; /* extends zend_object */
|
||||
|
||||
typedef struct {
|
||||
char *reason;
|
||||
char sqlstate[6];
|
||||
int errorno;
|
||||
void *next;
|
||||
} MYSQLI_WARNING;
|
||||
|
||||
typedef struct _mysqli_property_entry {
|
||||
char *pname;
|
||||
int (*r_func)(mysqli_object *obj, zval **retval TSRMLS_DC);
|
||||
int (*w_func)(mysqli_object *obj, zval *value TSRMLS_DC);
|
||||
} mysqli_property_entry;
|
||||
|
||||
typedef struct {
|
||||
char error_msg[LOCAL_INFILE_ERROR_LEN];
|
||||
void *userdata;
|
||||
} mysqli_local_infile;
|
||||
|
||||
#define phpext_mysqli_ptr &mysqli_module_entry
|
||||
|
||||
#ifdef PHP_WIN32
|
||||
#define PHP_MYSQLI_API __declspec(dllexport)
|
||||
#define MYSQLI_LLU_SPEC "%I64u"
|
||||
#define MYSQLI_LL_SPEC "%I64d"
|
||||
#else
|
||||
#define PHP_MYSQLI_API
|
||||
#define MYSQLI_LLU_SPEC "%llu"
|
||||
#define MYSQLI_LL_SPEC "%lld"
|
||||
#endif
|
||||
|
||||
#ifdef ZTS
|
||||
#include "TSRM.h"
|
||||
#endif
|
||||
|
||||
#define PHP_MYSQLI_EXPORT(__type) PHP_MYSQLI_API __type
|
||||
|
||||
extern zend_module_entry mysqli_module_entry;
|
||||
extern const zend_function_entry mysqli_functions[];
|
||||
extern const zend_function_entry mysqli_link_methods[];
|
||||
extern const zend_function_entry mysqli_stmt_methods[];
|
||||
extern const zend_function_entry mysqli_result_methods[];
|
||||
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 void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flag, int into_object);
|
||||
extern void php_clear_stmt_bind(MY_STMT *stmt);
|
||||
extern void php_clear_mysql(MY_MYSQL *);
|
||||
extern MYSQLI_WARNING *php_get_warnings(MYSQL *mysql);
|
||||
extern void php_clear_warnings(MYSQLI_WARNING *w);
|
||||
extern void php_free_stmt_bind_buffer(BIND_BUFFER bbuf, int type);
|
||||
extern void php_mysqli_report_error(char *sqlstate, int errorno, char *error TSRMLS_DC);
|
||||
extern void php_mysqli_report_index(char *query, unsigned int status TSRMLS_DC);
|
||||
extern int php_local_infile_init(void **, const char *, void *);
|
||||
extern int php_local_infile_read(void *, char *, uint);
|
||||
extern void php_local_infile_end(void *);
|
||||
extern int php_local_infile_error(void *, char *, uint);
|
||||
extern void php_set_local_infile_handler_default(MY_MYSQL *);
|
||||
extern void php_mysqli_throw_sql_exception(char *sqlstate, int errorno TSRMLS_DC, char *format, ...);
|
||||
extern zend_class_entry *mysqli_link_class_entry;
|
||||
extern zend_class_entry *mysqli_stmt_class_entry;
|
||||
extern zend_class_entry *mysqli_result_class_entry;
|
||||
extern zend_class_entry *mysqli_driver_class_entry;
|
||||
extern zend_class_entry *mysqli_warning_class_entry;
|
||||
extern zend_class_entry *mysqli_exception_class_entry;
|
||||
|
||||
#ifdef HAVE_SPL
|
||||
extern PHPAPI zend_class_entry *spl_ce_RuntimeException;
|
||||
#endif
|
||||
|
||||
PHP_MYSQLI_EXPORT(zend_object_value) mysqli_objects_new(zend_class_entry * TSRMLS_DC);
|
||||
|
||||
#define MYSQLI_DISABLE_MQ if (mysql->multi_query) { \
|
||||
mysql_set_server_option(mysql->mysql, MYSQL_OPTION_MULTI_STATEMENTS_OFF); \
|
||||
mysql->multi_query = 0; \
|
||||
}
|
||||
|
||||
#define MYSQLI_ENABLE_MQ if (!mysql->multi_query) { \
|
||||
mysql_set_server_option(mysql->mysql, MYSQL_OPTION_MULTI_STATEMENTS_ON); \
|
||||
mysql->multi_query = 1; \
|
||||
}
|
||||
|
||||
#define REGISTER_MYSQLI_CLASS_ENTRY(name, mysqli_entry, class_functions) { \
|
||||
zend_class_entry ce; \
|
||||
INIT_CLASS_ENTRY(ce, name,class_functions); \
|
||||
ce.create_object = mysqli_objects_new; \
|
||||
mysqli_entry = zend_register_internal_class(&ce TSRMLS_CC); \
|
||||
} \
|
||||
|
||||
#define MYSQLI_REGISTER_RESOURCE_EX(__ptr, __zval) \
|
||||
((mysqli_object *) zend_object_store_get_object(__zval TSRMLS_CC))->ptr = __ptr; \
|
||||
|
||||
#define MYSQLI_RETURN_RESOURCE(__ptr, __ce) \
|
||||
Z_TYPE_P(return_value) = IS_OBJECT; \
|
||||
(return_value)->value.obj = mysqli_objects_new(__ce TSRMLS_CC); \
|
||||
MYSQLI_REGISTER_RESOURCE_EX(__ptr, return_value)
|
||||
|
||||
#define MYSQLI_REGISTER_RESOURCE(__ptr, __ce) \
|
||||
{\
|
||||
zval *object = getThis();\
|
||||
if (!object || !instanceof_function(Z_OBJCE_P(object), mysqli_link_class_entry TSRMLS_CC)) {\
|
||||
object = return_value;\
|
||||
Z_TYPE_P(object) = IS_OBJECT;\
|
||||
(object)->value.obj = mysqli_objects_new(__ce TSRMLS_CC);\
|
||||
}\
|
||||
MYSQLI_REGISTER_RESOURCE_EX(__ptr, object)\
|
||||
}
|
||||
|
||||
#define MYSQLI_FETCH_RESOURCE(__ptr, __type, __id, __name, __check) \
|
||||
{ \
|
||||
MYSQLI_RESOURCE *my_res; \
|
||||
mysqli_object *intern = (mysqli_object *)zend_object_store_get_object(*(__id) TSRMLS_CC);\
|
||||
if (!(my_res = (MYSQLI_RESOURCE *)intern->ptr)) {\
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Couldn't fetch %s", intern->zo.ce->name);\
|
||||
RETURN_NULL();\
|
||||
}\
|
||||
__ptr = (__type)my_res->ptr; \
|
||||
if (__check && my_res->status < __check) { \
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid object or resource %s\n", intern->zo.ce->name); \
|
||||
RETURN_NULL();\
|
||||
}\
|
||||
}
|
||||
|
||||
#define MYSQLI_SET_STATUS(__id, __value) \
|
||||
{ \
|
||||
mysqli_object *intern = (mysqli_object *)zend_object_store_get_object(*(__id) TSRMLS_CC);\
|
||||
((MYSQLI_RESOURCE *)intern->ptr)->status = __value; \
|
||||
} \
|
||||
|
||||
#define MYSQLI_CLEAR_RESOURCE(__id) \
|
||||
{ \
|
||||
mysqli_object *intern = (mysqli_object *)zend_object_store_get_object(*(__id) TSRMLS_CC);\
|
||||
efree(intern->ptr); \
|
||||
intern->ptr = NULL; \
|
||||
}
|
||||
|
||||
#define MYSQLI_RETURN_LONG_LONG(__val) \
|
||||
{ \
|
||||
if ((__val) < LONG_MAX) { \
|
||||
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); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define MYSQLI_ADD_PROPERTIES(a,b) \
|
||||
{ \
|
||||
int i = 0; \
|
||||
while (b[i].pname != NULL) { \
|
||||
mysqli_add_property(a, b[i].pname, (mysqli_read_t)b[i].r_func, (mysqli_write_t)b[i].w_func TSRMLS_CC); \
|
||||
i++; \
|
||||
}\
|
||||
}
|
||||
|
||||
#if WIN32|WINNT
|
||||
#define SCLOSE(a) closesocket(a)
|
||||
#else
|
||||
#define SCLOSE(a) close(a)
|
||||
#endif
|
||||
|
||||
#define MYSQLI_STORE_RESULT 0
|
||||
#define MYSQLI_USE_RESULT 1
|
||||
|
||||
/* for mysqli_fetch_assoc */
|
||||
#define MYSQLI_ASSOC 1
|
||||
#define MYSQLI_NUM 2
|
||||
#define MYSQLI_BOTH 3
|
||||
|
||||
/* for mysqli_bind_param */
|
||||
#define MYSQLI_BIND_INT 1
|
||||
#define MYSQLI_BIND_DOUBLE 2
|
||||
#define MYSQLI_BIND_STRING 3
|
||||
#define MYSQLI_BIND_SEND_DATA 4
|
||||
|
||||
/* fetch types */
|
||||
#define FETCH_SIMPLE 1
|
||||
#define FETCH_RESULT 2
|
||||
|
||||
/*** REPORT MODES ***/
|
||||
#define MYSQLI_REPORT_OFF 0
|
||||
#define MYSQLI_REPORT_ERROR 1
|
||||
#define MYSQLI_REPORT_STRICT 2
|
||||
#define MYSQLI_REPORT_INDEX 4
|
||||
#define MYSQLI_REPORT_CLOSE 8
|
||||
#define MYSQLI_REPORT_ALL 255
|
||||
|
||||
#define MYSQLI_REPORT_MYSQL_ERROR(mysql) \
|
||||
if ((MyG(report_mode) & MYSQLI_REPORT_ERROR) && mysql->net.last_errno) { \
|
||||
php_mysqli_report_error(mysql->net.sqlstate, mysql->net.last_errno, mysql->net.last_error TSRMLS_CC); \
|
||||
}
|
||||
|
||||
#define MYSQLI_REPORT_STMT_ERROR(stmt) \
|
||||
if ((MyG(report_mode) & MYSQLI_REPORT_ERROR) && stmt->last_errno) { \
|
||||
php_mysqli_report_error(stmt->sqlstate, stmt->last_errno, stmt->last_error TSRMLS_CC); \
|
||||
}
|
||||
|
||||
PHP_MYSQLI_API void mysqli_register_link(zval *return_value, void *link TSRMLS_DC);
|
||||
PHP_MYSQLI_API void mysqli_register_stmt(zval *return_value, void *stmt TSRMLS_DC);
|
||||
PHP_MYSQLI_API void mysqli_register_result(zval *return_value, void *result TSRMLS_DC);
|
||||
PHP_MYSQLI_API void php_mysqli_set_error(long mysql_errno, char *mysql_err TSRMLS_DC);
|
||||
|
||||
PHP_MINIT_FUNCTION(mysqli);
|
||||
PHP_MSHUTDOWN_FUNCTION(mysqli);
|
||||
@ -317,9 +35,7 @@ PHP_FUNCTION(mysqli_affected_rows);
|
||||
PHP_FUNCTION(mysqli_autocommit);
|
||||
PHP_FUNCTION(mysqli_change_user);
|
||||
PHP_FUNCTION(mysqli_character_set_name);
|
||||
#ifdef HAVE_MYSQLI_SET_CHARSET
|
||||
PHP_FUNCTION(mysqli_set_charset);
|
||||
#endif
|
||||
PHP_FUNCTION(mysqli_close);
|
||||
PHP_FUNCTION(mysqli_commit);
|
||||
PHP_FUNCTION(mysqli_connect);
|
||||
@ -334,6 +50,7 @@ PHP_FUNCTION(mysqli_enable_reads_from_master);
|
||||
PHP_FUNCTION(mysqli_enable_rpl_parse);
|
||||
PHP_FUNCTION(mysqli_errno);
|
||||
PHP_FUNCTION(mysqli_error);
|
||||
PHP_FUNCTION(mysqli_fetch_all);
|
||||
PHP_FUNCTION(mysqli_fetch_array);
|
||||
PHP_FUNCTION(mysqli_fetch_assoc);
|
||||
PHP_FUNCTION(mysqli_fetch_object);
|
||||
@ -346,9 +63,10 @@ PHP_FUNCTION(mysqli_field_count);
|
||||
PHP_FUNCTION(mysqli_field_seek);
|
||||
PHP_FUNCTION(mysqli_field_tell);
|
||||
PHP_FUNCTION(mysqli_free_result);
|
||||
#ifdef HAVE_MYSQLI_GET_CHARSET
|
||||
PHP_FUNCTION(mysqli_get_cache_stats);
|
||||
PHP_FUNCTION(mysqli_get_client_stats);
|
||||
PHP_FUNCTION(mysqli_get_connection_stats);
|
||||
PHP_FUNCTION(mysqli_get_charset);
|
||||
#endif
|
||||
PHP_FUNCTION(mysqli_get_client_info);
|
||||
PHP_FUNCTION(mysqli_get_client_version);
|
||||
PHP_FUNCTION(mysqli_get_host_info);
|
||||
@ -408,6 +126,7 @@ PHP_FUNCTION(mysqli_stmt_data_seek);
|
||||
PHP_FUNCTION(mysqli_stmt_errno);
|
||||
PHP_FUNCTION(mysqli_stmt_error);
|
||||
PHP_FUNCTION(mysqli_stmt_free_result);
|
||||
PHP_FUNCTION(mysqli_stmt_get_result);
|
||||
PHP_FUNCTION(mysqli_stmt_get_warnings);
|
||||
PHP_FUNCTION(mysqli_stmt_reset);
|
||||
PHP_FUNCTION(mysqli_stmt_insert_id);
|
||||
@ -425,53 +144,11 @@ ZEND_FUNCTION(mysqli_result_construct);
|
||||
ZEND_FUNCTION(mysqli_driver_construct);
|
||||
ZEND_METHOD(mysqli_warning,__construct);
|
||||
|
||||
ZEND_BEGIN_MODULE_GLOBALS(mysqli)
|
||||
long default_link;
|
||||
long num_links;
|
||||
long max_links;
|
||||
unsigned int default_port;
|
||||
char *default_host;
|
||||
char *default_user;
|
||||
char *default_socket;
|
||||
char *default_pw;
|
||||
int reconnect;
|
||||
int strict;
|
||||
long error_no;
|
||||
char *error_msg;
|
||||
int report_mode;
|
||||
HashTable *report_ht;
|
||||
unsigned int multi_query;
|
||||
unsigned int embedded;
|
||||
ZEND_END_MODULE_GLOBALS(mysqli)
|
||||
|
||||
|
||||
#define MYSQLI_PROPERTY(a) extern int a(mysqli_object *obj, zval **retval TSRMLS_DC)
|
||||
|
||||
MYSQLI_PROPERTY(my_prop_link_host);
|
||||
|
||||
#ifdef ZTS
|
||||
#define MyG(v) TSRMG(mysqli_globals_id, zend_mysqli_globals *, v)
|
||||
#else
|
||||
#define MyG(v) (mysqli_globals.v)
|
||||
#endif
|
||||
|
||||
#define my_estrdup(x) (x) ? estrdup(x) : NULL
|
||||
#define my_efree(x) if (x) efree(x)
|
||||
|
||||
#ifdef PHP_WIN32
|
||||
#define L64(x) x##i64
|
||||
typedef __int64 my_longlong;
|
||||
#else
|
||||
#define L64(x) x##LL
|
||||
typedef long long my_longlong;
|
||||
#endif
|
||||
|
||||
|
||||
ZEND_EXTERN_MODULE_GLOBALS(mysqli)
|
||||
#define phpext_mysqli_ptr &mysqli_module_entry
|
||||
extern zend_module_entry mysqli_module_entry;
|
||||
|
||||
#endif /* PHP_MYSQLI.H */
|
||||
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
|
396
ext/mysqli/php_mysqli_structs.h
Normal file
396
ext/mysqli/php_mysqli_structs.h
Normal file
@ -0,0 +1,396 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| PHP Version 5 |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1997-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. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Author: Georg Richter <georg@php.net> |
|
||||
+----------------------------------------------------------------------+
|
||||
|
||||
$Id$
|
||||
*/
|
||||
|
||||
#ifndef PHP_MYSQLI_STRUCTS_H
|
||||
#define PHP_MYSQLI_STRUCTS_H
|
||||
|
||||
/* A little hack to prevent build break, when mysql is used together with
|
||||
* c-client, which also defines LIST.
|
||||
*/
|
||||
#ifdef LIST
|
||||
#undef LIST
|
||||
#endif
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MYSQLND
|
||||
#include "ext/mysqlnd/mysqlnd.h"
|
||||
#include "ext/mysqli/mysqli_mysqlnd.h"
|
||||
#else
|
||||
#include <mysql.h>
|
||||
#include <errmsg.h>
|
||||
#include "ext/mysqli/mysqli_libmysql.h"
|
||||
#endif
|
||||
|
||||
#include "php_mysqli.h"
|
||||
|
||||
/* character set support */
|
||||
#if defined(MYSQLND_VERSION_ID) || MYSQL_VERSION_ID > 50009
|
||||
#define HAVE_MYSQLI_GET_CHARSET
|
||||
#endif
|
||||
|
||||
#if defined(MYSQLND_VERSION_ID) || (MYSQL_VERSION_ID > 40112 && MYSQL_VERSION_ID < 50000) || MYSQL_VERSION_ID > 50005
|
||||
#define HAVE_MYSQLI_SET_CHARSET
|
||||
#endif
|
||||
|
||||
#define MYSQLI_VERSION_ID 101009
|
||||
|
||||
enum mysqli_status {
|
||||
MYSQLI_STATUS_UNKNOWN=0,
|
||||
MYSQLI_STATUS_CLEARED,
|
||||
MYSQLI_STATUS_INITIALIZED,
|
||||
MYSQLI_STATUS_VALID
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
ulong buflen;
|
||||
char *val;
|
||||
ulong type;
|
||||
} VAR_BUFFER;
|
||||
|
||||
typedef struct {
|
||||
unsigned int var_cnt;
|
||||
VAR_BUFFER *buf;
|
||||
zval **vars;
|
||||
char *is_null;
|
||||
} BIND_BUFFER;
|
||||
|
||||
typedef struct {
|
||||
MYSQL_STMT *stmt;
|
||||
BIND_BUFFER param;
|
||||
BIND_BUFFER result;
|
||||
char *query;
|
||||
} MY_STMT;
|
||||
|
||||
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;
|
||||
} MY_MYSQL;
|
||||
|
||||
typedef struct {
|
||||
int mode;
|
||||
int socket;
|
||||
FILE *fp;
|
||||
} PROFILER;
|
||||
|
||||
typedef struct {
|
||||
void *ptr; /* resource: (mysql, result, stmt) */
|
||||
void *info; /* additional buffer */
|
||||
enum mysqli_status status; /* object status */
|
||||
} MYSQLI_RESOURCE;
|
||||
|
||||
typedef struct _mysqli_object {
|
||||
zend_object zo;
|
||||
void *ptr;
|
||||
HashTable *prop_handler;
|
||||
} mysqli_object; /* extends zend_object */
|
||||
|
||||
typedef struct st_mysqli_warning MYSQLI_WARNING;
|
||||
|
||||
struct st_mysqli_warning {
|
||||
zval reason;
|
||||
zval sqlstate;
|
||||
int errorno;
|
||||
MYSQLI_WARNING *next;
|
||||
};
|
||||
|
||||
typedef struct _mysqli_property_entry {
|
||||
char *pname;
|
||||
int (*r_func)(mysqli_object *obj, zval **retval TSRMLS_DC);
|
||||
int (*w_func)(mysqli_object *obj, zval *value TSRMLS_DC);
|
||||
} mysqli_property_entry;
|
||||
|
||||
#if !defined(HAVE_MYSQLND)
|
||||
typedef struct {
|
||||
char error_msg[LOCAL_INFILE_ERROR_LEN];
|
||||
void *userdata;
|
||||
} 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"
|
||||
#define MYSQLI_LL_SPEC "%I64d"
|
||||
#define L64(x) x##i64
|
||||
typedef __int64 my_longlong;
|
||||
#else
|
||||
#define PHP_MYSQLI_API
|
||||
#define MYSQLI_LLU_SPEC "%llu"
|
||||
#define MYSQLI_LL_SPEC "%lld"
|
||||
#define L64(x) x##LL
|
||||
typedef long long my_longlong;
|
||||
#endif
|
||||
|
||||
#ifdef ZTS
|
||||
#include "TSRM.h"
|
||||
#endif
|
||||
|
||||
#define PHP_MYSQLI_EXPORT(__type) PHP_MYSQLI_API __type
|
||||
|
||||
extern const zend_function_entry mysqli_functions[];
|
||||
extern const zend_function_entry mysqli_link_methods[];
|
||||
extern const zend_function_entry mysqli_stmt_methods[];
|
||||
extern const zend_function_entry mysqli_result_methods[];
|
||||
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 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;
|
||||
extern MYSQLND_QCACHE *mysqli_mysqlnd_qcache;
|
||||
#endif
|
||||
|
||||
extern void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flag, int into_object);
|
||||
extern void php_clear_stmt_bind(MY_STMT *stmt TSRMLS_DC);
|
||||
extern void php_clear_mysql(MY_MYSQL *);
|
||||
extern MYSQLI_WARNING *php_get_warnings(MYSQL *mysql TSRMLS_DC);
|
||||
extern void php_clear_warnings(MYSQLI_WARNING *w);
|
||||
extern void php_free_stmt_bind_buffer(BIND_BUFFER bbuf, int type);
|
||||
extern void php_mysqli_report_error(const char *sqlstate, int errorno, const char *error TSRMLS_DC);
|
||||
extern void php_mysqli_report_index(const char *query, unsigned int status TSRMLS_DC);
|
||||
extern int php_local_infile_init(void **, const char *, void *);
|
||||
extern int php_local_infile_read(void *, char *, uint);
|
||||
extern void php_local_infile_end(void *);
|
||||
extern int php_local_infile_error(void *, char *, uint);
|
||||
extern void php_set_local_infile_handler_default(MY_MYSQL *);
|
||||
extern void php_mysqli_throw_sql_exception(char *sqlstate, int errorno TSRMLS_DC, char *format, ...);
|
||||
extern zend_class_entry *mysqli_link_class_entry;
|
||||
extern zend_class_entry *mysqli_stmt_class_entry;
|
||||
extern zend_class_entry *mysqli_result_class_entry;
|
||||
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;
|
||||
#endif
|
||||
|
||||
PHP_MYSQLI_EXPORT(zend_object_value) mysqli_objects_new(zend_class_entry * TSRMLS_DC);
|
||||
|
||||
#define MYSQLI_DISABLE_MQ if (mysql->multi_query) { \
|
||||
mysql_set_server_option(mysql->mysql, MYSQL_OPTION_MULTI_STATEMENTS_OFF); \
|
||||
mysql->multi_query = 0; \
|
||||
}
|
||||
|
||||
#define MYSQLI_ENABLE_MQ if (!mysql->multi_query) { \
|
||||
mysql_set_server_option(mysql->mysql, MYSQL_OPTION_MULTI_STATEMENTS_ON); \
|
||||
mysql->multi_query = 1; \
|
||||
}
|
||||
|
||||
#define REGISTER_MYSQLI_CLASS_ENTRY(name, mysqli_entry, class_functions) { \
|
||||
zend_class_entry ce; \
|
||||
INIT_CLASS_ENTRY(ce, name,class_functions); \
|
||||
ce.create_object = mysqli_objects_new; \
|
||||
mysqli_entry = zend_register_internal_class(&ce TSRMLS_CC); \
|
||||
} \
|
||||
|
||||
#define MYSQLI_REGISTER_RESOURCE_EX(__ptr, __zval) \
|
||||
((mysqli_object *) zend_object_store_get_object(__zval TSRMLS_CC))->ptr = __ptr;
|
||||
|
||||
#define MYSQLI_RETURN_RESOURCE(__ptr, __ce) \
|
||||
Z_TYPE_P(return_value) = IS_OBJECT; \
|
||||
(return_value)->value.obj = mysqli_objects_new(__ce TSRMLS_CC); \
|
||||
MYSQLI_REGISTER_RESOURCE_EX(__ptr, return_value)
|
||||
|
||||
#define MYSQLI_REGISTER_RESOURCE(__ptr, __ce) \
|
||||
{\
|
||||
zval *object = getThis();\
|
||||
if (!object || !instanceof_function(Z_OBJCE_P(object), mysqli_link_class_entry TSRMLS_CC)) {\
|
||||
object = return_value;\
|
||||
Z_TYPE_P(object) = IS_OBJECT;\
|
||||
(object)->value.obj = mysqli_objects_new(__ce TSRMLS_CC);\
|
||||
}\
|
||||
MYSQLI_REGISTER_RESOURCE_EX(__ptr, object)\
|
||||
}
|
||||
|
||||
#define MYSQLI_FETCH_RESOURCE(__ptr, __type, __id, __name, __check) \
|
||||
{ \
|
||||
MYSQLI_RESOURCE *my_res; \
|
||||
mysqli_object *intern = (mysqli_object *)zend_object_store_get_object(*(__id) TSRMLS_CC);\
|
||||
if (!(my_res = (MYSQLI_RESOURCE *)intern->ptr)) {\
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Couldn't fetch %s", intern->zo.ce->name);\
|
||||
RETURN_NULL();\
|
||||
}\
|
||||
__ptr = (__type)my_res->ptr; \
|
||||
if (__check && my_res->status < __check) { \
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid object or resource %s\n", intern->zo.ce->name); \
|
||||
RETURN_NULL();\
|
||||
}\
|
||||
}
|
||||
|
||||
#define MYSQLI_SET_STATUS(__id, __value) \
|
||||
{ \
|
||||
mysqli_object *intern = (mysqli_object *)zend_object_store_get_object(*(__id) TSRMLS_CC);\
|
||||
((MYSQLI_RESOURCE *)intern->ptr)->status = __value; \
|
||||
} \
|
||||
|
||||
#define MYSQLI_CLEAR_RESOURCE(__id) \
|
||||
{ \
|
||||
mysqli_object *intern = (mysqli_object *)zend_object_store_get_object(*(__id) TSRMLS_CC);\
|
||||
efree(intern->ptr); \
|
||||
intern->ptr = NULL; \
|
||||
}
|
||||
|
||||
#define MYSQLI_RETURN_LONG_LONG(__val) \
|
||||
{ \
|
||||
if ((__val) < LONG_MAX) { \
|
||||
RETURN_LONG((__val)); \
|
||||
} else { \
|
||||
char *ret; \
|
||||
int l = spprintf(&ret, 0, "%llu", (__val)); \
|
||||
RETURN_STRINGL(ret, l, 0); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define MYSQLI_ADD_PROPERTIES(a,b) \
|
||||
{ \
|
||||
int i = 0; \
|
||||
while (b[i].pname != NULL) { \
|
||||
mysqli_add_property(a, b[i].pname, (mysqli_read_t)b[i].r_func, (mysqli_write_t)b[i].w_func TSRMLS_CC); \
|
||||
i++; \
|
||||
}\
|
||||
}
|
||||
|
||||
#if WIN32|WINNT
|
||||
#define SCLOSE(a) closesocket(a)
|
||||
#else
|
||||
#define SCLOSE(a) close(a)
|
||||
#endif
|
||||
|
||||
#define MYSQLI_STORE_RESULT 0
|
||||
#define MYSQLI_USE_RESULT 1
|
||||
|
||||
/* for mysqli_fetch_assoc */
|
||||
#define MYSQLI_ASSOC 1
|
||||
#define MYSQLI_NUM 2
|
||||
#define MYSQLI_BOTH 3
|
||||
|
||||
/* for mysqli_bind_param */
|
||||
#define MYSQLI_BIND_INT 1
|
||||
#define MYSQLI_BIND_DOUBLE 2
|
||||
#define MYSQLI_BIND_STRING 3
|
||||
#define MYSQLI_BIND_SEND_DATA 4
|
||||
|
||||
/* fetch types */
|
||||
#define FETCH_SIMPLE 1
|
||||
#define FETCH_RESULT 2
|
||||
|
||||
/*** REPORT MODES ***/
|
||||
#define MYSQLI_REPORT_OFF 0
|
||||
#define MYSQLI_REPORT_ERROR 1
|
||||
#define MYSQLI_REPORT_STRICT 2
|
||||
#define MYSQLI_REPORT_INDEX 4
|
||||
#define MYSQLI_REPORT_CLOSE 8
|
||||
#define MYSQLI_REPORT_ALL 255
|
||||
|
||||
#define MYSQLI_REPORT_MYSQL_ERROR(mysql) \
|
||||
if ((MyG(report_mode) & MYSQLI_REPORT_ERROR) && mysql_errno(mysql)) { \
|
||||
php_mysqli_report_error(mysql_sqlstate(mysql), mysql_errno(mysql), mysql_error(mysql) TSRMLS_CC); \
|
||||
}
|
||||
|
||||
#define MYSQLI_REPORT_STMT_ERROR(stmt) \
|
||||
if ((MyG(report_mode) & MYSQLI_REPORT_ERROR) && mysql_stmt_errno(stmt)) { \
|
||||
php_mysqli_report_error(mysql_stmt_sqlstate(stmt), mysql_stmt_errno(stmt), mysql_stmt_error(stmt) TSRMLS_CC); \
|
||||
}
|
||||
|
||||
PHP_MYSQLI_API void mysqli_register_link(zval *return_value, void *link TSRMLS_DC);
|
||||
PHP_MYSQLI_API void mysqli_register_stmt(zval *return_value, void *stmt TSRMLS_DC);
|
||||
PHP_MYSQLI_API void mysqli_register_result(zval *return_value, void *result TSRMLS_DC);
|
||||
PHP_MYSQLI_API void php_mysqli_set_error(long mysql_errno, char *mysql_err TSRMLS_DC);
|
||||
|
||||
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;
|
||||
char *default_user;
|
||||
char *default_socket;
|
||||
char *default_pw;
|
||||
long reconnect;
|
||||
long allow_local_infile;
|
||||
long strict;
|
||||
long error_no;
|
||||
char *error_msg;
|
||||
long report_mode;
|
||||
HashTable *report_ht;
|
||||
unsigned long multi_query;
|
||||
unsigned long embedded;
|
||||
#ifdef HAVE_MYSQLND
|
||||
MYSQLND_THD_ZVAL_PCACHE *mysqlnd_thd_zval_cache;
|
||||
#endif
|
||||
ZEND_END_MODULE_GLOBALS(mysqli)
|
||||
|
||||
#define MYSQLI_PROPERTY(a) extern int a(mysqli_object *obj, zval **retval TSRMLS_DC)
|
||||
|
||||
MYSQLI_PROPERTY(my_prop_link_host);
|
||||
|
||||
#ifdef ZTS
|
||||
#define MyG(v) TSRMG(mysqli_globals_id, zend_mysqli_globals *, v)
|
||||
#else
|
||||
#define MyG(v) (mysqli_globals.v)
|
||||
#endif
|
||||
|
||||
#define my_estrdup(x) (x) ? estrdup(x) : NULL
|
||||
#define my_efree(x) if (x) efree(x)
|
||||
|
||||
ZEND_EXTERN_MODULE_GLOBALS(mysqli)
|
||||
|
||||
#endif /* PHP_MYSQLI_STRUCTS.H */
|
||||
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: t
|
||||
* End:
|
||||
* vim600: noet sw=4 ts=4 fdm=marker
|
||||
* vim<600: noet sw=4 ts=4
|
||||
*/
|
2
ext/mysqlnd/CREDITS
Normal file
2
ext/mysqlnd/CREDITS
Normal file
@ -0,0 +1,2 @@
|
||||
MySQLnd
|
||||
Georg Richter, Andrey Hristov, Ulf Wendel
|
98
ext/mysqlnd/config-win.h
Normal file
98
ext/mysqlnd/config-win.h
Normal file
@ -0,0 +1,98 @@
|
||||
/* Copyright Abandoned 1996 TCX DataKonsult AB & Monty Program KB & Detron HB
|
||||
This file is public domain and comes with NO WARRANTY of any kind */
|
||||
|
||||
/* Defines for Win32 to make it compatible for MySQL */
|
||||
|
||||
#include <sys/locking.h>
|
||||
#include <windows.h>
|
||||
#include <math.h> /* Because of rint() */
|
||||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#if defined(__NT__)
|
||||
#define SYSTEM_TYPE "NT"
|
||||
#elif defined(__WIN2000__)
|
||||
#define SYSTEM_TYPE "WIN2000"
|
||||
#else
|
||||
#define SYSTEM_TYPE "Win95/Win98"
|
||||
#endif
|
||||
|
||||
#ifdef _WIN64
|
||||
#define MACHINE_TYPE "ia64" /* Define to machine type name */
|
||||
#else
|
||||
#define MACHINE_TYPE "i32" /* Define to machine type name */
|
||||
#ifndef _WIN32
|
||||
#define _WIN32 /* Compatible with old source */
|
||||
#endif
|
||||
#ifndef __WIN32__
|
||||
#define __WIN32__
|
||||
#endif
|
||||
#endif /* _WIN64 */
|
||||
#ifndef __WIN__
|
||||
#define __WIN__ /* To make it easier in VC++ */
|
||||
#endif
|
||||
|
||||
#define LONGLONG_MIN ((__int64) 0x8000000000000000)
|
||||
#define LONGLONG_MAX ((__int64) 0x7FFFFFFFFFFFFFFF)
|
||||
#define LL(A) ((__int64) A)
|
||||
|
||||
/* Type information */
|
||||
|
||||
typedef unsigned short ushort;
|
||||
typedef unsigned int uint;
|
||||
typedef unsigned __int64 ulonglong; /* Microsofts 64 bit types */
|
||||
typedef __int64 longlong;
|
||||
typedef int sigset_t;
|
||||
#define longlong_defined
|
||||
|
||||
#define SIZEOF_CHAR 1
|
||||
#define SIZEOF_LONG 4
|
||||
#define SIZEOF_LONG_LONG 8
|
||||
|
||||
|
||||
#ifndef _WIN64
|
||||
/* Optimized store functions for Intel x86 */
|
||||
|
||||
#define sint2korr(A) (*((int16 *) (A)))
|
||||
#define sint3korr(A) ((int32) ((((uchar) (A)[2]) & 128) ? \
|
||||
(((uint32) 255L << 24) | \
|
||||
(((uint32) (uchar) (A)[2]) << 16) |\
|
||||
(((uint32) (uchar) (A)[1]) << 8) | \
|
||||
((uint32) (uchar) (A)[0])) : \
|
||||
(((uint32) (uchar) (A)[2]) << 16) |\
|
||||
(((uint32) (uchar) (A)[1]) << 8) | \
|
||||
((uint32) (uchar) (A)[0])))
|
||||
#define sint4korr(A) (*((long *) (A)))
|
||||
#define uint2korr(A) (*((uint16 *) (A)))
|
||||
#define uint3korr(A) (long) (*((unsigned long *) (A)) & 0xFFFFFF)
|
||||
#define uint4korr(A) (*((unsigned long *) (A)))
|
||||
#define uint5korr(A) ((ulonglong)(((uint32) ((uchar) (A)[0])) +\
|
||||
(((uint32) ((uchar) (A)[1])) << 8) +\
|
||||
(((uint32) ((uchar) (A)[2])) << 16) +\
|
||||
(((uint32) ((uchar) (A)[3])) << 24)) +\
|
||||
(((ulonglong) ((uchar) (A)[4])) << 32))
|
||||
#define uint8korr(A) (*((ulonglong *) (A)))
|
||||
#define sint8korr(A) (*((longlong *) (A)))
|
||||
#define int2store(T,A) *((uint16*) (T))= (uint16) (A)
|
||||
#define int3store(T,A) { *(T)= (uchar) ((A));\
|
||||
*(T+1)=(uchar) (((uint) (A) >> 8));\
|
||||
*(T+2)=(uchar) (((A) >> 16)); }
|
||||
#define int4store(T,A) *((long *) (T))= (long) (A)
|
||||
#define int5store(T,A) { *(T)= (uchar)((A));\
|
||||
*((T)+1)=(uchar) (((A) >> 8));\
|
||||
*((T)+2)=(uchar) (((A) >> 16));\
|
||||
*((T)+3)=(uchar) (((A) >> 24)); \
|
||||
*((T)+4)=(uchar) (((A) >> 32)); }
|
||||
#define int8store(T,A) *((ulonglong *) (T))= (ulonglong) (A)
|
||||
|
||||
#define doubleget(V,M) { *((long *) &V) = *((long*) M); \
|
||||
*(((long *) &V)+1) = *(((long*) M)+1); }
|
||||
#define doublestore(T,V) { *((long *) T) = *((long*) &V); \
|
||||
*(((long *) T)+1) = *(((long*) &V)+1); }
|
||||
#define float4get(V,M) { *((long *) &(V)) = *((long*) (M)); }
|
||||
#define float8get(V,M) doubleget((V),(M))
|
||||
#define float4store(V,M) memcpy((byte*) V,(byte*) (&M),sizeof(float))
|
||||
#define float8store(V,M) doublestore((V),(M))
|
||||
|
||||
#endif /* _WIN64 */
|
20
ext/mysqlnd/config.w32
Normal file
20
ext/mysqlnd/config.w32
Normal file
@ -0,0 +1,20 @@
|
||||
// $Id$
|
||||
// vim:ft=javascript
|
||||
|
||||
mysqld_source = "";
|
||||
if (CHECK_LIB("ws2_32.lib", "mysqlnd")) {
|
||||
mysqlnd_source =
|
||||
"mysqlnd.c " +
|
||||
"mysqlnd_debug.c " +
|
||||
"mysqlnd_charset.c " +
|
||||
"mysqlnd_loaddata.c " +
|
||||
"mysqlnd_palloc.c " +
|
||||
"mysqlnd_ps.c " +
|
||||
"mysqlnd_ps_codec.c " +
|
||||
"mysqlnd_qcache.c " +
|
||||
"mysqlnd_result.c " +
|
||||
"mysqlnd_result_meta.c " +
|
||||
"mysqlnd_statistics.c " +
|
||||
"mysqlnd_wireprotocol.c";
|
||||
EXTENSION("mysqlnd", mysqlnd_source, false);
|
||||
}
|
29
ext/mysqlnd/config9.m4
Normal file
29
ext/mysqlnd/config9.m4
Normal file
@ -0,0 +1,29 @@
|
||||
dnl
|
||||
dnl $Id$
|
||||
dnl config.m4 for mysqlnd driver
|
||||
|
||||
dnl If some extension uses mysqlnd it will get compiled in PHP core
|
||||
if test "$PHP_MYSQLND_ENABLED" = "yes"; then
|
||||
mysqlnd_sources="mysqlnd.c mysqlnd_charset.c mysqlnd_wireprotocol.c \
|
||||
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_debug.c"
|
||||
|
||||
PHP_NEW_EXTENSION(mysqlnd, $mysqlnd_sources, no)
|
||||
PHP_ADD_BUILD_DIR([ext/mysqlnd], 1)
|
||||
PHP_INSTALL_HEADERS([ext/mysqlnd])
|
||||
PHP_INSTALL_HEADERS([$ext_builddir/php_mysqlnd_config.h])
|
||||
AC_DEFINE([HAVE_MYSQLND], 1, [Whether mysqlnd is enabled])
|
||||
|
||||
dnl This creates a file so it has to be after above macros
|
||||
PHP_CHECK_TYPES([int8 uint8 int16 uint16 int32 uint32 uchar ulong int8_t uint8_t int16_t uint16_t int32_t uint32_t int64_t uint64_t], [
|
||||
$ext_builddir/php_mysqlnd_config.h
|
||||
],[
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
])
|
||||
fi
|
2078
ext/mysqlnd/mysqlnd.c
Normal file
2078
ext/mysqlnd/mysqlnd.c
Normal file
File diff suppressed because it is too large
Load Diff
354
ext/mysqlnd/mysqlnd.h
Normal file
354
ext/mysqlnd/mysqlnd.h
Normal file
@ -0,0 +1,354 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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_H
|
||||
#define MYSQLND_H
|
||||
|
||||
#define MYSQLND_VERSION "mysqlnd 5.0.2-dev - 070928 - $Revision$"
|
||||
#define MYSQLND_VERSION_ID 50002
|
||||
|
||||
/* This forces inlining of some accessor functions */
|
||||
#define MYSQLND_USE_OPTIMISATIONS 0
|
||||
|
||||
/* #define MYSQLND_STRING_TO_INT_CONVERSION */
|
||||
/*
|
||||
This force mysqlnd to do a single (or more depending on ammount of data)
|
||||
non-blocking read() calls before sending a command to the server. Useful
|
||||
for debugging, if previous function hasn't consumed all the output sent
|
||||
to it - like stmt_send_long_data() error because the data was larger that
|
||||
max_allowed_packet_size, and COM_STMT_SEND_LONG_DATA by protocol doesn't
|
||||
use response packets, thus letting the next command to fail miserably, if
|
||||
the connector implementor is not aware of this deficiency. Should be off
|
||||
on production systems, if of course measured performance degradation is not
|
||||
minimal.
|
||||
*/
|
||||
#if PHP_DEBUG
|
||||
#define MYSQLND_DO_WIRE_CHECK_BEFORE_COMMAND 1
|
||||
#endif
|
||||
|
||||
#ifdef ZTS
|
||||
#include "TSRM.h"
|
||||
#endif
|
||||
|
||||
#include "mysqlnd_portability.h"
|
||||
#include "mysqlnd_enum_n_def.h"
|
||||
#include "mysqlnd_structs.h"
|
||||
|
||||
|
||||
/* Library related */
|
||||
#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
|
||||
|
||||
PHPAPI const MYSQLND_CHARSET * mysqlnd_find_charset_nr(uint charsetno);
|
||||
PHPAPI const MYSQLND_CHARSET * mysqlnd_find_charset_name(const char * const charsetname);
|
||||
|
||||
|
||||
/* Connect */
|
||||
#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,
|
||||
char *db, unsigned int db_len,
|
||||
unsigned int port,
|
||||
char *socket,
|
||||
unsigned int mysql_flags,
|
||||
MYSQLND_THD_ZVAL_PCACHE *zval_cache
|
||||
TSRMLS_DC);
|
||||
|
||||
#define mysqlnd_change_user(conn, user, passwd, db) (conn)->m->change_user((conn), (user), (passwd), (db) TSRMLS_CC)
|
||||
|
||||
#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)
|
||||
#define mysqlnd_fetch_all(result, flags, return_value) (result)->m.fetch_all((result), (flags), (return_value) TSRMLS_CC ZEND_FILE_LINE_CC)
|
||||
#define mysqlnd_result_fetch_field_data(res,offset,ret) (res)->m.fetch_field_data((res), (offset), (ret) TSRMLS_CC)
|
||||
#define mysqlnd_get_connection_stats(conn, values) (conn)->m->get_statistics((conn), (values) TSRMLS_CC ZEND_FILE_LINE_CC)
|
||||
#define mysqlnd_get_client_stats(values) _mysqlnd_get_client_stats((values) TSRMLS_CC ZEND_FILE_LINE_CC)
|
||||
|
||||
#define mysqlnd_close(conn,is_forced) (conn)->m->close((conn), (is_forced) TSRMLS_CC)
|
||||
#define mysqlnd_query(conn, query_str, query_len) (conn)->m->query((conn), (query_str), (query_len) TSRMLS_CC)
|
||||
#define mysqlnd_unbuffered_skip_result(result) (result)->m.skip_result((result) TSRMLS_CC)
|
||||
|
||||
|
||||
#define mysqlnd_use_result(conn) (conn)->m->use_result((conn) TSRMLS_CC)
|
||||
#define mysqlnd_store_result(conn) (conn)->m->store_result((conn) TSRMLS_CC)
|
||||
#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) TSRMLS_CC)
|
||||
|
||||
/*****************************************************************************************************/
|
||||
#if defined(MYSQLND_USE_OPTIMISATIONS) && MYSQLND_USE_OPTIMISATIONS == 1
|
||||
|
||||
/* Errors */
|
||||
#define mysqlnd_errno(conn) (conn)->error_info.error_no
|
||||
#define mysqlnd_error(conn) (conn)->error_info.error
|
||||
#define mysqlnd_sqlstate(conn) ((conn)->error_info.sqlstate[0] ? conn->error_info.sqlstate:MYSQLND_SQLSTATE_NULL)
|
||||
|
||||
/* Charset */
|
||||
#define mysqlnd_character_set_name(conn) (conn)->charset->name
|
||||
|
||||
/* Simple metadata */
|
||||
#define mysqlnd_field_count(conn) (conn)->field_count
|
||||
#define mysqlnd_insert_id(conn) (conn)->upsert_status.last_insert_id
|
||||
#define mysqlnd_affected_rows(conn) (conn)->upsert_status.affected_rows
|
||||
#define mysqlnd_warning_count(conn) (conn)->upsert_status.warning_count
|
||||
#define mysqlnd_info(conn) (conn)->last_message
|
||||
#define mysqlnd_get_server_info(conn) (conn)->server_version
|
||||
#define mysqlnd_get_host_info(conn) (conn)->host_info
|
||||
#define mysqlnd_get_proto_info(conn) (conn)->protocol_version
|
||||
#define mysqlnd_thread_id(conn) (conn)->thread_id
|
||||
|
||||
#define mysqlnd_num_rows(result) ((result)->data? (result)->data->row_count:0)
|
||||
#define mysqlnd_num_fields(result) (result)->field_count
|
||||
|
||||
#define mysqlnd_fetch_lengths(result) ((result)->m.fetch_lengths? (result)->m.fetch_lengths((result)):NULL)
|
||||
|
||||
#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) TSRMLS_CC)
|
||||
#define mysqlnd_fetch_field_direct(result,fnr) ((result)->meta? &((result)->meta->fields[(fnr)]):NULL)
|
||||
|
||||
/* mysqlnd metadata */
|
||||
#define mysqlnd_get_client_info() MYSQLND_VERSION
|
||||
#define mysqlnd_get_client_version() MYSQLND_VERSION_ID
|
||||
|
||||
/* PS */
|
||||
#define mysqlnd_stmt_insert_id(stmt) (stmt)->upsert_status.last_insert_id
|
||||
#define mysqlnd_stmt_affected_rows(stmt) (stmt)->upsert_status.affected_rows
|
||||
#define mysqlnd_stmt_num_rows(stmt) (stmt)->result? mysqlnd_num_rows((stmt)->result):0
|
||||
#define mysqlnd_stmt_param_count(stmt) (stmt)->param_count
|
||||
#define mysqlnd_stmt_field_count(stmt) (stmt)->field_count
|
||||
#define mysqlnd_stmt_warning_count(stmt) (stmt)->upsert_status.warning_count
|
||||
#define mysqlnd_stmt_errno(stmt) (stmt)->error_info.error_no
|
||||
#define mysqlnd_stmt_error(stmt) (stmt)->error_info.error
|
||||
#define mysqlnd_stmt_sqlstate(stmt) ((stmt)->error_info.sqlstate[0] ? (stmt)->error_info.sqlstate:MYSQLND_SQLSTATE_NULL)
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************************************/
|
||||
#else /* Using plain functions */
|
||||
/*****************************************************************************************************/
|
||||
|
||||
/* Errors */
|
||||
#define mysqlnd_errno(conn) (conn)->m->get_error_no((conn))
|
||||
#define mysqlnd_error(conn) (conn)->m->get_error_str((conn))
|
||||
#define mysqlnd_sqlstate(conn) (conn)->m->get_sqlstate((conn))
|
||||
|
||||
/* Charset */
|
||||
#define mysqlnd_character_set_name(conn) (conn)->m->charset_name((conn))
|
||||
|
||||
/* Simple metadata */
|
||||
#define mysqlnd_field_count(conn) (conn)->m->get_field_count((conn))
|
||||
#define mysqlnd_insert_id(conn) (conn)->m->get_last_insert_id((conn))
|
||||
#define mysqlnd_affected_rows(conn) (conn)->m->get_affected_rows((conn))
|
||||
#define mysqlnd_warning_count(conn) (conn)->m->get_warning_count((conn))
|
||||
#define mysqlnd_info(conn) (conn)->m->get_last_message((conn))
|
||||
#define mysqlnd_get_server_info(conn) (conn)->m->get_server_information((conn))
|
||||
#define mysqlnd_get_host_info(conn) (conn)->m->get_host_information((conn))
|
||||
#define mysqlnd_get_proto_info(conn) (conn)->m->get_protocol_information((conn))
|
||||
#define mysqlnd_thread_id(conn) (conn)->m->get_thread_id((conn))
|
||||
|
||||
#define mysqlnd_num_rows(result) (result)->m.num_rows((result))
|
||||
#define mysqlnd_num_fields(result) (result)->m.num_fields((result))
|
||||
|
||||
PHPAPI unsigned long * mysqlnd_fetch_lengths(MYSQLND_RES * const result);
|
||||
|
||||
#define mysqlnd_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) 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();
|
||||
PHPAPI unsigned int mysqlnd_get_client_version();
|
||||
|
||||
/* PS */
|
||||
#define mysqlnd_stmt_insert_id(stmt) (stmt)->m->get_last_insert_id((stmt))
|
||||
#define mysqlnd_stmt_affected_rows(stmt) (stmt)->m->get_affected_rows((stmt))
|
||||
#define mysqlnd_stmt_num_rows(stmt) (stmt)->m->get_num_rows((stmt))
|
||||
#define mysqlnd_stmt_param_count(stmt) (stmt)->m->get_param_count((stmt))
|
||||
#define mysqlnd_stmt_field_count(stmt) (stmt)->m->get_field_count((stmt))
|
||||
#define mysqlnd_stmt_warning_count(stmt) (stmt)->m->get_warning_count((stmt))
|
||||
#define mysqlnd_stmt_errno(stmt) (stmt)->m->get_error_no((stmt))
|
||||
#define mysqlnd_stmt_error(stmt) (stmt)->m->get_error_str((stmt))
|
||||
#define mysqlnd_stmt_sqlstate(stmt) (stmt)->m->get_sqlstate((stmt))
|
||||
#endif /* MYSQLND_USE_OPTIMISATIONS */
|
||||
/*****************************************************************************************************/
|
||||
|
||||
|
||||
|
||||
PHPAPI const char * mysqlnd_field_type_name(enum mysqlnd_field_types field_type);
|
||||
|
||||
/* LOAD DATA LOCAL */
|
||||
PHPAPI void mysqlnd_local_infile_default(MYSQLND *conn);
|
||||
PHPAPI void mysqlnd_set_local_infile_handler(MYSQLND * const conn, const char * const funcname);
|
||||
|
||||
/* Simple commands */
|
||||
#define mysqlnd_autocommit(conn, mode) (conn)->m->query((conn),(mode) ? "SET AUTOCOMMIT=1":"SET AUTOCOMMIT=0", 16 TSRMLS_CC)
|
||||
#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_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)
|
||||
#define mysqlnd_select_db(conn, db, db_len) (conn)->m->select_db((conn), (db), (db_len) TSRMLS_CC)
|
||||
#define mysqlnd_ping(conn) (conn)->m->ping((conn) TSRMLS_CC)
|
||||
#define mysqlnd_kill(conn, pid) (conn)->m->kill_connection((conn), (pid) TSRMLS_CC)
|
||||
#define mysqlnd_refresh(conn, options) (conn)->m->refresh_server((conn), (options) TSRMLS_CC)
|
||||
#define mysqlnd_shutdown(conn, level) (conn)->m->shutdown_server((conn), (level) TSRMLS_CC)
|
||||
#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) 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) TSRMLS_CC)
|
||||
#define mysqlnd_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 TSRMLS_DC);
|
||||
|
||||
|
||||
/* PS */
|
||||
#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) 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) 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) 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) 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)
|
||||
|
||||
|
||||
/* Performance statistics */
|
||||
PHPAPI void _mysqlnd_get_client_stats(zval *return_value TSRMLS_DC ZEND_FILE_LINE_DC);
|
||||
|
||||
/* Persistent caching zval allocator */
|
||||
#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);
|
||||
|
||||
#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);
|
||||
|
||||
|
||||
#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 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);
|
||||
|
||||
|
||||
|
||||
/* ---------------------- QUERY CACHE ---------------*/
|
||||
struct st_mysqlnd_qcache {
|
||||
HashTable *ht;
|
||||
unsigned int references;
|
||||
#ifdef ZTS
|
||||
MUTEX_T LOCK_access;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
typedef struct st_mysqlnd_qcache_element {
|
||||
MYSQLND_RES_BUFFERED *data;
|
||||
MYSQLND_RES_METADATA *meta;
|
||||
const char * query;
|
||||
size_t query_len;
|
||||
} MYSQLND_QCACHE_ELEMENT;
|
||||
|
||||
|
||||
PHPAPI MYSQLND_QCACHE * mysqlnd_qcache_init_cache();
|
||||
PHPAPI MYSQLND_QCACHE * mysqlnd_qcache_get_cache_reference(MYSQLND_QCACHE * const cache);
|
||||
PHPAPI void mysqlnd_qcache_free_cache_reference(MYSQLND_QCACHE **cache);
|
||||
PHPAPI void mysqlnd_qcache_stats(const MYSQLND_QCACHE * const cache, zval *return_value);
|
||||
MYSQLND_RES * mysqlnd_qcache_get(MYSQLND_QCACHE * const cache, const char * query,
|
||||
size_t query_len);
|
||||
void mysqlnd_qcache_put(MYSQLND_QCACHE * const cache, char * query, size_t query_len,
|
||||
MYSQLND_RES_BUFFERED * const result, MYSQLND_RES_METADATA * const meta);
|
||||
|
||||
|
||||
|
||||
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
|
||||
#define MYSQLND_G(v) (mysqlnd_globals.v)
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* MYSQLND_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
|
||||
*/
|
285
ext/mysqlnd/mysqlnd_alloc.c
Normal file
285
ext/mysqlnd/mysqlnd_alloc.c
Normal file
@ -0,0 +1,285 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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$ */
|
||||
#include "php.h"
|
||||
#include "mysqlnd.h"
|
||||
#include "mysqlnd_priv.h"
|
||||
#include "mysqlnd_palloc.h"
|
||||
|
||||
|
||||
#define MYSQLND_SILENT
|
||||
#define MYSQLND_DONT_DUMP_STATS
|
||||
|
||||
#define MYSQLND_ZVALS_MAX_CACHE 5000
|
||||
|
||||
|
||||
#if A0
|
||||
/* Caching zval allocator */
|
||||
zval * mysqlnd_alloc_get_zval(MYSQLND_ZVAL_CACHE * const cache);
|
||||
void mysqlnd_alloc_zval_ptr_dtor(zval **zv, MYSQLND_ZVAL_CACHE * const cache);
|
||||
MYSQLND_ZVAL_CACHE* mysqlnd_alloc_init_cache();
|
||||
MYSQLND_ZVAL_CACHE* mysqlnd_alloc_get_cache_reference(MYSQLND_ZVAL_CACHE *cache);
|
||||
void mysqlnd_alloc_free_cache_reference(MYSQLND_ZVAL_CACHE **cache);
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
The cache line is a big contiguous array of zval pointers.
|
||||
Because the CPU cache will cache starting from an address, and not
|
||||
before it, then we have to organize our structure according to this.
|
||||
Thus, if 'last_added' is valid pointer (not NULL) then last_added is
|
||||
increased. When zval is cached, if there is room, last_added is decreased
|
||||
and then the zval pointer will be assigned to it. This means that some
|
||||
positions may become hot points and stay in the cache.
|
||||
Imagine we have 5 pointers in a line
|
||||
1. last_added = list_item->ptr_line + cache->max_items;
|
||||
2. get_zval -> *last_added = NULL. Use MAKE_STD_ZVAL
|
||||
3. get_zval -> *last_added = NULL. Use MAKE_STD_ZVAL
|
||||
4. get_zval -> *last_added = NULL. Use MAKE_STD_ZVAL
|
||||
0x0
|
||||
0x0
|
||||
0x0
|
||||
0x0
|
||||
0x0
|
||||
---
|
||||
empty_position, always 0x0 <-- last_added
|
||||
|
||||
5. free_zval -> if (free_items++ != max_items) {// we can add more
|
||||
*(--last_added) = zval_ptr;
|
||||
}
|
||||
(memory addresses increase downwards)
|
||||
0x0
|
||||
0x0
|
||||
0x0
|
||||
0x0
|
||||
0xA <-- last_added
|
||||
---
|
||||
0x0
|
||||
|
||||
6. free_zval -> if (free_items++ != max_items) {// we can add more
|
||||
*(--last_added) = zval_ptr;
|
||||
}
|
||||
0x0
|
||||
0x0
|
||||
0x0
|
||||
0xB <-- last_added
|
||||
0xA
|
||||
---
|
||||
0x0
|
||||
|
||||
7. free_zval -> if (free_items++ != max_items) {// we can add more
|
||||
*(--last_added) = zval_ptr;
|
||||
}
|
||||
0x0
|
||||
0x0
|
||||
0xC <-- last_added
|
||||
0xB
|
||||
0xA
|
||||
---
|
||||
0x0
|
||||
|
||||
8. get_zval -> *last_added != NULL. -> p = *last_added; *last_added++ = NULL;
|
||||
0x0
|
||||
0x0
|
||||
0x0
|
||||
0xB <-- last_added
|
||||
0xA
|
||||
---
|
||||
0x0
|
||||
|
||||
9. get_zval -> *last_added != NULL. -> p = *last_added; *last_added++ = NULL;
|
||||
0x0
|
||||
0x0
|
||||
0x0
|
||||
0x0
|
||||
0xA <-- last_added
|
||||
---
|
||||
0x0
|
||||
|
||||
10. get_zval -> *last_added != NULL. -> p = *last_added; *last_added++ = NULL;
|
||||
0x0
|
||||
0x0
|
||||
0x0
|
||||
0x0
|
||||
0x0
|
||||
---
|
||||
0x0 <-- last_added
|
||||
|
||||
*/
|
||||
|
||||
|
||||
zval * mysqlnd_alloc_get_zval(MYSQLND_ZVAL_CACHE * const cache)
|
||||
{
|
||||
zval *ret = NULL;
|
||||
|
||||
#ifndef MYSQLND_SILENT
|
||||
php_printf("[mysqlnd_alloc_get_zval %p] *last_added=%p free_items=%d ", cache, cache? cache->free_list->last_added:NULL, cache->free_items);
|
||||
#endif
|
||||
|
||||
if (cache) {
|
||||
if ((ret = *cache->free_list->last_added)) {
|
||||
*cache->free_list->last_added++ = NULL;
|
||||
|
||||
--cache->free_items;
|
||||
++cache->get_hits;
|
||||
} else {
|
||||
++cache->get_misses;
|
||||
}
|
||||
}
|
||||
if (!ret) {
|
||||
ALLOC_ZVAL(ret);
|
||||
}
|
||||
INIT_PZVAL(ret);
|
||||
|
||||
#ifndef MYSQLND_SILENT
|
||||
php_printf("ret=%p\n", ret);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
static
|
||||
void mysqlnd_alloc_cache_prealloc(MYSQLND_ZVAL_CACHE * const cache, unsigned int count)
|
||||
{
|
||||
zval *data;
|
||||
cache->free_items = count;
|
||||
while (count--) {
|
||||
MAKE_STD_ZVAL(data);
|
||||
ZVAL_NULL(data);
|
||||
#ifndef MYSQLND_SILENT
|
||||
php_printf("[mysqlnd_alloc_prealloc %p] items=%d data=%p\n", cache, cache->free_items, data);
|
||||
#endif
|
||||
|
||||
*(--cache->free_list->last_added) = data;
|
||||
}
|
||||
}
|
||||
|
||||
void mysqlnd_alloc_zval_ptr_dtor(zval **zv, MYSQLND_ZVAL_CACHE * const cache)
|
||||
{
|
||||
if (!cache || ZVAL_REFCOUNT(*zv) > 1 || cache->max_items == cache->free_items) {
|
||||
#ifndef MYSQLND_SILENT
|
||||
php_printf("[mysqlnd_alloc_zval_ptr_dtor %p]1 last_added-1=%p *zv=%p\n", cache->free_list->last_added, *zv);
|
||||
#endif
|
||||
/* We can't cache zval's with refcount > 1 */
|
||||
zval_ptr_dtor(zv);
|
||||
if (cache) {
|
||||
if (cache->max_items == cache->free_items) {
|
||||
++cache->put_full_misses;
|
||||
} else {
|
||||
++cache->put_refcount_misses;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* refcount is 1 and there is place. Go, cache it! */
|
||||
++cache->free_items;
|
||||
zval_dtor(*zv);
|
||||
ZVAL_NULL(*zv);
|
||||
*(--cache->free_list->last_added) = *zv;
|
||||
++cache->put_hits;
|
||||
}
|
||||
#ifndef MYSQLND_SILENT
|
||||
php_printf("[mysqlnd_alloc_zval_ptr_dtor %p] free_items=%d\n", cache, cache->free_items);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
MYSQLND_ZVAL_CACHE* mysqlnd_alloc_init_cache(void)
|
||||
{
|
||||
MYSQLND_ZVAL_CACHE *ret = ecalloc(1, sizeof(MYSQLND_ZVAL_CACHE));
|
||||
|
||||
#ifndef MYSQLND_SILENT
|
||||
php_printf("[mysqlnd_alloc_init_cache %p]\n", ret);
|
||||
#endif
|
||||
|
||||
ret->max_items = MYSQLND_ZVALS_MAX_CACHE;
|
||||
ret->free_items = 0;
|
||||
ret->references = 1;
|
||||
|
||||
/* Let's have always one, so we don't need to do a check in get_zval */
|
||||
ret->free_list = ecalloc(1, sizeof(struct st_mysqlnd_zval_list));
|
||||
|
||||
/* One more for empty position of last_added */
|
||||
ret->free_list->ptr_line = ecalloc(ret->max_items + 1, sizeof(zval *));
|
||||
ret->free_list->last_added = ret->free_list->ptr_line + ret->max_items;
|
||||
|
||||
mysqlnd_alloc_cache_prealloc(ret, (ret->max_items / 100) * 100);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
MYSQLND_ZVAL_CACHE* mysqlnd_alloc_get_cache_reference(MYSQLND_ZVAL_CACHE *cache)
|
||||
{
|
||||
if (cache) {
|
||||
cache->references++;
|
||||
}
|
||||
return cache;
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
void mysqlnd_alloc_free_cache(MYSQLND_ZVAL_CACHE *cache)
|
||||
{
|
||||
#ifndef MYSQLND_SILENT
|
||||
uint i = 0;
|
||||
php_printf("[mysqlnd_alloc_free_cache %p]\n", cache);
|
||||
#endif
|
||||
|
||||
while (*cache->free_list->last_added) {
|
||||
#ifndef MYSQLND_SILENT
|
||||
php_printf("\t[free_item %d %p]\n", i++, *cache->free_list->last_added);
|
||||
#endif
|
||||
zval_ptr_dtor(cache->free_list->last_added);
|
||||
cache->free_list->last_added++;
|
||||
}
|
||||
#ifndef MYSQLND_DONT_DUMP_STATS
|
||||
php_printf("CACHE STATS:\n\tGET\n\t\tHITS:%lu\n\t\tMISSES=%lu\n\t\tHIT RATIO=%1.3f\n\t"
|
||||
"PUT\n\t\tHITS:%lu\n\t\tFULL_MISS=%lu\n\t\tREFC_MISS=%lu\n\t\tHIT RATIO=%1.3f\n\n",
|
||||
cache->get_hits, cache->get_misses, (1.0*cache->get_hits/(cache->get_hits + cache->get_misses)),
|
||||
cache->put_hits, cache->put_full_misses, cache->put_refcount_misses,
|
||||
(1.0 * cache->put_hits / (cache->put_hits + cache->put_full_misses + cache->put_refcount_misses)));
|
||||
#endif
|
||||
efree(cache->free_list->ptr_line);
|
||||
efree(cache->free_list);
|
||||
efree(cache);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void mysqlnd_alloc_free_cache_reference(MYSQLND_ZVAL_CACHE **cache)
|
||||
{
|
||||
#ifndef MYSQLND_SILENT
|
||||
php_printf("[mysqlnd_alloc_free_cache_reference %p] refs=%d\n", *cache, (*cache)->references);
|
||||
#endif
|
||||
if (*cache && --(*cache)->references == 0) {
|
||||
mysqlnd_alloc_free_cache(*cache);
|
||||
}
|
||||
*cache = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
603
ext/mysqlnd/mysqlnd_charset.c
Normal file
603
ext/mysqlnd/mysqlnd_charset.c
Normal file
@ -0,0 +1,603 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
#include "php.h"
|
||||
#include "php_globals.h"
|
||||
#include "mysqlnd.h"
|
||||
#include "mysqlnd_priv.h"
|
||||
#include "mysqlnd_debug.h"
|
||||
|
||||
/* {{{ utf8 functions */
|
||||
|
||||
static uint check_mb_utf8_sequence(const char *start, const char *end)
|
||||
{
|
||||
zend_uchar c;
|
||||
|
||||
if (start >= end) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
c = (zend_uchar) start[0];
|
||||
|
||||
if (c < 0x80) {
|
||||
return 1; /* single byte character */
|
||||
}
|
||||
if (c < 0xC2) {
|
||||
return 0; /* invalid mb character */
|
||||
}
|
||||
if (c < 0xE0) {
|
||||
if (start + 2 > end) {
|
||||
return 0; /* too small */
|
||||
}
|
||||
if (!(((zend_uchar)start[1] ^ 0x80) < 0x40)) {
|
||||
return 0;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
if (c < 0xF0) {
|
||||
if (start + 3 > end) {
|
||||
return 0; /* too small */
|
||||
}
|
||||
if (!(((zend_uchar)start[1] ^ 0x80) < 0x40 && ((zend_uchar)start[2] ^ 0x80) < 0x40 &&
|
||||
(c >= 0xE1 || (zend_uchar)start[1] >= 0xA0))) {
|
||||
return 0; /* invalid utf8 character */
|
||||
}
|
||||
return 3;
|
||||
}
|
||||
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)
|
||||
{
|
||||
if (utf8 < 0x80) {
|
||||
return 1; /* single byte character */
|
||||
}
|
||||
if (utf8 < 0xC2) {
|
||||
return 0; /* invalid multibyte header */
|
||||
}
|
||||
if (utf8 < 0xE0) {
|
||||
return 2; /* double byte character */
|
||||
}
|
||||
if (utf8 < 0xF0) {
|
||||
return 3; /* triple byte character */
|
||||
}
|
||||
/* We still don't support characters out of the BMP */
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ big5 functions */
|
||||
#define valid_big5head(c) (0xA1 <= (uint)(c) && (uint)(c) <= 0xF9)
|
||||
#define valid_big5tail(c) ((0x40 <= (uint)(c) && (uint)(c) <= 0x7E) || \
|
||||
(0xA1 <= (uint)(c) && (uint)(c) <= 0xFE))
|
||||
|
||||
#define isbig5code(c,d) (isbig5head(c) && isbig5tail(d))
|
||||
|
||||
static uint check_mb_big5(const char *start, const char *end)
|
||||
{
|
||||
return (valid_big5head(*(start)) && (end - start) > 1 && valid_big5tail(*(start + 1)) ? 2 : 0);
|
||||
}
|
||||
|
||||
|
||||
static uint mysqlnd_mbcharlen_big5(uint big5)
|
||||
{
|
||||
return (valid_big5head(big5)) ? 2 : 1;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ cp932 functions */
|
||||
#define valid_cp932head(c) ((0x81 <= (c) && (c) <= 0x9F) || (0xE0 <= (c) && c <= 0xFC))
|
||||
#define valid_cp932tail(c) ((0x40 <= (c) && (c) <= 0x7E) || (0x80 <= (c) && c <= 0xFC))
|
||||
|
||||
|
||||
static uint check_mb_cp932(const char *start, const char *end)
|
||||
{
|
||||
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((zend_uchar)cp932)) ? 2 : 1;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ euckr functions */
|
||||
#define valid_euckr(c) ((0xA1 <= (zend_uchar)(c) && (zend_uchar)(c) <= 0xFE))
|
||||
|
||||
static uint check_mb_euckr(const char *start, const char *end)
|
||||
{
|
||||
if (end - start <= 1) {
|
||||
return 0; /* invalid length */
|
||||
}
|
||||
if (*(zend_uchar *)start < 0x80) {
|
||||
return 0; /* invalid euckr character */
|
||||
}
|
||||
if (valid_euckr(start[1])) {
|
||||
return 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static uint mysqlnd_mbcharlen_euckr(uint kr)
|
||||
{
|
||||
return (valid_euckr(kr)) ? 2 : 1;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ eucjpms functions */
|
||||
#define valid_eucjpms(c) (((c) & 0xFF) >= 0xA1 && ((c) & 0xFF) <= 0xFE)
|
||||
#define valid_eucjpms_kata(c) (((c) & 0xFF) >= 0xA1 && ((c) & 0xFF) <= 0xDF)
|
||||
#define valid_eucjpms_ss2(c) (((c) & 0xFF) == 0x8E)
|
||||
#define valid_eucjpms_ss3(c) (((c) & 0xFF) == 0x8F)
|
||||
|
||||
static uint check_mb_eucjpms(const char *start, const char *end)
|
||||
{
|
||||
if (*((zend_uchar *)start) < 0x80) {
|
||||
return 0; /* invalid eucjpms character */
|
||||
}
|
||||
if (valid_eucjpms(start[0]) && (end - start) > 1 && valid_eucjpms(start[1])) {
|
||||
return 2;
|
||||
}
|
||||
if (valid_eucjpms_ss2(start[0]) && (end - start) > 1 && valid_eucjpms_kata(start[1])) {
|
||||
return 2;
|
||||
}
|
||||
if (valid_eucjpms_ss3(start[0]) && (end - start) > 2 && valid_eucjpms(start[1]) &&
|
||||
valid_eucjpms(start[2])) {
|
||||
return 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static uint mysqlnd_mbcharlen_eucjpms(uint jpms)
|
||||
{
|
||||
if (valid_eucjpms(jpms) || valid_eucjpms_ss2(jpms)) {
|
||||
return 2;
|
||||
}
|
||||
if (valid_eucjpms_ss3(jpms)) {
|
||||
return 3;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ gb2312 functions */
|
||||
#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 (valid_gb2312_head((uint)start[0]) && end - start > 1 &&
|
||||
valid_gb2312_tail((uint)start[1])) ? 2 : 0;
|
||||
}
|
||||
|
||||
|
||||
static uint mysqlnd_mbcharlen_gb2312(uint gb)
|
||||
{
|
||||
return (valid_gb2312_head(gb)) ? 2 : 1;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ gbk functions */
|
||||
#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)
|
||||
{
|
||||
return (valid_gbk_head(start[0]) && (end) - (start) > 1 && valid_gbk_tail(start[1])) ? 2 : 0;
|
||||
}
|
||||
|
||||
static uint mysqlnd_mbcharlen_gbk(uint gbk)
|
||||
{
|
||||
return (valid_gbk_head(gbk) ? 2 : 1);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ sjis functions */
|
||||
#define valid_sjis_head(c) ((0x81 <= (c) && (c) <= 0x9F) && \
|
||||
(0xE0 <= (c) && (c) <= 0xFC))
|
||||
#define valid_sjis_tail(c) ((0x40 <= (c) && (c) <= 0x7E) && \
|
||||
(0x80 <= (c) && (c) <= 0x7C))
|
||||
|
||||
|
||||
static uint check_mb_sjis(const char *start, const char *end)
|
||||
{
|
||||
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((zend_uchar)sjis)) ? 2 : 1;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ ucs2 functions */
|
||||
static uint check_mb_ucs2(const char *start __attribute((unused)), const char *end __attribute((unused)))
|
||||
{
|
||||
return 2; /* always 2 */
|
||||
}
|
||||
|
||||
static uint mysqlnd_mbcharlen_ucs2(uint ucs2 __attribute((unused)))
|
||||
{
|
||||
return 2; /* always 2 */
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ ujis functions */
|
||||
#define valid_ujis(c) ((0xA1 <= ((c)&0xFF) && ((c)&0xFF) <= 0xFE))
|
||||
#define valid_ujis_kata(c) ((0xA1 <= ((c)&0xFF) && ((c)&0xFF) <= 0xDF))
|
||||
#define valid_ujis_ss2(c) (((c)&0xFF) == 0x8E)
|
||||
#define valid_ujis_ss3(c) (((c)&0xFF) == 0x8F)
|
||||
|
||||
static uint check_mb_ujis(const char *start, const char *end)
|
||||
{
|
||||
if (*(uchar*)start < 0x80) {
|
||||
return 0; /* invalid ujis character */
|
||||
}
|
||||
if (valid_ujis(*(start)) && valid_ujis(*((start)+1))) {
|
||||
return 2;
|
||||
}
|
||||
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))) {
|
||||
return 3;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static uint mysqlnd_mbcharlen_ujis(uint ujis)
|
||||
{
|
||||
return (valid_ujis(ujis)? 2: valid_ujis_ss2(ujis)? 2: valid_ujis_ss3(ujis)? 3: 1);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
|
||||
/* {{{ mysqlnd_charsets */
|
||||
const MYSQLND_CHARSET mysqlnd_charsets[] =
|
||||
{
|
||||
{ 1, "big5","big5_chinese_ci", 1, 2, 0, mysqlnd_mbcharlen_big5, check_mb_big5},
|
||||
{ 3, "dec8", "dec8_swedisch_ci", 1, 1, 0, NULL, NULL},
|
||||
{ 4, "cp850", "cp850_general_ci", 1, 1, 0, NULL, NULL},
|
||||
{ 6, "hp8", "hp8_english_ci", 1, 1, 0, NULL, NULL},
|
||||
{ 7, "koi8r", "koi8r_general_ci", 1, 1, 0, NULL, NULL},
|
||||
{ 8, "latin1", "latin1_swedish_ci", 1, 1, 0, NULL, NULL},
|
||||
{ 9, "latin2", "latin2_general_ci", 1, 1, 0, NULL, NULL},
|
||||
{ 10, "swe7", "swe7_swedish_ci", 1, 1, 0, NULL, NULL},
|
||||
{ 11, "ascii", "ascii_general_ci", 1, 1, 0, NULL, NULL},
|
||||
{ 12, "ujis", "ujis_japanese_ci", 1, 3, 0, mysqlnd_mbcharlen_ujis, check_mb_ujis},
|
||||
{ 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_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},
|
||||
{ 26, "cp1250", "cp1250_general_ci", 1, 1, 0, NULL, NULL},
|
||||
{ 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_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},
|
||||
{ 38, "macce", "macce_general_ci", 1, 1, 0, NULL, NULL},
|
||||
{ 39, "macroman", "macroman_general_ci", 1, 1, 0, NULL, NULL},
|
||||
{ 40, "cp852", "cp852_general_ci", 1, 1, 0, NULL, NULL},
|
||||
{ 41, "latin7", "latin7_general_ci", 1, 1, 0, NULL, NULL},
|
||||
{ 51, "cp1251", "cp1251_general_ci", 1, 1, 0, NULL, NULL},
|
||||
{ 57, "cp1256", "cp1256_general_ci", 1, 1, 0, NULL, NULL},
|
||||
{ 59, "cp1257", "cp1257_general_ci", 1, 1, 0, NULL, NULL},
|
||||
{ 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, 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},
|
||||
{ 15, "latin1", "latin1_danish_ci", 1, 1, 0, NULL, NULL},
|
||||
{ 17, "filename", "filename", 1, 5, 1, NULL, NULL},
|
||||
{ 20, "latin7", "latin7_estonian_cs", 1, 1, 0, NULL, NULL},
|
||||
{ 21, "latin2", "latin2_hungarian_ci", 1, 1, 0, NULL, NULL},
|
||||
{ 23, "cp1251", "cp1251_ukrainian_ci", 1, 1, 0, NULL, NULL},
|
||||
{ 27, "latin2", "latin2_croatian_ci", 1, 1, 0, NULL, NULL},
|
||||
{ 29, "cp1257", "cp1257_lithunian_ci", 1, 1, 0, NULL, NULL},
|
||||
{ 31, "latin1", "latin1_german2_ci", 1, 1, 0, NULL, NULL},
|
||||
{ 34, "cp1250", "cp1250_czech_cs", 1, 1, 0, NULL, NULL},
|
||||
{ 42, "latin7", "latin7_general_cs", 1, 1, 0, NULL, NULL},
|
||||
{ 43, "macce", "macce_bin", 1, 1, 0, NULL, NULL},
|
||||
{ 44, "cp1250", "cp1250_croatian_ci", 1, 1, 0, NULL, NULL},
|
||||
{ 47, "latin1", "latin1_bin", 1, 1, 0, NULL, NULL},
|
||||
{ 48, "latin1", "latin1_general_ci", 1, 1, 0, NULL, NULL},
|
||||
{ 49, "latin1", "latin1_general_cs", 1, 1, 0, NULL, NULL},
|
||||
{ 50, "cp1251", "cp1251_bin", 1, 1, 0, NULL, NULL},
|
||||
{ 52, "cp1251", "cp1251_general_cs", 1, 1, 0, NULL, NULL},
|
||||
{ 53, "macroman", "macroman_bin", 1, 1, 0, NULL, NULL},
|
||||
{ 58, "cp1257", "cp1257_bin", 1, 1, 0, NULL, NULL},
|
||||
{ 60, "armascii8", "armascii8_bin", 1, 1, 0, NULL, NULL},
|
||||
{ 65, "ascii", "ascii_bin", 1, 1, 0, NULL, NULL},
|
||||
{ 66, "cp1250", "cp1250_bin", 1, 1, 0, NULL, NULL},
|
||||
{ 67, "cp1256", "cp1256_bin", 1, 1, 0, NULL, NULL},
|
||||
{ 68, "cp866", "cp866_bin", 1, 1, 0, NULL, NULL},
|
||||
{ 69, "dec8", "dec8_bin", 1, 1, 0, NULL, NULL},
|
||||
{ 70, "greek", "greek_bin", 1, 1, 0, NULL, NULL},
|
||||
{ 71, "hebew", "hebrew_bin", 1, 1, 0, NULL, NULL},
|
||||
{ 72, "hp8", "hp8_bin", 1, 1, 0, NULL, NULL},
|
||||
{ 73, "keybcs2", "keybcs2_bin", 1, 1, 0, NULL, NULL},
|
||||
{ 74, "koi8r", "koi8r_bin", 1, 1, 0, NULL, NULL},
|
||||
{ 75, "koi8u", "koi8u_bin", 1, 1, 0, NULL, NULL},
|
||||
{ 77, "latin2", "latin2_bin", 1, 1, 0, NULL, NULL},
|
||||
{ 78, "latin5", "latin5_bin", 1, 1, 0, NULL, NULL},
|
||||
{ 79, "latin7", "latin7_bin", 1, 1, 0, NULL, NULL},
|
||||
{ 80, "cp850", "cp850_bin", 1, 1, 0, NULL, NULL},
|
||||
{ 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_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},
|
||||
{ 87, "gbk", "gbk_bin", 1, 2, 0, mysqlnd_mbcharlen_gbk, check_mb_gbk},
|
||||
{ 88, "sjis", "sjis_bin", 1, 2, 0, mysqlnd_mbcharlen_sjis, check_mb_sjis},
|
||||
{ 89, "tis620", "tis620_bin", 1, 1, 0, NULL, NULL},
|
||||
{ 90, "ucs2", "ucs2_bin", 2, 2, 0, mysqlnd_mbcharlen_ucs2, check_mb_ucs2},
|
||||
{ 91, "ujis", "ujis_bin", 1, 3, 0, mysqlnd_mbcharlen_ujis, check_mb_ujis},
|
||||
{ 94, "latin1", "latin1_spanish_ci", 1, 1, 0, NULL, NULL},
|
||||
{ 96, "cp932", "cp932_bin", 1, 2, 1, mysqlnd_mbcharlen_cp932, check_mb_cp932},
|
||||
{ 99, "cp1250", "cp1250_polish_ci", 1, 1, 0, NULL, NULL},
|
||||
{ 98, "eucjpms", "eucjpms_bin", 1, 3, 0, mysqlnd_mbcharlen_eucjpms, check_mb_eucjpms},
|
||||
{ 128, "ucs2", "ucs2_unicode_ci", 2, 2, 0, mysqlnd_mbcharlen_ucs2, check_mb_ucs2},
|
||||
{ 129, "ucs2", "ucs2_icelandic_ci", 2, 2, 0, mysqlnd_mbcharlen_ucs2, check_mb_ucs2},
|
||||
{ 130, "ucs2", "ucs2_latvian_ci", 2, 2, 0, mysqlnd_mbcharlen_ucs2, check_mb_ucs2},
|
||||
{ 131, "ucs2", "ucs2_romanian_ci", 2, 2, 0, mysqlnd_mbcharlen_ucs2, check_mb_ucs2},
|
||||
{ 132, "ucs2", "ucs2_slovenian_ci", 2, 2, 0, mysqlnd_mbcharlen_ucs2, check_mb_ucs2},
|
||||
{ 133, "ucs2", "ucs2_polish_ci", 2, 2, 0, mysqlnd_mbcharlen_ucs2, check_mb_ucs2},
|
||||
{ 134, "ucs2", "ucs2_estonian_ci", 2, 2, 0, mysqlnd_mbcharlen_ucs2, check_mb_ucs2},
|
||||
{ 135, "ucs2", "ucs2_spanish_ci", 2, 2, 0, mysqlnd_mbcharlen_ucs2, check_mb_ucs2},
|
||||
{ 136, "ucs2", "ucs2_swedish_ci", 2, 2, 0, mysqlnd_mbcharlen_ucs2, check_mb_ucs2},
|
||||
{ 137, "ucs2", "ucs2_turkish_ci", 2, 2, 0, mysqlnd_mbcharlen_ucs2, check_mb_ucs2},
|
||||
{ 138, "ucs2", "ucs2_czech_ci", 2, 2, 0, mysqlnd_mbcharlen_ucs2, check_mb_ucs2},
|
||||
{ 139, "ucs2", "ucs2_danish_ci", 2, 2, 0, mysqlnd_mbcharlen_ucs2, check_mb_ucs2},
|
||||
{ 140, "ucs2", "ucs2_lithunian_ci", 2, 2, 0, mysqlnd_mbcharlen_ucs2, check_mb_ucs2},
|
||||
{ 141, "ucs2", "ucs2_slovak_ci", 2, 2, 0, mysqlnd_mbcharlen_ucs2, check_mb_ucs2},
|
||||
{ 142, "ucs2", "ucs2_spanish2_ci", 2, 2, 0, mysqlnd_mbcharlen_ucs2, check_mb_ucs2},
|
||||
{ 143, "ucs2", "ucs2_roman_ci", 2, 2, 0, mysqlnd_mbcharlen_ucs2, check_mb_ucs2},
|
||||
{ 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_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}
|
||||
};
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_find_charset_nr */
|
||||
PHPAPI const MYSQLND_CHARSET * mysqlnd_find_charset_nr(uint charsetnr)
|
||||
{
|
||||
const MYSQLND_CHARSET * c = mysqlnd_charsets;
|
||||
|
||||
do {
|
||||
if (c->nr == charsetnr) {
|
||||
return c;
|
||||
}
|
||||
++c;
|
||||
} while (c[0].nr != 0);
|
||||
return NULL;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_find_charset_name */
|
||||
PHPAPI const MYSQLND_CHARSET * mysqlnd_find_charset_name(const char * const name)
|
||||
{
|
||||
const MYSQLND_CHARSET *c = mysqlnd_charsets;
|
||||
|
||||
do {
|
||||
if (!strcasecmp(c->name, name)) {
|
||||
return c;
|
||||
}
|
||||
++c;
|
||||
} while (c[0].nr != 0);
|
||||
return NULL;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_cset_escape_quotes */
|
||||
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 && (len = cset->mb_valid(escapestr, end))) {
|
||||
|
||||
/* check possible overflow */
|
||||
if ((newstr + len) > newstr_e) {
|
||||
escape_overflow = TRUE;
|
||||
break;
|
||||
}
|
||||
/* copy mb char without escaping it */
|
||||
while (len--) {
|
||||
*newstr++ = *escapestr++;
|
||||
}
|
||||
escapestr--;
|
||||
continue;
|
||||
}
|
||||
if (*escapestr == '\'') {
|
||||
if (newstr + 2 > newstr_e) {
|
||||
escape_overflow = TRUE;
|
||||
break;
|
||||
}
|
||||
*newstr++ = '\'';
|
||||
*newstr++ = '\'';
|
||||
} else {
|
||||
if (newstr + 1 > newstr_e) {
|
||||
escape_overflow = TRUE;
|
||||
break;
|
||||
}
|
||||
*newstr++ = *escapestr;
|
||||
}
|
||||
}
|
||||
*newstr = '\0';
|
||||
|
||||
if (escape_overflow) {
|
||||
DBG_RETURN((ulong)~0);
|
||||
}
|
||||
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 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 && (len = cset->mb_valid(escapestr, end))) {
|
||||
/* check possible overflow */
|
||||
if ((newstr + len) > newstr_e) {
|
||||
escape_overflow = TRUE;
|
||||
break;
|
||||
}
|
||||
/* copy mb char without escaping it */
|
||||
while (len--) {
|
||||
*newstr++ = *escapestr++;
|
||||
}
|
||||
escapestr--;
|
||||
continue;
|
||||
}
|
||||
if (cset->char_maxlen > 1 && cset->mb_charlen(*escapestr) > 1) {
|
||||
esc = *escapestr;
|
||||
} else {
|
||||
switch (*escapestr) {
|
||||
case 0:
|
||||
esc = '0';
|
||||
break;
|
||||
case '\n':
|
||||
esc = 'n';
|
||||
break;
|
||||
case '\r':
|
||||
esc = 'r';
|
||||
break;
|
||||
case '\\':
|
||||
case '\'':
|
||||
case '"':
|
||||
esc = *escapestr;
|
||||
break;
|
||||
case '\032':
|
||||
esc = 'Z';
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (esc) {
|
||||
if (newstr + 2 > newstr_e) {
|
||||
escape_overflow = TRUE;
|
||||
break;
|
||||
}
|
||||
/* copy escaped character */
|
||||
*newstr++ = '\\';
|
||||
*newstr++ = esc;
|
||||
} else {
|
||||
if (newstr + 1 > newstr_e) {
|
||||
escape_overflow = TRUE;
|
||||
break;
|
||||
}
|
||||
/* copy non escaped character */
|
||||
*newstr++ = *escapestr;
|
||||
}
|
||||
}
|
||||
*newstr = '\0';
|
||||
|
||||
if (escape_overflow) {
|
||||
DBG_RETURN((ulong)~0);
|
||||
}
|
||||
DBG_RETURN((ulong)(newstr - newstr_s));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
35
ext/mysqlnd/mysqlnd_charset.h
Normal file
35
ext/mysqlnd/mysqlnd_charset.h
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| PHP Version 6 |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1997-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> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
PHPAPI ulong mysqlnd_cset_escape_quotes(const MYSQLND_CHARSET * const charset, char *newstr,
|
||||
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 TSRMLS_DC);
|
||||
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
1345
ext/mysqlnd/mysqlnd_debug.c
Normal file
1345
ext/mysqlnd/mysqlnd_debug.c
Normal file
File diff suppressed because it is too large
Load Diff
145
ext/mysqlnd/mysqlnd_debug.h
Normal file
145
ext/mysqlnd/mysqlnd_debug.h
Normal file
@ -0,0 +1,145 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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, uint 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
|
||||
static inline void DBG_INF(char *msg) {}
|
||||
static inline void DBG_ERR(char *msg) {}
|
||||
static inline void DBG_INF_FMT(char *format, ...) {}
|
||||
static inline void DBG_ERR_FMT(char *format, ...) {}
|
||||
static inline void DBG_ENTER(char *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
|
||||
*/
|
367
ext/mysqlnd/mysqlnd_enum_n_def.h
Normal file
367
ext/mysqlnd/mysqlnd_enum_n_def.h
Normal file
@ -0,0 +1,367 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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_ENUM_N_DEF_H
|
||||
#define MYSQLND_ENUM_N_DEF_H
|
||||
|
||||
|
||||
#define MYSQLND_ERRMSG_SIZE 512
|
||||
#define MYSQLND_SQLSTATE_LENGTH 5
|
||||
#define MYSQLND_SQLSTATE_NULL "00000"
|
||||
|
||||
#define MYSQLND_SERVER_QUERY_NO_GOOD_INDEX_USED 16
|
||||
#define MYSQLND_SERVER_QUERY_NO_INDEX_USED 32
|
||||
|
||||
#define MYSQLND_NO_DATA 100
|
||||
#define MYSQLND_DATA_TRUNCATED 101
|
||||
|
||||
#define SHA1_MAX_LENGTH 20
|
||||
#define SCRAMBLE_LENGTH 20
|
||||
#define SCRAMBLE_LENGTH_323 8
|
||||
|
||||
#define CLIENT_LONG_PASSWORD 1 /* new more secure passwords */
|
||||
#define CLIENT_FOUND_ROWS 2 /* Found instead of affected rows */
|
||||
#define CLIENT_LONG_FLAG 4 /* Get all column flags */
|
||||
#define CLIENT_CONNECT_WITH_DB 8 /* One can specify db on connect */
|
||||
#define CLIENT_NO_SCHEMA 16 /* Don't allow database.table.column */
|
||||
#define CLIENT_COMPRESS 32 /* Can use compression protocol */
|
||||
#define CLIENT_ODBC 64 /* Odbc client */
|
||||
#define CLIENT_LOCAL_FILES 128 /* Can use LOAD DATA LOCAL */
|
||||
#define CLIENT_IGNORE_SPACE 256 /* Ignore spaces before '(' */
|
||||
#define CLIENT_PROTOCOL_41 512 /* New 4.1 protocol */
|
||||
#define CLIENT_INTERACTIVE 1024 /* This is an interactive client */
|
||||
#define CLIENT_SSL 2048 /* Switch to SSL after handshake */
|
||||
#define CLIENT_IGNORE_SIGPIPE 4096 /* IGNORE sigpipes */
|
||||
#define CLIENT_TRANSACTIONS 8192 /* Client knows about transactions */
|
||||
#define CLIENT_RESERVED 16384 /* Old flag for 4.1 protocol */
|
||||
#define CLIENT_SECURE_CONNECTION 32768 /* New 4.1 authentication */
|
||||
#define CLIENT_MULTI_STATEMENTS (1UL << 16) /* Enable/disable multi-stmt support */
|
||||
#define CLIENT_MULTI_RESULTS (1UL << 17) /* Enable/disable multi-results */
|
||||
|
||||
typedef enum mysqlnd_extension
|
||||
{
|
||||
MYSQLND_MYSQL = 0,
|
||||
MYSQLND_MYSQLI,
|
||||
} enum_mysqlnd_extension;
|
||||
|
||||
enum
|
||||
{
|
||||
MYSQLND_FETCH_ASSOC = 1,
|
||||
MYSQLND_FETCH_NUM = 2,
|
||||
MYSQLND_FETCH_BOTH = 1|2,
|
||||
};
|
||||
|
||||
/* Follow libmysql convention */
|
||||
typedef enum func_status
|
||||
{
|
||||
PASS = 0,
|
||||
FAIL = 1,
|
||||
} enum_func_status;
|
||||
|
||||
typedef enum mysqlnd_query_type
|
||||
{
|
||||
QUERY_UPSERT,
|
||||
QUERY_SELECT,
|
||||
QUERY_LOAD_LOCAL
|
||||
} enum_mysqlnd_query_type;
|
||||
|
||||
typedef enum mysqlnd_res_type
|
||||
{
|
||||
MYSQLND_RES_NORMAL = 1,
|
||||
MYSQLND_RES_PS_BUF,
|
||||
MYSQLND_RES_PS_UNBUF
|
||||
} enum_mysqlnd_res_type;
|
||||
|
||||
typedef enum mysqlnd_option
|
||||
{
|
||||
MYSQL_OPT_CONNECT_TIMEOUT,
|
||||
MYSQL_OPT_COMPRESS,
|
||||
MYSQL_OPT_NAMED_PIPE,
|
||||
MYSQL_INIT_COMMAND,
|
||||
MYSQL_READ_DEFAULT_FILE,
|
||||
MYSQL_READ_DEFAULT_GROUP,
|
||||
MYSQL_SET_CHARSET_DIR,
|
||||
MYSQL_SET_CHARSET_NAME,
|
||||
MYSQL_OPT_LOCAL_INFILE,
|
||||
MYSQL_OPT_PROTOCOL,
|
||||
MYSQL_SHARED_MEMORY_BASE_NAME,
|
||||
MYSQL_OPT_READ_TIMEOUT,
|
||||
MYSQL_OPT_WRITE_TIMEOUT,
|
||||
MYSQL_OPT_USE_RESULT,
|
||||
MYSQL_OPT_USE_REMOTE_CONNECTION,
|
||||
MYSQL_OPT_USE_EMBEDDED_CONNECTION,
|
||||
MYSQL_OPT_GUESS_CONNECTION,
|
||||
MYSQL_SET_CLIENT_IP,
|
||||
MYSQL_SECURE_AUTH,
|
||||
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;
|
||||
|
||||
|
||||
typedef enum mysqlnd_field_types
|
||||
{
|
||||
MYSQL_TYPE_DECIMAL,
|
||||
MYSQL_TYPE_TINY,
|
||||
MYSQL_TYPE_SHORT,
|
||||
MYSQL_TYPE_LONG,
|
||||
MYSQL_TYPE_FLOAT,
|
||||
MYSQL_TYPE_DOUBLE,
|
||||
MYSQL_TYPE_NULL,
|
||||
MYSQL_TYPE_TIMESTAMP,
|
||||
MYSQL_TYPE_LONGLONG,
|
||||
MYSQL_TYPE_INT24,
|
||||
MYSQL_TYPE_DATE,
|
||||
MYSQL_TYPE_TIME,
|
||||
MYSQL_TYPE_DATETIME,
|
||||
MYSQL_TYPE_YEAR,
|
||||
MYSQL_TYPE_NEWDATE,
|
||||
MYSQL_TYPE_VARCHAR,
|
||||
MYSQL_TYPE_BIT,
|
||||
MYSQL_TYPE_NEWDECIMAL=246,
|
||||
MYSQL_TYPE_ENUM=247,
|
||||
MYSQL_TYPE_SET=248,
|
||||
MYSQL_TYPE_TINY_BLOB=249,
|
||||
MYSQL_TYPE_MEDIUM_BLOB=250,
|
||||
MYSQL_TYPE_LONG_BLOB=251,
|
||||
MYSQL_TYPE_BLOB=252,
|
||||
MYSQL_TYPE_VAR_STRING=253,
|
||||
MYSQL_TYPE_STRING=254,
|
||||
MYSQL_TYPE_GEOMETRY=255
|
||||
} enum_mysqlnd_field_types;
|
||||
|
||||
/* Please update this if there is a new type after MYSQL_TYPE_GEOMETRY */
|
||||
#define MYSQL_TYPE_LAST MYSQL_TYPE_GEOMETRY
|
||||
|
||||
|
||||
typedef enum mysqlnd_server_option
|
||||
{
|
||||
MYSQL_OPTION_MULTI_STATEMENTS_ON,
|
||||
MYSQL_OPTION_MULTI_STATEMENTS_OFF
|
||||
} enum_mysqlnd_server_option;
|
||||
|
||||
|
||||
#define FIELD_TYPE_DECIMAL MYSQL_TYPE_DECIMAL
|
||||
#define FIELD_TYPE_NEWDECIMAL MYSQL_TYPE_NEWDECIMAL
|
||||
#define FIELD_TYPE_TINY MYSQL_TYPE_TINY
|
||||
#define FIELD_TYPE_SHORT MYSQL_TYPE_SHORT
|
||||
#define FIELD_TYPE_LONG MYSQL_TYPE_LONG
|
||||
#define FIELD_TYPE_FLOAT MYSQL_TYPE_FLOAT
|
||||
#define FIELD_TYPE_DOUBLE MYSQL_TYPE_DOUBLE
|
||||
#define FIELD_TYPE_NULL MYSQL_TYPE_NULL
|
||||
#define FIELD_TYPE_TIMESTAMP MYSQL_TYPE_TIMESTAMP
|
||||
#define FIELD_TYPE_LONGLONG MYSQL_TYPE_LONGLONG
|
||||
#define FIELD_TYPE_INT24 MYSQL_TYPE_INT24
|
||||
#define FIELD_TYPE_DATE MYSQL_TYPE_DATE
|
||||
#define FIELD_TYPE_TIME MYSQL_TYPE_TIME
|
||||
#define FIELD_TYPE_DATETIME MYSQL_TYPE_DATETIME
|
||||
#define FIELD_TYPE_YEAR MYSQL_TYPE_YEAR
|
||||
#define FIELD_TYPE_NEWDATE MYSQL_TYPE_NEWDATE
|
||||
#define FIELD_TYPE_ENUM MYSQL_TYPE_ENUM
|
||||
#define FIELD_TYPE_SET MYSQL_TYPE_SET
|
||||
#define FIELD_TYPE_TINY_BLOB MYSQL_TYPE_TINY_BLOB
|
||||
#define FIELD_TYPE_MEDIUM_BLOB MYSQL_TYPE_MEDIUM_BLOB
|
||||
#define FIELD_TYPE_LONG_BLOB MYSQL_TYPE_LONG_BLOB
|
||||
#define FIELD_TYPE_BLOB MYSQL_TYPE_BLOB
|
||||
#define FIELD_TYPE_VAR_STRING MYSQL_TYPE_VAR_STRING
|
||||
#define FIELD_TYPE_STRING MYSQL_TYPE_STRING
|
||||
#define FIELD_TYPE_CHAR MYSQL_TYPE_TINY
|
||||
#define FIELD_TYPE_INTERVAL MYSQL_TYPE_ENUM
|
||||
#define FIELD_TYPE_GEOMETRY MYSQL_TYPE_GEOMETRY
|
||||
#define FIELD_TYPE_BIT MYSQL_TYPE_BIT
|
||||
|
||||
#define NOT_NULL_FLAG 1
|
||||
#define PRI_KEY_FLAG 2
|
||||
#define UNIQUE_KEY_FLAG 4
|
||||
#define MULTIPLE_KEY_FLAG 8
|
||||
#define BLOB_FLAG 16
|
||||
#define UNSIGNED_FLAG 32
|
||||
#define ZEROFILL_FLAG 64
|
||||
#define BINARY_FLAG 128
|
||||
#define ENUM_FLAG 256
|
||||
#define AUTO_INCREMENT_FLAG 512
|
||||
#define TIMESTAMP_FLAG 1024
|
||||
#define SET_FLAG 2048
|
||||
#define NO_DEFAULT_VALUE_FLAG 4096
|
||||
#define PART_KEY_FLAG 16384
|
||||
#define GROUP_FLAG 32768
|
||||
#define NUM_FLAG 32768
|
||||
|
||||
#define IS_PRI_KEY(n) ((n) & PRI_KEY_FLAG)
|
||||
#define IS_NOT_NULL(n) ((n) & NOT_NULL_FLAG)
|
||||
#define IS_BLOB(n) ((n) & BLOB_FLAG)
|
||||
#define IS_NUM(t) ((t) <= FIELD_TYPE_INT24 || (t) == FIELD_TYPE_YEAR || (t) == FIELD_TYPE_NEWDECIMAL)
|
||||
|
||||
|
||||
/* 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 */
|
||||
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
121
ext/mysqlnd/mysqlnd_libmysql_compat.h
Normal file
121
ext/mysqlnd/mysqlnd_libmysql_compat.h
Normal file
@ -0,0 +1,121 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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> |
|
||||
+----------------------------------------------------------------------+
|
||||
|
||||
*/
|
||||
|
||||
#ifndef MYSQLND_LIBMYSQL_COMPAT_H
|
||||
#define MYSQLND_LIBMYSQL_COMPAT_H
|
||||
|
||||
/* Global types and definitions*/
|
||||
#define MYSQL_NO_DATA MYSQLND_NO_DATA
|
||||
#define MYSQL_DATA_TRUNCATED MYSQLND_DATA_TRUNCATED
|
||||
#define MYSQL_STMT MYSQLND_STMT
|
||||
#define MYSQL_FIELD MYSQLND_FIELD
|
||||
#define MYSQL_RES MYSQLND_RES
|
||||
#define MYSQL_ROW MYSQLND_ROW
|
||||
#define MYSQL MYSQLND
|
||||
#define my_bool zend_bool
|
||||
#define my_ulonglong mynd_ulonglong
|
||||
|
||||
#define MYSQL_VERSION_ID MYSQLND_VERSION_ID
|
||||
#define MYSQL_SERVER_VERSION MYSQLND_VERSION
|
||||
#define MYSQL_ERRMSG_SIZE MYSQLND_ERRMSG_SIZE
|
||||
#define SQLSTATE_LENGTH MYSQLND_SQLSTATE_LENGTH
|
||||
|
||||
#define SERVER_QUERY_NO_GOOD_INDEX_USED MYSQLND_SERVER_QUERY_NO_GOOD_INDEX_USED
|
||||
#define SERVER_QUERY_NO_INDEX_USED MYSQLND_SERVER_QUERY_NO_INDEX_USED
|
||||
|
||||
|
||||
/* functions */
|
||||
#define mysql_affected_rows(r) mysqlnd_affected_rows((r))
|
||||
#define mysql_autocommit(r,m) mysqlnd_autocommit((r),(m))
|
||||
#define mysql_change_user(r,a,b,c) mysqlnd_change_user((r), (a), (b), (c))
|
||||
#define mysql_character_set_name(c) mysqlnd_character_set_name((c))
|
||||
#define mysql_close(r) mysqlnd_close((r), MYSQLND_CLOSE_EXPLICIT)
|
||||
#define mysql_commit(r) mysqlnd_commit((r))
|
||||
#define mysql_data_seek(r,o) mysqlnd_data_seek((r),(o))
|
||||
#define mysql_debug(x) mysqlnd_debug((x))
|
||||
#define mysql_dump_debug_info(r) mysqlnd_dump_debug_info((r))
|
||||
#define mysql_errno(r) mysqlnd_errno((r))
|
||||
#define mysql_error(r) mysqlnd_error((r))
|
||||
#define mysql_escape_string(a,b,c) mysqlnd_escape_string((a), (b), (c))
|
||||
#define mysql_fetch_field(r) mysqlnd_fetch_field((r))
|
||||
#define mysql_fetch_field_direct(r,o) mysqlnd_fetch_field_direct((r), (o))
|
||||
#define mysql_fetch_lengths(r) mysqlnd_fetch_lengths((r))
|
||||
#define mysql_fetch_row(r) mysqlnd_fetch_row((r))
|
||||
#define mysql_field_count(r) mysqlnd_field_count((r))
|
||||
#define mysql_field_seek(r,o) mysqlnd_field_seek((r), (o))
|
||||
#define mysql_field_tell(r) mysqlnd_field_tell((r))
|
||||
#define mysql_init(a) mysqlnd_init((a))
|
||||
#define mysql_insert_id(r) mysqlnd_insert_id((r))
|
||||
#define mysql_kill(r,n) mysqlnd_kill((r), (n))
|
||||
#define mysql_list_dbs(c, wild) mysqlnd_list_dbs((c), (wild))
|
||||
#define mysql_list_fields(c, tab, wild) mysqlnd_list_fields((c), (tab), (wild))
|
||||
#define mysql_list_processes(c) mysqlnd_list_processes((c))
|
||||
#define mysql_list_tables(c, wild) mysqlnd_list_tables((c), (wild))
|
||||
#define mysql_more_results(r) mysqlnd_more_results((r))
|
||||
#define mysql_next_result(r) mysqlnd_next_result((r))
|
||||
#define mysql_num_fields(r) mysqlnd_num_fields((r))
|
||||
#define mysql_num_rows(r) mysqlnd_num_rows((r))
|
||||
#define mysql_ping(r) mysqlnd_ping((r))
|
||||
#define mysql_real_escape_string(r,a,b,c) mysqlnd_real_escape_string((r), (a), (b), (c))
|
||||
#define mysql_real_query(r,a,b) mysqlnd_query((r), (a), (b))
|
||||
#define mysql_rollback(r) mysqlnd_rollback((r))
|
||||
#define mysql_select_db(r,a) mysqlnd_select_db((r), (a) ,strlen((a)))
|
||||
#define mysql_set_server_option(r,o) mysqlnd_set_server_option((r), (o))
|
||||
#define mysql_set_character_set(r,a) mysqlnd_set_character_set((r), (a))
|
||||
#define mysql_sqlstate(r) mysqlnd_sqlstate((r))
|
||||
#define mysql_stmt_affected_rows(s) mysqlnd_stmt_affected_rows((s))
|
||||
#define mysql_stmt_field_count(s) mysqlnd_stmt_field_count((s))
|
||||
#define mysql_stmt_param_count(s) mysqlnd_stmt_param_count((s))
|
||||
#define mysql_stmt_num_rows(s) mysqlnd_stmt_num_rows((s))
|
||||
#define mysql_stmt_insert_id(s) mysqlnd_stmt_insert_id((s))
|
||||
#define mysql_stmt_close(s) mysqlnd_stmt_close((s))
|
||||
#define mysql_stmt_errno(s) mysqlnd_stmt_errno((s))
|
||||
#define mysql_stmt_error(s) mysqlnd_stmt_error((s))
|
||||
#define mysql_stmt_sqlstate(s) mysqlnd_stmt_sqlstate((s))
|
||||
#define mysql_stmt_prepare(s,q,l) mysqlnd_stmt_prepare((s), (q), (l))
|
||||
#define mysql_stmt_execute(s) mysqlnd_stmt_execute((s))
|
||||
#define mysql_stmt_reset(s) mysqlnd_stmt_reset((s))
|
||||
#define mysql_stmt_store_result(s) mysqlnd_stmt_store_result((s))
|
||||
#define mysql_stmt_free_result(s) mysqlnd_stmt_free_result((s))
|
||||
#define mysql_stmt_data_seek(s,r) mysqlnd_stmt_data_seek((s), (r))
|
||||
#define mysql_stmt_send_long_data(s,p,d,l) mysqlnd_stmt_send_long_data((s), (p), (d), (l))
|
||||
#define mysql_stmt_attr_get(s,a,v) mysqlnd_stmt_attr_get((s), (a), (v))
|
||||
#define mysql_stmt_attr_set(s,a,v) mysqlnd_stmt_attr_set((s), (a), (v))
|
||||
#define mysql_stmt_param_metadata(s) mysqlnd_stmt_param_metadata((s))
|
||||
#define mysql_stmt_result_metadata(s) mysqlnd_stmt_result_metadata((s))
|
||||
#define mysql_thread_safe() mysqlnd_thread_safe()
|
||||
#define mysql_info(r) mysqlnd_info((r))
|
||||
#define mysql_options(r,a,b) mysqlnd_options((r), (a), (b))
|
||||
#define mysql_stmt_init(r) mysqlnd_stmt_init((r))
|
||||
#define mysql_free_result(r) mysqlnd_free_result((r), FALSE)
|
||||
#define mysql_store_result(r) mysqlnd_store_result((r))
|
||||
#define mysql_use_result(r) mysqlnd_use_result((r))
|
||||
#define mysql_thread_id(r) mysqlnd_thread_id((r))
|
||||
#define mysql_get_client_info() mysqlnd_get_client_info()
|
||||
#define mysql_get_client_version() mysqlnd_get_client_version()
|
||||
#define mysql_get_host_info(r) mysqlnd_get_host_info((r))
|
||||
#define mysql_get_proto_info(r) mysqlnd_get_proto_info((r))
|
||||
#define mysql_get_server_info(r) mysqlnd_get_server_info((r))
|
||||
#define mysql_get_server_version(r) mysqlnd_get_server_version((r))
|
||||
#define mysql_warning_count(r) mysqlnd_warning_count((r))
|
||||
#define mysql_eof(r) (((r)->unbuf && (r)->unbuf->eof_reached) || (r)->data)
|
||||
|
||||
#endif /* MYSQLND_LIBMYSQL_COMPAT_H */
|
263
ext/mysqlnd/mysqlnd_loaddata.c
Normal file
263
ext/mysqlnd/mysqlnd_loaddata.c
Normal file
@ -0,0 +1,263 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#include "php.h"
|
||||
#include "php_globals.h"
|
||||
#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,
|
||||
zend_bool silent, enum php_mysqlnd_server_command command
|
||||
TSRMLS_DC);
|
||||
|
||||
|
||||
#define ALLOC_CALLBACK_ARGS(a, b, c)\
|
||||
if (c) {\
|
||||
a = (zval ***)safe_emalloc(c, sizeof(zval **), 0);\
|
||||
for (i = b; i < c; i++) {\
|
||||
a[i] = mnd_emalloc(sizeof(zval *));\
|
||||
MAKE_STD_ZVAL(*a[i]);\
|
||||
}\
|
||||
}
|
||||
|
||||
#define FREE_CALLBACK_ARGS(a, b, c)\
|
||||
if (a) {\
|
||||
for (i=b; i < c; i++) {\
|
||||
zval_ptr_dtor(a[i]);\
|
||||
mnd_efree(a[i]);\
|
||||
}\
|
||||
mnd_efree(a);\
|
||||
}
|
||||
|
||||
/* {{{ mysqlnd_local_infile_init */
|
||||
static
|
||||
int mysqlnd_local_infile_init(void **ptr, char *filename, void **userdata TSRMLS_DC)
|
||||
{
|
||||
MYSQLND_INFILE_INFO *info;
|
||||
php_stream_context *context = NULL;
|
||||
|
||||
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;
|
||||
DBG_RETURN(1);
|
||||
}
|
||||
}
|
||||
|
||||
info->filename = filename;
|
||||
info->fd = php_stream_open_wrapper_ex((char *)filename, "r", 0, NULL, context);
|
||||
|
||||
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;
|
||||
DBG_RETURN(1);
|
||||
}
|
||||
|
||||
DBG_RETURN(0);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_local_infile_read */
|
||||
static
|
||||
int mysqlnd_local_infile_read(void *ptr, char *buf, uint buf_len TSRMLS_DC)
|
||||
{
|
||||
MYSQLND_INFILE_INFO *info = (MYSQLND_INFILE_INFO *)ptr;
|
||||
int count;
|
||||
|
||||
DBG_ENTER("mysqlnd_local_infile_read");
|
||||
|
||||
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);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_local_infile_error */
|
||||
static
|
||||
int mysqlnd_local_infile_error(void *ptr, char *error_buf, uint error_buf_len TSRMLS_DC)
|
||||
{
|
||||
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);
|
||||
DBG_INF_FMT("have info, %d", info->error_no);
|
||||
DBG_RETURN(info->error_no);
|
||||
}
|
||||
|
||||
strncpy(error_buf, "Unknown error", error_buf_len);
|
||||
DBG_INF_FMT("no info, %d", CR_UNKNOWN_ERROR);
|
||||
DBG_RETURN(CR_UNKNOWN_ERROR);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_local_infile_end */
|
||||
static
|
||||
void mysqlnd_local_infile_end(void *ptr TSRMLS_DC)
|
||||
{
|
||||
MYSQLND_INFILE_INFO *info = (MYSQLND_INFILE_INFO *)ptr;
|
||||
|
||||
if (info) {
|
||||
/* php_stream_close segfaults on NULL */
|
||||
if (info->fd) {
|
||||
php_stream_close(info->fd);
|
||||
info->fd = NULL;
|
||||
}
|
||||
mnd_efree(info);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_local_infile_default */
|
||||
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;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ mysqlnd_set_local_infile_handler */
|
||||
PHPAPI void mysqlnd_set_local_infile_handler(MYSQLND * const conn, const char * const funcname)
|
||||
{
|
||||
if (!conn->infile.callback) {
|
||||
MAKE_STD_ZVAL(conn->infile.callback);
|
||||
} else {
|
||||
zval_dtor(conn->infile.callback);
|
||||
}
|
||||
ZVAL_STRING(conn->infile.callback, (char*) funcname, 1);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
static const char *lost_conn = "Lost connection to MySQL server during LOAD DATA of local file";
|
||||
|
||||
|
||||
/* {{{ mysqlnd_handle_local_infile */
|
||||
enum_func_status
|
||||
mysqlnd_handle_local_infile(MYSQLND *conn, const char *filename, zend_bool *is_warning TSRMLS_DC)
|
||||
{
|
||||
char *buf;
|
||||
char empty_packet[MYSQLND_HEADER_SIZE];
|
||||
enum_func_status result = FAIL;
|
||||
uint buflen = 4096;
|
||||
void *info = NULL;
|
||||
int bufsize;
|
||||
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 */
|
||||
ret = mysqlnd_stream_write_w_header(conn, empty_packet, 0 TSRMLS_CC);
|
||||
*is_warning = TRUE;
|
||||
goto infile_error;
|
||||
}
|
||||
|
||||
infile = conn->infile;
|
||||
/* allocate buffer for reading data */
|
||||
buf = (char *)mnd_ecalloc(1, buflen);
|
||||
|
||||
*is_warning = FALSE;
|
||||
|
||||
/* init handler: allocate read buffer and open file */
|
||||
if (infile.local_infile_init(&info, (char *)filename, conn->infile.userdata TSRMLS_CC)) {
|
||||
*is_warning = TRUE;
|
||||
/* error occured */
|
||||
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);
|
||||
/* write empty packet to server */
|
||||
ret = mysqlnd_stream_write_w_header(conn, empty_packet, 0 TSRMLS_CC);
|
||||
goto infile_error;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
/* send empty packet for eof */
|
||||
if ((ret = mysqlnd_stream_write_w_header(conn, empty_packet, 0 TSRMLS_CC)) < 0) {
|
||||
SET_CLIENT_ERROR(conn->error_info, CR_SERVER_LOST, UNKNOWN_SQLSTATE, lost_conn);
|
||||
goto infile_error;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
goto infile_error;
|
||||
}
|
||||
|
||||
result = PASS;
|
||||
|
||||
infile_error:
|
||||
/* get response from server and update upsert values */
|
||||
if (FAIL == mysqlnd_simple_command_handle_response(conn, PROT_OK_PACKET, FALSE, COM_QUERY TSRMLS_CC)) {
|
||||
result = FAIL;
|
||||
goto infile_error;
|
||||
}
|
||||
|
||||
(*conn->infile.local_infile_end)(info TSRMLS_CC);
|
||||
mnd_efree(buf);
|
||||
DBG_INF_FMT("%s", result == PASS? "PASS":"FAIL");
|
||||
DBG_RETURN(result);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
565
ext/mysqlnd/mysqlnd_palloc.c
Normal file
565
ext/mysqlnd/mysqlnd_palloc.c
Normal file
@ -0,0 +1,565 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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$ */
|
||||
#include "php.h"
|
||||
#include "mysqlnd.h"
|
||||
#include "mysqlnd_priv.h"
|
||||
#include "mysqlnd_palloc.h"
|
||||
#include "mysqlnd_debug.h"
|
||||
|
||||
/* 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
|
||||
#define LOCK_PCACHE(cache) tsrm_mutex_lock((cache)->LOCK_access)
|
||||
#define UNLOCK_PCACHE(cache) tsrm_mutex_unlock((cache)->LOCK_access)
|
||||
#else
|
||||
#define LOCK_PCACHE(cache)
|
||||
#define UNLOCK_PCACHE(cache)
|
||||
#endif
|
||||
|
||||
|
||||
#if PHP_MAJOR_VERSION < 6
|
||||
#define IS_UNICODE_DISABLED (1)
|
||||
#else
|
||||
#define IS_UNICODE_DISABLED (!UG(unicode))
|
||||
#endif
|
||||
|
||||
|
||||
/* {{{ _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;
|
||||
|
||||
DBG_ENTER("_mysqlnd_palloc_init_cache");
|
||||
DBG_INF_FMT("cache=%p size=%u", ret, cache_size);
|
||||
|
||||
#ifdef ZTS
|
||||
ret->LOCK_access = tsrm_mutex_alloc();
|
||||
#endif
|
||||
|
||||
ret->max_items = cache_size;
|
||||
ret->free_items = cache_size;
|
||||
ret->references = 1;
|
||||
|
||||
/* 1. First initialize the free list part of the structure */
|
||||
/* One more for empty position of last_added - always 0x0, bounds checking */
|
||||
ret->free_list.ptr_line = calloc(ret->max_items + 1, sizeof(mysqlnd_zval *));
|
||||
ret->free_list.last_added = ret->free_list.ptr_line + ret->max_items;
|
||||
|
||||
/* 3. Allocate and initialize our zvals and initialize the free list */
|
||||
ret->block = calloc(ret->max_items, sizeof(mysqlnd_zval));
|
||||
ret->last_in_block = &(ret->block[ret->max_items]);
|
||||
for (i = 0; i < ret->max_items; i++) {
|
||||
/* 1. Initialize */
|
||||
INIT_PZVAL(&(ret->block[i].zv));
|
||||
ZVAL_NULL(&(ret->block[i].zv));
|
||||
/* Assure it will never be freed before MSHUTDOWN */
|
||||
ZVAL_ADDREF(&(ret->block[i].zv));
|
||||
/* 2. Add to the free list */
|
||||
*(--ret->free_list.last_added) = &(ret->block[i]);
|
||||
}
|
||||
|
||||
DBG_RETURN(ret);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_palloc_get_cache_reference */
|
||||
MYSQLND_ZVAL_PCACHE* mysqlnd_palloc_get_cache_reference(MYSQLND_ZVAL_PCACHE * const cache)
|
||||
{
|
||||
if (cache) {
|
||||
LOCK_PCACHE(cache);
|
||||
cache->references++;
|
||||
UNLOCK_PCACHE(cache);
|
||||
}
|
||||
return cache;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_palloc_free_cache */
|
||||
/*
|
||||
As this call will happen on MSHUTDOWN(), then we don't need to copy the zvals with
|
||||
copy_ctor but scrap what they point to with zval_dtor() and then just free our
|
||||
pre-allocated block. Precondition is that we ZVAL_NULL() the zvals when we put them
|
||||
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 TSRMLS_DC)
|
||||
{
|
||||
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 */
|
||||
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 TSRMLS_DC)
|
||||
{
|
||||
MYSQLND_THD_ZVAL_PCACHE *ret = calloc(1, sizeof(MYSQLND_THD_ZVAL_PCACHE));
|
||||
DBG_ENTER("_mysqlnd_palloc_init_thd_cache");
|
||||
DBG_INF_FMT("ret = %p", ret);
|
||||
|
||||
ret->parent = mysqlnd_palloc_get_cache_reference(cache);
|
||||
|
||||
#ifdef ZTS
|
||||
ret->thread_id = tsrm_thread_id();
|
||||
#endif
|
||||
|
||||
ret->references = 1;
|
||||
|
||||
/* 1. Initialize the GC list */
|
||||
ret->gc_list.ptr_line = calloc(cache->max_items, sizeof(mysqlnd_zval *));
|
||||
/* Backward and forward looping is possible */
|
||||
ret->gc_list.last_added = ret->gc_list.ptr_line;
|
||||
|
||||
DBG_RETURN(ret);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_palloc_get_thd_cache_reference */
|
||||
MYSQLND_THD_ZVAL_PCACHE* mysqlnd_palloc_get_thd_cache_reference(MYSQLND_THD_ZVAL_PCACHE * const cache)
|
||||
{
|
||||
if (cache) {
|
||||
++cache->references;
|
||||
mysqlnd_palloc_get_cache_reference(cache->parent);
|
||||
}
|
||||
return cache;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_palloc_free_cache */
|
||||
/*
|
||||
As this call will happen on MSHUTDOWN(), then we don't need to copy the zvals with
|
||||
copy_ctor but scrap what they point to with zval_dtor() and then just free our
|
||||
pre-allocated block. Precondition is that we ZVAL_NULL() the zvals when we put them
|
||||
to the free list after usage. We ZVAL_NULL() them when we allocate them in the
|
||||
constructor of the cache.
|
||||
*/
|
||||
static
|
||||
void mysqlnd_palloc_free_thd_cache(MYSQLND_THD_ZVAL_PCACHE *cache TSRMLS_DC)
|
||||
{
|
||||
DBG_ENTER("mysqlnd_palloc_free_thd_cache");
|
||||
DBG_INF_FMT("cache=%p", 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 TSRMLS_DC)
|
||||
{
|
||||
DBG_ENTER("_mysqlnd_palloc_free_thd_cache_reference");
|
||||
if (*cache) {
|
||||
DBG_INF_FMT("cache=%p refs=%d", *cache, (*cache)->references);
|
||||
--(*cache)->parent->references;
|
||||
|
||||
if (--(*cache)->references == 0) {
|
||||
mysqlnd_palloc_free_thd_cache(*cache TSRMLS_CC);
|
||||
}
|
||||
*cache = NULL;
|
||||
}
|
||||
DBG_VOID_RETURN;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/*
|
||||
The cache line is a big contiguous array of zval pointers.
|
||||
Because the CPU cache will cache starting from an address, and not
|
||||
before it, then we have to organize our structure according to this.
|
||||
Thus, if 'last_added' is valid pointer (not NULL) then last_added is
|
||||
increased. When zval is cached, if there is room, last_added is decreased
|
||||
and then the zval pointer will be assigned to it. This means that some
|
||||
positions may become hot points and stay in the cache.
|
||||
Imagine we have 5 pointers in a line
|
||||
1. last_added = list_item->ptr_line + cache->max_items;
|
||||
2. get_zval -> *last_added = NULL. Use MAKE_STD_ZVAL
|
||||
3. get_zval -> *last_added = NULL. Use MAKE_STD_ZVAL
|
||||
4. get_zval -> *last_added = NULL. Use MAKE_STD_ZVAL
|
||||
0x0
|
||||
0x0
|
||||
0x0
|
||||
0x0
|
||||
0x0
|
||||
---
|
||||
empty_position, always 0x0 <-- last_added
|
||||
|
||||
5. free_zval -> if (free_items++ != max_items) {// we can add more
|
||||
*(--last_added) = zval_ptr;
|
||||
}
|
||||
(memory addresses increase downwards)
|
||||
0x0
|
||||
0x0
|
||||
0x0
|
||||
0x0
|
||||
0xA <-- last_added
|
||||
---
|
||||
0x0
|
||||
|
||||
6. free_zval -> if (free_items++ != max_items) {// we can add more
|
||||
*(--last_added) = zval_ptr;
|
||||
}
|
||||
0x0
|
||||
0x0
|
||||
0x0
|
||||
0xB <-- last_added
|
||||
0xA
|
||||
---
|
||||
0x0
|
||||
|
||||
7. free_zval -> if (free_items++ != max_items) {// we can add more
|
||||
*(--last_added) = zval_ptr;
|
||||
}
|
||||
0x0
|
||||
0x0
|
||||
0xC <-- last_added
|
||||
0xB
|
||||
0xA
|
||||
---
|
||||
0x0
|
||||
|
||||
8. get_zval -> *last_added != NULL. -> p = *last_added; *last_added++ = NULL;
|
||||
0x0
|
||||
0x0
|
||||
0x0
|
||||
0xB <-- last_added
|
||||
0xA
|
||||
---
|
||||
0x0
|
||||
|
||||
9. get_zval -> *last_added != NULL. -> p = *last_added; *last_added++ = NULL;
|
||||
0x0
|
||||
0x0
|
||||
0x0
|
||||
0x0
|
||||
0xA <-- last_added
|
||||
---
|
||||
0x0
|
||||
|
||||
10. get_zval -> *last_added != NULL. -> p = *last_added; *last_added++ = NULL;
|
||||
0x0
|
||||
0x0
|
||||
0x0
|
||||
0x0
|
||||
0x0
|
||||
---
|
||||
0x0 <-- last_added
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/* {{{ mysqlnd_palloc_get_zval */
|
||||
void *mysqlnd_palloc_get_zval(MYSQLND_THD_ZVAL_PCACHE * const thd_cache, zend_bool *allocated TSRMLS_DC)
|
||||
{
|
||||
void *ret = NULL;
|
||||
|
||||
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);
|
||||
|
||||
if (thd_cache) {
|
||||
MYSQLND_ZVAL_PCACHE *cache = thd_cache->parent;
|
||||
LOCK_PCACHE(cache);
|
||||
|
||||
if ((ret = *cache->free_list.last_added)) {
|
||||
*cache->free_list.last_added++ = NULL;
|
||||
*allocated = FALSE;
|
||||
#ifdef ZTS
|
||||
((mysqlnd_zval *) ret)->thread_id = thd_cache->thread_id;
|
||||
#endif
|
||||
--cache->free_items;
|
||||
++cache->get_hits;
|
||||
} else {
|
||||
++cache->get_misses;
|
||||
}
|
||||
UNLOCK_PCACHE(cache);
|
||||
}
|
||||
if (!ret) {
|
||||
/*
|
||||
We allocate a bit more. The user of this function will use it, but at
|
||||
end it will use only the zval part. Because the zval part is first then
|
||||
when freeing the zval part the whole allocated block will be cleaned, not
|
||||
only the zval part (by the Engine when destructing the zval).
|
||||
*/
|
||||
ALLOC_ZVAL(ret);
|
||||
INIT_PZVAL((zval *) ret);
|
||||
*allocated = TRUE;
|
||||
} else {
|
||||
/* This will set the refcount to 1, increase it, to keep the variable */
|
||||
INIT_PZVAL(&((mysqlnd_zval *) ret)->zv);
|
||||
ZVAL_ADDREF(&(((mysqlnd_zval *)ret)->zv));
|
||||
}
|
||||
|
||||
DBG_INF_FMT("allocated=%d ret=%p", *allocated, ret);
|
||||
DBG_RETURN(ret);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_palloc_zval_ptr_dtor */
|
||||
void mysqlnd_palloc_zval_ptr_dtor(zval **zv, MYSQLND_THD_ZVAL_PCACHE * const thd_cache,
|
||||
enum_mysqlnd_res_type type, zend_bool *copy_ctor_called TSRMLS_DC)
|
||||
{
|
||||
MYSQLND_ZVAL_PCACHE *cache;
|
||||
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, 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 ||
|
||||
(char *)*zv > (char *)thd_cache->parent->last_in_block)) {
|
||||
/*
|
||||
This zval is not from the cache block.
|
||||
Thus the refcount is -1 than of a zval from the cache,
|
||||
because the zvals from the cache are owned by it.
|
||||
*/
|
||||
if (type == MYSQLND_RES_PS_BUF || type == MYSQLND_RES_PS_UNBUF) {
|
||||
; /* do nothing, zval_ptr_dtor will do the job*/
|
||||
} else if (ZVAL_REFCOUNT(*zv) > 1) {
|
||||
/*
|
||||
Not a prepared statement, then we have to
|
||||
call copy_ctor and then zval_ptr_dtor()
|
||||
|
||||
In Unicode mode the destruction of the zvals should not call
|
||||
zval_copy_ctor() because then we will leak.
|
||||
I suppose we can use UG(unicode) in mysqlnd.c when freeing a result set
|
||||
to check if we need to call copy_ctor().
|
||||
|
||||
If the type is IS_UNICODE, which can happen with PHP6, then we don't
|
||||
need to copy_ctor, as the data doesn't point to our internal buffers.
|
||||
If it's string (in PHP5 always) and in PHP6 if data is binary, then
|
||||
it still points to internal buffers and has to be copied.
|
||||
*/
|
||||
if (Z_TYPE_PP(zv) == IS_STRING) {
|
||||
zval_copy_ctor(*zv);
|
||||
}
|
||||
*copy_ctor_called = TRUE;
|
||||
} else {
|
||||
if (Z_TYPE_PP(zv) == IS_STRING) {
|
||||
ZVAL_NULL(*zv);
|
||||
}
|
||||
}
|
||||
zval_ptr_dtor(zv);
|
||||
DBG_VOID_RETURN;
|
||||
}
|
||||
|
||||
/* The zval is from our cache */
|
||||
/* refcount is always > 1, because we call ZVAL_ADDREF(). Thus test refcount > 2 */
|
||||
if (ZVAL_REFCOUNT(*zv) > 2) {
|
||||
/*
|
||||
Because the zval is first element in mysqlnd_zval structure, then we can
|
||||
do upcasting from zval to mysqlnd_zval here. Because we know that this
|
||||
zval is part of our pre-allocated block.
|
||||
|
||||
Now check whether this zval points to ZE allocated memory or to our
|
||||
buffers. If it points to the internal buffers, call copy_ctor()
|
||||
which will do estrndup for strings. And nothing for null, int, double.
|
||||
|
||||
This branch will be skipped for PS, because there is no need to copy
|
||||
what is pointed by them, as they don't point to the internal buffers.
|
||||
*/
|
||||
if (((mysqlnd_zval *)*zv)->point_type == MYSQLND_POINTS_INT_BUFFER) {
|
||||
zval_copy_ctor(*zv);
|
||||
*copy_ctor_called = TRUE;
|
||||
((mysqlnd_zval *)*zv)->point_type = MYSQLND_POINTS_EXT_BUFFER;
|
||||
}
|
||||
/*
|
||||
This will decrease the counter of the user-level (mysqlnd). When the engine
|
||||
layer (the script) has finished working this this zval, when the variable is
|
||||
no more used, out of scope whatever, then it will try zval_ptr_dtor() but
|
||||
and the refcount will reach 1 and the engine won't try to destruct the
|
||||
memory allocated by us.
|
||||
*/
|
||||
zval_ptr_dtor(zv);
|
||||
|
||||
/*
|
||||
Unfortunately, we can't return this variable to the free_list
|
||||
because it's still used. And this cleaning up will happen at request
|
||||
shutdown :(.
|
||||
*/
|
||||
LOCK_PCACHE(cache);
|
||||
++cache->put_misses;
|
||||
*(thd_cache->gc_list.last_added++) = (mysqlnd_zval *)*zv;
|
||||
UNLOCK_PCACHE(cache);
|
||||
} else {
|
||||
/* No user reference */
|
||||
if (((mysqlnd_zval *)*zv)->point_type == MYSQLND_POINTS_EXT_BUFFER) {
|
||||
/* PS are here and also in Unicode mode, for non-binary */
|
||||
zval_dtor(*zv);
|
||||
}
|
||||
LOCK_PCACHE(cache);
|
||||
++cache->put_hits;
|
||||
++cache->free_items;
|
||||
((mysqlnd_zval *)*zv)->point_type = MYSQLND_POINTS_FREE;
|
||||
ZVAL_DELREF(*zv); /* Make it 1 */
|
||||
ZVAL_NULL(*zv);
|
||||
#ifdef ZTS
|
||||
memset(&((mysqlnd_zval *)*zv)->thread_id, 0, sizeof(THREAD_T));
|
||||
#endif
|
||||
*(--cache->free_list.last_added) = (mysqlnd_zval *)*zv;
|
||||
|
||||
UNLOCK_PCACHE(cache);
|
||||
}
|
||||
DBG_VOID_RETURN;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ _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 TSRMLS_DC)
|
||||
{
|
||||
MYSQLND_ZVAL_PCACHE *cache;
|
||||
mysqlnd_zval **p;
|
||||
|
||||
DBG_ENTER("_mysqlnd_palloc_rshutdown");
|
||||
DBG_INF_FMT("cache=%p", thd_cache);
|
||||
|
||||
if (!thd_cache || !(cache = thd_cache->parent)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
Keep in mind that for pthreads pthread_equal() should be used to be
|
||||
fully standard compliant. However, the PHP code all-around, incl. the
|
||||
the Zend MM uses direct comparison.
|
||||
*/
|
||||
p = thd_cache->gc_list.ptr_line;
|
||||
while (p < thd_cache->gc_list.last_added) {
|
||||
zval_dtor(&(*p)->zv);
|
||||
p++;
|
||||
}
|
||||
|
||||
p = thd_cache->gc_list.ptr_line;
|
||||
LOCK_PCACHE(cache);
|
||||
while (p < thd_cache->gc_list.last_added) {
|
||||
(*p)->point_type = MYSQLND_POINTS_FREE;
|
||||
*(--cache->free_list.last_added) = *p;
|
||||
++cache->free_items;
|
||||
#ifdef ZTS
|
||||
memset(&((*p)->thread_id), 0, sizeof(THREAD_T));
|
||||
#endif
|
||||
p++;
|
||||
}
|
||||
UNLOCK_PCACHE(cache);
|
||||
|
||||
mysqlnd_palloc_free_thd_cache_reference(&thd_cache);
|
||||
|
||||
DBG_VOID_RETURN;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_palloc_rshutdown */
|
||||
PHPAPI void mysqlnd_palloc_stats(const MYSQLND_ZVAL_PCACHE * const cache, zval *return_value)
|
||||
{
|
||||
if (cache) {
|
||||
#if PHP_MAJOR_VERSION >= 6
|
||||
TSRMLS_FETCH();
|
||||
#endif
|
||||
|
||||
LOCK_PCACHE(cache);
|
||||
array_init(return_value);
|
||||
#if PHP_MAJOR_VERSION >= 6
|
||||
if (UG(unicode)) {
|
||||
UChar *ustr;
|
||||
int ulen;
|
||||
|
||||
zend_string_to_unicode(UG(utf8_conv), &ustr, &ulen, "put_hits", sizeof("put_hits") TSRMLS_CC);
|
||||
add_u_assoc_long_ex(return_value, IS_UNICODE, ZSTR(ustr), ulen + 1, cache->put_hits);
|
||||
efree(ustr);
|
||||
zend_string_to_unicode(UG(utf8_conv), &ustr, &ulen, "put_misses", sizeof("put_misses") TSRMLS_CC);
|
||||
add_u_assoc_long_ex(return_value, IS_UNICODE, ZSTR(ustr), ulen + 1, cache->put_hits);
|
||||
efree(ustr);
|
||||
zend_string_to_unicode(UG(utf8_conv), &ustr, &ulen, "get_hits", sizeof("get_hits") TSRMLS_CC);
|
||||
add_u_assoc_long_ex(return_value, IS_UNICODE, ZSTR(ustr), ulen + 1, cache->put_hits);
|
||||
efree(ustr);
|
||||
zend_string_to_unicode(UG(utf8_conv), &ustr, &ulen, "get_misses", sizeof("get_misses") TSRMLS_CC);
|
||||
add_u_assoc_long_ex(return_value, IS_UNICODE, ZSTR(ustr), ulen + 1, cache->put_hits);
|
||||
efree(ustr);
|
||||
zend_string_to_unicode(UG(utf8_conv), &ustr, &ulen, "size", sizeof("size") TSRMLS_CC);
|
||||
add_u_assoc_long_ex(return_value, IS_UNICODE, ZSTR(ustr), ulen + 1, cache->put_hits);
|
||||
efree(ustr);
|
||||
zend_string_to_unicode(UG(utf8_conv), &ustr, &ulen, "free_items", sizeof("free_items") TSRMLS_CC);
|
||||
add_u_assoc_long_ex(return_value, IS_UNICODE, ZSTR(ustr), ulen + 1, cache->put_hits);
|
||||
efree(ustr);
|
||||
zend_string_to_unicode(UG(utf8_conv), &ustr, &ulen, "references", sizeof("references") TSRMLS_CC);
|
||||
add_u_assoc_long_ex(return_value, IS_UNICODE, ZSTR(ustr), ulen + 1, cache->put_hits);
|
||||
efree(ustr);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
add_assoc_long_ex(return_value, "put_hits", sizeof("put_hits"), cache->put_hits);
|
||||
add_assoc_long_ex(return_value, "put_misses", sizeof("put_misses"), cache->put_misses);
|
||||
add_assoc_long_ex(return_value, "get_hits", sizeof("get_hits"), cache->get_hits);
|
||||
add_assoc_long_ex(return_value, "get_misses", sizeof("get_misses"), cache->get_misses);
|
||||
add_assoc_long_ex(return_value, "size", sizeof("size"), cache->max_items);
|
||||
add_assoc_long_ex(return_value, "free_items", sizeof("free_items"), cache->free_items);
|
||||
add_assoc_long_ex(return_value, "references", sizeof("references"), cache->references);
|
||||
}
|
||||
UNLOCK_PCACHE(cache);
|
||||
} else {
|
||||
ZVAL_NULL(return_value);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
114
ext/mysqlnd/mysqlnd_palloc.h
Normal file
114
ext/mysqlnd/mysqlnd_palloc.h
Normal file
@ -0,0 +1,114 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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_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;
|
||||
zval **last_added;
|
||||
};
|
||||
|
||||
typedef struct st_mysqlnd_zval_cache MYSQLND_ZVAL_CACHE;
|
||||
|
||||
struct st_mysqlnd_zval_cache {
|
||||
struct st_mysqlnd_zval_list *free_list;
|
||||
unsigned int free_items;
|
||||
unsigned int max_items;
|
||||
unsigned int references;
|
||||
unsigned long get_hits;
|
||||
unsigned long get_misses;
|
||||
unsigned long put_hits;
|
||||
unsigned long put_full_misses;
|
||||
unsigned long put_refcount_misses;
|
||||
};
|
||||
|
||||
|
||||
enum mysqlnd_zval_ptr_type
|
||||
{
|
||||
MYSQLND_POINTS_INT_BUFFER,
|
||||
MYSQLND_POINTS_EXT_BUFFER,
|
||||
MYSQLND_POINTS_FREE
|
||||
};
|
||||
|
||||
/* Persistent caching allocator */
|
||||
typedef struct st_mysqlnd_zval {
|
||||
/* Should be first */
|
||||
zval zv;
|
||||
enum mysqlnd_zval_ptr_type point_type;
|
||||
#ifdef ZTS
|
||||
THREAD_T thread_id;
|
||||
#endif
|
||||
} mysqlnd_zval;
|
||||
|
||||
|
||||
typedef struct st_mysqlnd_ndzval_list {
|
||||
mysqlnd_zval **ptr_line; /* we allocate this, all are pointers to the block */
|
||||
mysqlnd_zval **last_added; /* this points to the ptr_line, and moves left-right. It's our stack */
|
||||
} mysqlnd_ndzval_list;
|
||||
|
||||
|
||||
struct st_mysqlnd_zval_pcache {
|
||||
mysqlnd_zval *block;
|
||||
mysqlnd_zval *last_in_block;
|
||||
mysqlnd_ndzval_list free_list; /* Fetch from here */
|
||||
|
||||
#ifdef ZTS
|
||||
MUTEX_T LOCK_access;
|
||||
#endif
|
||||
unsigned int references;
|
||||
|
||||
/* These are just for statistics and not used for operational purposes */
|
||||
unsigned int free_items;
|
||||
unsigned int max_items;
|
||||
|
||||
unsigned long get_hits;
|
||||
unsigned long get_misses;
|
||||
unsigned long put_hits;
|
||||
unsigned long put_misses;
|
||||
};
|
||||
|
||||
struct st_mysqlnd_thread_zval_pcache {
|
||||
struct st_mysqlnd_zval_pcache *parent;
|
||||
|
||||
unsigned int references;
|
||||
#ifdef ZTS
|
||||
THREAD_T thread_id;
|
||||
#endif
|
||||
mysqlnd_ndzval_list gc_list; /* GC these from time to time */
|
||||
};
|
||||
|
||||
#endif /* MYSQLND_PALLOC_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
|
||||
*/
|
515
ext/mysqlnd/mysqlnd_portability.h
Normal file
515
ext/mysqlnd/mysqlnd_portability.h
Normal file
@ -0,0 +1,515 @@
|
||||
/* Copyright Abandoned 1996 TCX DataKonsult AB & Monty Program KB & Detron HB
|
||||
This file is public domain and comes with NO WARRANTY of any kind */
|
||||
|
||||
/*
|
||||
Parts of the original, which are not applicable to mysqlnd have been removed.
|
||||
|
||||
With small modifications, mostly casting but adding few more macros by
|
||||
Andrey Hristov <andrey@mysql.com> . The additions are in the public domain and
|
||||
were added to improve the header file, to get it more consistent.
|
||||
*/
|
||||
|
||||
/* Comes from global.h as OFFSET, renamed to STRUCT_OFFSET */
|
||||
#define STRUCT_OFFSET(t, f) ((size_t)(char *)&((t *)0)->f)
|
||||
|
||||
#ifndef __attribute
|
||||
#if !defined(__GNUC__)
|
||||
#define __attribute(A)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
/* We use a Unix API, so pretend it's not Windows */
|
||||
#undef WIN
|
||||
#undef WIN32
|
||||
#undef _WIN
|
||||
#undef _WIN32
|
||||
#undef _WIN64
|
||||
#undef __WIN__
|
||||
#undef __WIN32__
|
||||
#endif /* __CYGWIN__ */
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32)
|
||||
# include <ext/mysqlnd/config-win.h>
|
||||
#else
|
||||
# include "ext/mysqlnd/php_mysqlnd_config.h"
|
||||
#endif /* _WIN32... */
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#if SIZEOF_LONG_LONG > 4 && !defined(_LONG_LONG)
|
||||
#define _LONG_LONG 1 /* For AIX string library */
|
||||
#endif
|
||||
|
||||
|
||||
/* Go around some bugs in different OS and compilers */
|
||||
#if defined(_HPUX_SOURCE) && defined(HAVE_SYS_STREAM_H)
|
||||
#include <sys/stream.h> /* HPUX 10.20 defines ulong here. UGLY !!! */
|
||||
#define HAVE_ULONG
|
||||
#endif
|
||||
|
||||
|
||||
#if SIZEOF_LONG_LONG > 4
|
||||
#define HAVE_LONG_LONG 1
|
||||
#endif
|
||||
|
||||
/* Typdefs for easyier portability */
|
||||
|
||||
#ifndef HAVE_INT8
|
||||
#ifndef HAVE_INT8_T
|
||||
typedef signed char int8; /* Signed integer >= 8 bits */
|
||||
#else
|
||||
typedef int8_t int8; /* Signed integer >= 8 bits */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_UINT8
|
||||
#ifndef HAVE_UINT8_T
|
||||
typedef unsigned char uint8; /* Unsigned integer >= 8 bits */
|
||||
#else
|
||||
typedef uint8_t uint8; /* Signed integer >= 8 bits */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_INT16
|
||||
#ifndef HAVE_INT16_T
|
||||
typedef signed short int16; /* Signed integer >= 16 bits */
|
||||
#else
|
||||
typedef int16_t int16; /* Signed integer >= 16 bits */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_UINT16
|
||||
#ifndef HAVE_UINT16_T
|
||||
typedef unsigned short uint16; /* Signed integer >= 16 bits */
|
||||
#else
|
||||
typedef uint16_t uint16; /* Signed integer >= 16 bits */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_UCHAR
|
||||
typedef unsigned char uchar; /* Short for unsigned char */
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(HAVE_INT32_T) && defined(HAVE_UINT32_T)
|
||||
typedef int32_t int32;
|
||||
typedef uint32_t uint32;
|
||||
|
||||
#elif SIZEOF_INT == 4
|
||||
|
||||
#ifndef HAVE_INT32
|
||||
typedef signed int int32;
|
||||
#endif
|
||||
#ifndef HAVE_UINT32
|
||||
typedef unsigned int uint32;
|
||||
#endif
|
||||
|
||||
#elif SIZEOF_LONG == 4
|
||||
|
||||
#ifndef HAVE_INT32
|
||||
typedef signed long int32;
|
||||
#endif
|
||||
#ifndef HAVE_UINT32
|
||||
typedef unsigned long uint32;
|
||||
#endif
|
||||
|
||||
#else
|
||||
error "Neither int or long is of 4 bytes width"
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_ULONG) && !defined(__USE_MISC) && !defined(ulong)
|
||||
typedef unsigned long ulong; /* Short for unsigned long */
|
||||
#endif
|
||||
#ifndef longlong_defined
|
||||
#if defined(HAVE_LONG_LONG) && SIZEOF_LONG != 8
|
||||
typedef unsigned long long int ulonglong; /* ulong or unsigned long long */
|
||||
typedef long long int longlong;
|
||||
#else
|
||||
typedef unsigned long ulonglong; /* ulong or unsigned long long */
|
||||
typedef long longlong;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#define int1store(T,A) do { *((zend_uchar*) (T)) = (A); } while(0)
|
||||
#define uint1korr(A) (*(((uint8*)(A))))
|
||||
|
||||
/* Bit values are sent in reverted order of bytes, compared to normal !!! */
|
||||
#define bit_uint2korr(A) ((uint16) (((uint16) (((uchar*) (A))[1])) +\
|
||||
((uint16) (((uchar*) (A))[0]) << 8)))
|
||||
#define bit_uint3korr(A) ((uint32) (((uint32) (((uchar*) (A))[2])) +\
|
||||
(((uint32) (((uchar*) (A))[1])) << 8) +\
|
||||
(((uint32) (((uchar*) (A))[0])) << 16)))
|
||||
|
||||
#define bit_uint4korr(A) ((uint32) (((uint32) (((uchar*) (A))[3])) +\
|
||||
(((uint32) (((uchar*) (A))[2])) << 8) +\
|
||||
(((uint32) (((uchar*) (A))[1])) << 16) +\
|
||||
(((uint32) (((uchar*) (A))[0])) << 24)))
|
||||
|
||||
#define bit_uint5korr(A) ((ulonglong)(((uint32) ((uchar) (A)[4])) +\
|
||||
(((uint32) ((uchar) (A)[3])) << 8) +\
|
||||
(((uint32) ((uchar) (A)[2])) << 16) +\
|
||||
(((uint32) ((uchar) (A)[1])) << 24)) +\
|
||||
(((ulonglong) ((uchar) (A)[0])) << 32))
|
||||
|
||||
#define bit_uint6korr(A) ((ulonglong)(((uint32) (((uchar*) (A))[5])) +\
|
||||
(((uint32) (((uchar*) (A))[4])) << 8) +\
|
||||
(((uint32) (((uchar*) (A))[3])) << 16) +\
|
||||
(((uint32) (((uchar*) (A))[2])) << 24)) +\
|
||||
(((ulonglong) (((uint32) (((uchar*) (A))[1])) +\
|
||||
(((uint32) (((uchar*) (A))[0]) << 8)))) << 32))
|
||||
|
||||
#define bit_uint7korr(A) ((ulonglong)(((uint32) (((uchar*) (A))[6])) +\
|
||||
(((uint32) (((uchar*) (A))[5])) << 8) +\
|
||||
(((uint32) (((uchar*) (A))[4])) << 16) +\
|
||||
(((uint32) (((uchar*) (A))[3])) << 24)) +\
|
||||
(((ulonglong) (((uint32) (((uchar*) (A))[2])) +\
|
||||
(((uint32) (((uchar*) (A))[1])) << 8) +\
|
||||
(((uint32) (((uchar*) (A))[0])) << 16))) << 32))
|
||||
|
||||
|
||||
#define bit_uint8korr(A) ((ulonglong)(((uint32) (((uchar*) (A))[7])) +\
|
||||
(((uint32) (((uchar*) (A))[6])) << 8) +\
|
||||
(((uint32) (((uchar*) (A))[5])) << 16) +\
|
||||
(((uint32) (((uchar*) (A))[4])) << 24)) +\
|
||||
(((ulonglong) (((uint32) (((uchar*) (A))[3])) +\
|
||||
(((uint32) (((uchar*) (A))[2])) << 8) +\
|
||||
(((uint32) (((uchar*) (A))[1])) << 16) +\
|
||||
(((uint32) (((uchar*) (A))[0])) << 24))) << 32))
|
||||
|
||||
|
||||
/*
|
||||
** Define-funktions for reading and storing in machine independent format
|
||||
** (low byte first)
|
||||
*/
|
||||
|
||||
/* Optimized store functions for Intel x86, non-valid for WIN64 */
|
||||
#if defined(__i386__) && !defined(_WIN64)
|
||||
#define sint2korr(A) (*((int16 *) (A)))
|
||||
#define sint3korr(A) ((int32) ((((uchar) (A)[2]) & 128) ? \
|
||||
(((uint32) 255L << 24) | \
|
||||
(((uint32) (uchar) (A)[2]) << 16) |\
|
||||
(((uint32) (uchar) (A)[1]) << 8) | \
|
||||
((uint32) (uchar) (A)[0])) : \
|
||||
(((uint32) (uchar) (A)[2]) << 16) |\
|
||||
(((uint32) (uchar) (A)[1]) << 8) | \
|
||||
((uint32) (uchar) (A)[0])))
|
||||
#define sint4korr(A) (*((long *) (A)))
|
||||
|
||||
#define uint2korr(A) (*((uint16 *) (A)))
|
||||
#define uint3korr(A) (uint32) (((uint32) ((uchar) (A)[0])) +\
|
||||
(((uint32) ((uchar) (A)[1])) << 8) +\
|
||||
(((uint32) ((uchar) (A)[2])) << 16))
|
||||
#define uint4korr(A) (*((unsigned long *) (A)))
|
||||
|
||||
|
||||
|
||||
#define uint8korr(A) (*((ulonglong *) (A)))
|
||||
#define sint8korr(A) (*((longlong *) (A)))
|
||||
#define int2store(T,A) *((uint16*) (T))= (uint16) (A)
|
||||
#define int3store(T,A) { \
|
||||
*(T)= (uchar) ((A));\
|
||||
*(T+1)=(uchar) (((uint) (A) >> 8));\
|
||||
*(T+2)=(uchar) (((A) >> 16)); }
|
||||
#define int4store(T,A) *((long *) (T))= (long) (A)
|
||||
#define int5store(T,A) { \
|
||||
*((uchar *)(T))= (uchar)((A));\
|
||||
*(((uchar *)(T))+1)=(uchar) (((A) >> 8));\
|
||||
*(((uchar *)(T))+2)=(uchar) (((A) >> 16));\
|
||||
*(((uchar *)(T))+3)=(uchar) (((A) >> 24)); \
|
||||
*(((uchar *)(T))+4)=(uchar) (((A) >> 32)); }
|
||||
|
||||
/* From Andrey Hristov, based on int5store() */
|
||||
#define int6store(T,A) { \
|
||||
*(((uchar *)(T)))= (uchar)((A));\
|
||||
*(((uchar *)(T))+1))=(uchar) (((A) >> 8));\
|
||||
*(((uchar *)(T))+2))=(uchar) (((A) >> 16));\
|
||||
*(((uchar *)(T))+3))=(uchar) (((A) >> 24)); \
|
||||
*(((uchar *)(T))+4))=(uchar) (((A) >> 32)); \
|
||||
*(((uchar *)(T))+5))=(uchar) (((A) >> 40)); }
|
||||
|
||||
#define int8store(T,A) *((ulonglong *) (T))= (ulonglong) (A)
|
||||
|
||||
typedef union {
|
||||
double v;
|
||||
long m[2];
|
||||
} doubleget_union;
|
||||
#define doubleget(V,M) { ((doubleget_union *)&(V))->m[0] = *((long*) (M)); \
|
||||
((doubleget_union *)&(V))->m[1] = *(((long*) (M))+1); }
|
||||
#define doublestore(T,V) { *((long *) (T)) = ((doubleget_union *)&(V))->m[0]; \
|
||||
*(((long *) (T))+1) = ((doubleget_union *)&(V))->m[1]; }
|
||||
#define float4get(V,M) { *((float *) &(V)) = *((float*) (M)); }
|
||||
#define float8get(V,M) doubleget((V),(M))
|
||||
/* From Andrey Hristov based on doubleget */
|
||||
#define floatget(V,M) memcpy((char*) &(V),(char*) (M),sizeof(float))
|
||||
#define floatstore float4store
|
||||
#define float4store(V,M) memcpy((char*) (V),(char*) (&M),sizeof(float))
|
||||
#define float8store(V,M) doublestore((V),(M))
|
||||
#endif /* __i386__ */
|
||||
|
||||
#ifndef sint2korr
|
||||
#define sint2korr(A) (int16) (((int16) ((uchar) (A)[0])) +\
|
||||
((int16) ((int16) (A)[1]) << 8))
|
||||
#define sint3korr(A) ((int32) ((((uchar) (A)[2]) & 128) ? \
|
||||
(((uint32) 255L << 24) | \
|
||||
(((uint32) (uchar) (A)[2]) << 16) |\
|
||||
(((uint32) (uchar) (A)[1]) << 8) | \
|
||||
((uint32) (uchar) (A)[0])) : \
|
||||
(((uint32) (uchar) (A)[2]) << 16) |\
|
||||
(((uint32) (uchar) (A)[1]) << 8) | \
|
||||
((uint32) (uchar) (A)[0])))
|
||||
#define sint4korr(A) (int32) (((int32) ((uchar) (A)[0])) +\
|
||||
(((int32) ((uchar) (A)[1]) << 8)) +\
|
||||
(((int32) ((uchar) (A)[2]) << 16)) +\
|
||||
(((int32) ((int16) (A)[3]) << 24)))
|
||||
|
||||
#define sint8korr(A) (longlong) uint8korr(A)
|
||||
#define uint2korr(A) (uint16) (((uint16) ((uchar) (A)[0])) +\
|
||||
((uint16) ((uchar) (A)[1]) << 8))
|
||||
#define uint3korr(A) (uint32) (((uint32) ((uchar) (A)[0])) +\
|
||||
(((uint32) ((uchar) (A)[1])) << 8) +\
|
||||
(((uint32) ((uchar) (A)[2])) << 16))
|
||||
#define uint4korr(A) (uint32) (((uint32) ((uchar) (A)[0])) +\
|
||||
(((uint32) ((uchar) (A)[1])) << 8) +\
|
||||
(((uint32) ((uchar) (A)[2])) << 16) +\
|
||||
(((uint32) ((uchar) (A)[3])) << 24))
|
||||
#define bit_uint5korr(A) ((ulonglong)(((uint32) ((uchar) (A)[0])) +\
|
||||
(((uint32) ((uchar) (A)[1])) << 8) +\
|
||||
(((uint32) ((uchar) (A)[2])) << 16) +\
|
||||
(((uint32) ((uchar) (A)[3])) << 24)) +\
|
||||
(((ulonglong) ((uchar) (A)[4])) << 32))
|
||||
/* From Andrey Hristov, based on uint5korr */
|
||||
#define bit_uint6korr(A) ((ulonglong)(((uint32) (((uchar*) (A))[5])) +\
|
||||
(((uint32) (((uchar*) (A))[4])) << 8) +\
|
||||
(((uint32) (((uchar*) (A))[3])) << 16) +\
|
||||
(((uint32) (((uchar*) (A))[2])) << 24)) +\
|
||||
(((ulonglong) (((uint32) (((uchar*) (A))[1])) +\
|
||||
(((uint32) (((uchar*) (A))[0]) << 8)))) << 32))
|
||||
|
||||
#define bit_uint7korr(A) ((ulonglong)(((uint32) (((uchar*) (A))[6])) +\
|
||||
(((uint32) (((uchar*) (A))[5])) << 8) +\
|
||||
(((uint32) (((uchar*) (A))[4])) << 16) +\
|
||||
(((uint32) (((uchar*) (A))[3])) << 24)) +\
|
||||
(((ulonglong) (((uint32) (((uchar*) (A))[2])) +\
|
||||
(((uint32) (((uchar*) (A))[1])) << 8) +\
|
||||
(((uint32) (((uchar*) (A))[0])) << 16))) << 32))
|
||||
|
||||
|
||||
#define bit_uint8korr(A) ((ulonglong)(((uint32) (((uchar*) (A))[7])) +\
|
||||
(((uint32) (((uchar*) (A))[6])) << 8) +\
|
||||
(((uint32) (((uchar*) (A))[5])) << 16) +\
|
||||
(((uint32) (((uchar*) (A))[4])) << 24)) +\
|
||||
(((ulonglong) (((uint32) (((uchar*) (A))[3])) +\
|
||||
(((uint32) (((uchar*) (A))[2])) << 8) +\
|
||||
(((uint32) (((uchar*) (A))[1])) << 16) +\
|
||||
(((uint32) (((uchar*) (A))[0])) << 24))) << 32))
|
||||
|
||||
#define uint8korr(A) ((ulonglong)(((uint32) ((uchar) (A)[0])) +\
|
||||
(((uint32) ((uchar) (A)[1])) << 8) +\
|
||||
(((uint32) ((uchar) (A)[2])) << 16) +\
|
||||
(((uint32) ((uchar) (A)[3])) << 24)) +\
|
||||
(((ulonglong) (((uint32) ((uchar) (A)[4])) +\
|
||||
(((uint32) ((uchar) (A)[5])) << 8) +\
|
||||
(((uint32) ((uchar) (A)[6])) << 16) +\
|
||||
(((uint32) ((uchar) (A)[7])) << 24))) << 32))
|
||||
|
||||
|
||||
#define int2store(T,A) do { uint def_temp= (uint) (A) ;\
|
||||
*((uchar*) (T)) = (uchar)(def_temp); \
|
||||
*((uchar*) (T+1)) = (uchar)((def_temp >> 8)); } while (0)
|
||||
#define int3store(T,A) do { /*lint -save -e734 */\
|
||||
*(((char *)(T))) = (char) ((A));\
|
||||
*(((char *)(T))+1) = (char) (((A) >> 8));\
|
||||
*(((char *)(T))+2) = (char) (((A) >> 16)); \
|
||||
/*lint -restore */} while (0)
|
||||
#define int4store(T,A) do { \
|
||||
*(((char *)(T))) = (char) ((A));\
|
||||
*(((char *)(T))+1) = (char) (((A) >> 8));\
|
||||
*(((char *)(T))+2) = (char) (((A) >> 16));\
|
||||
*(((char *)(T))+3) = (char) (((A) >> 24)); } while (0)
|
||||
#define int5store(T,A) do { \
|
||||
*(((char *)(T))) = (char)((A));\
|
||||
*(((char *)(T))+1) = (char)(((A) >> 8));\
|
||||
*(((char *)(T))+2) = (char)(((A) >> 16));\
|
||||
*(((char *)(T))+3) = (char)(((A) >> 24)); \
|
||||
*(((char *)(T))+4) = (char)(((A) >> 32)); } while (0)
|
||||
/* Based on int5store() from Andrey Hristov */
|
||||
#define int6store(T,A) do { \
|
||||
*(((char *)(T))) = (char)((A));\
|
||||
*(((char *)(T))+1) = (char)(((A) >> 8));\
|
||||
*(((char *)(T))+2) = (char)(((A) >> 16));\
|
||||
*(((char *)(T))+3) = (char)(((A) >> 24)); \
|
||||
*(((char *)(T))+4) = (char)(((A) >> 32)); \
|
||||
*(((char *)(T))+5) = (char)(((A) >> 40)); } while (0)
|
||||
#define int8store(T,A) { uint def_temp= (uint) (A), def_temp2= (uint) ((A) >> 32); \
|
||||
int4store((T),def_temp); \
|
||||
int4store((T+4),def_temp2); \
|
||||
}
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
#define float4store(T,A) do { \
|
||||
*(((char *)(T))) = (char) ((char *) &A)[3];\
|
||||
*(((char *)(T))+1) = (char) ((char *) &A)[2];\
|
||||
*(((char *)(T))+2) = (char) ((char *) &A)[1];\
|
||||
*(((char *)(T))+3) = (char) ((char *) &A)[0]; } while (0)
|
||||
|
||||
#define float4get(V,M) do { float def_temp;\
|
||||
((char*) &def_temp)[0] = (M)[3];\
|
||||
((char*) &def_temp)[1] = (M)[2];\
|
||||
((char*) &def_temp)[2] = (M)[1];\
|
||||
((char*) &def_temp)[3] = (M)[0];\
|
||||
(V)=def_temp; } while (0)
|
||||
#define float8store(T,V) do { \
|
||||
*(((char *)(T))) = (char) ((char *) &(V))[7];\
|
||||
*(((char *)(T))+1) = (char) ((char *) &(V))[6];\
|
||||
*(((char *)(T))+2) = (char) ((char *) &(V))[5];\
|
||||
*(((char *)(T))+3) = (char) ((char *) &(V))[4];\
|
||||
*(((char *)(T))+4) = (char) ((char *) &(V))[3];\
|
||||
*(((char *)(T))+5) = (char) ((char *) &(V))[2];\
|
||||
*(((char *)(T))+6) = (char) ((char *) &(V))[1];\
|
||||
*(((char *)(T))+7) = (char) ((char *) &(V))[0]; } while (0)
|
||||
|
||||
#define float8get(V,M) do { double def_temp;\
|
||||
((char*) &def_temp)[0] = (M)[7];\
|
||||
((char*) &def_temp)[1] = (M)[6];\
|
||||
((char*) &def_temp)[2] = (M)[5];\
|
||||
((char*) &def_temp)[3] = (M)[4];\
|
||||
((char*) &def_temp)[4] = (M)[3];\
|
||||
((char*) &def_temp)[5] = (M)[2];\
|
||||
((char*) &def_temp)[6] = (M)[1];\
|
||||
((char*) &def_temp)[7] = (M)[0];\
|
||||
(V) = def_temp; \
|
||||
} while (0)
|
||||
#else
|
||||
#define float4get(V,M) memcpy((char*) &(V),(char*) (M),sizeof(float))
|
||||
#define float4store(V,M) memcpy((char*) (V),(char*) (&M),sizeof(float))
|
||||
|
||||
#if defined(__FLOAT_WORD_ORDER) && (__FLOAT_WORD_ORDER == __BIG_ENDIAN)
|
||||
#define doublestore(T,V) do { \
|
||||
*(((char *)(T)))= ((char *) &(V))[4];\
|
||||
*(((char *)(T))+1)=(char) ((char *) &(V))[5];\
|
||||
*(((char *)(T))+2)=(char) ((char *) &(V))[6];\
|
||||
*(((char *)(T))+3)=(char) ((char *) &(V))[7];\
|
||||
*(((char *)(T))+4)=(char) ((char *) &(V))[0];\
|
||||
*(((char *)(T))+5)=(char) ((char *) &(V))[1];\
|
||||
*(((char *)(T))+6)=(char) ((char *) &(V))[2];\
|
||||
*(((char *)(T))+7)=(char) ((char *) &(V))[3];} while (0)
|
||||
#define doubleget(V,M) do { double def_temp;\
|
||||
((char*) &def_temp)[0]=(M)[4];\
|
||||
((char*) &def_temp)[1]=(M)[5];\
|
||||
((char*) &def_temp)[2]=(M)[6];\
|
||||
((char*) &def_temp)[3]=(M)[7];\
|
||||
((char*) &def_temp)[4]=(M)[0];\
|
||||
((char*) &def_temp)[5]=(M)[1];\
|
||||
((char*) &def_temp)[6]=(M)[2];\
|
||||
((char*) &def_temp)[7]=(M)[3];\
|
||||
(V) = def_temp; } while (0)
|
||||
#endif /* __FLOAT_WORD_ORDER */
|
||||
|
||||
#define float8get(V,M) doubleget((V),(M))
|
||||
#define float8store(V,M) doublestore((V),(M))
|
||||
#endif /* WORDS_BIGENDIAN */
|
||||
|
||||
#endif /* sint2korr */
|
||||
|
||||
/* Define-funktions for reading and storing in machine format from/to
|
||||
short/long to/from some place in memory V should be a (not
|
||||
register) variable, M is a pointer to byte */
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
|
||||
#define ushortget(V,M) { V = (uint16) (((uint16) ((uchar) (M)[1]))+\
|
||||
((uint16) ((uint16) (M)[0]) << 8)); }
|
||||
#define shortget(V,M) { V = (short) (((short) ((uchar) (M)[1]))+\
|
||||
((short) ((short) (M)[0]) << 8)); }
|
||||
#define longget(V,M) do { int32 def_temp;\
|
||||
((char*) &def_temp)[0]=(M)[0];\
|
||||
((char*) &def_temp)[1]=(M)[1];\
|
||||
((char*) &def_temp)[2]=(M)[2];\
|
||||
((char*) &def_temp)[3]=(M)[3];\
|
||||
(V)=def_temp; } while (0)
|
||||
#define ulongget(V,M) do { uint32 def_temp;\
|
||||
((char*) &def_temp)[0]=(M)[0];\
|
||||
((char*) &def_temp)[1]=(M)[1];\
|
||||
((char*) &def_temp)[2]=(M)[2];\
|
||||
((char*) &def_temp)[3]=(M)[3];\
|
||||
(V)=def_temp; } while (0)
|
||||
#define shortstore(T,A) do { \
|
||||
uint def_temp=(uint) (A) ;\
|
||||
*(((char *)(T))+1)=(char)(def_temp); \
|
||||
*(((char *)(T))+0)=(char)(def_temp >> 8); } while (0)
|
||||
#define longstore(T,A) do { \
|
||||
*(((char *)(T))+3)=(char)((A));\
|
||||
*(((char *)(T))+2)=(char)(((A) >> 8));\
|
||||
*(((char *)(T))+1)=(char)(((A) >> 16));\
|
||||
*(((char *)(T))+0)=(char)(((A) >> 24)); } while (0)
|
||||
|
||||
#define doubleget(V,M) memcpy((char*) &(V),(char*) (M), sizeof(double))
|
||||
#define doublestore(T,V) memcpy((char*) (T),(char*) &(V), sizeof(double))
|
||||
#define longlongget(V,M) memcpy((char*) &(V),(char*) (M), sizeof(ulonglong))
|
||||
#define longlongstore(T,V) memcpy((char*) (T),(char*) &(V), sizeof(ulonglong))
|
||||
|
||||
#else
|
||||
|
||||
#define ushortget(V,M) { V = uint2korr((M)); }
|
||||
#define shortget(V,M) { V = sint2korr((M)); }
|
||||
#define longget(V,M) { V = sint4korr((M)); }
|
||||
#define ulongget(V,M) { V = uint4korr((M)); }
|
||||
#define shortstore(T,V) int2store((T),(V))
|
||||
#define longstore(T,V) int4store((T),(V))
|
||||
#ifndef doubleget
|
||||
#define doubleget(V,M) memcpy((char*) &(V),(char*) (M),sizeof(double))
|
||||
#define doublestore(T,V) memcpy((char*) (T),(char*) &(V),sizeof(double))
|
||||
#endif /* doubleget */
|
||||
#define longlongget(V,M) memcpy((char*) &(V),(char*) (M),sizeof(ulonglong))
|
||||
#define longlongstore(T,V) memcpy((char*) (T),(char*) &(V),sizeof(ulonglong))
|
||||
|
||||
#endif /* WORDS_BIGENDIAN */
|
||||
|
||||
|
||||
#ifdef PHP_WIN32
|
||||
#define MYSQLND_LLU_SPEC "%I64u"
|
||||
#define MYSQLND_LL_SPEC "%I64d"
|
||||
#ifndef L64
|
||||
#define L64(x) x##i64
|
||||
#endif
|
||||
typedef unsigned __int64 my_uint64;
|
||||
typedef __int64 my_int64;
|
||||
typedef unsigned __int64 mynd_ulonglong;
|
||||
typedef __int64 mynd_longlong;
|
||||
#else
|
||||
#define MYSQLND_LLU_SPEC "%llu"
|
||||
#define MYSQLND_LL_SPEC "%lld"
|
||||
#ifndef L64
|
||||
#define L64(x) x##LL
|
||||
#endif
|
||||
#ifndef HAVE_UINT64_T
|
||||
typedef unsigned long long my_uint64;
|
||||
typedef unsigned long long mynd_ulonglong;
|
||||
#else
|
||||
typedef uint64_t my_uint64;
|
||||
typedef uint64_t mynd_ulonglong;
|
||||
#endif
|
||||
#ifndef HAVE_INT64_T
|
||||
typedef long long my_int64;
|
||||
typedef long long mynd_longlong;
|
||||
#else
|
||||
typedef int64_t my_int64;
|
||||
typedef int64_t mynd_longlong;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
191
ext/mysqlnd/mysqlnd_priv.h
Normal file
191
ext/mysqlnd/mysqlnd_priv.h
Normal file
@ -0,0 +1,191 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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_PRIV_H
|
||||
#define MYSQLND_PRIV_H
|
||||
|
||||
#ifdef ZTS
|
||||
#include "TSRM.h"
|
||||
#endif
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
#ifndef pestrndup
|
||||
#define pestrndup(s, length, persistent) ((persistent)?zend_strndup((s),(length)):estrndup((s),(length)))
|
||||
#endif
|
||||
|
||||
|
||||
#define MYSQLND_CLASS_METHODS_START(class) static \
|
||||
struct st_##class##_methods mysqlnd_##class##_methods = {
|
||||
#define MYSQLND_CLASS_METHODS_END }
|
||||
#define MYSQLND_METHOD(class, method) php_##class##_##method##_pub
|
||||
#define MYSQLND_METHOD_PRIVATE(class, method) php_##class##_##method##_priv
|
||||
|
||||
#if PHP_MAJOR_VERSION < 6
|
||||
#define mysqlnd_array_init(arg, field_count) \
|
||||
{ \
|
||||
ALLOC_HASHTABLE_REL(Z_ARRVAL_P(arg));\
|
||||
zend_hash_init(Z_ARRVAL_P(arg), (field_count), NULL, ZVAL_PTR_DTOR, 0); \
|
||||
Z_TYPE_P(arg) = IS_ARRAY;\
|
||||
}
|
||||
#else
|
||||
#define mysqlnd_array_init(arg, field_count) \
|
||||
{ \
|
||||
ALLOC_HASHTABLE_REL(Z_ARRVAL_P(arg));\
|
||||
zend_u_hash_init(Z_ARRVAL_P(arg), (field_count), NULL, ZVAL_PTR_DTOR, 0, 0);\
|
||||
Z_TYPE_P(arg) = IS_ARRAY;\
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#define SERVER_STATUS_IN_TRANS 1 /* Transaction has started */
|
||||
#define SERVER_STATUS_AUTOCOMMIT 2 /* Server in auto_commit mode */
|
||||
#define SERVER_MORE_RESULTS_EXISTS 8 /* Multi query - next query exists */
|
||||
/*
|
||||
The server was able to fulfill the clients request and opened a
|
||||
read-only non-scrollable cursor for a query. This flag comes
|
||||
in reply to COM_STMT_EXECUTE and COM_STMT_FETCH commands.
|
||||
*/
|
||||
#define SERVER_STATUS_CURSOR_EXISTS 64
|
||||
/*
|
||||
This flag is sent when a read-only cursor is exhausted, in reply to
|
||||
COM_STMT_FETCH command.
|
||||
*/
|
||||
#define SERVER_STATUS_LAST_ROW_SENT 128
|
||||
#define SERVER_STATUS_DB_DROPPED 256 /* A database was dropped */
|
||||
#define SERVER_STATUS_NO_BACKSLASH_ESCAPES 512
|
||||
|
||||
|
||||
|
||||
/* Client Error codes */
|
||||
#define CR_UNKNOWN_ERROR 2000
|
||||
#define CR_CONNECTION_ERROR 2002
|
||||
#define CR_SERVER_GONE_ERROR 2006
|
||||
#define CR_OUT_OF_MEMORY 2008
|
||||
#define CR_SERVER_LOST 2013
|
||||
#define CR_COMMANDS_OUT_OF_SYNC 2014
|
||||
#define CR_CANT_FIND_CHARSET 2019
|
||||
#define CR_MALFORMED_PACKET 2027
|
||||
#define CR_NOT_IMPLEMENTED 2054
|
||||
#define CR_NO_PREPARE_STMT 2030
|
||||
#define CR_PARAMS_NOT_BOUND 2031
|
||||
#define CR_INVALID_PARAMETER_NO 2034
|
||||
#define CR_INVALID_BUFFER_USE 2035
|
||||
|
||||
#define MYSQLND_EE_FILENOTFOUND 7890
|
||||
|
||||
#define UNKNOWN_SQLSTATE "HY000"
|
||||
|
||||
#define MAX_CHARSET_LEN 32
|
||||
|
||||
|
||||
#define SET_ERROR_AFF_ROWS(s) (s)->upsert_status.affected_rows = (mynd_ulonglong) ~0
|
||||
|
||||
/* Error handling */
|
||||
#define SET_NEW_MESSAGE(buf, buf_len, message, len, persistent) \
|
||||
{\
|
||||
if ((buf)) { \
|
||||
pefree((buf), (persistent)); \
|
||||
} \
|
||||
(buf) = (message); \
|
||||
(buf_len) = (len); \
|
||||
/* Transfer ownership*/ \
|
||||
(message) = NULL; \
|
||||
}
|
||||
|
||||
#define SET_EMPTY_MESSAGE(buf, buf_len, persistent) \
|
||||
{\
|
||||
if ((buf)) { \
|
||||
pefree((buf), (persistent)); \
|
||||
(buf) = NULL; \
|
||||
} \
|
||||
(buf_len) = 0; \
|
||||
}
|
||||
|
||||
|
||||
#define SET_EMPTY_ERROR(error_info) \
|
||||
{ \
|
||||
error_info.error_no = 0; \
|
||||
error_info.error[0] = '\0'; \
|
||||
strncpy(error_info.sqlstate, "00000", sizeof("00000") - 1); \
|
||||
}
|
||||
|
||||
#define SET_CLIENT_ERROR(error_info, a, b, c) \
|
||||
{ \
|
||||
error_info.error_no = a; \
|
||||
strncpy(error_info.sqlstate, b, sizeof(error_info.sqlstate)); \
|
||||
strncpy(error_info.error, c, sizeof(error_info.error)); \
|
||||
}
|
||||
|
||||
#define SET_STMT_ERROR(stmt, a, b, c) SET_CLIENT_ERROR(stmt->error_info, a, b, c)
|
||||
|
||||
|
||||
|
||||
/* PS stuff */
|
||||
typedef void (*ps_field_fetch_func)(zval *zv, const MYSQLND_FIELD * const field,
|
||||
uint pack_len, zend_uchar **row,
|
||||
zend_bool everything_as_unicode TSRMLS_DC);
|
||||
struct st_mysqlnd_perm_bind {
|
||||
ps_field_fetch_func func;
|
||||
/* should be signed int */
|
||||
int pack_len;
|
||||
unsigned int php_type;
|
||||
zend_bool is_possibly_blob;
|
||||
zend_bool can_ret_as_str_in_uni;
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
|
||||
void _mysqlnd_init_ps_subsystem();/* This one is private, mysqlnd_library_init() will call it */
|
||||
|
||||
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);
|
||||
|
||||
|
||||
|
||||
int mysqlnd_set_sock_no_delay(php_stream *stream);
|
||||
#endif /* MYSQLND_PRIV_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
|
||||
*/
|
1740
ext/mysqlnd/mysqlnd_ps.c
Normal file
1740
ext/mysqlnd/mysqlnd_ps.c
Normal file
File diff suppressed because it is too large
Load Diff
854
ext/mysqlnd/mysqlnd_ps_codec.c
Normal file
854
ext/mysqlnd/mysqlnd_ps_codec.c
Normal file
@ -0,0 +1,854 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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$ */
|
||||
#include "php.h"
|
||||
#include "mysqlnd.h"
|
||||
#include "mysqlnd_wireprotocol.h"
|
||||
#include "mysqlnd_priv.h"
|
||||
#include "mysqlnd_debug.h"
|
||||
|
||||
#define MYSQLND_SILENT
|
||||
|
||||
|
||||
|
||||
typedef int8 my_int8;
|
||||
typedef uint8 my_uint8;
|
||||
|
||||
typedef int16 my_int16;
|
||||
typedef uint16 my_uint16;
|
||||
|
||||
typedef int32 my_int32;
|
||||
typedef uint32 my_uint32;
|
||||
|
||||
|
||||
enum mysqlnd_timestamp_type
|
||||
{
|
||||
MYSQLND_TIMESTAMP_NONE= -2,
|
||||
MYSQLND_TIMESTAMP_ERROR= -1,
|
||||
MYSQLND_TIMESTAMP_DATE= 0,
|
||||
MYSQLND_TIMESTAMP_DATETIME= 1,
|
||||
MYSQLND_TIMESTAMP_TIME= 2
|
||||
};
|
||||
|
||||
|
||||
struct st_mysqlnd_time
|
||||
{
|
||||
unsigned int year, month, day, hour, minute, second;
|
||||
unsigned long second_part;
|
||||
zend_bool neg;
|
||||
enum mysqlnd_timestamp_type time_type;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct st_mysqlnd_perm_bind mysqlnd_ps_fetch_functions[MYSQL_TYPE_LAST + 1];
|
||||
|
||||
#define MYSQLND_PS_SKIP_RESULT_W_LEN -1
|
||||
#define MYSQLND_PS_SKIP_RESULT_STR -2
|
||||
|
||||
/* {{{ ps_fetch_from_1_to_8_bytes */
|
||||
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)
|
||||
{
|
||||
char tmp[22];
|
||||
size_t tmp_len = 0;
|
||||
zend_bool is_bit = field->type == MYSQL_TYPE_BIT;
|
||||
if (field->flags & UNSIGNED_FLAG) {
|
||||
my_uint64 uval = 0;
|
||||
|
||||
switch (byte_count) {
|
||||
case 8:uval = is_bit? (my_uint64) bit_uint8korr(*row):(my_uint64) uint8korr(*row);break;
|
||||
case 7:uval = bit_uint7korr(*row);break;
|
||||
case 6:uval = bit_uint6korr(*row);break;
|
||||
case 5:uval = bit_uint5korr(*row);break;
|
||||
case 4:uval = is_bit? (my_uint64) bit_uint4korr(*row):(my_uint64) uint4korr(*row);break;
|
||||
case 3:uval = is_bit? (my_uint64) bit_uint3korr(*row):(my_uint64) uint3korr(*row);break;
|
||||
case 2:uval = is_bit? (my_uint64) bit_uint2korr(*row):(my_uint64) uint2korr(*row);break;
|
||||
case 1:uval = (my_uint64) uint1korr(*row);break;
|
||||
}
|
||||
|
||||
#if SIZEOF_LONG==4
|
||||
if (uval > INT_MAX) {
|
||||
tmp_len = sprintf((char *)&tmp, MYSQLND_LLU_SPEC, uval);
|
||||
} else
|
||||
#endif /* #if SIZEOF_LONG==4 */
|
||||
{
|
||||
if (byte_count < 8 || uval <= L64(9223372036854775807)) {
|
||||
ZVAL_LONG(zv, uval);
|
||||
} else {
|
||||
tmp_len = sprintf((char *)&tmp, MYSQLND_LLU_SPEC, uval);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* SIGNED */
|
||||
my_int64 lval = 0;
|
||||
switch (byte_count) {
|
||||
case 8:lval = (my_int64) sint8korr(*row);break;
|
||||
/*
|
||||
7, 6 and 5 are not possible.
|
||||
BIT is only unsigned, thus only uint5|6|7 macroses exist
|
||||
*/
|
||||
case 4:lval = (my_int64) sint4korr(*row);break;
|
||||
case 3:lval = (my_int64) sint3korr(*row);break;
|
||||
case 2:lval = (my_int64) sint2korr(*row);break;
|
||||
case 1:lval = (my_int64) *(my_int8*)*row;break;
|
||||
}
|
||||
|
||||
#if SIZEOF_LONG==4
|
||||
if ((L64(2147483647) < (my_int64) lval) || (L64(-2147483648) > (my_int64) lval)) {
|
||||
tmp_len = sprintf((char *)&tmp, MYSQLND_LL_SPEC, lval);
|
||||
} else
|
||||
#endif /* SIZEOF */
|
||||
{
|
||||
ZVAL_LONG(zv, lval);
|
||||
}
|
||||
}
|
||||
|
||||
if (tmp_len) {
|
||||
#if PHP_MAJOR_VERSION >= 6
|
||||
if (as_unicode) {
|
||||
ZVAL_UTF8_STRINGL(zv, tmp, tmp_len, ZSTR_DUPLICATE);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
ZVAL_STRINGL(zv, tmp, tmp_len, 1);
|
||||
}
|
||||
}
|
||||
(*row)+= byte_count;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ ps_fetch_null */
|
||||
static
|
||||
void ps_fetch_null(zval *zv, const MYSQLND_FIELD * const field,
|
||||
uint pack_len, zend_uchar **row,
|
||||
zend_bool as_unicode TSRMLS_DC)
|
||||
{
|
||||
ZVAL_NULL(zv);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ ps_fetch_int8 */
|
||||
static
|
||||
void ps_fetch_int8(zval *zv, const MYSQLND_FIELD * const field,
|
||||
uint pack_len, zend_uchar **row,
|
||||
zend_bool as_unicode TSRMLS_DC)
|
||||
{
|
||||
ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, as_unicode, 1 TSRMLS_CC);
|
||||
#if 0
|
||||
if (field->flags & UNSIGNED_FLAG) {
|
||||
ZVAL_LONG(zv, *(my_uint8*)*row);
|
||||
} else {
|
||||
ZVAL_LONG(zv, *(my_int8*)*row);
|
||||
}
|
||||
(*row)++;
|
||||
#endif
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ ps_fetch_int16 */
|
||||
static
|
||||
void ps_fetch_int16(zval *zv, const MYSQLND_FIELD * const field,
|
||||
uint pack_len, zend_uchar **row,
|
||||
zend_bool as_unicode TSRMLS_DC)
|
||||
{
|
||||
ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, as_unicode, 2 TSRMLS_CC);
|
||||
#if 0
|
||||
if (field->flags & UNSIGNED_FLAG) {
|
||||
ZVAL_LONG(zv, (my_uint16) sint2korr(*row));
|
||||
} else {
|
||||
ZVAL_LONG(zv, (my_int16) sint2korr(*row));
|
||||
}
|
||||
(*row)+= 2;
|
||||
#endif
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ ps_fetch_int32 */
|
||||
static
|
||||
void ps_fetch_int32(zval *zv, const MYSQLND_FIELD * const field,
|
||||
uint pack_len, zend_uchar **row,
|
||||
zend_bool as_unicode TSRMLS_DC)
|
||||
{
|
||||
ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, as_unicode, 4 TSRMLS_CC);
|
||||
#if 0
|
||||
|
||||
if (field->flags & UNSIGNED_FLAG) {
|
||||
my_uint32 uval;
|
||||
|
||||
/* unsigned int (11) */
|
||||
uval= (my_uint32) sint4korr(*row);
|
||||
#if SIZEOF_LONG==4
|
||||
if (uval > INT_MAX) {
|
||||
char *tmp, *p;
|
||||
int j=10;
|
||||
tmp= mnd_emalloc(11);
|
||||
p= &tmp[9];
|
||||
do {
|
||||
*p-- = (uval % 10) + 48;
|
||||
uval = uval / 10;
|
||||
} while (--j > 0);
|
||||
tmp[10]= '\0';
|
||||
/* unsigned int > INT_MAX is 10 digits - ALWAYS */
|
||||
#if PHP_MAJOR_VERSION >= 6
|
||||
if (!as_unicode) {
|
||||
#endif
|
||||
ZVAL_STRING(zv, tmp, 0);
|
||||
#if PHP_MAJOR_VERSION >= 6
|
||||
} else {
|
||||
ZVAL_UTF8_STRINGL(zv, tmp, 10, ZSTR_AUTOFREE);
|
||||
}
|
||||
#endif /* PHP_MAJOR_VERSION >= 6 */
|
||||
} else
|
||||
#endif /* #if SIZEOF_LONG==4 */
|
||||
{
|
||||
ZVAL_LONG(zv, uval);
|
||||
}
|
||||
} else {
|
||||
ZVAL_LONG(zv, (my_int32) sint4korr(*row));
|
||||
}
|
||||
(*row)+= 4;
|
||||
#endif /* 0 */
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ ps_fetch_int64 */
|
||||
static
|
||||
void ps_fetch_int64(zval *zv, const MYSQLND_FIELD * const field,
|
||||
uint pack_len, zend_uchar **row,
|
||||
zend_bool as_unicode TSRMLS_DC)
|
||||
{
|
||||
ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, as_unicode, 8 TSRMLS_CC);
|
||||
#if 0
|
||||
|
||||
my_uint64 llval = (my_uint64) sint8korr(*row);
|
||||
zend_bool uns = field->flags & UNSIGNED_FLAG? TRUE:FALSE;
|
||||
|
||||
#if SIZEOF_LONG==8
|
||||
if (uns == TRUE && llval > 9223372036854775807L) {
|
||||
#elif SIZEOF_LONG==4
|
||||
if ((uns == TRUE && llval > L64(2147483647)) ||
|
||||
(uns == FALSE && ((L64( 2147483647) < (my_int64) llval) ||
|
||||
(L64(-2147483648) > (my_int64) llval))))
|
||||
{
|
||||
#endif
|
||||
char tmp[22];
|
||||
/* even though lval is declared as unsigned, the value
|
||||
* may be negative. Therefor we cannot use MYSQLND_LLU_SPEC and must
|
||||
* use MYSQLND_LL_SPEC.
|
||||
*/
|
||||
sprintf((char *)&tmp, uns == TRUE? MYSQLND_LLU_SPEC : MYSQLND_LL_SPEC, llval);
|
||||
#if PHP_MAJOR_VERSION >= 6
|
||||
if (!as_unicode) {
|
||||
#endif
|
||||
ZVAL_STRING(zv, tmp, 1);
|
||||
#if PHP_MAJOR_VERSION >= 6
|
||||
} else {
|
||||
ZVAL_UTF8_STRING(zv, tmp, ZSTR_DUPLICATE);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
/* This cast is safe, as we have checked the values above */
|
||||
ZVAL_LONG(zv, (long) llval);
|
||||
}
|
||||
(*row)+= 8;
|
||||
#endif /* 0 */
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ ps_fetch_float */
|
||||
static
|
||||
void ps_fetch_float(zval *zv, const MYSQLND_FIELD * const field,
|
||||
uint pack_len, zend_uchar **row,
|
||||
zend_bool as_unicode TSRMLS_DC)
|
||||
{
|
||||
float value;
|
||||
float4get(value, *row);
|
||||
ZVAL_DOUBLE(zv, value);
|
||||
(*row)+= 4;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ ps_fetch_double */
|
||||
static
|
||||
void ps_fetch_double(zval *zv, const MYSQLND_FIELD * const field,
|
||||
uint pack_len, zend_uchar **row,
|
||||
zend_bool as_unicode TSRMLS_DC)
|
||||
{
|
||||
double value;
|
||||
float8get(value, *row);
|
||||
ZVAL_DOUBLE(zv, value);
|
||||
(*row)+= 8;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ ps_fetch_time */
|
||||
static
|
||||
void ps_fetch_time(zval *zv, const MYSQLND_FIELD * const field,
|
||||
uint pack_len, zend_uchar **row,
|
||||
zend_bool as_unicode TSRMLS_DC)
|
||||
{
|
||||
struct st_mysqlnd_time t;
|
||||
unsigned int length; /* First byte encodes the length*/
|
||||
char *to;
|
||||
|
||||
if ((length = php_mysqlnd_net_field_length(row))) {
|
||||
zend_uchar *to= *row;
|
||||
|
||||
t.time_type = MYSQLND_TIMESTAMP_TIME;
|
||||
t.neg = (zend_bool) to[0];
|
||||
|
||||
t.day = (unsigned long) sint4korr(to+1);
|
||||
t.hour = (unsigned int) to[5];
|
||||
t.minute = (unsigned int) to[6];
|
||||
t.second = (unsigned int) to[7];
|
||||
t.second_part = (length > 8) ? (unsigned long) sint4korr(to+8) : 0;
|
||||
t.year = t.month= 0;
|
||||
if (t.day) {
|
||||
/* Convert days to hours at once */
|
||||
t.hour += t.day*24;
|
||||
t.day = 0;
|
||||
}
|
||||
|
||||
(*row) += length;
|
||||
} else {
|
||||
memset(&t, 0, sizeof(t));
|
||||
t.time_type = MYSQLND_TIMESTAMP_TIME;
|
||||
}
|
||||
|
||||
/*
|
||||
QQ : How to make this unicode without copying two times the buffer -
|
||||
Unicode equivalent of spprintf?
|
||||
*/
|
||||
length = spprintf(&to, 0, "%s%02u:%02u:%02u",
|
||||
(t.neg ? "-" : ""), t.hour, t.minute, t.second);
|
||||
|
||||
#if PHP_MAJOR_VERSION >= 6
|
||||
if (!as_unicode) {
|
||||
#endif
|
||||
ZVAL_STRINGL(zv, to, length, 1);
|
||||
mnd_efree(to);
|
||||
#if PHP_MAJOR_VERSION >= 6
|
||||
} else {
|
||||
ZVAL_UTF8_STRINGL(zv, to, length, ZSTR_AUTOFREE);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ ps_fetch_date */
|
||||
static
|
||||
void ps_fetch_date(zval *zv, const MYSQLND_FIELD * const field,
|
||||
uint pack_len, zend_uchar **row,
|
||||
zend_bool as_unicode TSRMLS_DC)
|
||||
{
|
||||
struct st_mysqlnd_time t = {0};
|
||||
unsigned int length; /* First byte encodes the length*/
|
||||
char *to;
|
||||
|
||||
if ((length = php_mysqlnd_net_field_length(row))) {
|
||||
zend_uchar *to= *row;
|
||||
|
||||
t.time_type= MYSQLND_TIMESTAMP_DATE;
|
||||
t.neg= 0;
|
||||
|
||||
t.second_part = t.hour = t.minute = t.second = 0;
|
||||
|
||||
t.year = (unsigned int) sint2korr(to);
|
||||
t.month = (unsigned int) to[2];
|
||||
t.day = (unsigned int) to[3];
|
||||
|
||||
(*row)+= length;
|
||||
} else {
|
||||
memset(&t, 0, sizeof(t));
|
||||
t.time_type = MYSQLND_TIMESTAMP_DATE;
|
||||
}
|
||||
|
||||
/*
|
||||
QQ : How to make this unicode without copying two times the buffer -
|
||||
Unicode equivalent of spprintf?
|
||||
*/
|
||||
length = spprintf(&to, 0, "%04u-%02u-%02u", t.year, t.month, t.day);
|
||||
|
||||
#if PHP_MAJOR_VERSION >= 6
|
||||
if (!as_unicode) {
|
||||
#endif
|
||||
ZVAL_STRINGL(zv, to, length, 1);
|
||||
mnd_efree(to);
|
||||
#if PHP_MAJOR_VERSION >= 6
|
||||
} else {
|
||||
ZVAL_UTF8_STRINGL(zv, to, length, ZSTR_AUTOFREE);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ ps_fetch_datetime */
|
||||
static
|
||||
void ps_fetch_datetime(zval *zv, const MYSQLND_FIELD * const field,
|
||||
uint pack_len, zend_uchar **row,
|
||||
zend_bool as_unicode TSRMLS_DC)
|
||||
{
|
||||
struct st_mysqlnd_time t;
|
||||
unsigned int length; /* First byte encodes the length*/
|
||||
char *to;
|
||||
|
||||
if ((length = php_mysqlnd_net_field_length(row))) {
|
||||
zend_uchar *to= *row;
|
||||
|
||||
t.time_type = MYSQLND_TIMESTAMP_DATETIME;
|
||||
t.neg = 0;
|
||||
|
||||
t.year = (unsigned int) sint2korr(to);
|
||||
t.month = (unsigned int) to[2];
|
||||
t.day = (unsigned int) to[3];
|
||||
|
||||
if (length > 4) {
|
||||
t.hour = (unsigned int) to[4];
|
||||
t.minute = (unsigned int) to[5];
|
||||
t.second = (unsigned int) to[6];
|
||||
} else {
|
||||
t.hour = t.minute = t.second= 0;
|
||||
}
|
||||
t.second_part = (length > 7) ? (unsigned long) sint4korr(to+7) : 0;
|
||||
|
||||
(*row)+= length;
|
||||
} else {
|
||||
memset(&t, 0, sizeof(t));
|
||||
t.time_type = MYSQLND_TIMESTAMP_DATETIME;
|
||||
}
|
||||
|
||||
/*
|
||||
QQ : How to make this unicode without copying two times the buffer -
|
||||
Unicode equivalent of spprintf?
|
||||
*/
|
||||
length = spprintf(&to, 0, "%04u-%02u-%02u %02u:%02u:%02u",
|
||||
t.year, t.month, t.day, t.hour, t.minute, t.second);
|
||||
|
||||
#if PHP_MAJOR_VERSION >= 6
|
||||
if (!as_unicode) {
|
||||
#endif
|
||||
ZVAL_STRINGL(zv, to, length, 1);
|
||||
mnd_efree(to);
|
||||
#if PHP_MAJOR_VERSION >= 6
|
||||
} else {
|
||||
ZVAL_UTF8_STRINGL(zv, to, length, ZSTR_AUTOFREE);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ ps_fetch_string */
|
||||
static
|
||||
void ps_fetch_string(zval *zv, const MYSQLND_FIELD * const field,
|
||||
uint pack_len, zend_uchar **row,
|
||||
zend_bool as_unicode TSRMLS_DC)
|
||||
{
|
||||
/*
|
||||
For now just copy, before we make it possible
|
||||
to write \0 to the row buffer
|
||||
*/
|
||||
unsigned long length= php_mysqlnd_net_field_length(row);
|
||||
|
||||
#if PHP_MAJOR_VERSION < 6
|
||||
ZVAL_STRINGL(zv, (char *)*row, length, 1);
|
||||
#else
|
||||
if (field->charsetnr == MYSQLND_BINARY_CHARSET_NR) {
|
||||
ZVAL_STRINGL(zv, (char *)*row, length, 1);
|
||||
} else {
|
||||
ZVAL_UTF8_STRINGL(zv, (char*)*row, length, ZSTR_DUPLICATE);
|
||||
}
|
||||
#endif
|
||||
|
||||
(*row) += length;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ ps_fetch_bit */
|
||||
static
|
||||
void ps_fetch_bit(zval *zv, const MYSQLND_FIELD * const field,
|
||||
uint pack_len, zend_uchar **row,
|
||||
zend_bool as_unicode TSRMLS_DC)
|
||||
{
|
||||
unsigned long length= php_mysqlnd_net_field_length(row);
|
||||
ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, as_unicode, length TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ _mysqlnd_init_ps_subsystem */
|
||||
void _mysqlnd_init_ps_subsystem()
|
||||
{
|
||||
memset(mysqlnd_ps_fetch_functions, 0, sizeof(mysqlnd_ps_fetch_functions));
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_NULL].func = ps_fetch_null;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_NULL].pack_len = 0;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_NULL].php_type = IS_NULL;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_NULL].can_ret_as_str_in_uni = TRUE;
|
||||
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_TINY].func = ps_fetch_int8;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_TINY].pack_len = 1;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_TINY].php_type = IS_LONG;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_TINY].can_ret_as_str_in_uni = TRUE;
|
||||
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_SHORT].func = ps_fetch_int16;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_SHORT].pack_len = 2;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_SHORT].php_type = IS_LONG;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_SHORT].can_ret_as_str_in_uni = TRUE;
|
||||
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_YEAR].func = ps_fetch_int16;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_YEAR].pack_len = 2;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_YEAR].php_type = IS_LONG;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_YEAR].can_ret_as_str_in_uni = TRUE;
|
||||
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_INT24].func = ps_fetch_int32;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_INT24].pack_len = 4;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_INT24].php_type = IS_LONG;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_INT24].can_ret_as_str_in_uni = TRUE;
|
||||
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONG].func = ps_fetch_int32;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONG].pack_len = 4;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONG].php_type = IS_LONG;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONG].can_ret_as_str_in_uni = TRUE;
|
||||
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONGLONG].func = ps_fetch_int64;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONGLONG].pack_len= 8;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONGLONG].php_type = IS_LONG;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONGLONG].can_ret_as_str_in_uni = TRUE;
|
||||
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_FLOAT].func = ps_fetch_float;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_FLOAT].pack_len = 4;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_FLOAT].php_type = IS_DOUBLE;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_FLOAT].can_ret_as_str_in_uni = TRUE;
|
||||
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_DOUBLE].func = ps_fetch_double;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_DOUBLE].pack_len = 8;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_DOUBLE].php_type = IS_DOUBLE;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_DOUBLE].can_ret_as_str_in_uni = TRUE;
|
||||
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_TIME].func = ps_fetch_time;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_TIME].pack_len = MYSQLND_PS_SKIP_RESULT_W_LEN;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_TIME].php_type = IS_STRING;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_TIME].can_ret_as_str_in_uni = TRUE;
|
||||
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_DATE].func = ps_fetch_date;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_DATE].pack_len = MYSQLND_PS_SKIP_RESULT_W_LEN;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_DATE].php_type = IS_STRING;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_DATE].can_ret_as_str_in_uni = TRUE;
|
||||
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_NEWDATE].func = ps_fetch_date;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_NEWDATE].pack_len = MYSQLND_PS_SKIP_RESULT_W_LEN;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_NEWDATE].php_type = IS_STRING;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_NEWDATE].can_ret_as_str_in_uni = TRUE;
|
||||
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_DATETIME].func = ps_fetch_datetime;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_DATETIME].pack_len= MYSQLND_PS_SKIP_RESULT_W_LEN;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_DATETIME].php_type= IS_STRING;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_DATETIME].can_ret_as_str_in_uni = TRUE;
|
||||
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_TIMESTAMP].func = ps_fetch_datetime;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_TIMESTAMP].pack_len= MYSQLND_PS_SKIP_RESULT_W_LEN;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_TIMESTAMP].php_type= IS_STRING;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_TIMESTAMP].can_ret_as_str_in_uni = TRUE;
|
||||
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_TINY_BLOB].func = ps_fetch_string;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_TINY_BLOB].pack_len= MYSQLND_PS_SKIP_RESULT_STR;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_TINY_BLOB].php_type = IS_STRING;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_TINY_BLOB].is_possibly_blob = TRUE;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_TINY_BLOB].can_ret_as_str_in_uni = TRUE;
|
||||
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_BLOB].func = ps_fetch_string;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_BLOB].pack_len = MYSQLND_PS_SKIP_RESULT_STR;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_BLOB].php_type = IS_STRING;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_BLOB].is_possibly_blob = TRUE;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_BLOB].can_ret_as_str_in_uni = TRUE;
|
||||
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_MEDIUM_BLOB].func = ps_fetch_string;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_MEDIUM_BLOB].pack_len= MYSQLND_PS_SKIP_RESULT_STR;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_MEDIUM_BLOB].php_type= IS_STRING;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_MEDIUM_BLOB].is_possibly_blob = TRUE;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_MEDIUM_BLOB].can_ret_as_str_in_uni = TRUE;
|
||||
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONG_BLOB].func = ps_fetch_string;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONG_BLOB].pack_len = MYSQLND_PS_SKIP_RESULT_STR;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONG_BLOB].php_type = IS_STRING;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONG_BLOB].is_possibly_blob = TRUE;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONG_BLOB].can_ret_as_str_in_uni = TRUE;
|
||||
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_BIT].func = ps_fetch_bit;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_BIT].pack_len = 8;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_BIT].php_type = IS_LONG;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_BIT].can_ret_as_str_in_uni = TRUE;
|
||||
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_VAR_STRING].func = ps_fetch_string;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_VAR_STRING].pack_len = MYSQLND_PS_SKIP_RESULT_STR;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_VAR_STRING].php_type = IS_STRING;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_VAR_STRING].is_possibly_blob = TRUE;
|
||||
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_VARCHAR].func = ps_fetch_string;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_VARCHAR].pack_len = MYSQLND_PS_SKIP_RESULT_STR;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_VARCHAR].php_type = IS_STRING;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_VARCHAR].is_possibly_blob = TRUE;
|
||||
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_STRING].func = ps_fetch_string;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_STRING].pack_len = MYSQLND_PS_SKIP_RESULT_STR;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_STRING].php_type = IS_STRING;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_STRING].is_possibly_blob = TRUE;
|
||||
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_DECIMAL].func = ps_fetch_string;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_DECIMAL].pack_len = MYSQLND_PS_SKIP_RESULT_STR;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_DECIMAL].php_type = IS_STRING;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_DECIMAL].can_ret_as_str_in_uni = TRUE;
|
||||
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_NEWDECIMAL].func = ps_fetch_string;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_NEWDECIMAL].pack_len = MYSQLND_PS_SKIP_RESULT_STR;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_NEWDECIMAL].php_type = IS_STRING;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_NEWDECIMAL].can_ret_as_str_in_uni = TRUE;
|
||||
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_ENUM].func = ps_fetch_string;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_ENUM].pack_len = MYSQLND_PS_SKIP_RESULT_STR;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_ENUM].php_type = IS_STRING;
|
||||
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_SET].func = ps_fetch_string;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_SET].pack_len = MYSQLND_PS_SKIP_RESULT_STR;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_SET].php_type = IS_STRING;
|
||||
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_GEOMETRY].func = ps_fetch_string;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_GEOMETRY].pack_len= MYSQLND_PS_SKIP_RESULT_STR;
|
||||
mysqlnd_ps_fetch_functions[MYSQL_TYPE_GEOMETRY].php_type= IS_STRING;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ 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 TSRMLS_DC)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
unsigned left = (*buf_len - (*p - *buf));
|
||||
unsigned int data_size = 0;
|
||||
|
||||
/* 1. Store type information */
|
||||
if (stmt->send_types_to_server) {
|
||||
|
||||
/* 2 bytes per type, and leave 20 bytes for future use */
|
||||
if (left < ((stmt->param_count * 2) + 20)) {
|
||||
unsigned int offset = *p - *buf;
|
||||
zend_uchar *tmp_buf;
|
||||
*buf_len = offset + stmt->param_count * 2 + 20;
|
||||
tmp_buf = mnd_emalloc(*buf_len);
|
||||
memcpy(tmp_buf, *buf, offset);
|
||||
*buf = tmp_buf;
|
||||
|
||||
/* Update our pos pointer */
|
||||
*p = *buf + offset;
|
||||
}
|
||||
for (i = 0; i < stmt->param_count; i++) {
|
||||
/* our types are not unsigned */
|
||||
#if SIZEOF_LONG==8
|
||||
if (stmt->param_bind[i].type == MYSQL_TYPE_LONG) {
|
||||
stmt->param_bind[i].type = MYSQL_TYPE_LONGLONG;
|
||||
}
|
||||
#endif
|
||||
int2store(*p, stmt->param_bind[i].type);
|
||||
*p+= 2;
|
||||
}
|
||||
}
|
||||
|
||||
/* 2. Store data */
|
||||
/* 2.1 Calculate how much space we need */
|
||||
for (i = 0; i < stmt->param_count; i++) {
|
||||
if (stmt->param_bind[i].zv &&
|
||||
Z_TYPE_P(stmt->param_bind[i].zv) == IS_NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (stmt->param_bind[i].type) {
|
||||
case MYSQL_TYPE_DOUBLE:
|
||||
data_size += 8;
|
||||
break;
|
||||
#if SIZEOF_LONG==8
|
||||
case MYSQL_TYPE_LONGLONG:
|
||||
data_size += 8;
|
||||
break;
|
||||
#elif SIZEOF_LONG==4
|
||||
case MYSQL_TYPE_LONG:
|
||||
data_size += 4;
|
||||
break;
|
||||
#else
|
||||
#error "Should not happen"
|
||||
#endif
|
||||
case MYSQL_TYPE_LONG_BLOB:
|
||||
if (!(stmt->param_bind[i].flags & MYSQLND_PARAM_BIND_BLOB_USED)) {
|
||||
/*
|
||||
User hasn't sent anything, we will send empty string.
|
||||
Empty string has length of 0, encoded in 1 byte. No real
|
||||
data will follow after it.
|
||||
*/
|
||||
data_size++;
|
||||
}
|
||||
break;
|
||||
case MYSQL_TYPE_VAR_STRING:
|
||||
data_size += 8; /* max 8 bytes for size */
|
||||
convert_to_string_ex(&stmt->param_bind[i].zv);
|
||||
data_size += Z_STRLEN_P(stmt->param_bind[i].zv);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* 2.2 Enlarge the buffer, if needed */
|
||||
left = (*buf_len - (*p - *buf));
|
||||
if (left < data_size) {
|
||||
unsigned int offset = *p - *buf;
|
||||
zend_uchar *tmp_buf;
|
||||
*buf_len = offset + data_size + 10; /* Allocate + 10 for safety */
|
||||
tmp_buf = mnd_emalloc(*buf_len);
|
||||
memcpy(tmp_buf, *buf, offset);
|
||||
*buf = tmp_buf;
|
||||
/* Update our pos pointer */
|
||||
*p = *buf + offset;
|
||||
}
|
||||
|
||||
/* 2.3 Store the actual data */
|
||||
for (i = 0; i < stmt->param_count; i++) {
|
||||
zval *data = stmt->param_bind[i].zv;
|
||||
/* Handle long data */
|
||||
if (stmt->param_bind[i].zv && Z_TYPE_P(data) == IS_NULL) {
|
||||
(*buf + null_byte_offset)[i/8] |= (zend_uchar) (1 << (i & 7));
|
||||
} else {
|
||||
switch (stmt->param_bind[i].type) {
|
||||
case MYSQL_TYPE_DOUBLE:
|
||||
convert_to_double_ex(&data);
|
||||
float8store(*p, Z_DVAL_P(data));
|
||||
(*p) += 8;
|
||||
break;
|
||||
#if SIZEOF_LONG==8
|
||||
case MYSQL_TYPE_LONGLONG:
|
||||
convert_to_long_ex(&data);
|
||||
int8store(*p, Z_LVAL_P(data));
|
||||
(*p) += 8;
|
||||
break;
|
||||
#elif SIZEOF_LONG==4
|
||||
case MYSQL_TYPE_LONG:
|
||||
convert_to_long_ex(&data);
|
||||
int4store(*p, Z_LVAL_P(data));
|
||||
(*p) += 4;
|
||||
break;
|
||||
#else
|
||||
#error "Should not happen"
|
||||
#endif
|
||||
case MYSQL_TYPE_LONG_BLOB:
|
||||
if (stmt->param_bind[i].flags & MYSQLND_PARAM_BIND_BLOB_USED) {
|
||||
stmt->param_bind[i].flags &= ~MYSQLND_PARAM_BIND_BLOB_USED;
|
||||
} else {
|
||||
/* send_long_data() not called, send empty string */
|
||||
*p = php_mysqlnd_net_store_length(*p, 0);
|
||||
}
|
||||
break;
|
||||
case MYSQL_TYPE_VAR_STRING:
|
||||
/*
|
||||
If the user uses refs, it could be that the type has
|
||||
has changed and we need to convert, again. Which is noop,
|
||||
if the type hasn't changed.
|
||||
*/
|
||||
convert_to_string_ex(&stmt->param_bind[i].zv);
|
||||
{
|
||||
unsigned int len = Z_STRLEN_P(data);
|
||||
/* to is after p. The latter hasn't been moved */
|
||||
*p = php_mysqlnd_net_store_length(*p, len);
|
||||
memcpy(*p, Z_STRVAL_P(data), len);
|
||||
(*p) += len;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
/* Won't happen, but set to NULL */
|
||||
(*buf + null_byte_offset)[i/8] |= (zend_uchar) (1 << (i & 7));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_stmt_execute_generate_request */
|
||||
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;
|
||||
size_t cmd_buffer_length = stmt->cmd_buffer.length;
|
||||
unsigned int null_byte_offset,
|
||||
null_count= (stmt->param_count + 7) / 8;
|
||||
|
||||
int4store(p, stmt->stmt_id);
|
||||
p += 4;
|
||||
|
||||
/* flags is 4 bytes, we store just 1 */
|
||||
int1store(p, (zend_uchar) stmt->flags);
|
||||
p++;
|
||||
|
||||
/* Make it all zero */
|
||||
int4store(p, 0);
|
||||
|
||||
int1store(p, 1); /* and send 1 for iteration count */
|
||||
p+= 4;
|
||||
|
||||
|
||||
null_byte_offset = p - cmd_buffer;
|
||||
memset(p, 0, null_count);
|
||||
p += null_count;
|
||||
|
||||
|
||||
int1store(p, stmt->send_types_to_server);
|
||||
p++;
|
||||
|
||||
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);
|
||||
return cmd_buffer;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
141
ext/mysqlnd/mysqlnd_qcache.c
Normal file
141
ext/mysqlnd/mysqlnd_qcache.c
Normal file
@ -0,0 +1,141 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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$ */
|
||||
#include "php.h"
|
||||
#include "mysqlnd.h"
|
||||
#include "mysqlnd_priv.h"
|
||||
#include "mysqlnd_statistics.h"
|
||||
|
||||
#define MYSQLND_SILENT
|
||||
|
||||
#ifdef ZTS
|
||||
#define LOCK_QCACHE(cache) tsrm_mutex_lock((cache)->LOCK_access)
|
||||
#define UNLOCK_QCACHE(cache) tsrm_mutex_unlock((cache)->LOCK_access)
|
||||
#else
|
||||
#define LOCK_QCACHE(cache)
|
||||
#define UNLOCK_QCACHE(cache)
|
||||
#endif
|
||||
|
||||
|
||||
/* {{{ mysqlnd_qcache_init_cache */
|
||||
PHPAPI MYSQLND_QCACHE * mysqlnd_qcache_init_cache()
|
||||
{
|
||||
MYSQLND_QCACHE *cache = calloc(1, sizeof(MYSQLND_QCACHE));
|
||||
#ifndef MYSQLND_SILENT
|
||||
php_printf("[mysqlnd_qcache_init_cache %p]\n", cache);
|
||||
#endif
|
||||
|
||||
cache->references = 1;
|
||||
#ifdef ZTS
|
||||
cache->LOCK_access = tsrm_mutex_alloc();
|
||||
#endif
|
||||
cache->ht = malloc(sizeof(HashTable));
|
||||
zend_hash_init(cache->ht, 10 /* init_elements */, NULL, NULL, TRUE /*pers*/);
|
||||
|
||||
return cache;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_qcache_get_cache_reference */
|
||||
PHPAPI MYSQLND_QCACHE * mysqlnd_qcache_get_cache_reference(MYSQLND_QCACHE * const cache)
|
||||
{
|
||||
if (cache) {
|
||||
#ifndef MYSQLND_SILENT
|
||||
php_printf("[mysqlnd_qcache_get_cache_reference %p will become %d]\n", cache, cache->references+1);
|
||||
#endif
|
||||
LOCK_QCACHE(cache);
|
||||
cache->references++;
|
||||
UNLOCK_QCACHE(cache);
|
||||
}
|
||||
return cache;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_qcache_free_cache */
|
||||
/*
|
||||
As this call will happen on MSHUTDOWN(), then we don't need to copy the zvals with
|
||||
copy_ctor but scrap what they point to with zval_dtor() and then just free our
|
||||
pre-allocated block. Precondition is that we ZVAL_NULL() the zvals when we put them
|
||||
to the free list after usage. We ZVAL_NULL() them when we allocate them in the
|
||||
constructor of the cache.
|
||||
*/
|
||||
static
|
||||
void mysqlnd_qcache_free_cache(MYSQLND_QCACHE *cache)
|
||||
{
|
||||
#ifndef MYSQLND_SILENT
|
||||
php_printf("[mysqlnd_qcache_free_cache %p]\n", cache);
|
||||
#endif
|
||||
|
||||
#ifdef ZTS
|
||||
tsrm_mutex_free(cache->LOCK_access);
|
||||
#endif
|
||||
zend_hash_destroy(cache->ht);
|
||||
free(cache->ht);
|
||||
free(cache);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_qcache_free_cache_reference */
|
||||
PHPAPI void mysqlnd_qcache_free_cache_reference(MYSQLND_QCACHE **cache)
|
||||
{
|
||||
if (*cache) {
|
||||
zend_bool to_free;
|
||||
#ifndef MYSQLND_SILENT
|
||||
php_printf("[mysqlnd_qcache_free_cache_reference %p] refs=%d\n", *cache, (*cache)->references);
|
||||
#endif
|
||||
LOCK_QCACHE(*cache);
|
||||
to_free = --(*cache)->references == 0;
|
||||
/* Unlock before destroying */
|
||||
UNLOCK_QCACHE(*cache);
|
||||
if (to_free) {
|
||||
mysqlnd_qcache_free_cache(*cache);
|
||||
}
|
||||
*cache = NULL;
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_qcache_free_cache_reference */
|
||||
PHPAPI void mysqlnd_qcache_stats(const MYSQLND_QCACHE * const cache, zval *return_value)
|
||||
{
|
||||
if (cache) {
|
||||
LOCK_QCACHE(cache);
|
||||
array_init(return_value);
|
||||
add_assoc_long_ex(return_value, "references", sizeof("references"), cache->references);
|
||||
UNLOCK_QCACHE(cache);
|
||||
} else {
|
||||
ZVAL_NULL(return_value);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
1194
ext/mysqlnd/mysqlnd_result.c
Normal file
1194
ext/mysqlnd/mysqlnd_result.c
Normal file
File diff suppressed because it is too large
Load Diff
48
ext/mysqlnd/mysqlnd_result.h
Normal file
48
ext/mysqlnd/mysqlnd_result.h
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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_RESULT_H
|
||||
#define MYSQLND_RESULT_H
|
||||
|
||||
MYSQLND_RES *mysqlnd_result_init(unsigned int field_count, MYSQLND_THD_ZVAL_PCACHE *cache TSRMLS_DC);
|
||||
|
||||
void mysqlnd_unbuffered_free_last_data(MYSQLND_RES *result TSRMLS_DC);
|
||||
|
||||
enum_func_status
|
||||
mysqlnd_store_result_fetch_data(MYSQLND * const conn, MYSQLND_RES *result,
|
||||
MYSQLND_RES_METADATA *meta,
|
||||
zend_bool binary_protocol,
|
||||
zend_bool update_max_length,
|
||||
zend_bool to_cache TSRMLS_DC);
|
||||
|
||||
enum_func_status mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT *stmt TSRMLS_DC);
|
||||
|
||||
#endif /* MYSQLND_RESULT_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
|
||||
*/
|
440
ext/mysqlnd/mysqlnd_result_meta.c
Normal file
440
ext/mysqlnd/mysqlnd_result_meta.c
Normal file
@ -0,0 +1,440 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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$ */
|
||||
#include "php.h"
|
||||
#include "mysqlnd.h"
|
||||
#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 TSRMLS_DC)
|
||||
{
|
||||
if (meta) {
|
||||
if (meta->root) {
|
||||
mnd_pefree(meta->root, persistent);
|
||||
meta->root = NULL;
|
||||
}
|
||||
if (meta->def) {
|
||||
mnd_pefree(meta->def, persistent);
|
||||
meta->def = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_handle_numeric */
|
||||
/*
|
||||
The following code is stolen from ZE - HANDLE_NUMERIC() macro from zend_hash.c
|
||||
and modified for the needs of mysqlnd.
|
||||
*/
|
||||
static
|
||||
zend_bool mysqlnd_is_key_numeric(char *key, size_t length, long *idx)
|
||||
{
|
||||
register char *tmp=key;
|
||||
|
||||
if (*tmp=='-') {
|
||||
tmp++;
|
||||
}
|
||||
if ((*tmp>='0' && *tmp<='9')) {
|
||||
do { /* possibly a numeric index */
|
||||
char *end=key+length-1;
|
||||
|
||||
if (*tmp++=='0' && length>2) { /* don't accept numbers with leading zeros */
|
||||
break;
|
||||
}
|
||||
while (tmp<end) {
|
||||
if (!(*tmp>='0' && *tmp<='9')) {
|
||||
break;
|
||||
}
|
||||
tmp++;
|
||||
}
|
||||
if (tmp==end && *tmp=='\0') { /* a numeric index */
|
||||
if (*key=='-') {
|
||||
*idx = strtol(key, NULL, 10);
|
||||
if (*idx!=LONG_MIN) {
|
||||
return TRUE;
|
||||
}
|
||||
} else {
|
||||
*idx = strtol(key, NULL, 10);
|
||||
if (*idx!=LONG_MAX) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (0);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
#if PHP_MAJOR_VERSION >= 6
|
||||
/* {{{ mysqlnd_unicode_is_key_numeric */
|
||||
static
|
||||
zend_bool mysqlnd_unicode_is_key_numeric(UChar *key, size_t length, long *idx)
|
||||
{
|
||||
register UChar *tmp=key;
|
||||
|
||||
if (*tmp==0x2D /*'-'*/) {
|
||||
tmp++;
|
||||
}
|
||||
if ((*tmp>=0x30 /*'0'*/ && *tmp<=0x39 /*'9'*/)) { /* possibly a numeric index */
|
||||
do {
|
||||
UChar *end=key+length-1;
|
||||
|
||||
if (*tmp++==0x30 && length>2) { /* don't accept numbers with leading zeros */
|
||||
break;
|
||||
}
|
||||
while (tmp<end) {
|
||||
if (!(*tmp>=0x30 /*'0'*/ && *tmp<=0x39 /*'9'*/)) {
|
||||
break;
|
||||
}
|
||||
tmp++;
|
||||
}
|
||||
if (tmp==end && *tmp==0) { /* a numeric index */
|
||||
if (*key==0x2D /*'-'*/) {
|
||||
*idx = zend_u_strtol(key, NULL, 10);
|
||||
if (*idx!=LONG_MIN) {
|
||||
return TRUE;
|
||||
}
|
||||
} else {
|
||||
*idx = zend_u_strtol(key, NULL, 10);
|
||||
if (*idx!=LONG_MAX) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (0);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
/* }}} */
|
||||
#endif
|
||||
|
||||
|
||||
/* {{{ mysqlnd_res_meta::read_metadata */
|
||||
static enum_func_status
|
||||
MYSQLND_METHOD(mysqlnd_res_meta, read_metadata)(MYSQLND_RES_METADATA * const meta,
|
||||
MYSQLND *conn TSRMLS_DC)
|
||||
{
|
||||
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 */
|
||||
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);
|
||||
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);
|
||||
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;
|
||||
/*
|
||||
If there is rest, add one byte :
|
||||
8 bits = 1 byte but 9 bits = 2 bytes
|
||||
*/
|
||||
if (meta->fields[i].length % 8) {
|
||||
++field_len;
|
||||
}
|
||||
switch (field_len) {
|
||||
case 8:
|
||||
case 7:
|
||||
case 6:
|
||||
case 5:
|
||||
meta->bit_fields_total_len += 20;/* 21 digis, no sign*/
|
||||
break;
|
||||
case 4:
|
||||
meta->bit_fields_total_len += 10;/* 2 000 000 000*/
|
||||
break;
|
||||
case 3:
|
||||
meta->bit_fields_total_len += 8;/* 12 000 000*/
|
||||
break;
|
||||
case 2:
|
||||
meta->bit_fields_total_len += 5;/* 32 500 */
|
||||
break;
|
||||
case 1:
|
||||
meta->bit_fields_total_len += 3;/* 120 */
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#if PHP_MAJOR_VERSION >= 6
|
||||
if (UG(unicode)) {
|
||||
UChar *ustr;
|
||||
int ulen;
|
||||
zend_string_to_unicode(UG(utf8_conv), &ustr, &ulen,
|
||||
meta->fields[i].name,
|
||||
meta->fields[i].name_length TSRMLS_CC);
|
||||
if ((meta->zend_hash_keys[i].is_numeric =
|
||||
mysqlnd_unicode_is_key_numeric(ustr, ulen + 1, &idx)))
|
||||
{
|
||||
meta->zend_hash_keys[i].key = idx;
|
||||
mnd_efree(ustr);
|
||||
} else {
|
||||
meta->zend_hash_keys[i].ustr.u = ustr;
|
||||
meta->zend_hash_keys[i].ulen = ulen;
|
||||
meta->zend_hash_keys[i].key = zend_u_get_hash_value(IS_UNICODE, ZSTR(ustr), ulen + 1);
|
||||
}
|
||||
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
/* For BC we have to check whether the key is numeric and use it like this */
|
||||
if ((meta->zend_hash_keys[i].is_numeric =
|
||||
mysqlnd_is_key_numeric(field_packet.metadata->name,
|
||||
field_packet.metadata->name_length + 1,
|
||||
&idx)))
|
||||
{
|
||||
meta->zend_hash_keys[i].key = idx;
|
||||
} else {
|
||||
meta->zend_hash_keys[i].key =
|
||||
zend_get_hash_value(field_packet.metadata->name,
|
||||
field_packet.metadata->name_length + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
PACKET_FREE_ALLOCA(field_packet);
|
||||
|
||||
DBG_RETURN(PASS);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_res_meta::free */
|
||||
static void
|
||||
MYSQLND_METHOD(mysqlnd_res_meta, free)(MYSQLND_RES_METADATA *meta, zend_bool persistent TSRMLS_DC)
|
||||
{
|
||||
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 TSRMLS_CC);
|
||||
}
|
||||
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) {
|
||||
mnd_pefree(meta->zend_hash_keys[i].ustr.v, persistent);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
mnd_pefree(meta->zend_hash_keys, persistent);
|
||||
meta->zend_hash_keys = NULL;
|
||||
}
|
||||
DBG_INF("Freeing metadata structure");
|
||||
mnd_pefree(meta, persistent);
|
||||
|
||||
DBG_VOID_RETURN;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_res::clone_metadata */
|
||||
static MYSQLND_RES_METADATA *
|
||||
MYSQLND_METHOD(mysqlnd_res_meta, clone_metadata)(const MYSQLND_RES_METADATA * const meta,
|
||||
zend_bool persistent TSRMLS_DC)
|
||||
{
|
||||
unsigned int i;
|
||||
/* +1 is to have empty marker at the end */
|
||||
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);
|
||||
|
||||
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;
|
||||
|
||||
/*
|
||||
This will copy also the strings and the root, which we will have
|
||||
to adjust in the loop
|
||||
*/
|
||||
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 = 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) {
|
||||
new_fields[i].name = new_fields[i].root +
|
||||
(orig_fields[i].name - orig_fields[i].root);
|
||||
}
|
||||
if (orig_fields[i].org_name && orig_fields[i].org_name != mysqlnd_empty_string) {
|
||||
new_fields[i].org_name = new_fields[i].root +
|
||||
(orig_fields[i].org_name - orig_fields[i].root);
|
||||
}
|
||||
if (orig_fields[i].table && orig_fields[i].table != mysqlnd_empty_string) {
|
||||
new_fields[i].table = new_fields[i].root +
|
||||
(orig_fields[i].table - orig_fields[i].root);
|
||||
}
|
||||
if (orig_fields[i].org_table && orig_fields[i].org_table != mysqlnd_empty_string) {
|
||||
new_fields[i].org_table = new_fields[i].root +
|
||||
(orig_fields[i].org_table - orig_fields[i].root);
|
||||
}
|
||||
if (orig_fields[i].db && orig_fields[i].db != mysqlnd_empty_string) {
|
||||
new_fields[i].db = new_fields[i].root + (orig_fields[i].db - orig_fields[i].root);
|
||||
}
|
||||
if (orig_fields[i].catalog && orig_fields[i].catalog != mysqlnd_empty_string) {
|
||||
new_fields[i].catalog = new_fields[i].root + (orig_fields[i].catalog - orig_fields[i].root);
|
||||
}
|
||||
/* def is not on the root, if allocated at all */
|
||||
if (orig_fields[i].def) {
|
||||
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);
|
||||
}
|
||||
#if PHP_MAJOR_VERSION >= 6
|
||||
if (new_meta->zend_hash_keys[i].ustr.u) {
|
||||
new_meta->zend_hash_keys[i].ustr.u =
|
||||
eustrndup(new_meta->zend_hash_keys[i].ustr.u, new_meta->zend_hash_keys[i].ulen);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
new_meta->current_field = 0;
|
||||
new_meta->field_count = meta->field_count;
|
||||
|
||||
new_meta->fields = new_fields;
|
||||
|
||||
DBG_RETURN(new_meta);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ mysqlnd_res_meta::fetch_field */
|
||||
static MYSQLND_FIELD *
|
||||
MYSQLND_METHOD(mysqlnd_res_meta, fetch_field)(MYSQLND_RES_METADATA * const meta TSRMLS_DC)
|
||||
{
|
||||
DBG_ENTER("mysqlnd_res_meta::fetch_field");
|
||||
if (meta->current_field >= meta->field_count) {
|
||||
DBG_RETURN(NULL);
|
||||
}
|
||||
DBG_RETURN(&meta->fields[meta->current_field++]);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ 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 TSRMLS_DC)
|
||||
{
|
||||
DBG_ENTER("mysqlnd_res_meta::fetch_field_direct");
|
||||
DBG_INF_FMT("fieldnr=%d", fieldnr);
|
||||
DBG_RETURN(&meta->fields[fieldnr]);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_res_meta::field_tell */
|
||||
static MYSQLND_FIELD_OFFSET
|
||||
MYSQLND_METHOD(mysqlnd_res_meta, field_tell)(const MYSQLND_RES_METADATA * const meta)
|
||||
{
|
||||
return meta->current_field;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
MYSQLND_CLASS_METHODS_START(mysqlnd_res_meta)
|
||||
MYSQLND_METHOD(mysqlnd_res_meta, fetch_field),
|
||||
MYSQLND_METHOD(mysqlnd_res_meta, fetch_field_direct),
|
||||
MYSQLND_METHOD(mysqlnd_res_meta, field_tell),
|
||||
MYSQLND_METHOD(mysqlnd_res_meta, read_metadata),
|
||||
MYSQLND_METHOD(mysqlnd_res_meta, clone_metadata),
|
||||
MYSQLND_METHOD(mysqlnd_res_meta, free),
|
||||
MYSQLND_CLASS_METHODS_END;
|
||||
|
||||
|
||||
/* {{{ mysqlnd_result_meta_init */
|
||||
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 = 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;
|
||||
DBG_INF_FMT("meta=%p", ret);
|
||||
DBG_RETURN(ret);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
40
ext/mysqlnd/mysqlnd_result_meta.h
Normal file
40
ext/mysqlnd/mysqlnd_result_meta.h
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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_RESULT_META_H
|
||||
#define MYSQLND_RESULT_META_H
|
||||
|
||||
|
||||
MYSQLND_RES_METADATA *mysqlnd_result_meta_init(unsigned int field_count TSRMLS_DC);
|
||||
|
||||
|
||||
|
||||
#endif /* MYSQLND_RESULT_META_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
|
||||
*/
|
155
ext/mysqlnd/mysqlnd_statistics.c
Normal file
155
ext/mysqlnd/mysqlnd_statistics.c
Normal file
@ -0,0 +1,155 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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$ */
|
||||
#include "php.h"
|
||||
#include "mysqlnd.h"
|
||||
#include "mysqlnd_priv.h"
|
||||
#include "mysqlnd_statistics.h"
|
||||
#include "mysqlnd_debug.h"
|
||||
|
||||
|
||||
#define STR_W_LEN(str) str, (sizeof(str) - 1)
|
||||
|
||||
/* {{{ mysqlnd_stats_values_names
|
||||
*/
|
||||
const MYSQLND_STRING mysqlnd_stats_values_names[STAT_LAST] =
|
||||
{
|
||||
{ STR_W_LEN("bytes_sent") },
|
||||
{ STR_W_LEN("bytes_received") },
|
||||
{ STR_W_LEN("packets_sent") },
|
||||
{ STR_W_LEN("packets_received") },
|
||||
{ STR_W_LEN("protocol_overhead_in") },
|
||||
{ STR_W_LEN("protocol_overhead_out") },
|
||||
{ STR_W_LEN("result_set_queries") },
|
||||
{ STR_W_LEN("non_result_set_queries") },
|
||||
{ STR_W_LEN("no_index_used") },
|
||||
{ STR_W_LEN("bad_index_used") },
|
||||
{ STR_W_LEN("buffered_sets") },
|
||||
{ STR_W_LEN("unbuffered_sets") },
|
||||
{ STR_W_LEN("ps_buffered_sets") },
|
||||
{ STR_W_LEN("ps_unbuffered_sets") },
|
||||
{ STR_W_LEN("flushed_normal_sets") },
|
||||
{ STR_W_LEN("flushed_ps_sets") },
|
||||
{ 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") },
|
||||
{ STR_W_LEN("in_middle_of_command_close") },
|
||||
{ STR_W_LEN("explicit_free_result") },
|
||||
{ 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)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
mysqlnd_array_init(return_value, STAT_LAST);
|
||||
for (i = 0; i < STAT_LAST; i++) {
|
||||
char tmp[22];
|
||||
|
||||
sprintf((char *)&tmp, MYSQLND_LLU_SPEC, stats->values[i]);
|
||||
#if PHP_MAJOR_VERSION >= 6
|
||||
if (UG(unicode)) {
|
||||
UChar *ustr, *tstr;
|
||||
int ulen, tlen;
|
||||
|
||||
zend_string_to_unicode(UG(utf8_conv), &ustr, &ulen, mysqlnd_stats_values_names[i].s,
|
||||
mysqlnd_stats_values_names[i].l + 1 TSRMLS_CC);
|
||||
zend_string_to_unicode(UG(utf8_conv), &tstr, &tlen, tmp, strlen(tmp) + 1 TSRMLS_CC);
|
||||
add_u_assoc_unicode_ex(return_value, IS_UNICODE, ZSTR(ustr), ulen, tstr, 1);
|
||||
efree(ustr);
|
||||
efree(tstr);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
add_assoc_string_ex(return_value, mysqlnd_stats_values_names[i].s,
|
||||
mysqlnd_stats_values_names[i].l + 1, tmp, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ _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;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
209
ext/mysqlnd/mysqlnd_statistics.h
Normal file
209
ext/mysqlnd/mysqlnd_statistics.h
Normal file
@ -0,0 +1,209 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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_STATISTICS_H
|
||||
#define MYSQLND_STATISTICS_H
|
||||
|
||||
|
||||
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_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)]++; \
|
||||
tsrm_mutex_unlock(mysqlnd_global_stats->LOCK_access); \
|
||||
if ((conn_stats)) { \
|
||||
((MYSQLND_STATS *) conn_stats)->values[(statistic)]++; \
|
||||
} \
|
||||
}\
|
||||
}
|
||||
|
||||
#define MYSQLND_INC_CONN_STATISTIC_W_VALUE(conn_stats, statistic, 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; \
|
||||
tsrm_mutex_unlock(mysqlnd_global_stats->LOCK_access); \
|
||||
if ((conn_stats)) { \
|
||||
((MYSQLND_STATS *) conn_stats)->values[(statistic)]+= v; \
|
||||
} \
|
||||
}\
|
||||
}
|
||||
|
||||
#define MYSQLND_INC_CONN_STATISTIC_W_VALUE3(conn_stats, statistic1, value1, statistic2, value2, statistic3, 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; \
|
||||
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; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
#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_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)]++; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define MYSQLND_INC_CONN_STATISTIC_W_VALUE(conn_stats, statistic, value) \
|
||||
{ \
|
||||
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; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define MYSQLND_INC_CONN_STATISTIC_W_VALUE3(conn_stats, statistic1, value1, statistic2, value2, statistic3, 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; \
|
||||
if ((conn_stats)) { \
|
||||
((MYSQLND_STATS *) conn_stats)->values[(statistic1)]+= v1; \
|
||||
((MYSQLND_STATS *) conn_stats)->values[(statistic2)]+= v2; \
|
||||
((MYSQLND_STATS *) conn_stats)->values[(statistic3)]+= v3; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void mysqlnd_fill_stats_hash(const MYSQLND_STATS * const stats, zval *return_value
|
||||
TSRMLS_DC ZEND_FILE_LINE_DC);
|
||||
|
||||
#endif /* MYSQLND_STATISTICS_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
|
||||
*/
|
540
ext/mysqlnd/mysqlnd_structs.h
Normal file
540
ext/mysqlnd/mysqlnd_structs.h
Normal 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;
|
||||
mynd_ulonglong affected_rows;
|
||||
mynd_ulonglong 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;
|
||||
mynd_ulonglong 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 */
|
1956
ext/mysqlnd/mysqlnd_wireprotocol.c
Normal file
1956
ext/mysqlnd/mysqlnd_wireprotocol.c
Normal file
File diff suppressed because it is too large
Load Diff
335
ext/mysqlnd/mysqlnd_wireprotocol.h
Normal file
335
ext/mysqlnd/mysqlnd_wireprotocol.h
Normal file
@ -0,0 +1,335 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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_WIREPROTOCOL_H
|
||||
#define MYSQLND_WIREPROTOCOL_H
|
||||
|
||||
#define MYSQLND_HEADER_SIZE 4
|
||||
|
||||
#define MYSQLND_NULL_LENGTH (unsigned long) ~0
|
||||
|
||||
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) \
|
||||
{ \
|
||||
packet = (c_type) ecalloc(1, packet_methods[enum_type].struct_size); \
|
||||
((c_type) (packet))->header.m = &packet_methods[enum_type]; \
|
||||
}
|
||||
#define PACKET_WRITE(packet, conn) ((packet)->header.m->write_to_net((packet), (conn) TSRMLS_CC))
|
||||
#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 TSRMLS_CC)); \
|
||||
} while (0);
|
||||
|
||||
#define PACKET_INIT_ALLOCA(packet, enum_type) \
|
||||
{ \
|
||||
memset(&(packet), 0, packet_methods[enum_type].struct_size); \
|
||||
(packet).header.m = &packet_methods[enum_type]; \
|
||||
}
|
||||
#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 TSRMLS_CC))
|
||||
|
||||
/* Enums */
|
||||
enum php_mysql_packet_type
|
||||
{
|
||||
PROT_GREET_PACKET= 0,
|
||||
PROT_AUTH_PACKET,
|
||||
PROT_OK_PACKET,
|
||||
PROT_EOF_PACKET,
|
||||
PROT_CMD_PACKET,
|
||||
PROT_RSET_HEADER_PACKET,
|
||||
PROT_RSET_FLD_PACKET,
|
||||
PROT_ROW_PACKET,
|
||||
PROT_STATS_PACKET,
|
||||
PROT_PREPARE_RESP_PACKET,
|
||||
PROT_CHG_USER_PACKET,
|
||||
PROT_LAST, /* should always be last */
|
||||
};
|
||||
|
||||
|
||||
enum php_mysqlnd_server_command
|
||||
{
|
||||
COM_SLEEP = 0,
|
||||
COM_QUIT,
|
||||
COM_INIT_DB,
|
||||
COM_QUERY,
|
||||
COM_FIELD_LIST,
|
||||
COM_CREATE_DB,
|
||||
COM_DROP_DB,
|
||||
COM_REFRESH,
|
||||
COM_SHUTDOWN,
|
||||
COM_STATISTICS,
|
||||
COM_PROCESS_INFO,
|
||||
COM_CONNECT,
|
||||
COM_PROCESS_KILL,
|
||||
COM_DEBUG,
|
||||
COM_PING,
|
||||
COM_TIME = 15,
|
||||
COM_DELAYED_INSERT,
|
||||
COM_CHANGE_USER,
|
||||
COM_BINLOG_DUMP,
|
||||
COM_TABLE_DUMP,
|
||||
COM_CONNECT_OUT = 20,
|
||||
COM_REGISTER_SLAVE,
|
||||
COM_STMT_PREPARE = 22,
|
||||
COM_STMT_EXECUTE = 23,
|
||||
COM_STMT_SEND_LONG_DATA = 24,
|
||||
COM_STMT_CLOSE = 25,
|
||||
COM_STMT_RESET = 26,
|
||||
COM_SET_OPTION = 27,
|
||||
COM_STMT_FETCH = 28,
|
||||
COM_DAEMON,
|
||||
COM_END
|
||||
};
|
||||
|
||||
extern const char * const mysqlnd_command_to_text[COM_END];
|
||||
|
||||
/* Low-level extraction functionality */
|
||||
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 TSRMLS_DC);
|
||||
} mysqlnd_packet_methods;
|
||||
|
||||
extern mysqlnd_packet_methods packet_methods[];
|
||||
|
||||
|
||||
typedef struct st_mysqlnd_packet_header {
|
||||
size_t size;
|
||||
zend_uchar packet_no;
|
||||
mysqlnd_packet_methods *m;
|
||||
} mysqlnd_packet_header;
|
||||
|
||||
/* Server greets the client */
|
||||
typedef struct st_php_mysql_packet_greet {
|
||||
mysqlnd_packet_header header;
|
||||
mysqlnd_1b protocol_version;
|
||||
char *server_version;
|
||||
mysqlnd_4b thread_id;
|
||||
zend_uchar scramble_buf[SCRAMBLE_LENGTH];
|
||||
/* 1 byte pad */
|
||||
mysqlnd_2b server_capabilities;
|
||||
mysqlnd_1b charset_no;
|
||||
mysqlnd_2b server_status;
|
||||
/* 13 byte pad*/
|
||||
zend_bool pre41;
|
||||
/* If error packet, we use these */
|
||||
char error[MYSQLND_ERRMSG_SIZE+1];
|
||||
char sqlstate[MYSQLND_SQLSTATE_LENGTH + 1];
|
||||
unsigned int error_no;
|
||||
} php_mysql_packet_greet;
|
||||
|
||||
|
||||
/* Client authenticates */
|
||||
typedef struct st_php_mysql_packet_auth {
|
||||
mysqlnd_packet_header header;
|
||||
mysqlnd_4b client_flags;
|
||||
uint32 max_packet_size;
|
||||
mysqlnd_1b charset_no;
|
||||
/* 23 byte pad */
|
||||
char *user;
|
||||
/* 8 byte scramble */
|
||||
char *db;
|
||||
/* 12 byte scramble */
|
||||
|
||||
/* Here the packet ends. This is user supplied data */
|
||||
char *password;
|
||||
/* +1 for \0 because of scramble() */
|
||||
unsigned char *server_scramble_buf;
|
||||
size_t db_len;
|
||||
} php_mysql_packet_auth;
|
||||
|
||||
/* OK packet */
|
||||
typedef struct st_php_mysql_packet_ok {
|
||||
mysqlnd_packet_header header;
|
||||
mysqlnd_1b field_count; /* always 0x0 */
|
||||
mynd_ulonglong affected_rows;
|
||||
mynd_ulonglong last_insert_id;
|
||||
mysqlnd_2b server_status;
|
||||
mysqlnd_2b warning_count;
|
||||
char *message;
|
||||
size_t message_len;
|
||||
/* If error packet, we use these */
|
||||
char error[MYSQLND_ERRMSG_SIZE+1];
|
||||
char sqlstate[MYSQLND_SQLSTATE_LENGTH + 1];
|
||||
unsigned int error_no;
|
||||
} php_mysql_packet_ok;
|
||||
|
||||
|
||||
/* Command packet */
|
||||
typedef struct st_php_mysql_packet_command {
|
||||
mysqlnd_packet_header header;
|
||||
enum php_mysqlnd_server_command command;
|
||||
const char *argument;
|
||||
size_t arg_len;
|
||||
} php_mysql_packet_command;
|
||||
|
||||
|
||||
/* EOF packet */
|
||||
typedef struct st_php_mysql_packet_eof {
|
||||
mysqlnd_packet_header header;
|
||||
mysqlnd_1b field_count; /* 0xFE */
|
||||
mysqlnd_2b warning_count;
|
||||
mysqlnd_2b server_status;
|
||||
/* If error packet, we use these */
|
||||
char error[MYSQLND_ERRMSG_SIZE+1];
|
||||
char sqlstate[MYSQLND_SQLSTATE_LENGTH + 1];
|
||||
unsigned int error_no;
|
||||
} php_mysql_packet_eof;
|
||||
/* EOF packet */
|
||||
|
||||
|
||||
/* Result Set header*/
|
||||
typedef struct st_php_mysql_packet_rset_header {
|
||||
mysqlnd_packet_header header;
|
||||
/*
|
||||
0x00 => ok
|
||||
~0 => LOAD DATA LOCAL
|
||||
error_no != 0 => error
|
||||
others => result set -> Read res_field packets up to field_count
|
||||
*/
|
||||
unsigned long field_count;
|
||||
/*
|
||||
These are filled if no SELECT query. For SELECT warning_count
|
||||
and server status are in the last row packet, the EOF packet.
|
||||
*/
|
||||
mysqlnd_2b warning_count;
|
||||
mysqlnd_2b server_status;
|
||||
mynd_ulonglong affected_rows;
|
||||
mynd_ulonglong last_insert_id;
|
||||
/* This is for both LOAD DATA or info, when no result set */
|
||||
char *info_or_local_file;
|
||||
size_t info_or_local_file_len;
|
||||
/* If error packet, we use these */
|
||||
mysqlnd_error_info error_info;
|
||||
} php_mysql_packet_rset_header;
|
||||
|
||||
|
||||
/* Result set field packet */
|
||||
typedef struct st_php_mysql_packet_res_field {
|
||||
mysqlnd_packet_header header;
|
||||
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;
|
||||
|
||||
|
||||
/* Row packet */
|
||||
struct st_php_mysql_packet_row {
|
||||
mysqlnd_packet_header header;
|
||||
zval **fields;
|
||||
mysqlnd_4b field_count;
|
||||
zend_bool eof;
|
||||
/*
|
||||
These are, of course, only for SELECT in the EOF packet,
|
||||
which is detected by this packet
|
||||
*/
|
||||
mysqlnd_2b warning_count;
|
||||
mysqlnd_2b server_status;
|
||||
|
||||
zend_uchar *row_buffer;
|
||||
|
||||
zend_bool skip_extraction;
|
||||
zend_bool binary_protocol;
|
||||
zend_bool persistent_alloc;
|
||||
MYSQLND_FIELD *fields_metadata;
|
||||
/* We need this to alloc bigger bufs in non-PS mode */
|
||||
unsigned int bit_fields_count;
|
||||
size_t bit_fields_total_len; /* trailing \0 not counted */
|
||||
|
||||
/* If error packet, we use these */
|
||||
mysqlnd_error_info error_info;
|
||||
};
|
||||
|
||||
|
||||
/* Statistics packet */
|
||||
typedef struct st_php_mysql_packet_stats {
|
||||
mysqlnd_packet_header header;
|
||||
char *message;
|
||||
/* message_len is not part of the packet*/
|
||||
size_t message_len;
|
||||
} php_mysql_packet_stats;
|
||||
|
||||
|
||||
/* COM_PREPARE response packet */
|
||||
typedef struct st_php_mysql_packet_prepare_response {
|
||||
mysqlnd_packet_header header;
|
||||
/* also known as field_count 0x00=OK , 0xFF=error */
|
||||
unsigned char error_code;
|
||||
unsigned long stmt_id;
|
||||
unsigned int field_count;
|
||||
unsigned int param_count;
|
||||
unsigned int warning_count;
|
||||
|
||||
/* present in case of error */
|
||||
mysqlnd_error_info error_info;
|
||||
} php_mysql_packet_prepare_response;
|
||||
|
||||
|
||||
/* Statistics packet */
|
||||
typedef struct st_php_mysql_packet_chg_user_resp {
|
||||
mysqlnd_packet_header header;
|
||||
mysqlnd_4b field_count;
|
||||
|
||||
/* message_len is not part of the packet*/
|
||||
mysqlnd_2b server_capabilities;
|
||||
/* If error packet, we use these */
|
||||
mysqlnd_error_info error_info;
|
||||
} php_mysql_packet_chg_user_resp;
|
||||
|
||||
|
||||
size_t mysqlnd_stream_write(MYSQLND * const conn, char * const buf, size_t count TSRMLS_DC);
|
||||
size_t mysqlnd_stream_write_w_header(MYSQLND * const conn, char * const buf, size_t count TSRMLS_DC);
|
||||
|
||||
#ifdef MYSQLND_DO_WIRE_CHECK_BEFORE_COMMAND
|
||||
size_t php_mysqlnd_consume_uneaten_data(MYSQLND * const conn, enum php_mysqlnd_server_command cmd TSRMLS_DC);
|
||||
#endif
|
||||
|
||||
void php_mysqlnd_scramble(zend_uchar * const buffer, const zend_uchar * const scramble, const zend_uchar * const pass);
|
||||
|
||||
unsigned long php_mysqlnd_net_field_length(zend_uchar **packet);
|
||||
zend_uchar * php_mysqlnd_net_store_length(zend_uchar *packet, mynd_ulonglong length);
|
||||
|
||||
extern char * const mysqlnd_empty_string;
|
||||
|
||||
#endif /* MYSQLND_WIREPROTOCOL_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
|
||||
*/
|
29
ext/mysqlnd/php_mysqlnd.h
Normal file
29
ext/mysqlnd/php_mysqlnd.h
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| PHP Version 6 |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1997-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@php.net> |
|
||||
| Andrey Hristov <andrey@php.net> |
|
||||
| Ulf Wendel <uw@php.net> |
|
||||
+----------------------------------------------------------------------+
|
||||
|
||||
$Id$
|
||||
*/
|
||||
|
||||
#ifndef PHP_MYSQLND_H
|
||||
#define PHP_MYSQLND_H
|
||||
|
||||
#define phpext_mysqlnd_ptr &mysqlnd_module_entry
|
||||
extern zend_module_entry mysqlnd_module_entry;
|
||||
|
||||
#endif /* PHP_MYSQLND_H */
|
Loading…
Reference in New Issue
Block a user