summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/limit.result11
-rw-r--r--mysql-test/t/limit.test17
-rw-r--r--sql/item.cc3
-rw-r--r--sql/item.h9
-rw-r--r--sql/sql_yacc.yy3
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); }