summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHe Zhenxing <zhenxing.he@sun.com>2009-03-09 16:44:18 +0800
committerHe Zhenxing <zhenxing.he@sun.com>2009-03-09 16:44:18 +0800
commitf79ce334a202df9c8daeaf1b4d62940e93d98446 (patch)
tree7f0724aa8bde2946a063e1fec22f52dd5fc6b38a
parenta8bc9544bc4d0861efc4c22cbdd499580e4005fe (diff)
parente327e572b03f13f237574d33fe035cb6c320f176 (diff)
downloadmariadb-git-f79ce334a202df9c8daeaf1b4d62940e93d98446.tar.gz
Auto merge
-rw-r--r--sql/sql_cache.cc47
-rw-r--r--sql/sql_class.cc6
-rw-r--r--tests/mysql_client_test.c173
3 files changed, 226 insertions, 0 deletions
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index b55fa148e24..4a060ba7178 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -363,6 +363,43 @@ TYPELIB query_cache_type_typelib=
array_elements(query_cache_type_names)-1,"", query_cache_type_names, NULL
};
+
+/**
+ Helper function for determine if a SELECT statement has a SQL_NO_CACHE
+ directive.
+
+ @param sql A pointer to the first white space character after SELECT
+
+ @return
+ @retval TRUE The character string contains SQL_NO_CACHE
+ @retval FALSE No directive found.
+*/
+
+static bool has_no_cache_directive(char *sql)
+{
+ int i=0;
+ while (sql[i] == ' ')
+ ++i;
+
+ if (my_toupper(system_charset_info, sql[i]) == 'S' &&
+ my_toupper(system_charset_info, sql[i+1]) == 'Q' &&
+ my_toupper(system_charset_info, sql[i+2]) == 'L' &&
+ my_toupper(system_charset_info, sql[i+3]) == '_' &&
+ my_toupper(system_charset_info, sql[i+4]) == 'N' &&
+ my_toupper(system_charset_info, sql[i+5]) == 'O' &&
+ my_toupper(system_charset_info, sql[i+6]) == '_' &&
+ my_toupper(system_charset_info, sql[i+7]) == 'C' &&
+ my_toupper(system_charset_info, sql[i+8]) == 'A' &&
+ my_toupper(system_charset_info, sql[i+9]) == 'C' &&
+ my_toupper(system_charset_info, sql[i+10]) == 'H' &&
+ my_toupper(system_charset_info, sql[i+11]) == 'E' &&
+ my_toupper(system_charset_info, sql[i+12]) == ' ')
+ return TRUE;
+
+ return FALSE;
+}
+
+
/*****************************************************************************
Query_cache_block_table method(s)
*****************************************************************************/
@@ -1095,6 +1132,16 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
DBUG_PRINT("qcache", ("The statement is not a SELECT; Not cached"));
goto err;
}
+
+ if (query_length > 20 && has_no_cache_directive(&sql[i+6]))
+ {
+ /*
+ We do not increase 'refused' statistics here since it will be done
+ later when the query is parsed.
+ */
+ DBUG_PRINT("qcache", ("The statement has a SQL_NO_CACHE directive"));
+ goto err;
+ }
}
#ifdef __WIN__
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 4ea621f428d..88b7dfb46d7 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -343,6 +343,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/tests/mysql_client_test.c b/tests/mysql_client_test.c
index 7df84c600c9..32c39b149d4 100644
--- a/tests/mysql_client_test.c
+++ b/tests/mysql_client_test.c
@@ -115,6 +115,8 @@ static void client_disconnect(void);
#define DIE_UNLESS(expr) \
((void) ((expr) ? 0 : (die(__FILE__, __LINE__, #expr), 0)))
+#define DIE_IF(expr) \
+ ((void) ((expr) ? (die(__FILE__, __LINE__, #expr), 0) : 0))
#define DIE(expr) \
die(__FILE__, __LINE__, #expr)
@@ -16276,6 +16278,176 @@ static void test_bug38486(void)
DBUG_VOID_RETURN;
}
+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);
+}
+
static void test_bug40365(void)
{
uint rc, i;
@@ -16780,6 +16952,7 @@ static struct my_tests_st my_tests[]= {
{ "test_bug36326", test_bug36326 },
#endif
{ "test_bug41078", test_bug41078 },
+ { "test_bug20023", test_bug20023 },
{ 0, 0 }
};