mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 20:12:31 +01:00
Bug #6172: RAND(a) should only accept constant values as arguments
RAND() must accept scalar expressions regardless of their kind. That includes both constant expressions and expressions that depend on column values. When the expression is constant the random seed can be initialized at compile time. However when the expression is not constant the random seed must be initialized at each invocation (while it still can be allocated at compile time). Implemented the above rules by extending Item_func_rand::val_real() to initialize the random seed at the correct place. mysql-test/r/func_math.result: Bug #6172: RAND(a) should only accept constant values as arguments - extened the test case mysql-test/t/func_math.test: Bug #6172: RAND(a) should only accept constant values as arguments - extened the test case sql/item_func.cc: Bug #6172: RAND(a) should only accept constant values as arguments - allow specifying non-const expressions as RAND() arguments sql/item_func.h: Bug #6172: RAND(a) should only accept constant values as arguments - allow specifying non-const expressions as RAND() arguments
This commit is contained in:
parent
9af4bbc7b0
commit
d74a7b9def
4 changed files with 78 additions and 29 deletions
|
@ -177,11 +177,46 @@ 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;
|
||||
CREATE TABLE t1 (a INT);
|
||||
INSERT INTO t1 VALUES (1),(1),(1),(2);
|
||||
SELECT CAST(RAND(2) * 1000 AS UNSIGNED), CAST(RAND(a) * 1000 AS UNSIGNED)
|
||||
FROM t1;
|
||||
CAST(RAND(2) * 1000 AS UNSIGNED) CAST(RAND(a) * 1000 AS UNSIGNED)
|
||||
656 405
|
||||
122 405
|
||||
645 405
|
||||
858 656
|
||||
SELECT CAST(RAND(2) * 1000 AS UNSIGNED), CAST(RAND(a) * 1000 AS UNSIGNED)
|
||||
FROM t1 WHERE a = 1;
|
||||
CAST(RAND(2) * 1000 AS UNSIGNED) CAST(RAND(a) * 1000 AS UNSIGNED)
|
||||
656 405
|
||||
122 405
|
||||
645 405
|
||||
INSERT INTO t1 VALUES (3);
|
||||
SELECT CAST(RAND(2) * 1000 AS UNSIGNED), CAST(RAND(a) * 1000 AS UNSIGNED)
|
||||
FROM t1;
|
||||
CAST(RAND(2) * 1000 AS UNSIGNED) CAST(RAND(a) * 1000 AS UNSIGNED)
|
||||
656 405
|
||||
122 405
|
||||
645 405
|
||||
858 656
|
||||
354 906
|
||||
SELECT CAST(RAND(2) * 1000 AS UNSIGNED), CAST(RAND(a) * 1000 AS UNSIGNED)
|
||||
FROM t1 WHERE a = 1;
|
||||
CAST(RAND(2) * 1000 AS UNSIGNED) CAST(RAND(a) * 1000 AS UNSIGNED)
|
||||
656 405
|
||||
122 405
|
||||
645 405
|
||||
PREPARE stmt FROM
|
||||
"SELECT CAST(RAND(2) * 1000 AS UNSIGNED), CAST(RAND(?) * 1000 AS UNSIGNED)
|
||||
FROM t1 WHERE a = 1";
|
||||
set @var=2;
|
||||
EXECUTE stmt USING @var;
|
||||
CAST(RAND(2) * 1000 AS UNSIGNED) CAST(RAND(?) * 1000 AS UNSIGNED)
|
||||
656 656
|
||||
122 122
|
||||
645 645
|
||||
DROP TABLE t1;
|
||||
create table t1 (a varchar(90), ts datetime not null, index (a)) engine=innodb default charset=utf8;
|
||||
insert into t1 values ('http://www.foo.com/', now());
|
||||
select a from t1 where a='http://www.foo.com/' order by abs(timediff(ts, 0));
|
||||
|
|
|
@ -115,11 +115,25 @@ 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;
|
||||
CREATE TABLE t1 (a INT);
|
||||
|
||||
INSERT INTO t1 VALUES (1),(1),(1),(2);
|
||||
SELECT CAST(RAND(2) * 1000 AS UNSIGNED), CAST(RAND(a) * 1000 AS UNSIGNED)
|
||||
FROM t1;
|
||||
SELECT CAST(RAND(2) * 1000 AS UNSIGNED), CAST(RAND(a) * 1000 AS UNSIGNED)
|
||||
FROM t1 WHERE a = 1;
|
||||
INSERT INTO t1 VALUES (3);
|
||||
SELECT CAST(RAND(2) * 1000 AS UNSIGNED), CAST(RAND(a) * 1000 AS UNSIGNED)
|
||||
FROM t1;
|
||||
SELECT CAST(RAND(2) * 1000 AS UNSIGNED), CAST(RAND(a) * 1000 AS UNSIGNED)
|
||||
FROM t1 WHERE a = 1;
|
||||
PREPARE stmt FROM
|
||||
"SELECT CAST(RAND(2) * 1000 AS UNSIGNED), CAST(RAND(?) * 1000 AS UNSIGNED)
|
||||
FROM t1 WHERE a = 1";
|
||||
set @var=2;
|
||||
EXECUTE stmt USING @var;
|
||||
|
||||
DROP TABLE t1;
|
||||
|
||||
#
|
||||
# Bug #14009: use of abs() on null value causes problems with filesort
|
||||
|
|
|
@ -2042,6 +2042,18 @@ my_decimal *Item_func_round::decimal_op(my_decimal *decimal_value)
|
|||
}
|
||||
|
||||
|
||||
void Item_func_rand::seed_random(Item *arg)
|
||||
{
|
||||
/*
|
||||
TODO: do not do reinit 'rand' for every execute of PS/SP if
|
||||
args[0] is a constant.
|
||||
*/
|
||||
uint32 tmp= (uint32) arg->val_int();
|
||||
randominit(rand, (uint32) (tmp*0x10001L+55555555L),
|
||||
(uint32) (tmp*0x10000001L));
|
||||
}
|
||||
|
||||
|
||||
bool Item_func_rand::fix_fields(THD *thd,Item **ref)
|
||||
{
|
||||
if (Item_real_func::fix_fields(thd, ref))
|
||||
|
@ -2049,11 +2061,6 @@ 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
|
||||
|
@ -2065,20 +2072,9 @@ bool Item_func_rand::fix_fields(THD *thd,Item **ref)
|
|||
if (!rand && !(rand= (struct rand_struct*)
|
||||
thd->stmt_arena->alloc(sizeof(*rand))))
|
||||
return TRUE;
|
||||
/*
|
||||
PARAM_ITEM is returned if we're in statement prepare and consequently
|
||||
no placeholder value is set yet.
|
||||
*/
|
||||
if (args[0]->type() != PARAM_ITEM)
|
||||
{
|
||||
/*
|
||||
TODO: do not do reinit 'rand' for every execute of PS/SP if
|
||||
args[0] is a constant.
|
||||
*/
|
||||
uint32 tmp= (uint32) args[0]->val_int();
|
||||
randominit(rand, (uint32) (tmp*0x10001L+55555555L),
|
||||
(uint32) (tmp*0x10000001L));
|
||||
}
|
||||
|
||||
if (args[0]->const_item())
|
||||
seed_random (args[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2108,6 +2104,8 @@ void Item_func_rand::update_used_tables()
|
|||
double Item_func_rand::val_real()
|
||||
{
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
if (arg_count && !args[0]->const_item())
|
||||
seed_random (args[0]);
|
||||
return my_rnd(rand);
|
||||
}
|
||||
|
||||
|
|
|
@ -679,6 +679,8 @@ public:
|
|||
bool const_item() const { return 0; }
|
||||
void update_used_tables();
|
||||
bool fix_fields(THD *thd, Item **ref);
|
||||
private:
|
||||
void seed_random (Item * val);
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue