summaryrefslogtreecommitdiff
path: root/ext/mysqli
diff options
context:
space:
mode:
Diffstat (limited to 'ext/mysqli')
-rw-r--r--ext/mysqli/mysqli.c38
-rw-r--r--ext/mysqli/mysqli_api.c125
-rw-r--r--ext/mysqli/mysqli_fe.c8
-rw-r--r--ext/mysqli/mysqli_nonapi.c47
-rw-r--r--ext/mysqli/php_mysqli.h19
-rw-r--r--ext/mysqli/tests/033.phpt6
-rw-r--r--ext/mysqli/tests/064.phpt21
-rw-r--r--ext/mysqli/tests/065.phpt37
-rw-r--r--ext/mysqli/tests/bug31668.phpt56
-rw-r--r--ext/mysqli/tests/bug32405.phpt38
-rw-r--r--ext/mysqli/tests/bug33090.phpt21
-rw-r--r--ext/mysqli/tests/bug33263.phpt31
12 files changed, 392 insertions, 55 deletions
diff --git a/ext/mysqli/mysqli.c b/ext/mysqli/mysqli.c
index fe4b828f6..71a0477dd 100644
--- a/ext/mysqli/mysqli.c
+++ b/ext/mysqli/mysqli.c
@@ -15,7 +15,7 @@
| Author: Georg Richter <georg@php.net> |
+----------------------------------------------------------------------+
- $Id: mysqli.c,v 1.43.2.12 2005/03/06 21:41:38 helly Exp $
+ $Id: mysqli.c,v 1.43.2.17 2005/06/27 18:22:00 tony2001 Exp $
*/
#ifdef HAVE_CONFIG_H
@@ -66,7 +66,7 @@ void php_free_stmt_bind_buffer(BIND_BUFFER bbuf, int type)
for (i=0; i < bbuf.var_cnt; i++) {
/* free temporary bind buffer */
- if (type == FETCH_RESULT) {
+ if (type == FETCH_RESULT && bbuf.buf[i].val) {
efree(bbuf.buf[i].val);
}
@@ -120,19 +120,33 @@ void php_clear_mysql(MY_MYSQL *mysql) {
static void mysqli_objects_free_storage(zend_object *object TSRMLS_DC)
{
mysqli_object *intern = (mysqli_object *)object;
+
+ zend_objects_free_object_storage(&(intern->zo) TSRMLS_CC);
+}
+/* }}} */
+
+/* {{{ mysqli_objects_destroy_object
+ */
+static void mysqli_objects_destroy_object(void *object, zend_object_handle handle TSRMLS_DC)
+{
+ mysqli_object *intern = (mysqli_object *)object;
MYSQLI_RESOURCE *my_res = (MYSQLI_RESOURCE *)intern->ptr;
- zend_hash_destroy(intern->zo.properties);
- FREE_HASHTABLE(intern->zo.properties);
+ zend_objects_destroy_object(object, handle TSRMLS_CC);
/* link object */
if (instanceof_function(intern->zo.ce, mysqli_link_class_entry TSRMLS_CC)) {
if (my_res && my_res->ptr) {
MY_MYSQL *mysql = (MY_MYSQL *)my_res->ptr;
- mysql_close(mysql->mysql);
+ if (mysql->mysql) {
+ mysql_close(mysql->mysql);
+ }
+
+ php_clear_mysql(mysql);
+ efree(mysql);
- php_clear_mysql(mysql);
+ my_res->ptr = NULL;
}
} else if (intern->zo.ce == mysqli_stmt_class_entry) { /* stmt object */
if (my_res && my_res->ptr) {
@@ -143,8 +157,8 @@ static void mysqli_objects_free_storage(zend_object *object TSRMLS_DC)
mysql_free_result(my_res->ptr);
}
}
+ intern->ptr = NULL;
my_efree(my_res);
- efree(object);
}
/* }}} */
@@ -328,7 +342,7 @@ PHP_MYSQLI_EXPORT(zend_object_value) mysqli_objects_new(zend_class_entry *class_
zend_hash_copy(intern->zo.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref,
(void *) &tmp, sizeof(zval *));
- retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) mysqli_objects_free_storage, NULL TSRMLS_CC);
+ retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t) mysqli_objects_destroy_object, (zend_objects_free_object_storage_t) mysqli_objects_free_storage, NULL TSRMLS_CC);
retval.handlers = &mysqli_object_handlers;
return retval;
@@ -387,7 +401,6 @@ static void php_mysqli_init_globals(zend_mysqli_globals *mysqli_globals)
mysqli_globals->reconnect = 0;
mysqli_globals->report_mode = 0;
mysqli_globals->report_ht = 0;
- mysqli_globals->multi_query = 0;
}
/* }}} */
@@ -456,7 +469,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);
-#ifdef STMT_ATTR_CURSOR_TYPE
+#if MYSQL_VERSION_ID > 50003
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);
@@ -513,6 +526,9 @@ PHP_MINIT_FUNCTION(mysqli)
/* bind blob support */
REGISTER_LONG_CONSTANT("MYSQLI_NO_DATA", MYSQL_NO_DATA, CONST_CS | CONST_PERSISTENT);
+#ifdef MYSQL_DATA_TRUNCATED
+ REGISTER_LONG_CONSTANT("MYSQLI_DATA_TRUNCATED", MYSQL_DATA_TRUNCATED, CONST_CS | CONST_PERSISTENT);
+#endif
/* reporting */
REGISTER_LONG_CONSTANT("MYSQLI_REPORT_INDEX", MYSQLI_REPORT_INDEX, CONST_CS | CONST_PERSISTENT);
@@ -582,7 +598,7 @@ void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flags
{
MYSQL_RES *result;
zval *mysql_result;
- int fetchtype;
+ long fetchtype;
unsigned int i;
MYSQL_FIELD *fields;
MYSQL_ROW row;
diff --git a/ext/mysqli/mysqli_api.c b/ext/mysqli/mysqli_api.c
index 1ad52797c..da27a44b2 100644
--- a/ext/mysqli/mysqli_api.c
+++ b/ext/mysqli/mysqli_api.c
@@ -15,7 +15,7 @@
| Author: Georg Richter <georg@php.net> |
+----------------------------------------------------------------------+
- $Id: mysqli_api.c,v 1.87.2.12 2005/03/17 18:12:30 tony2001 Exp $
+ $Id: mysqli_api.c,v 1.87.2.22 2005/06/17 16:37:07 georg Exp $
*/
#ifdef HAVE_CONFIG_H
@@ -109,12 +109,13 @@ PHP_FUNCTION(mysqli_stmt_bind_param)
start = 1;
}
- if (strlen(types) != argc - start) {
+ if (typelen != argc - start) {
/* number of bind variables doesn't match number of elements in type definition string */
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number of elements in type definition string doesn't match number of bind variables");
+ RETURN_FALSE;
}
- if (argc - start != stmt->stmt->param_count) {
+ if (typelen != stmt->stmt->param_count) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number of variables doesn't match number of parameters in prepared statement");
RETURN_FALSE;
}
@@ -301,7 +302,14 @@ PHP_FUNCTION(mysqli_stmt_bind_result)
bind[ofs].is_null = &stmt->result.is_null[ofs];
bind[ofs].buffer_length = stmt->result.buf[ofs].buflen;
break;
-
+ case MYSQL_TYPE_NULL:
+ stmt->result.buf[ofs].type = IS_NULL;
+ stmt->result.buf[ofs].buflen = 0;
+ bind[ofs].buffer_type = MYSQL_TYPE_NULL;
+ bind[ofs].buffer = 0;
+ bind[ofs].is_null = &stmt->result.is_null[ofs];
+ bind[ofs].buffer_length = 0;
+ break;
case MYSQL_TYPE_DATE:
case MYSQL_TYPE_TIME:
case MYSQL_TYPE_DATETIME:
@@ -311,9 +319,24 @@ PHP_FUNCTION(mysqli_stmt_bind_result)
case MYSQL_TYPE_BLOB:
case MYSQL_TYPE_TIMESTAMP:
case MYSQL_TYPE_DECIMAL:
+#ifdef FIELD_TYPE_NEWDECIMAL
+ case MYSQL_TYPE_NEWDECIMAL:
+#endif
stmt->result.buf[ofs].type = IS_STRING;
- stmt->result.buf[ofs].buflen =
- (stmt->stmt->fields) ? (stmt->stmt->fields[ofs].length) ? stmt->stmt->fields[ofs].length + 1: 256: 256;
+ /*
+ If the user has called $stmt->store_result() then we have asked
+ max_length to be updated. this is done only for BLOBS because we don't want to allocate
+ big chunkgs of memory 2^16 or 2^24
+ */
+ if (stmt->stmt->fields[ofs].max_length == 0) {
+ stmt->result.buf[ofs].buflen =
+ (stmt->stmt->fields) ? (stmt->stmt->fields[ofs].length) ? stmt->stmt->fields[ofs].length + 1: 256: 256;
+ } else {
+ /*
+ the user has called store_result(). if he does not there is no way to determine the
+ */
+ stmt->result.buf[ofs].buflen = stmt->stmt->fields[ofs].max_length;
+ }
stmt->result.buf[ofs].val = (char *)emalloc(stmt->result.buf[ofs].buflen);
bind[ofs].buffer_type = MYSQL_TYPE_STRING;
bind[ofs].buffer = stmt->result.buf[ofs].val;
@@ -410,7 +433,9 @@ PHP_FUNCTION(mysqli_close)
mysql_close(mysql->mysql);
php_clear_mysql(mysql);
+ efree(mysql);
MYSQLI_CLEAR_RESOURCE(&mysql_link);
+
RETURN_TRUE;
}
/* }}} */
@@ -585,7 +610,7 @@ PHP_FUNCTION(mysqli_stmt_fetch)
zval *mysql_stmt;
unsigned int i;
ulong ret;
- long lval;
+ int lval;
double dval;
my_ulonglong llval;
@@ -603,19 +628,24 @@ PHP_FUNCTION(mysqli_stmt_fetch)
memset(stmt->result.buf[i].val, 0, stmt->result.buf[i].buflen);
}
}
- if (!(ret = mysql_stmt_fetch(stmt->stmt))) {
+ ret = mysql_stmt_fetch(stmt->stmt);
+#ifdef MYSQL_DATA_TRUNCATED
+ if (!ret || ret == MYSQL_DATA_TRUNCATED) {
+#else
+ if (!ret) {
+#endif
for (i = 0; i < stmt->result.var_cnt; i++) {
if (stmt->result.vars[i]->type == IS_STRING && stmt->result.vars[i]->value.str.len) {
- efree(stmt->result.vars[i]->value.str.val);
+ efree(stmt->result.vars[i]->value.str.val);
}
if (!stmt->result.is_null[i]) {
switch (stmt->result.buf[i].type) {
case IS_LONG:
- memcpy(&lval, stmt->result.buf[i].val, sizeof(long));
+ memcpy(&lval, stmt->result.buf[i].val, sizeof(lval));
ZVAL_LONG(stmt->result.vars[i], lval);
break;
case IS_DOUBLE:
- memcpy(&dval, stmt->result.buf[i].val, sizeof(double));
+ memcpy(&dval, stmt->result.buf[i].val, sizeof(dval));
ZVAL_DOUBLE(stmt->result.vars[i], dval);
break;
case IS_STRING:
@@ -749,7 +779,7 @@ PHP_FUNCTION(mysqli_fetch_field_direct)
MYSQL_RES *result;
zval *mysql_result;
MYSQL_FIELD *field;
- int offset;
+ long offset;
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ol", &mysql_result, mysqli_result_class_entry, &offset) == FAILURE) {
return;
@@ -839,7 +869,7 @@ PHP_FUNCTION(mysqli_field_seek)
{
MYSQL_RES *result;
zval *mysql_result;
- unsigned int fieldnr;
+ unsigned long fieldnr;
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ol", &mysql_result, mysqli_result_class_entry, &fieldnr) == FAILURE) {
return;
@@ -993,7 +1023,7 @@ PHP_FUNCTION(mysqli_info)
PHP_FUNCTION(mysqli_init)
{
MYSQLI_RESOURCE *mysqli_resource;
- MY_MYSQL *mysql = (MY_MYSQL *)calloc(1, sizeof(MY_MYSQL));
+ MY_MYSQL *mysql = (MY_MYSQL *)ecalloc(1, sizeof(MY_MYSQL));
if (!(mysql->mysql = mysql_init(NULL))) {
efree(mysql);
@@ -1002,7 +1032,13 @@ PHP_FUNCTION(mysqli_init)
mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
mysqli_resource->ptr = (void *)mysql;
- MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_link_class_entry);
+
+ if (!getThis()) {
+ MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_link_class_entry);
+ } else {
+ ((mysqli_object *) zend_object_store_get_object(getThis() TSRMLS_CC))->ptr = mysqli_resource;
+ ((mysqli_object *) zend_object_store_get_object(getThis() TSRMLS_CC))->valid = 1;
+ }
}
/* }}} */
@@ -1029,7 +1065,7 @@ PHP_FUNCTION(mysqli_kill)
{
MY_MYSQL *mysql;
zval *mysql_link;
- int processid;
+ unsigned long processid;
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ol", &mysql_link, mysqli_link_class_entry, &processid) == FAILURE) {
return;
@@ -1044,7 +1080,7 @@ PHP_FUNCTION(mysqli_kill)
}
/* }}} */
-/* {{{ proto mysqli_set_local_infile_default(object link)
+/* {{{ proto void mysqli_set_local_infile_default(object link)
unsets user defined handler for load local infile command */
PHP_FUNCTION(mysqli_set_local_infile_default)
{
@@ -1241,18 +1277,30 @@ PHP_FUNCTION(mysqli_prepare)
}
MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link");
+ if (mysql->mysql->status == MYSQL_STATUS_GET_RESULT) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "All data must be fetched before a new preparing of a statement takes place");
+ RETURN_FALSE;
+ }
stmt = (MY_STMT *)ecalloc(1,sizeof(MY_STMT));
if ((stmt->stmt = mysql_stmt_init(mysql->mysql))) {
if (mysql_stmt_prepare(stmt->stmt, query, query_len)) {
- if (stmt->stmt->last_errno) {
- /* if we close the statement handle, we have to copy the errors to connection handle */
- mysql->mysql->net.last_errno = stmt->stmt->last_errno;
- strcpy(mysql->mysql->net.last_error, stmt->stmt->last_error);
- strcpy(mysql->mysql->net.sqlstate, stmt->stmt->sqlstate);
- }
+ char last_error[MYSQL_ERRMSG_SIZE];
+ char sqlstate[SQLSTATE_LENGTH+1];
+ unsigned int last_errno;
+
+ /* mysql_stmt_close clears errors, so we have to store them temporarily */
+ last_errno = stmt->stmt->last_errno;
+ memcpy(last_error, stmt->stmt->last_error, MYSQL_ERRMSG_SIZE);
+ memcpy(sqlstate, mysql->mysql->net.sqlstate, SQLSTATE_LENGTH+1);
+
mysql_stmt_close(stmt->stmt);
stmt->stmt = NULL;
+
+ /* restore error messages */
+ mysql->mysql->net.last_errno = last_errno;
+ memcpy(mysql->mysql->net.last_error, last_error, MYSQL_ERRMSG_SIZE);
+ memcpy(mysql->mysql->net.sqlstate, sqlstate, SQLSTATE_LENGTH+1);
}
}
@@ -1276,8 +1324,8 @@ PHP_FUNCTION(mysqli_real_connect)
{
MY_MYSQL *mysql;
char *hostname = NULL, *username=NULL, *passwd=NULL, *dbname=NULL, *socket=NULL;
- unsigned int hostname_len, username_len, passwd_len, dbname_len, socket_len;
- unsigned int port=0, flags=0;
+ unsigned int hostname_len = 0, username_len = 0, passwd_len = 0, dbname_len = 0, socket_len = 0;
+ unsigned long port=0, flags=0;
zval *mysql_link;
zval *object = getThis();
@@ -1416,7 +1464,8 @@ PHP_FUNCTION(mysqli_stmt_send_long_data)
MY_STMT *stmt;
zval *mysql_stmt;
char *data;
- long param_nr, data_len;
+ long param_nr;
+ int data_len;
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ols", &mysql_stmt, mysqli_stmt_class_entry, &param_nr, &data, &data_len) == FAILURE) {
@@ -1521,6 +1570,10 @@ PHP_FUNCTION(mysqli_stmt_data_seek)
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ol", &mysql_stmt, mysqli_stmt_class_entry, &offset) == FAILURE) {
return;
}
+ if (offset < 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Offset must be positive");
+ RETURN_FALSE;
+ }
MYSQLI_FETCH_RESOURCE(stmt, MY_STMT *, &mysql_stmt, "mysqli_stmt");
@@ -1732,7 +1785,7 @@ PHP_FUNCTION(mysqli_stmt_attr_set)
ulong attr;
int rc;
- if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Olb", &mysql_stmt, mysqli_stmt_class_entry, &attr, &mode) == FAILURE) {
+ if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oll", &mysql_stmt, mysqli_stmt_class_entry, &attr, &mode) == FAILURE) {
return;
}
MYSQLI_FETCH_RESOURCE(stmt, MY_STMT *, &mysql_stmt, "mysqli_stmt");
@@ -1880,11 +1933,27 @@ PHP_FUNCTION(mysqli_stmt_store_result)
{
MY_STMT *stmt;
zval *mysql_stmt;
-
+ int i;
+
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");
+
+ /*
+ If the user wants to store the data and we have BLOBs/TEXTs we try to allocate
+ not the maximal length of the type (which is 16MB even for LONGBLOB) but
+ the maximal length of the field in the result set. If he/she has quite big
+ BLOB/TEXT columns after calling store_result() the memory usage of PHP will
+ double - but this is a known problem of the simple MySQL API ;)
+ */
+ for (i = mysql_stmt_field_count(stmt->stmt) - 1; i >=0; --i) {
+ if (stmt->stmt->fields && stmt->stmt->fields[i].type == MYSQL_TYPE_BLOB) {
+ my_bool tmp=1;
+ mysql_stmt_attr_set(stmt->stmt, STMT_ATTR_UPDATE_MAX_LENGTH, &tmp);
+ break;
+ }
+ }
if (mysql_stmt_store_result(stmt->stmt)){
MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
diff --git a/ext/mysqli/mysqli_fe.c b/ext/mysqli/mysqli_fe.c
index bd4a697d6..32cb200ea 100644
--- a/ext/mysqli/mysqli_fe.c
+++ b/ext/mysqli/mysqli_fe.c
@@ -15,7 +15,7 @@
| Author: Georg Richter <georg@php.net> |
+----------------------------------------------------------------------+
- $Id: mysqli_fe.c,v 1.40.2.1 2004/07/23 12:48:20 georg Exp $
+ $Id: mysqli_fe.c,v 1.40.2.3 2005/05/13 13:53:08 georg Exp $
*/
#ifdef HAVE_CONFIG_H
@@ -117,6 +117,9 @@ function_entry mysqli_functions[] = {
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)
+#endif
PHP_FE(mysqli_stmt_attr_get, NULL)
PHP_FE(mysqli_stmt_attr_set, NULL)
PHP_FE(mysqli_stmt_field_count, NULL)
@@ -218,6 +221,9 @@ function_entry mysqli_link_methods[] = {
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)
PHP_FALIAS(ssl_set,mysqli_ssl_set,NULL)
diff --git a/ext/mysqli/mysqli_nonapi.c b/ext/mysqli/mysqli_nonapi.c
index 15204bb94..4efeb1d13 100644
--- a/ext/mysqli/mysqli_nonapi.c
+++ b/ext/mysqli/mysqli_nonapi.c
@@ -15,7 +15,7 @@
| Author: Georg Richter <georg@php.net> |
+----------------------------------------------------------------------+
- $Id: mysqli_nonapi.c,v 1.34.2.5 2005/02/24 23:59:49 iliaa Exp $
+ $Id: mysqli_nonapi.c,v 1.34.2.11 2005/08/06 16:56:06 andrey Exp $
*/
#ifdef HAVE_CONFIG_H
@@ -37,7 +37,7 @@ PHP_FUNCTION(mysqli_connect)
MYSQLI_RESOURCE *mysqli_resource;
zval *object = getThis();
char *hostname = NULL, *username=NULL, *passwd=NULL, *dbname=NULL, *socket=NULL;
- unsigned int hostname_len, username_len, passwd_len, dbname_len, socket_len;
+ unsigned int hostname_len = 0, username_len = 0, passwd_len = 0, dbname_len = 0, socket_len = 0;
long port=0;
if (getThis() && !ZEND_NUM_ARGS()) {
@@ -67,7 +67,7 @@ PHP_FUNCTION(mysqli_connect)
}
}
- mysql = (MY_MYSQL *)calloc(1, sizeof(MY_MYSQL));
+ mysql = (MY_MYSQL *)ecalloc(1, sizeof(MY_MYSQL));
if (!(mysql->mysql = mysql_init(NULL))) {
efree(mysql);
@@ -89,6 +89,7 @@ PHP_FUNCTION(mysqli_connect)
}
/* free mysql structure */
mysql_close(mysql->mysql);
+ efree(mysql);
RETURN_FALSE;
}
@@ -132,7 +133,7 @@ PHP_FUNCTION(mysqli_embedded_connect)
return;
}
- mysql = (MY_MYSQL *) calloc(1, sizeof(MY_MYSQL));
+ mysql = (MY_MYSQL *) ecalloc(1, sizeof(MY_MYSQL));
if (!(mysql = mysql_init(NULL))) {
efree(mysql);
@@ -217,7 +218,7 @@ PHP_FUNCTION(mysqli_multi_query)
MY_MYSQL *mysql;
zval *mysql_link;
char *query = NULL;
- unsigned int query_len;
+ unsigned long query_len;
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", &mysql_link, mysqli_link_class_entry, &query, &query_len) == FAILURE) {
return;
@@ -258,11 +259,20 @@ PHP_FUNCTION(mysqli_query)
MYSQL_RES *result;
char *query = NULL;
unsigned int query_len;
- unsigned int resultmode = 0;
+ unsigned long resultmode = MYSQLI_STORE_RESULT;
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os|l", &mysql_link, mysqli_link_class_entry, &query, &query_len, &resultmode) == FAILURE) {
return;
}
+ if (!query_len) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty query");
+ RETURN_FALSE;
+ }
+ if (resultmode != MYSQLI_USE_RESULT && resultmode != MYSQLI_STORE_RESULT) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid value for resultmode");
+ RETURN_FALSE;
+ }
+
MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL*, &mysql_link, "mysqli_link");
MYSQLI_DISABLE_MQ;
@@ -273,6 +283,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);
}
@@ -295,6 +306,30 @@ PHP_FUNCTION(mysqli_query)
}
/* }}} */
+#ifdef HAVE_MYSQLI_SET_CHARSET
+/* {{{ proto bool mysqli_set_charset(object link, string csname)
+ sets client character set */
+PHP_FUNCTION(mysqli_set_charset)
+{
+ MY_MYSQL *mysql;
+ zval *mysql_link;
+ char *cs_name = NULL;
+ unsigned int len;
+
+ if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", &mysql_link, mysqli_link_class_entry, &cs_name, &len) == FAILURE) {
+ return;
+ }
+ MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL*, &mysql_link, "mysqli_link");
+
+ if (mysql_set_character_set(mysql->mysql, cs_name))
+ {
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+#endif
+
/*
* Local variables:
* tab-width: 4
diff --git a/ext/mysqli/php_mysqli.h b/ext/mysqli/php_mysqli.h
index 412c849e9..faf68bd02 100644
--- a/ext/mysqli/php_mysqli.h
+++ b/ext/mysqli/php_mysqli.h
@@ -15,7 +15,7 @@
| Author: Georg Richter <georg@php.net> |
+----------------------------------------------------------------------+
- $Id: php_mysqli.h,v 1.38.2.2 2004/09/04 14:19:20 georg Exp $
+ $Id: php_mysqli.h,v 1.38.2.6 2005/05/21 08:54:56 georg Exp $
*/
/* A little hack to prevent build break, when mysql is used together with
@@ -55,6 +55,7 @@ typedef struct {
MYSQL *mysql;
zval *li_read;
php_stream *li_stream;
+ unsigned int multi_query;
} MY_MYSQL;
typedef struct {
@@ -94,6 +95,10 @@ typedef struct {
#define PHP_MYSQLI_API
#endif
+#if (MYSQL_VERSION_ID > 40112 && MYSQL_VERSION_ID < 50000) || MYSQL_VERSION_ID > 50005
+#define HAVE_MYSQLI_SET_CHARSET
+#endif
+
#ifdef ZTS
#include "TSRM.h"
#endif
@@ -131,14 +136,14 @@ zend_class_entry _mysqli_result_class_entry;
PHP_MYSQLI_EXPORT(zend_object_value) mysqli_objects_new(zend_class_entry * TSRMLS_DC);
-#define MYSQLI_DISABLE_MQ if (MyG(multi_query)) { \
+#define MYSQLI_DISABLE_MQ if (mysql->multi_query) { \
mysql_set_server_option(mysql->mysql, MYSQL_OPTION_MULTI_STATEMENTS_OFF); \
- MyG(multi_query) = 0; \
+ mysql->multi_query = 0; \
}
-#define MYSQLI_ENABLE_MQ if (!MyG(multi_query)) { \
+#define MYSQLI_ENABLE_MQ if (!mysql->multi_query) { \
mysql_set_server_option(mysql->mysql, MYSQL_OPTION_MULTI_STATEMENTS_ON); \
- MyG(multi_query) = 1; \
+ mysql->multi_query = 1; \
}
#define REGISTER_MYSQLI_CLASS_ENTRY(name, mysqli_entry, class_functions) { \
@@ -272,6 +277,9 @@ 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);
@@ -386,7 +394,6 @@ ZEND_BEGIN_MODULE_GLOBALS(mysqli)
char *error_msg;
int report_mode;
HashTable *report_ht;
- unsigned int multi_query;
#ifdef HAVE_EMBEDDED_MYSQLI
unsigned int embedded;
#endif
diff --git a/ext/mysqli/tests/033.phpt b/ext/mysqli/tests/033.phpt
index 3a56b5c67..025539ea4 100644
--- a/ext/mysqli/tests/033.phpt
+++ b/ext/mysqli/tests/033.phpt
@@ -11,9 +11,9 @@ function test: mysqli_get_host_info
$hinfo = mysqli_get_host_info($link);
- var_dump($hinfo);
+ var_dump(str_replace('/','', $hinfo));
mysqli_close($link);
?>
---EXPECT--
-string(25) "Localhost via UNIX socket"
+--EXPECTF--
+string(%d) "%s via %s" \ No newline at end of file
diff --git a/ext/mysqli/tests/064.phpt b/ext/mysqli/tests/064.phpt
new file mode 100644
index 000000000..1d6358e53
--- /dev/null
+++ b/ext/mysqli/tests/064.phpt
@@ -0,0 +1,21 @@
+--TEST--
+NULL binding
+--SKIPIF--
+<?php require_once('skipif.inc'); ?>
+--FILE--
+<?php
+ include "connect.inc";
+
+ $mysql = new mysqli($host, $user, $passwd);
+
+ $stmt = $mysql->prepare("SELECT NULL FROM DUAL");
+ $stmt->execute();
+ $stmt->bind_result($foo);
+ $stmt->fetch();
+ $stmt->close();
+ $mysql->close();
+
+ var_dump($foo);
+?>
+--EXPECT--
+NULL
diff --git a/ext/mysqli/tests/065.phpt b/ext/mysqli/tests/065.phpt
new file mode 100644
index 000000000..950a10a43
--- /dev/null
+++ b/ext/mysqli/tests/065.phpt
@@ -0,0 +1,37 @@
+--TEST--
+set character set
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+?>
+--FILE--
+<?php
+ include "connect.inc";
+
+ $mysql = new mysqli($host, $user, $passwd);
+
+ $esc_str = chr(0xbf) . chr(0x5c);
+
+ if ($mysql->set_charset("latin1")) {
+ /* 5C should be escaped */
+ $len[0] = strlen($mysql->real_escape_string($esc_str));
+ $charset[0] = $mysql->client_encoding();
+ }
+
+ if ($mysql->set_charset("gbk")) {
+ /* nothing should be escaped, it's a valid gbk character */
+ $len[1] = strlen($mysql->real_escape_string($esc_str));
+ $charset[1] = $mysql->client_encoding();
+ }
+
+ $mysql->close();
+ var_dump($len[0]);
+ var_dump($len[1]);
+ var_dump($charset[0]);
+ var_dump($charset[1]);
+?>
+--EXPECT--
+int(3)
+int(2)
+string(6) "latin1"
+string(3) "gbk"
diff --git a/ext/mysqli/tests/bug31668.phpt b/ext/mysqli/tests/bug31668.phpt
new file mode 100644
index 000000000..b813096a2
--- /dev/null
+++ b/ext/mysqli/tests/bug31668.phpt
@@ -0,0 +1,56 @@
+--TEST--
+Bug #31668 multi_query works exactly every other time (multi_query was global, now per connection)
+--SKIPIF--
+<?php require_once('skipif.inc'); ?>
+--FILE--
+<?php
+ include "connect.inc";
+
+ $mysql = new mysqli($host, $user, $passwd, "test");
+ $mysql->multi_query('SELECT 1;SELECT 2');
+ do {
+ $res = $mysql->store_result();
+ if ($mysql->errno == 0) {
+ while ($arr = $res->fetch_assoc()) {
+ var_dump($arr);
+ }
+ $res->free();
+ }
+ } while ($mysql->next_result());
+ var_dump($mysql->error, __LINE__);
+ $mysql->close();
+
+ $mysql = new mysqli($host, $user, $passwd, "test");
+ $mysql->multi_query('SELECT 1;SELECT 2');
+ do {
+ $res = $mysql->store_result();
+ if ($mysql->errno == 0) {
+ while ($arr = $res->fetch_assoc()) {
+ var_dump($arr);
+ }
+ $res->free();
+ }
+ } while ($mysql->next_result());
+ var_dump($mysql->error, __LINE__);
+?>
+--EXPECTF--
+array(1) {
+ [1]=>
+ string(1) "1"
+}
+array(1) {
+ [2]=>
+ string(1) "2"
+}
+string(0) ""
+int(%d)
+array(1) {
+ [1]=>
+ string(1) "1"
+}
+array(1) {
+ [2]=>
+ string(1) "2"
+}
+string(0) ""
+int(%d)
diff --git a/ext/mysqli/tests/bug32405.phpt b/ext/mysqli/tests/bug32405.phpt
new file mode 100644
index 000000000..9b58e3611
--- /dev/null
+++ b/ext/mysqli/tests/bug32405.phpt
@@ -0,0 +1,38 @@
+--TEST--
+Bug #32405
+--SKIPIF--
+<?php require_once('skipif.inc'); ?>
+--FILE--
+<?php
+ include ("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = mysqli_connect($host, $user, $passwd);
+ mysqli_select_db($link, "test");
+
+ /* two fields are needed. the problem does not occur with 1 field only selected. */
+ $link->query("CREATE TABLE test_users(user_id int(10) unsigned NOT NULL auto_increment, login varchar(50) default '', PRIMARY KEY (user_id))");
+ $link->query('INSERT INTO test_users VALUES (NULL, "user1"), (NULL, "user2"), (NULL, "user3"), (NULL, "user4")');
+
+
+ if ($stmt = $link->prepare("SELECT SQL_NO_CACHE user_id, login FROM test_users")) {
+ $stmt->execute();
+ $stmt->bind_result($col1, $col2);
+ while ($stmt->fetch()) {
+ var_dump($col1, $col2);
+ }
+ $stmt->close();
+ }
+
+ mysqli_query($link,"DROP TABLE test_users");
+ mysqli_close($link);
+?>
+--EXPECT--
+int(1)
+string(5) "user1"
+int(2)
+string(5) "user2"
+int(3)
+string(5) "user3"
+int(4)
+string(5) "user4"
diff --git a/ext/mysqli/tests/bug33090.phpt b/ext/mysqli/tests/bug33090.phpt
new file mode 100644
index 000000000..5c1cba961
--- /dev/null
+++ b/ext/mysqli/tests/bug33090.phpt
@@ -0,0 +1,21 @@
+--TEST--
+Bug #33090
+--SKIPIF--
+<?php require_once('skipif.inc'); ?>
+--FILE--
+<?php
+ include ("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = mysqli_connect($host, $user, $passwd);
+ mysqli_select_db($link, "test");
+
+ if (!($link->prepare("this makes no sense"))) {
+ printf("%d\n", $link->errno);
+ printf("%s\n", $link->sqlstate);
+ }
+ $link->close();
+?>
+--EXPECT--
+1064
+42000
diff --git a/ext/mysqli/tests/bug33263.phpt b/ext/mysqli/tests/bug33263.phpt
new file mode 100644
index 000000000..44f9167c9
--- /dev/null
+++ b/ext/mysqli/tests/bug33263.phpt
@@ -0,0 +1,31 @@
+--TEST--
+bug #33263 (mysqli_real_connect in __construct)
+--SKIPIF--
+<?php require_once('skipif.inc'); ?>
+--FILE--
+<?php
+
+ include "connect.inc";
+
+ class test extends mysqli
+ {
+ public function __construct($host, $user, $passwd, $db) {
+ parent::init();
+ parent::real_connect($host, $user, $passwd, $db);
+ }
+ }
+
+ $mysql = new test($host, $user, $passwd, "test");
+
+ $stmt = $mysql->prepare("SELECT DATABASE()");
+ $stmt->execute();
+ $stmt->bind_result($db);
+ $stmt->fetch();
+ $stmt->close();
+
+ var_dump($db);
+
+ $mysql->close();
+?>
+--EXPECT--
+string(4) "test"