Below is the list of changes that have just been committed into a local
5.0 repository of davi. When davi does a push these changes
will be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet@stripped, 2008-02-27 23:59:18-03:00, davi@stripped +9 -0
Bug#33851 Passing UNSIGNED param to EXECUTE returns ERROR 1210
The problem is that passing anything other than a integer to a limit
clause in a prepared statement would fail. This limitation was introduced
to avoid replication problems (e.g: replicating the statement with a
string argument would cause a parse failure in the slave).
The solution is to convert arguments to the limit clause to a integer
value and use this converted value when persisting the query to the log.
mysql-test/r/limit.result@stripped, 2008-02-27 23:59:14-03:00, davi@stripped +3 -3
Update test case result.
mysql-test/r/ps.result@stripped, 2008-02-27 23:59:14-03:00, davi@stripped +31 -1
Add test case result for Bug#33851
mysql-test/r/rpl_user_variables.result@stripped, 2008-02-27 23:59:15-03:00, davi@stripped +16 -0
Test case result for replication of prepared statement.
mysql-test/t/limit.test@stripped, 2008-02-27 23:59:15-03:00, davi@stripped +0 -3
Not a error anymore.
mysql-test/t/ps.test@stripped, 2008-02-27 23:59:15-03:00, davi@stripped +19 -0
Add test case for Bug#33851
mysql-test/t/rpl_user_variables.test@stripped, 2008-02-27 23:59:16-03:00, davi@stripped +17 -0
Test replication of a parameter which value is converted.
sql/item.cc@stripped, 2008-02-27 23:59:16-03:00, davi@stripped +11 -12
Convert the parameter value using the getter and setter methods
for each type.
sql/item_func.cc@stripped, 2008-02-27 23:59:16-03:00, davi@stripped +4 -4
Const members functions, object is not mutated.
sql/sql_class.h@stripped, 2008-02-27 23:59:16-03:00, davi@stripped +4 -4
Const members functions, object is not mutated.
diff -Nrup a/mysql-test/r/limit.result b/mysql-test/r/limit.result
--- a/mysql-test/r/limit.result 2007-05-18 04:08:05 -03:00
+++ b/mysql-test/r/limit.result 2008-02-27 23:59:14 -03:00
@@ -94,11 +94,11 @@ drop table t1;
prepare s from "select 1 limit ?";
set @a='qwe';
execute s using @a;
-ERROR HY000: Incorrect arguments to EXECUTE
+1
prepare s from "select 1 limit 1, ?";
execute s using @a;
-ERROR HY000: Incorrect arguments to EXECUTE
+1
prepare s from "select 1 limit ?, ?";
execute s using @a, @a;
-ERROR HY000: Incorrect arguments to EXECUTE
+1
End of 5.0 tests
diff -Nrup a/mysql-test/r/ps.result b/mysql-test/r/ps.result
--- a/mysql-test/r/ps.result 2008-02-21 14:58:27 -03:00
+++ b/mysql-test/r/ps.result 2008-02-27 23:59:14 -03:00
@@ -1690,7 +1690,7 @@ execute stmt using @a;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `?` decimal(2,1) default NULL
+ `?` decimal(2,1) NOT NULL default '0.0'
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
drop table if exists t1;
@@ -1861,4 +1861,34 @@ prepare stmt from "create view v1 as sel
ERROR 42S02: Table 'test.t1' doesn't exist
prepare stmt from "create view v1 as select * from `t1` `b`";
ERROR 42S02: Table 'test.t1' doesn't exist
+prepare stmt from "select ?";
+set @arg= 123456789.987654321;
+select @arg;
+@arg
+123456789.987654321
+execute stmt using @arg;
+?
+123456789.987654321
+set @arg= "string";
+select @arg;
+@arg
+string
+execute stmt using @arg;
+?
+string
+set @arg= 123456;
+select @arg;
+@arg
+123456
+execute stmt using @arg;
+?
+123456
+set @arg= cast(-12345.54321 as decimal(20, 10));
+select @arg;
+@arg
+-12345.5432100000
+execute stmt using @arg;
+?
+-12345.5432100000
+deallocate prepare stmt;
End of 5.0 tests.
diff -Nrup a/mysql-test/r/rpl_user_variables.result b/mysql-test/r/rpl_user_variables.result
--- a/mysql-test/r/rpl_user_variables.result 2007-05-24 07:35:42 -03:00
+++ b/mysql-test/r/rpl_user_variables.result 2008-02-27 23:59:15 -03:00
@@ -290,6 +290,22 @@ select * from t1;
a b
2 1
drop table t1;
+create table t1(a int);
+insert into t1 values (1),(2);
+prepare s1 from 'insert into t1 select a from t1 limit ?';
+set @x='1.1';
+execute s1 using @x;
+select * from t1;
+a
+1
+2
+1
+select * from t1;
+a
+1
+2
+1
+drop table t1;
End of 5.0 tests.
DROP FUNCTION IF EXISTS f1;
DROP FUNCTION IF EXISTS f2;
diff -Nrup a/mysql-test/t/limit.test b/mysql-test/t/limit.test
--- a/mysql-test/t/limit.test 2007-05-18 04:08:05 -03:00
+++ b/mysql-test/t/limit.test 2008-02-27 23:59:15 -03:00
@@ -78,13 +78,10 @@ drop table t1;
prepare s from "select 1 limit ?";
set @a='qwe';
---error 1210
execute s using @a;
prepare s from "select 1 limit 1, ?";
---error 1210
execute s using @a;
prepare s from "select 1 limit ?, ?";
---error 1210
execute s using @a, @a;
--echo End of 5.0 tests
diff -Nrup a/mysql-test/t/ps.test b/mysql-test/t/ps.test
--- a/mysql-test/t/ps.test 2008-02-21 14:58:27 -03:00
+++ b/mysql-test/t/ps.test 2008-02-27 23:59:15 -03:00
@@ -1947,4 +1947,23 @@ prepare stmt from "create view v1 as sel
--error ER_NO_SUCH_TABLE
prepare stmt from "create view v1 as select * from `t1` `b`";
+#
+# Bug#33851: Passing UNSIGNED param to EXECUTE returns ERROR 1210
+#
+
+prepare stmt from "select ?";
+set @arg= 123456789.987654321;
+select @arg;
+execute stmt using @arg;
+set @arg= "string";
+select @arg;
+execute stmt using @arg;
+set @arg= 123456;
+select @arg;
+execute stmt using @arg;
+set @arg= cast(-12345.54321 as decimal(20, 10));
+select @arg;
+execute stmt using @arg;
+deallocate prepare stmt;
+
--echo End of 5.0 tests.
diff -Nrup a/mysql-test/t/rpl_user_variables.test b/mysql-test/t/rpl_user_variables.test
--- a/mysql-test/t/rpl_user_variables.test 2007-05-24 07:35:42 -03:00
+++ b/mysql-test/t/rpl_user_variables.test 2008-02-27 23:59:16 -03:00
@@ -337,6 +337,23 @@ select * from t1;
connection master;
drop table t1;
+#
+# Bug#33851: Passing UNSIGNED param to EXECUTE returns ERROR 1210
+#
+
+connection master;
+create table t1(a int);
+insert into t1 values (1),(2);
+prepare s1 from 'insert into t1 select a from t1 limit ?';
+set @x='1.1';
+execute s1 using @x;
+select * from t1;
+sync_slave_with_master;
+connection slave;
+select * from t1;
+connection master;
+drop table t1;
+
--echo End of 5.0 tests.
# This test uses a stored function that uses user-defined variables to return data
diff -Nrup a/sql/item.cc b/sql/item.cc
--- a/sql/item.cc 2008-02-08 08:55:54 -02:00
+++ b/sql/item.cc 2008-02-27 23:59:16 -03:00
@@ -2576,20 +2576,19 @@ bool Item_param::set_longdata(const char
bool Item_param::set_from_user_var(THD *thd, const user_var_entry *entry)
{
+ my_bool tmp;
DBUG_ENTER("Item_param::set_from_user_var");
if (entry && entry->value)
{
- item_result_type= entry->type;
+ item_result_type= strict_type ? required_result_type : entry->type;
unsigned_flag= entry->unsigned_flag;
- if (strict_type && required_result_type != item_result_type)
- DBUG_RETURN(1);
switch (item_result_type) {
case REAL_RESULT:
- set_double(*(double*)entry->value);
+ set_double(entry->val_real(&tmp));
item_type= Item::REAL_ITEM;
break;
case INT_RESULT:
- set_int(*(longlong*)entry->value, MY_INT64_NUM_DECIMAL_DIGITS);
+ set_int(entry->val_int(&tmp), MY_INT64_NUM_DECIMAL_DIGITS);
item_type= Item::INT_ITEM;
break;
case STRING_RESULT:
@@ -2597,6 +2596,7 @@ bool Item_param::set_from_user_var(THD *
CHARSET_INFO *fromcs= entry->collation.collation;
CHARSET_INFO *tocs= thd->variables.collation_connection;
uint32 dummy_offset;
+ String str;
value.cs_info.character_set_of_placeholder= fromcs;
/*
@@ -2613,18 +2613,17 @@ bool Item_param::set_from_user_var(THD *
*/
item_type= Item::STRING_ITEM;
- if (set_str((const char *)entry->value, entry->length))
+ entry->val_str(&tmp, &str, NOT_FIXED_DEC);
+ if (set_str(str.ptr(), str.length()))
DBUG_RETURN(1);
break;
}
case DECIMAL_RESULT:
{
- const my_decimal *ent_value= (const my_decimal *)entry->value;
- my_decimal2decimal(ent_value, &decimal_value);
- state= DECIMAL_VALUE;
- decimals= ent_value->frac;
- max_length= my_decimal_precision_to_length(ent_value->precision(),
- decimals, unsigned_flag);
+ String str;
+ const my_decimal *dval= (const my_decimal *) entry->value;
+ entry->val_str(&tmp, &str, dval->frac);
+ set_decimal(str.ptr(), str.length());
item_type= Item::DECIMAL_ITEM;
break;
}
diff -Nrup a/sql/item_func.cc b/sql/item_func.cc
--- a/sql/item_func.cc 2008-01-17 15:13:30 -02:00
+++ b/sql/item_func.cc 2008-02-27 23:59:16 -03:00
@@ -3957,7 +3957,7 @@ Item_func_set_user_var::update_hash(void
/* Get the value of a variable as a double */
-double user_var_entry::val_real(my_bool *null_value)
+double user_var_entry::val_real(my_bool *null_value) const
{
if ((*null_value= (value == 0)))
return 0.0;
@@ -3985,7 +3985,7 @@ double user_var_entry::val_real(my_bool
/* Get the value of a variable as an integer */
-longlong user_var_entry::val_int(my_bool *null_value)
+longlong user_var_entry::val_int(my_bool *null_value) const
{
if ((*null_value= (value == 0)))
return LL(0);
@@ -4017,7 +4017,7 @@ longlong user_var_entry::val_int(my_bool
/* Get the value of a variable as a string */
String *user_var_entry::val_str(my_bool *null_value, String *str,
- uint decimals)
+ uint decimals) const
{
if ((*null_value= (value == 0)))
return (String*) 0;
@@ -4047,7 +4047,7 @@ String *user_var_entry::val_str(my_bool
/* Get the value of a variable as a decimal */
-my_decimal *user_var_entry::val_decimal(my_bool *null_value, my_decimal *val)
+my_decimal *user_var_entry::val_decimal(my_bool *null_value, my_decimal *val) const
{
if ((*null_value= (value == 0)))
return 0;
diff -Nrup a/sql/sql_class.h b/sql/sql_class.h
--- a/sql/sql_class.h 2007-12-15 09:04:58 -02:00
+++ b/sql/sql_class.h 2008-02-27 23:59:16 -03:00
@@ -2328,10 +2328,10 @@ class user_var_entry
Item_result type;
bool unsigned_flag;
- double val_real(my_bool *null_value);
- longlong val_int(my_bool *null_value);
- String *val_str(my_bool *null_value, String *str, uint decimals);
- my_decimal *val_decimal(my_bool *null_value, my_decimal *result);
+ double val_real(my_bool *null_value) const;
+ longlong val_int(my_bool *null_value) const;
+ String *val_str(my_bool *null_value, String *str, uint decimals) const;
+ my_decimal *val_decimal(my_bool *null_value, my_decimal *result) const;
DTCollation collation;
};