From a45c451e4002875187a40ec17e872d3b69a3452a Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Tue, 21 Aug 2012 08:46:32 +0300 Subject: [PATCH] Fix for bug lp:1039277 "Crash in sql_cache.cc". The crash happend when combining query cache, prepared statements and using a read only cursor. sql/sql_cache.cc: Fixed unlikely error when one adjust query cache size in middle of operation sql/sql_cursor.cc: Disable query cache when using cursors. This fixed lp:1039277 tests/mysql_client_test.c: Test case for lp:1039277 --- sql/sql_cache.cc | 3 +++ sql/sql_cursor.cc | 2 ++ tests/mysql_client_test.c | 47 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+) diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 7edd28446a2..191cc4e01c8 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -1813,7 +1813,10 @@ Query_cache::send_result_to_client(THD *thd, char *org_sql, uint query_length) goto err; if (query_cache_size == 0) + { + thd->query_cache_is_applicable= 0; // Query can't be cached goto err_unlock; + } Query_cache_block *query_block; if (thd->variables.query_cache_strip_comments) diff --git a/sql/sql_cursor.cc b/sql/sql_cursor.cc index c50cded7470..b8b979a282b 100644 --- a/sql/sql_cursor.cc +++ b/sql/sql_cursor.cc @@ -115,6 +115,8 @@ int mysql_open_cursor(THD *thd, select_result *result, &thd->security_ctx->priv_user[0], (char *) thd->security_ctx->host_or_ip, 2); + /* Mark that we can't use query cache with cursors */ + thd->query_cache_is_applicable= 0; rc= mysql_execute_command(thd); MYSQL_QUERY_EXEC_DONE(rc); diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 9c2329e609a..a0b18f1f717 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -357,6 +357,7 @@ static void test_prepare_insert_update() myquery(rc); } + /* Test simple prepares of all DML statements */ static void test_prepare_simple() @@ -2308,6 +2309,7 @@ static void test_ps_query_cache() if (!opt_silent) fprintf(stdout, "OK"); + break; } strmov(query, "select id1, value1 from t1 where id1= ? or " @@ -13024,6 +13026,49 @@ static void test_bug8880() mysql_stmt_close(*stmt); } +/* + Test executing a query with prepared statements while query cache is active +*/ + +static void test_open_cursor_prepared_statement_query_cache() +{ + MYSQL_STMT *stmt; + int rc; + MYSQL_RES *result; + + myheader("test_open_cursor_prepared_statement_query_cache"); + if (! is_query_cache_available()) + { + fprintf(stdout, "Skipping test_open_cursor_prepared_statement_query_cache: Query cache not available.\n"); + return; + } + + rc= mysql_query(mysql, "set global query_cache_size=1000000"); + myquery(rc); + + mysql_query(mysql, "drop table if exists t1"); + mysql_query(mysql, "create table t1 (a int not null primary key, b int)"); + rc= mysql_query(mysql, "insert into t1 values (1,1)"); + myquery(rc); /* one check is enough */ + + /* Store query in query cache */ + rc= mysql_query(mysql, "SELECT * FROM t1"); + myquery(rc); + result= mysql_store_result(mysql); + mytest(result); + (void) my_process_result_set(result); + mysql_free_result(result); + + /* Test using a cursor */ + stmt= open_cursor("select a from t1"); + rc= mysql_stmt_execute(stmt); + check_execute(stmt, rc); + mysql_stmt_close(stmt); + + rc= mysql_query(mysql, "set global query_cache_size=1000000"); + myquery(rc); +} + static void test_bug9159() { @@ -18917,6 +18962,8 @@ static struct my_tests_st my_tests[]= { { "test_bug8378", test_bug8378 }, { "test_bug8722", test_bug8722 }, { "test_bug8880", test_bug8880 }, + { "test_open_cursor_prepared_statement_query_cache", + test_open_cursor_prepared_statement_query_cache }, { "test_bug9159", test_bug9159 }, { "test_bug9520", test_bug9520 }, { "test_bug9478", test_bug9478 },