diff options
-rw-r--r-- | mysql-test/r/func_math.result | 5 | ||||
-rw-r--r-- | mysql-test/r/ps.result | 44 | ||||
-rw-r--r-- | mysql-test/t/func_math.test | 9 | ||||
-rw-r--r-- | mysql-test/t/ps.test | 4 | ||||
-rw-r--r-- | sql/item_func.cc | 5 | ||||
-rw-r--r-- | sql/mysql_priv.h | 2 | ||||
-rw-r--r-- | sql/sql_cache.cc | 114 | ||||
-rw-r--r-- | sql/sql_cache.h | 5 |
8 files changed, 126 insertions, 62 deletions
diff --git a/mysql-test/r/func_math.result b/mysql-test/r/func_math.result index 0149911e36b..5b6c29f87fb 100644 --- a/mysql-test/r/func_math.result +++ b/mysql-test/r/func_math.result @@ -165,3 +165,8 @@ drop table t1; select abs(-2) * -2; abs(-2) * -2 -4 +create table t1 (i int); +insert into t1 values (1); +select rand(i) from t1; +ERROR HY000: Incorrect arguments to RAND +drop table t1; diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 0050dfc0841..dc78f8d04ea 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -335,39 +335,37 @@ create table t1 (a int); insert into t1 (a) values (1), (2), (3), (4); set @precision=10000000000; select rand(), -cast(rand(10)*@precision as unsigned integer), -cast(rand(a)*@precision as unsigned integer) from t1; -rand() cast(rand(10)*@precision as unsigned integer) cast(rand(a)*@precision as unsigned integer) -- 6570515219 - -- 1282061302 - -- 6698761160 - -- 9647622201 - +cast(rand(10)*@precision as unsigned integer) from t1; +rand() cast(rand(10)*@precision as unsigned integer) +- 6570515219 +- 1282061302 +- 6698761160 +- 9647622201 prepare stmt from "select rand(), cast(rand(10)*@precision as unsigned integer), - cast(rand(a)*@precision as unsigned integer), cast(rand(?)*@precision as unsigned integer) from t1"; set @var=1; execute stmt using @var; -rand() cast(rand(10)*@precision as unsigned integer) cast(rand(a)*@precision as unsigned integer) cast(rand(?)*@precision as unsigned integer) -- 6570515219 - 4054035371 -- 1282061302 - 8716141803 -- 6698761160 - 1418603212 -- 9647622201 - 944590960 +rand() cast(rand(10)*@precision as unsigned integer) cast(rand(?)*@precision as unsigned integer) +- 6570515219 - +- 1282061302 - +- 6698761160 - +- 9647622201 - set @var=2; execute stmt using @var; -rand() cast(rand(10)*@precision as unsigned integer) cast(rand(a)*@precision as unsigned integer) cast(rand(?)*@precision as unsigned integer) -- 6570515219 1559528654 6555866465 -- 1282061302 6238114970 1223466192 -- 6698761160 6511989195 6449731873 -- 9647622201 3845601374 8578261098 +rand() cast(rand(10)*@precision as unsigned integer) cast(rand(?)*@precision as unsigned integer) +- 6570515219 6555866465 +- 1282061302 1223466192 +- 6698761160 6449731873 +- 9647622201 8578261098 set @var=3; execute stmt using @var; -rand() cast(rand(10)*@precision as unsigned integer) cast(rand(a)*@precision as unsigned integer) cast(rand(?)*@precision as unsigned integer) -- 6570515219 1559528654 9057697559 -- 1282061302 6238114970 3730790581 -- 6698761160 6511989195 1480860534 -- 9647622201 3845601374 6211931236 +rand() cast(rand(10)*@precision as unsigned integer) cast(rand(?)*@precision as unsigned integer) +- 6570515219 9057697559 +- 1282061302 3730790581 +- 6698761160 1480860534 +- 9647622201 6211931236 drop table t1; deallocate prepare stmt; create database mysqltest1; diff --git a/mysql-test/t/func_math.test b/mysql-test/t/func_math.test index bf692325a6a..633e36f51ab 100644 --- a/mysql-test/t/func_math.test +++ b/mysql-test/t/func_math.test @@ -107,4 +107,13 @@ drop table t1; # select abs(-2) * -2; +# +# Bug #6172 RAND(a) should only accept constant values as arguments +# +create table t1 (i int); +insert into t1 values (1); +--error 1210 +select rand(i) from t1; +drop table t1; + # End of 4.1 tests diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index b4c04e4432a..94596fbbc0e 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -371,12 +371,10 @@ insert into t1 (a) values (1), (2), (3), (4); set @precision=10000000000; --replace_column 1 - 3 - select rand(), - cast(rand(10)*@precision as unsigned integer), - cast(rand(a)*@precision as unsigned integer) from t1; + cast(rand(10)*@precision as unsigned integer) from t1; prepare stmt from "select rand(), cast(rand(10)*@precision as unsigned integer), - cast(rand(a)*@precision as unsigned integer), cast(rand(?)*@precision as unsigned integer) from t1"; set @var=1; --replace_column 1 - 3 - diff --git a/sql/item_func.cc b/sql/item_func.cc index 22d9fbbad34..7400a569342 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -1874,6 +1874,11 @@ bool Item_func_rand::fix_fields(THD *thd,Item **ref) used_tables_cache|= RAND_TABLE_BIT; if (arg_count) { // Only use argument once in query + if (!args[0]->const_during_execution()) + { + my_error(ER_WRONG_ARGUMENTS, MYF(0), "RAND"); + return TRUE; + } /* Allocate rand structure once: we must use thd->stmt_arena to create rand in proper mem_root if it's a prepared statement or diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 3430bd77e0f..0bddf92e6aa 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -545,6 +545,7 @@ struct Query_cache_query_flags #define query_cache_store_query(A, B) query_cache.store_query(A, B) #define query_cache_destroy() query_cache.destroy() #define query_cache_result_size_limit(A) query_cache.result_size_limit(A) +#define query_cache_init() query_cache.init() #define query_cache_resize(A) query_cache.resize(A) #define query_cache_set_min_res_unit(A) query_cache.set_min_res_unit(A) #define query_cache_invalidate3(A, B, C) query_cache.invalidate(A, B, C) @@ -558,6 +559,7 @@ struct Query_cache_query_flags #define query_cache_store_query(A, B) #define query_cache_destroy() #define query_cache_result_size_limit(A) +#define query_cache_init() #define query_cache_resize(A) #define query_cache_set_min_res_unit(A) #define query_cache_invalidate3(A, B, C) diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 81eed413a8e..04663c5b096 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -573,13 +573,18 @@ void query_cache_insert(NET *net, const char *packet, ulong length) { DBUG_ENTER("query_cache_insert"); -#ifndef DBUG_OFF - // Check if we have called query_cache.wreck() (which disables the cache) - if (query_cache.query_cache_size == 0) + STRUCT_LOCK(&query_cache.structure_guard_mutex); + /* + It is very unlikely that following condition is TRUE (it is possible + only if other thread is resizing cache), so we check it only after guard + mutex lock + */ + if (unlikely(query_cache.query_cache_size == 0)) + { + STRUCT_UNLOCK(&query_cache.structure_guard_mutex); DBUG_VOID_RETURN; -#endif + } - STRUCT_LOCK(&query_cache.structure_guard_mutex); Query_cache_block *query_block = ((Query_cache_block*) net->query_cache_query); if (query_block) @@ -623,14 +628,20 @@ void query_cache_abort(NET *net) { DBUG_ENTER("query_cache_abort"); -#ifndef DBUG_OFF - // Check if we have called query_cache.wreck() (which disables the cache) - if (query_cache.query_cache_size == 0) - DBUG_VOID_RETURN; -#endif if (net->query_cache_query != 0) // Quick check on unlocked structure { STRUCT_LOCK(&query_cache.structure_guard_mutex); + /* + It is very unlikely that following condition is TRUE (it is possible + only if other thread is resizing cache), so we check it only after guard + mutex lock + */ + if (unlikely(query_cache.query_cache_size == 0)) + { + STRUCT_UNLOCK(&query_cache.structure_guard_mutex); + DBUG_VOID_RETURN; + } + Query_cache_block *query_block = ((Query_cache_block*) net->query_cache_query); if (query_block) // Test if changed by other thread @@ -652,11 +663,6 @@ void query_cache_end_of_result(THD *thd) { DBUG_ENTER("query_cache_end_of_result"); -#ifndef DBUG_OFF - // Check if we have called query_cache.wreck() (which disables the cache) - if (query_cache.query_cache_size == 0) DBUG_VOID_RETURN; -#endif - if (thd->net.query_cache_query != 0) // Quick check on unlocked structure { #ifdef EMBEDDED_LIBRARY @@ -664,6 +670,17 @@ void query_cache_end_of_result(THD *thd) emb_count_querycache_size(thd)); #endif STRUCT_LOCK(&query_cache.structure_guard_mutex); + /* + It is very unlikely that following condition is TRUE (it is possible + only if other thread is resizing cache), so we check it only after guard + mutex lock + */ + if (unlikely(query_cache.query_cache_size == 0)) + { + STRUCT_UNLOCK(&query_cache.structure_guard_mutex); + DBUG_VOID_RETURN; + } + Query_cache_block *query_block = ((Query_cache_block*) thd->net.query_cache_query); if (query_block) @@ -743,9 +760,14 @@ ulong Query_cache::resize(ulong query_cache_size_arg) DBUG_ENTER("Query_cache::resize"); DBUG_PRINT("qcache", ("from %lu to %lu",query_cache_size, query_cache_size_arg)); - free_cache(0); + DBUG_ASSERT(initialized); + STRUCT_LOCK(&structure_guard_mutex); + if (query_cache_size > 0) + free_cache(); query_cache_size= query_cache_size_arg; - DBUG_RETURN(::query_cache_size= init_cache()); + ::query_cache_size= init_cache(); + STRUCT_UNLOCK(&structure_guard_mutex); + DBUG_RETURN(::query_cache_size); } @@ -1438,7 +1460,7 @@ void Query_cache::destroy() } else { - free_cache(1); + free_cache(); pthread_mutex_destroy(&structure_guard_mutex); initialized = 0; } @@ -1467,8 +1489,6 @@ ulong Query_cache::init_cache() int align; DBUG_ENTER("Query_cache::init_cache"); - if (!initialized) - init(); approx_additional_data_size = (sizeof(Query_cache) + sizeof(gptr)*(def_query_hash_size+ def_table_hash_size)); @@ -1526,14 +1546,9 @@ ulong Query_cache::init_cache() goto err; query_cache_size -= additional_data_size; - STRUCT_LOCK(&structure_guard_mutex); - - if (!(cache = (byte *) - my_malloc_lock(query_cache_size+additional_data_size, MYF(0)))) - { - STRUCT_UNLOCK(&structure_guard_mutex); + if (!(cache= (byte *) + my_malloc_lock(query_cache_size+additional_data_size, MYF(0)))) goto err; - } DBUG_PRINT("qcache", ("cache length %lu, min unit %lu, %u bins", query_cache_size, min_allocation_unit, mem_bin_num)); @@ -1629,7 +1644,6 @@ ulong Query_cache::init_cache() queries_in_cache = 0; queries_blocks = 0; - STRUCT_UNLOCK(&structure_guard_mutex); DBUG_RETURN(query_cache_size + additional_data_size + approx_additional_data_size); @@ -1645,6 +1659,7 @@ void Query_cache::make_disabled() { DBUG_ENTER("Query_cache::make_disabled"); query_cache_size= 0; + queries_blocks= 0; free_memory= 0; bins= 0; steps= 0; @@ -1656,14 +1671,11 @@ void Query_cache::make_disabled() } -void Query_cache::free_cache(my_bool destruction) +void Query_cache::free_cache() { DBUG_ENTER("Query_cache::free_cache"); if (query_cache_size > 0) { - if (!destruction) - STRUCT_LOCK(&structure_guard_mutex); - flush_cache(); #ifndef DBUG_OFF if (bins[0].free_blocks == 0) @@ -1685,8 +1697,6 @@ void Query_cache::free_cache(my_bool destruction) make_disabled(); hash_free(&queries); hash_free(&tables); - if (!destruction) - STRUCT_UNLOCK(&structure_guard_mutex); } DBUG_VOID_RETURN; } @@ -2401,7 +2411,19 @@ Query_cache::allocate_block(ulong len, my_bool not_less, ulong min, } if (!under_guard) + { STRUCT_LOCK(&structure_guard_mutex); + /* + It is very unlikely that following condition is TRUE (it is possible + only if other thread is resizing cache), so we check it only after + guard mutex lock + */ + if (unlikely(query_cache.query_cache_size == 0)) + { + STRUCT_UNLOCK(&structure_guard_mutex); + DBUG_RETURN(0); + } + } /* Free old queries until we have enough memory to store this block */ Query_cache_block *block; @@ -2947,6 +2969,17 @@ void Query_cache::pack_cache() { DBUG_ENTER("Query_cache::pack_cache"); STRUCT_LOCK(&structure_guard_mutex); + /* + It is very unlikely that following condition is TRUE (it is possible + only if other thread is resizing cache), so we check it only after + guard mutex lock + */ + if (unlikely(query_cache_size == 0)) + { + STRUCT_UNLOCK(&structure_guard_mutex); + DBUG_VOID_RETURN; + } + DBUG_EXECUTE("check_querycache",query_cache.check_integrity(1);); byte *border = 0; @@ -3256,6 +3289,7 @@ my_bool Query_cache::join_results(ulong join_limit) STRUCT_LOCK(&structure_guard_mutex); if (queries_blocks != 0) { + DBUG_ASSERT(query_cache_size > 0); Query_cache_block *block = queries_blocks; do { @@ -3552,7 +3586,19 @@ my_bool Query_cache::check_integrity(bool not_locked) DBUG_RETURN(0); } if (!not_locked) + { STRUCT_LOCK(&structure_guard_mutex); + /* + It is very unlikely that following condition is TRUE (it is possible + only if other thread is resizing cache), so we check it only after + guard mutex lock + */ + if (unlikely(query_cache_size == 0)) + { + STRUCT_UNLOCK(&query_cache.structure_guard_mutex); + DBUG_RETURN(0); + } + } if (hash_check(&queries)) { diff --git a/sql/sql_cache.h b/sql/sql_cache.h index c1b08904f51..123d16b606d 100644 --- a/sql/sql_cache.h +++ b/sql/sql_cache.h @@ -327,10 +327,9 @@ protected: Following function control structure_guard_mutex by themself or don't need structure_guard_mutex */ - void init(); ulong init_cache(); void make_disabled(); - void free_cache(my_bool destruction); + void free_cache(); Query_cache_block *write_block_data(ulong data_len, gptr data, ulong header_len, Query_cache_block::block_type type, @@ -366,6 +365,8 @@ protected: uint def_query_hash_size = QUERY_CACHE_DEF_QUERY_HASH_SIZE, uint def_table_hash_size = QUERY_CACHE_DEF_TABLE_HASH_SIZE); + /* initialize cache (mutex) */ + void init(); /* resize query cache (return real query size, 0 if disabled) */ ulong resize(ulong query_cache_size); /* set limit on result size */ |