Fixed bug #49027 (mysqli_options() doesn't work when using mysqlnd)

This commit is contained in:
Andrey Hristov 2009-08-27 13:16:39 +00:00
parent 2e92372322
commit 149914f644
6 changed files with 140 additions and 52 deletions

View File

@ -0,0 +1,28 @@
--TEST--
Bug #49027 (mysqli_options() doesn't work when using mysqlnd)
--SKIPIF--
<?php
require_once('skipif.inc');
require_once('skipifconnectfailure.inc');
?>
--FILE--
<?php
include ("connect.inc");
$link=mysqli_init();
if (!mysqli_options($link, MYSQLI_INIT_COMMAND, "SELECT 1")){
echo "Broken 2!\n";
}
if (!mysqli_options($link, MYSQLI_INIT_COMMAND, "SELECT 13")){
echo "Broken 2!\n";
}
require('table_real_connect.inc');
var_dump($link->query("SELECT 42")->fetch_row());
?>
--EXPECTF--
array(1) {
[0]=>
%unicode|string%(2) "42"
}

View File

@ -0,0 +1,23 @@
<?PHP
require_once('connect.inc');
if (!mysqli_real_connect($link, $host, $user, $passwd, $db, $port, $socket)) {
printf("Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
$host, $user, $db, $port, $socket);
exit(1);
}
if (!mysqli_query($link, 'DROP TABLE IF EXISTS test')) {
printf("Failed to drop old test table: [%d] %s\n", mysqli_errno($link), mysqli_error($link));
exit(1);
}
if (!mysqli_query($link, 'CREATE TABLE test(id INT, label CHAR(1), PRIMARY KEY(id)) ENGINE=' . $engine)) {
printf("Failed to create test table: [%d] %s\n", mysqli_errno($link), mysqli_error($link));
exit(1);
}
if (!mysqli_query($link, "INSERT INTO test(id, label) VALUES (1, 'a'), (2, 'b'), (3, 'c'), (4, 'd'), (5, 'e'), (6, 'f')")) {
printf("[%d] %s\n", mysqli_errno($link), mysqli_error($link));
}
?>

View File

@ -82,6 +82,56 @@ void mysqlnd_library_end(TSRMLS_D)
/* }}} */
/* {{{ mysqlnd_conn::free_options */
static void
MYSQLND_METHOD(mysqlnd_conn, free_options)(MYSQLND *conn TSRMLS_DC)
{
zend_bool pers = conn->persistent;
if (conn->options.charset_name) {
mnd_pefree(conn->options.charset_name, pers);
conn->options.charset_name = NULL;
}
if (conn->options.num_commands) {
unsigned int i;
for (i = 0; i < conn->options.num_commands; i++) {
/* allocated with pestrdup */
pefree(conn->options.init_commands[i], pers);
}
mnd_pefree(conn->options.init_commands, pers);
conn->options.init_commands = NULL;
}
if (conn->options.cfg_file) {
mnd_pefree(conn->options.cfg_file, pers);
conn->options.cfg_file = NULL;
}
if (conn->options.cfg_section) {
mnd_pefree(conn->options.cfg_section, pers);
conn->options.cfg_section = NULL;
}
if (conn->options.ssl_key) {
mnd_pefree(conn->options.ssl_key, pers);
conn->options.ssl_key = NULL;
}
if (conn->options.ssl_cert) {
mnd_pefree(conn->options.ssl_cert, pers);
conn->options.ssl_cert = NULL;
}
if (conn->options.ssl_ca) {
mnd_pefree(conn->options.ssl_ca, pers);
conn->options.ssl_ca = NULL;
}
if (conn->options.ssl_capath) {
mnd_pefree(conn->options.ssl_capath, pers);
conn->options.ssl_capath = NULL;
}
if (conn->options.ssl_cipher) {
mnd_pefree(conn->options.ssl_cipher, pers);
conn->options.ssl_cipher = NULL;
}
}
/* {{{ mysqlnd_conn::free_contents */
static void
MYSQLND_METHOD(mysqlnd_conn, free_contents)(MYSQLND *conn TSRMLS_DC)
@ -153,46 +203,6 @@ MYSQLND_METHOD(mysqlnd_conn, free_contents)(MYSQLND *conn TSRMLS_DC)
mnd_pefree(conn->last_message, pers);
conn->last_message = NULL;
}
if (conn->options.charset_name) {
mnd_pefree(conn->options.charset_name, pers);
conn->options.charset_name = NULL;
}
if (conn->options.num_commands) {
unsigned int i;
for (i = 0; i < conn->options.num_commands; i++) {
mnd_pefree(conn->options.init_commands[i], pers);
}
mnd_pefree(conn->options.init_commands, pers);
conn->options.init_commands = NULL;
}
if (conn->options.cfg_file) {
mnd_pefree(conn->options.cfg_file, pers);
conn->options.cfg_file = NULL;
}
if (conn->options.cfg_section) {
mnd_pefree(conn->options.cfg_section, pers);
conn->options.cfg_section = NULL;
}
if (conn->options.ssl_key) {
mnd_pefree(conn->options.ssl_key, pers);
conn->options.ssl_key = NULL;
}
if (conn->options.ssl_cert) {
mnd_pefree(conn->options.ssl_cert, pers);
conn->options.ssl_cert = NULL;
}
if (conn->options.ssl_ca) {
mnd_pefree(conn->options.ssl_ca, pers);
conn->options.ssl_ca = NULL;
}
if (conn->options.ssl_capath) {
mnd_pefree(conn->options.ssl_capath, pers);
conn->options.ssl_capath = NULL;
}
if (conn->options.ssl_cipher) {
mnd_pefree(conn->options.ssl_cipher, pers);
conn->options.ssl_cipher = NULL;
}
if (conn->zval_cache) {
DBG_INF("Freeing zval cache reference");
mysqlnd_palloc_free_thd_cache_reference(&conn->zval_cache);
@ -229,6 +239,7 @@ MYSQLND_METHOD_PRIVATE(mysqlnd_conn, dtor)(MYSQLND *conn TSRMLS_DC)
DBG_INF_FMT("conn=%llu", conn->thread_id);
conn->m->free_contents(conn TSRMLS_CC);
conn->m->free_options(conn TSRMLS_CC);
#ifdef MYSQLND_THREADED
if (conn->thread_is_running) {
@ -736,10 +747,6 @@ PHPAPI MYSQLND *mysqlnd_connect(MYSQLND *conn,
SET_EMPTY_ERROR(conn->error_info);
PACKET_FREE_ALLOCA(greet_packet);
PACKET_FREE(auth_packet);
PACKET_FREE_ALLOCA(ok_packet);
conn->zval_cache = mysqlnd_palloc_get_thd_cache_reference(zval_cache);
conn->net.cmd_buffer.length = 128L*1024L;
conn->net.cmd_buffer.buffer = mnd_pemalloc(conn->net.cmd_buffer.length, conn->persistent);
@ -791,6 +798,25 @@ PHPAPI MYSQLND *mysqlnd_connect(MYSQLND *conn,
}
#endif
if (conn->options.init_commands) {
int current_command = 0;
for (; current_command < conn->options.num_commands; ++current_command) {
const char * const command = conn->options.init_commands[current_command];
MYSQLND_INC_CONN_STATISTIC(&conn->stats, STAT_INIT_COMMAND_EXECUTED_COUNT);
if (PASS != conn->m->query(conn, command, strlen(command) TSRMLS_CC)) {
MYSQLND_INC_CONN_STATISTIC(&conn->stats, STAT_INIT_COMMAND_FAILED_COUNT);
goto err;
}
if (conn->last_query_type == QUERY_SELECT) {
MYSQLND_RES * result = conn->m->use_result(conn TSRMLS_CC);
result->m.free_result(result, TRUE TSRMLS_CC);
}
}
}
PACKET_FREE_ALLOCA(greet_packet);
PACKET_FREE(auth_packet);
PACKET_FREE_ALLOCA(ok_packet);
DBG_RETURN(conn);
}
@ -812,10 +838,6 @@ err:
conn->scheme = NULL;
}
/* This will also close conn->net.stream if it has been opened */
conn->m->free_contents(conn TSRMLS_CC);
if (self_alloced) {
/*
We have alloced, thus there are no references to this
@ -823,6 +845,8 @@ err:
*/
conn->m->dtor(conn TSRMLS_CC);
} else {
/* This will also close conn->net.stream if it has been opened */
conn->m->free_contents(conn TSRMLS_CC);
MYSQLND_INC_CONN_STATISTIC(&conn->stats, STAT_CONNECT_FAILURE);
}
DBG_RETURN(NULL);
@ -1411,8 +1435,9 @@ mysqlnd_send_close(MYSQLND * conn TSRMLS_DC)
switch (CONN_GET_STATE(conn)) {
case CONN_READY:
DBG_INF("Connection clean, sending COM_QUIT");
ret = mysqlnd_simple_command(conn, COM_QUIT, NULL, 0, PROT_LAST,
TRUE, TRUE TSRMLS_CC);
if (conn->net.stream) {
ret = mysqlnd_simple_command(conn, COM_QUIT, NULL, 0, PROT_LAST, TRUE, TRUE TSRMLS_CC);
}
/* Do nothing */
break;
case CONN_SENDING_LOAD_DATA:
@ -1949,10 +1974,16 @@ MYSQLND_METHOD(mysqlnd_conn, set_client_option)(MYSQLND * const conn,
conn->options.flags &= ~CLIENT_LOCAL_FILES;
}
break;
case MYSQL_INIT_COMMAND:
/* when num_commands is 0, then realloc will be effectively a malloc call, internally */
conn->options.init_commands = mnd_perealloc(conn->options.init_commands, sizeof(char *) * (conn->options.num_commands + 1),
conn->persistent);
conn->options.init_commands[conn->options.num_commands] = pestrdup(value, conn->persistent);
++conn->options.num_commands;
break;
#ifdef WHEN_SUPPORTED_BY_MYSQLI
case MYSQL_OPT_COMPRESS:
#endif
case MYSQL_INIT_COMMAND:
case MYSQL_READ_DEFAULT_FILE:
case MYSQL_READ_DEFAULT_GROUP:
#ifdef WHEN_SUPPORTED_BY_MYSQLI
@ -2161,6 +2192,7 @@ MYSQLND_CLASS_METHODS_START(mysqlnd_conn)
MYSQLND_METHOD(mysqlnd_conn, set_server_option),
MYSQLND_METHOD(mysqlnd_conn, set_client_option),
MYSQLND_METHOD(mysqlnd_conn, free_contents),
MYSQLND_METHOD(mysqlnd_conn, free_options),
MYSQLND_METHOD(mysqlnd_conn, close),
MYSQLND_METHOD_PRIVATE(mysqlnd_conn, dtor),

View File

@ -416,6 +416,8 @@ typedef enum mysqlnd_collected_stats
STAT_BINARY_TYPE_FETCHED_SET,
STAT_BINARY_TYPE_FETCHED_GEOMETRY,
STAT_BINARY_TYPE_FETCHED_OTHER,
STAT_INIT_COMMAND_EXECUTED_COUNT,
STAT_INIT_COMMAND_FAILED_COUNT,
STAT_LAST /* Should be always the last */
} enum_mysqlnd_collected_stats;

View File

@ -151,7 +151,9 @@ const MYSQLND_STRING mysqlnd_stats_values_names[STAT_LAST] =
{ STR_W_LEN("proto_binary_fetched_enum") },
{ STR_W_LEN("proto_binary_fetched_set") },
{ STR_W_LEN("proto_binary_fetched_geometry") },
{ STR_W_LEN("proto_binary_fetched_other") }
{ STR_W_LEN("proto_binary_fetched_other") },
{ STR_W_LEN("init_command_executed_count") },
{ STR_W_LEN("init_command_failed_count") }
};
/* }}} */

View File

@ -279,6 +279,7 @@ struct st_mysqlnd_conn_methods
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 */
void (*free_options)(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 */