summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/func_math.result45
-rw-r--r--mysql-test/t/func_math.test24
-rw-r--r--sql/item_func.cc36
-rw-r--r--sql/item_func.h2
4 files changed, 78 insertions, 29 deletions
diff --git a/mysql-test/r/func_math.result b/mysql-test/r/func_math.result
index 9a2c55b802d..565c283ee83 100644
--- a/mysql-test/r/func_math.result
+++ b/mysql-test/r/func_math.result
@@ -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));
diff --git a/mysql-test/t/func_math.test b/mysql-test/t/func_math.test
index 09aa5751301..639ced6a1c0 100644
--- a/mysql-test/t/func_math.test
+++ b/mysql-test/t/func_math.test
@@ -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
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 37778acd962..7dfd02c9887 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -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);
}
diff --git a/sql/item_func.h b/sql/item_func.h
index 7810c0ce9a9..3306b059097 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -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);
};