Commit c630de3f authored by unknown's avatar unknown

Fix for bug #28464: a string argument to 'limit ?' PS - replication fails

Problem: we may get syntactically incorrect queries in the binary log 
if we use a string value user variable executing a PS which 
contains '... limit ?' clause, e.g.
prepare s from "select 1 limit ?"; 
set @A='qwe'; execute s using @A;
  
Fix: raise an error in such cases.


mysql-test/r/limit.result:
  Fix for bug #28464: a string argument to 'limit ?' PS - replication fails
    - test result
mysql-test/t/limit.test:
  Fix for bug #28464: a string argument to 'limit ?' PS - replication fails
    - test case
sql/item.cc:
  Fix for bug #28464: a string argument to 'limit ?' PS - replication fails
    - if Item_param::strict_type is set, check given and required types,
      return an error if not equal.
sql/item.h:
  Fix for bug #28464: a string argument to 'limit ?' PS - replication fails
    - bool strict_type introduced, which indicates that a parameter value must be of 
      the required_result_type type.
    - set_strict_type() function introduced to set required type.
sql/sql_yacc.yy:
  Fix for bug #28464: a string argument to 'limit ?' PS - replication fails
    - as we accept only INTs in the 'limit' clause set parameter's required type.
parent 0fe5c3f5
...@@ -91,3 +91,14 @@ select sum(a) c FROM t1 WHERE a > 0 ORDER BY c LIMIT 3; ...@@ -91,3 +91,14 @@ select sum(a) c FROM t1 WHERE a > 0 ORDER BY c LIMIT 3;
c c
28 28
drop table t1; drop table t1;
prepare s from "select 1 limit ?";
set @a='qwe';
execute s using @a;
ERROR HY000: Incorrect arguments to EXECUTE
prepare s from "select 1 limit 1, ?";
execute s using @a;
ERROR HY000: Incorrect arguments to EXECUTE
prepare s from "select 1 limit ?, ?";
execute s using @a, @a;
ERROR HY000: Incorrect arguments to EXECUTE
End of 5.0 tests
...@@ -71,3 +71,20 @@ explain select sum(a) c FROM t1 WHERE a > 0 ORDER BY c LIMIT 3; ...@@ -71,3 +71,20 @@ explain select sum(a) c FROM t1 WHERE a > 0 ORDER BY c LIMIT 3;
select sum(a) c FROM t1 WHERE a > 0 ORDER BY c LIMIT 3; select sum(a) c FROM t1 WHERE a > 0 ORDER BY c LIMIT 3;
drop table t1; drop table t1;
# End of 4.1 tests # End of 4.1 tests
#
# Bug #28464: a string argument to 'limit ?' PS
#
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
...@@ -2312,6 +2312,7 @@ default_set_param_func(Item_param *param, ...@@ -2312,6 +2312,7 @@ default_set_param_func(Item_param *param,
Item_param::Item_param(unsigned pos_in_query_arg) : Item_param::Item_param(unsigned pos_in_query_arg) :
strict_type(FALSE),
state(NO_VALUE), state(NO_VALUE),
item_result_type(STRING_RESULT), item_result_type(STRING_RESULT),
/* Don't pretend to be a literal unless value for this item is set. */ /* Don't pretend to be a literal unless value for this item is set. */
...@@ -2506,6 +2507,8 @@ bool Item_param::set_from_user_var(THD *thd, const user_var_entry *entry) ...@@ -2506,6 +2507,8 @@ bool Item_param::set_from_user_var(THD *thd, const user_var_entry *entry)
if (entry && entry->value) if (entry && entry->value)
{ {
item_result_type= entry->type; item_result_type= entry->type;
if (strict_type && required_result_type != item_result_type)
DBUG_RETURN(1);
switch (entry->type) { switch (entry->type) {
case REAL_RESULT: case REAL_RESULT:
set_double(*(double*)entry->value); set_double(*(double*)entry->value);
......
...@@ -1358,8 +1358,10 @@ class Item_param :public Item ...@@ -1358,8 +1358,10 @@ class Item_param :public Item
char cnvbuf[MAX_FIELD_WIDTH]; char cnvbuf[MAX_FIELD_WIDTH];
String cnvstr; String cnvstr;
Item *cnvitem; Item *cnvitem;
public: bool strict_type;
enum Item_result required_result_type;
public:
enum enum_item_param_state enum enum_item_param_state
{ {
NO_VALUE, NULL_VALUE, INT_VALUE, REAL_VALUE, NO_VALUE, NULL_VALUE, INT_VALUE, REAL_VALUE,
...@@ -1487,6 +1489,11 @@ class Item_param :public Item ...@@ -1487,6 +1489,11 @@ class Item_param :public Item
Otherwise return FALSE. Otherwise return FALSE.
*/ */
bool eq(const Item *item, bool binary_cmp) const; bool eq(const Item *item, bool binary_cmp) const;
void set_strict_type(enum Item_result result_type_arg)
{
strict_type= TRUE;
required_result_type= result_type_arg;
}
}; };
......
...@@ -6216,6 +6216,9 @@ limit_options: ...@@ -6216,6 +6216,9 @@ limit_options:
; ;
limit_option: limit_option:
param_marker param_marker
{
((Item_param *) $1)->set_strict_type(INT_RESULT);
}
| ULONGLONG_NUM { $$= new Item_uint($1.str, $1.length); } | ULONGLONG_NUM { $$= new Item_uint($1.str, $1.length); }
| LONG_NUM { $$= new Item_uint($1.str, $1.length); } | LONG_NUM { $$= new Item_uint($1.str, $1.length); }
| NUM { $$= new Item_uint($1.str, $1.length); } | NUM { $$= new Item_uint($1.str, $1.length); }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment