diff options
-rw-r--r-- | mysql-test/r/limit.result | 11 | ||||
-rw-r--r-- | mysql-test/t/limit.test | 17 | ||||
-rw-r--r-- | sql/item.cc | 3 | ||||
-rw-r--r-- | sql/item.h | 9 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 3 |
5 files changed, 42 insertions, 1 deletions
diff --git a/mysql-test/r/limit.result b/mysql-test/r/limit.result index ac96ac8ff17..01d7d7ca218 100644 --- a/mysql-test/r/limit.result +++ b/mysql-test/r/limit.result @@ -91,3 +91,14 @@ select sum(a) c FROM t1 WHERE a > 0 ORDER BY c LIMIT 3; c 28 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 diff --git a/mysql-test/t/limit.test b/mysql-test/t/limit.test index bc599b20d36..286c04785ff 100644 --- a/mysql-test/t/limit.test +++ b/mysql-test/t/limit.test @@ -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; drop table t1; # 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 diff --git a/sql/item.cc b/sql/item.cc index 0f5d3c86485..a5dfa0db6b6 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -2313,6 +2313,7 @@ default_set_param_func(Item_param *param, Item_param::Item_param(unsigned pos_in_query_arg) : + strict_type(FALSE), state(NO_VALUE), item_result_type(STRING_RESULT), /* Don't pretend to be a literal unless value for this item is set. */ @@ -2507,6 +2508,8 @@ bool Item_param::set_from_user_var(THD *thd, const user_var_entry *entry) if (entry && entry->value) { item_result_type= entry->type; + if (strict_type && required_result_type != item_result_type) + DBUG_RETURN(1); switch (item_result_type) { case REAL_RESULT: set_double(*(double*)entry->value); diff --git a/sql/item.h b/sql/item.h index 11dce3a7758..a1704aa6103 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1359,8 +1359,10 @@ class Item_param :public Item char cnvbuf[MAX_FIELD_WIDTH]; String cnvstr; Item *cnvitem; -public: + bool strict_type; + enum Item_result required_result_type; +public: enum enum_item_param_state { NO_VALUE, NULL_VALUE, INT_VALUE, REAL_VALUE, @@ -1488,6 +1490,11 @@ public: Otherwise return FALSE. */ 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; + } }; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index c1da870960b..c65e8a859a7 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -6214,6 +6214,9 @@ limit_options: ; limit_option: param_marker + { + ((Item_param *) $1)->set_strict_type(INT_RESULT); + } | ULONGLONG_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); } |