From 3b4b925ea7575f8ceed273ff698df28b571cb0aa Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 10 Oct 2007 17:57:01 +0400 Subject: [PATCH] Fix for BUG#20023: mysql_change_user() resets the value of SQL_BIG_SELECTS. The bug was that SQL_BIG_SELECTS was not properly set in COM_CHANGE_USER. The fix is to update SQL_BIG_SELECTS properly. sql/mysql_priv.h: Cleanup: make prepare_new_connection_state() private for module. sql/sql_class.cc: Update THD::options with the respect to SQL_BIG_SELECTS in COM_CHANGE_USER. sql/sql_connect.cc: Cleanup: make prepare_new_connection_state() private for module. tests/mysql_client_test.c: Add a test case BUG#20023. --- sql/mysql_priv.h | 1 - sql/sql_class.cc | 6 ++ sql/sql_connect.cc | 4 +- tests/mysql_client_test.c | 171 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 179 insertions(+), 3 deletions(-) diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 6a7e3e00f6f..79d4c16f9c1 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -917,7 +917,6 @@ void decrease_user_connections(USER_CONN *uc); void thd_init_client_charset(THD *thd, uint cs_number); bool setup_connection_thread_globals(THD *thd); bool login_connection(THD *thd); -void prepare_new_connection_state(THD* thd); void end_connection(THD *thd); bool mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create, bool silent); diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 66a51d5bb00..490aedad0ef 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -585,6 +585,12 @@ void THD::init(void) if (variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES) server_status|= SERVER_STATUS_NO_BACKSLASH_ESCAPES; options= thd_startup_options; + + if (variables.max_join_size == HA_POS_ERROR) + options |= OPTION_BIG_SELECTS; + else + options &= ~OPTION_BIG_SELECTS; + transaction.all.modified_non_trans_table= transaction.stmt.modified_non_trans_table= FALSE; open_options=ha_open_options; update_lock_default= (variables.low_priority_updates ? diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index 9785b30ea00..094bef9324e 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -933,7 +933,7 @@ bool login_connection(THD *thd) NET *net= &thd->net; Security_context *sctx= thd->security_ctx; DBUG_ENTER("login_connection"); - DBUG_PRINT("info", ("handle_one_connection called by thread %lu", + DBUG_PRINT("info", ("login_connection called by thread %lu", thd->thread_id)); net->no_send_error= 0; @@ -1003,7 +1003,7 @@ void end_connection(THD *thd) Initialize THD to handle queries */ -void prepare_new_connection_state(THD* thd) +static void prepare_new_connection_state(THD* thd) { Security_context *sctx= thd->security_ctx; diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index eff8df8109a..9505340c24f 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -16819,6 +16819,176 @@ static void test_bug30472() mysql_close(&con); } +static void bug20023_change_user(MYSQL *con) +{ + DIE_IF(mysql_change_user(con, + opt_user, + opt_password, + opt_db ? opt_db : "test")); +} + +static void bug20023_query_int_variable(MYSQL *con, + const char *var_name, + int *var_value) +{ + MYSQL_RES *rs; + MYSQL_ROW row; + + char query_buffer[MAX_TEST_QUERY_LENGTH]; + + my_snprintf(query_buffer, + sizeof (query_buffer), + "SELECT @@%s", + (const char *) var_name); + + DIE_IF(mysql_query(con, query_buffer)); + DIE_UNLESS(rs= mysql_store_result(con)); + DIE_UNLESS(row= mysql_fetch_row(rs)); + *var_value= atoi(row[0]); + mysql_free_result(rs); +} + +static void test_bug20023() +{ + MYSQL con; + + int sql_big_selects_orig; + int max_join_size_orig; + + int sql_big_selects_2; + int sql_big_selects_3; + int sql_big_selects_4; + int sql_big_selects_5; + + char query_buffer[MAX_TEST_QUERY_LENGTH]; + + /* Create a new connection. */ + + DIE_UNLESS(mysql_init(&con)); + + DIE_UNLESS(mysql_real_connect(&con, + opt_host, + opt_user, + opt_password, + opt_db ? opt_db : "test", + opt_port, + opt_unix_socket, + CLIENT_FOUND_ROWS)); + + /*********************************************************************** + Remember original SQL_BIG_SELECTS, MAX_JOIN_SIZE values. + ***********************************************************************/ + + bug20023_query_int_variable(&con, + "session.sql_big_selects", + &sql_big_selects_orig); + + bug20023_query_int_variable(&con, + "global.max_join_size", + &max_join_size_orig); + + /*********************************************************************** + Test that COM_CHANGE_USER resets the SQL_BIG_SELECTS to the initial value. + ***********************************************************************/ + + /* Issue COM_CHANGE_USER. */ + + bug20023_change_user(&con); + + /* Query SQL_BIG_SELECTS. */ + + bug20023_query_int_variable(&con, + "session.sql_big_selects", + &sql_big_selects_2); + + /* Check that SQL_BIG_SELECTS is reset properly. */ + + DIE_UNLESS(sql_big_selects_orig == sql_big_selects_2); + + /*********************************************************************** + Test that if MAX_JOIN_SIZE set to non-default value, + SQL_BIG_SELECTS will be 0. + ***********************************************************************/ + + /* Set MAX_JOIN_SIZE to some non-default value. */ + + DIE_IF(mysql_query(&con, "SET @@global.max_join_size = 10000")); + DIE_IF(mysql_query(&con, "SET @@session.max_join_size = default")); + + /* Issue COM_CHANGE_USER. */ + + bug20023_change_user(&con); + + /* Query SQL_BIG_SELECTS. */ + + bug20023_query_int_variable(&con, + "session.sql_big_selects", + &sql_big_selects_3); + + /* Check that SQL_BIG_SELECTS is 0. */ + + DIE_UNLESS(sql_big_selects_3 == 0); + + /*********************************************************************** + Test that if MAX_JOIN_SIZE set to default value, + SQL_BIG_SELECTS will be 1. + ***********************************************************************/ + + /* Set MAX_JOIN_SIZE to the default value (-1). */ + + DIE_IF(mysql_query(&con, "SET @@global.max_join_size = -1")); + DIE_IF(mysql_query(&con, "SET @@session.max_join_size = default")); + + /* Issue COM_CHANGE_USER. */ + + bug20023_change_user(&con); + + /* Query SQL_BIG_SELECTS. */ + + bug20023_query_int_variable(&con, + "session.sql_big_selects", + &sql_big_selects_4); + + /* Check that SQL_BIG_SELECTS is 1. */ + + DIE_UNLESS(sql_big_selects_4 == 1); + + /*********************************************************************** + Restore MAX_JOIN_SIZE. + Check that SQL_BIG_SELECTS will be the original one. + ***********************************************************************/ + + /* Restore MAX_JOIN_SIZE. */ + + my_snprintf(query_buffer, + sizeof (query_buffer), + "SET @@global.max_join_size = %d", + (int) max_join_size_orig); + + DIE_IF(mysql_query(&con, query_buffer)); + DIE_IF(mysql_query(&con, "SET @@session.max_join_size = default")); + + /* Issue COM_CHANGE_USER. */ + + bug20023_change_user(&con); + + /* Query SQL_BIG_SELECTS. */ + + bug20023_query_int_variable(&con, + "session.sql_big_selects", + &sql_big_selects_5); + + /* Check that SQL_BIG_SELECTS is 1. */ + + DIE_UNLESS(sql_big_selects_5 == sql_big_selects_orig); + + /*********************************************************************** + That's it. Cleanup. + ***********************************************************************/ + + mysql_close(&con); +} + /* Read and parse arguments and MySQL options from my.cnf @@ -17115,6 +17285,7 @@ static struct my_tests_st my_tests[]= { { "test_bug29306", test_bug29306 }, { "test_change_user", test_change_user }, { "test_bug30472", test_bug30472 }, + { "test_bug20023", test_bug20023 }, { 0, 0 } };