diff options
Diffstat (limited to 'ext/mysqli')
-rw-r--r-- | ext/mysqli/mysqli.c | 38 | ||||
-rw-r--r-- | ext/mysqli/mysqli_api.c | 125 | ||||
-rw-r--r-- | ext/mysqli/mysqli_fe.c | 8 | ||||
-rw-r--r-- | ext/mysqli/mysqli_nonapi.c | 47 | ||||
-rw-r--r-- | ext/mysqli/php_mysqli.h | 19 | ||||
-rw-r--r-- | ext/mysqli/tests/033.phpt | 6 | ||||
-rw-r--r-- | ext/mysqli/tests/064.phpt | 21 | ||||
-rw-r--r-- | ext/mysqli/tests/065.phpt | 37 | ||||
-rw-r--r-- | ext/mysqli/tests/bug31668.phpt | 56 | ||||
-rw-r--r-- | ext/mysqli/tests/bug32405.phpt | 38 | ||||
-rw-r--r-- | ext/mysqli/tests/bug33090.phpt | 21 | ||||
-rw-r--r-- | ext/mysqli/tests/bug33263.phpt | 31 |
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, ¶m_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" |