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.
This commit is contained in:
parent
8ab53d5f4e
commit
5b3b80b44f
@ -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;
|
|||||||
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,
|
|||||||
|
|
||||||
|
|
||||||
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)
|
|||||||
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
|
|||||||
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 @@ public:
|
|||||||
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:
|
|||||||
;
|
;
|
||||||
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); }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user