diff --git a/mysql-test/r/parser.result b/mysql-test/r/parser.result
index afd78561898..5ba11d75a5a 100644
--- a/mysql-test/r/parser.result
+++ b/mysql-test/r/parser.result
@@ -386,3 +386,104 @@ select yearweek();
ERROR 42000: Incorrect parameter count in the call to native function 'yearweek'
select yearweek(1, 2, 3);
ERROR 42000: Incorrect parameter count in the call to native function 'yearweek'
+select abs(3);
+abs(3)
+3
+select abs(3 AS three);
+ERROR 42000: Incorrect parameters in the call to native function 'abs'
+select abs(3 three);
+ERROR 42000: Incorrect parameters in the call to native function 'abs'
+select abs(3 AS "three");
+ERROR 42000: Incorrect parameters in the call to native function 'abs'
+select abs(3 "three");
+ERROR 42000: Incorrect parameters in the call to native function 'abs'
+set @bar="bar";
+set @foobar="foobar";
+select instr("foobar", "bar");
+instr("foobar", "bar")
+4
+select instr("foobar" AS p1, "bar");
+ERROR 42000: Incorrect parameters in the call to native function 'instr'
+select instr("foobar" p1, "bar");
+ERROR 42000: Incorrect parameters in the call to native function 'instr'
+select instr("foobar" AS "p1", "bar");
+ERROR 42000: Incorrect parameters in the call to native function 'instr'
+select instr("foobar" "p1", "bar");
+instr("foobar" "p1", "bar")
+4
+select instr(@foobar "p1", "bar");
+ERROR 42000: Incorrect parameters in the call to native function 'instr'
+select instr("foobar", "bar" AS p2);
+ERROR 42000: Incorrect parameters in the call to native function 'instr'
+select instr("foobar", "bar" p2);
+ERROR 42000: Incorrect parameters in the call to native function 'instr'
+select instr("foobar", "bar" AS "p2");
+ERROR 42000: Incorrect parameters in the call to native function 'instr'
+select instr("foobar", "bar" "p2");
+instr("foobar", "bar" "p2")
+0
+select instr("foobar", @bar "p2");
+ERROR 42000: Incorrect parameters in the call to native function 'instr'
+select instr("foobar" AS p1, "bar" AS p2);
+ERROR 42000: Incorrect parameters in the call to native function 'instr'
+select conv(255, 10, 16);
+conv(255, 10, 16)
+FF
+select conv(255 AS p1, 10, 16);
+ERROR 42000: Incorrect parameters in the call to native function 'conv'
+select conv(255 p1, 10, 16);
+ERROR 42000: Incorrect parameters in the call to native function 'conv'
+select conv(255 AS "p1", 10, 16);
+ERROR 42000: Incorrect parameters in the call to native function 'conv'
+select conv(255 "p1", 10, 16);
+ERROR 42000: Incorrect parameters in the call to native function 'conv'
+select conv(255, 10 AS p2, 16);
+ERROR 42000: Incorrect parameters in the call to native function 'conv'
+select conv(255, 10 p2, 16);
+ERROR 42000: Incorrect parameters in the call to native function 'conv'
+select conv(255, 10 AS "p2", 16);
+ERROR 42000: Incorrect parameters in the call to native function 'conv'
+select conv(255, 10 "p2", 16);
+ERROR 42000: Incorrect parameters in the call to native function 'conv'
+select conv(255, 10, 16 AS p3);
+ERROR 42000: Incorrect parameters in the call to native function 'conv'
+select conv(255, 10, 16 p3);
+ERROR 42000: Incorrect parameters in the call to native function 'conv'
+select conv(255, 10, 16 AS "p3");
+ERROR 42000: Incorrect parameters in the call to native function 'conv'
+select conv(255, 10, 16 "p3");
+ERROR 42000: Incorrect parameters in the call to native function 'conv'
+select conv(255 AS p1, 10 AS p2, 16 AS p3);
+ERROR 42000: Incorrect parameters in the call to native function 'conv'
+select atan(10);
+atan(10)
+1.4711276743037
+select atan(10 AS p1);
+ERROR 42000: Incorrect parameters in the call to native function 'atan'
+select atan(10 p1);
+ERROR 42000: Incorrect parameters in the call to native function 'atan'
+select atan(10 AS "p1");
+ERROR 42000: Incorrect parameters in the call to native function 'atan'
+select atan(10 "p1");
+ERROR 42000: Incorrect parameters in the call to native function 'atan'
+select atan(10, 20);
+atan(10, 20)
+0.46364760900081
+select atan(10 AS p1, 20);
+ERROR 42000: Incorrect parameters in the call to native function 'atan'
+select atan(10 p1, 20);
+ERROR 42000: Incorrect parameters in the call to native function 'atan'
+select atan(10 AS "p1", 20);
+ERROR 42000: Incorrect parameters in the call to native function 'atan'
+select atan(10 "p1", 20);
+ERROR 42000: Incorrect parameters in the call to native function 'atan'
+select atan(10, 20 AS p2);
+ERROR 42000: Incorrect parameters in the call to native function 'atan'
+select atan(10, 20 p2);
+ERROR 42000: Incorrect parameters in the call to native function 'atan'
+select atan(10, 20 AS "p2");
+ERROR 42000: Incorrect parameters in the call to native function 'atan'
+select atan(10, 20 "p2");
+ERROR 42000: Incorrect parameters in the call to native function 'atan'
+select atan(10 AS p1, 20 AS p2);
+ERROR 42000: Incorrect parameters in the call to native function 'atan'
diff --git a/mysql-test/r/udf.result b/mysql-test/r/udf.result
index 69c860d8f85..52c59e6feb0 100644
--- a/mysql-test/r/udf.result
+++ b/mysql-test/r/udf.result
@@ -132,9 +132,9 @@ a c
1 1
2 2
SELECT a, fn(MIN(b) xx) as c FROM t1 GROUP BY a;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'xx) as c FROM t1 GROUP BY a' at line 1
+ERROR 42000: Incorrect parameters in the call to stored function 'fn'
SELECT myfunc_int(fn(MIN(b) xx)) as c FROM t1 GROUP BY a;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'xx)) as c FROM t1 GROUP BY a' at line 1
+ERROR 42000: Incorrect parameters in the call to stored function 'fn'
SELECT myfunc_int(test.fn(MIN(b) xx)) as c FROM t1 GROUP BY a;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'xx)) as c FROM t1 GROUP BY a' at line 1
SELECT myfunc_int(fn(MIN(b)) xx) as c FROM t1 GROUP BY a;
@@ -185,6 +185,28 @@ DROP VIEW v1;
DROP TABLE t1;
DROP FUNCTION fn;
End of 5.0 tests.
+select myfunc_double(3);
+myfunc_double(3)
+51.00
+select myfunc_double(3 AS three);
+myfunc_double(3 AS three)
+51.00
+select myfunc_double(abs(3));
+myfunc_double(abs(3))
+51.00
+select myfunc_double(abs(3) AS named_param);
+myfunc_double(abs(3) AS named_param)
+51.00
+select abs(myfunc_double(3));
+abs(myfunc_double(3))
+51.00
+select abs(myfunc_double(3 AS three));
+abs(myfunc_double(3 AS three))
+51.00
+select myfunc_double(abs(3 AS wrong));
+ERROR 42000: Incorrect parameters in the call to native function 'abs'
+select abs(myfunc_double(3) AS wrong);
+ERROR 42000: Incorrect parameters in the call to native function 'abs'
DROP FUNCTION metaphon;
DROP FUNCTION myfunc_double;
DROP FUNCTION myfunc_nonexist;
diff --git a/mysql-test/t/parser.test b/mysql-test/t/parser.test
index 11af7c691d8..63e5137b3a3 100644
--- a/mysql-test/t/parser.test
+++ b/mysql-test/t/parser.test
@@ -508,3 +508,113 @@ select yearweek();
-- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT
select yearweek(1, 2, 3);
+#
+# Bug#24736: UDF functions parsed as Stored Functions
+#
+
+# Verify that the syntax for calling UDF : foo(expr AS param, ...)
+# can not be used when calling native functions
+
+# Native function with 1 argument
+
+select abs(3);
+-- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT
+select abs(3 AS three);
+-- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT
+select abs(3 three);
+-- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT
+select abs(3 AS "three");
+-- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT
+select abs(3 "three");
+
+# Native function with 2 arguments
+
+set @bar="bar";
+set @foobar="foobar";
+
+select instr("foobar", "bar");
+-- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT
+select instr("foobar" AS p1, "bar");
+-- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT
+select instr("foobar" p1, "bar");
+-- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT
+select instr("foobar" AS "p1", "bar");
+## String concatenation, valid syntax
+select instr("foobar" "p1", "bar");
+-- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT
+select instr(@foobar "p1", "bar");
+-- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT
+select instr("foobar", "bar" AS p2);
+-- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT
+select instr("foobar", "bar" p2);
+-- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT
+select instr("foobar", "bar" AS "p2");
+## String concatenation, valid syntax
+select instr("foobar", "bar" "p2");
+-- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT
+select instr("foobar", @bar "p2");
+-- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT
+select instr("foobar" AS p1, "bar" AS p2);
+
+# Native function with 3 arguments
+
+select conv(255, 10, 16);
+-- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT
+select conv(255 AS p1, 10, 16);
+-- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT
+select conv(255 p1, 10, 16);
+-- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT
+select conv(255 AS "p1", 10, 16);
+-- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT
+select conv(255 "p1", 10, 16);
+-- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT
+select conv(255, 10 AS p2, 16);
+-- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT
+select conv(255, 10 p2, 16);
+-- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT
+select conv(255, 10 AS "p2", 16);
+-- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT
+select conv(255, 10 "p2", 16);
+-- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT
+select conv(255, 10, 16 AS p3);
+-- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT
+select conv(255, 10, 16 p3);
+-- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT
+select conv(255, 10, 16 AS "p3");
+-- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT
+select conv(255, 10, 16 "p3");
+-- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT
+select conv(255 AS p1, 10 AS p2, 16 AS p3);
+
+# Native function with a variable number of arguments
+
+select atan(10);
+-- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT
+select atan(10 AS p1);
+-- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT
+select atan(10 p1);
+-- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT
+select atan(10 AS "p1");
+-- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT
+select atan(10 "p1");
+
+select atan(10, 20);
+-- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT
+select atan(10 AS p1, 20);
+-- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT
+select atan(10 p1, 20);
+-- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT
+select atan(10 AS "p1", 20);
+-- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT
+select atan(10 "p1", 20);
+-- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT
+select atan(10, 20 AS p2);
+-- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT
+select atan(10, 20 p2);
+-- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT
+select atan(10, 20 AS "p2");
+-- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT
+select atan(10, 20 "p2");
+-- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT
+select atan(10 AS p1, 20 AS p2);
+
diff --git a/mysql-test/t/udf.test b/mysql-test/t/udf.test
index 52ae424e423..24ddc1d44bc 100644
--- a/mysql-test/t/udf.test
+++ b/mysql-test/t/udf.test
@@ -149,9 +149,9 @@ EXPLAIN EXTENDED SELECT myfunc_int(a AS attr_name) FROM t1;
EXPLAIN EXTENDED SELECT myfunc_int(a) FROM t1;
SELECT a,c FROM v1;
---error ER_PARSE_ERROR
+--error ER_WRONG_PARAMETERS_TO_STORED_FCT
SELECT a, fn(MIN(b) xx) as c FROM t1 GROUP BY a;
---error ER_PARSE_ERROR
+--error ER_WRONG_PARAMETERS_TO_STORED_FCT
SELECT myfunc_int(fn(MIN(b) xx)) as c FROM t1 GROUP BY a;
--error ER_PARSE_ERROR
SELECT myfunc_int(test.fn(MIN(b) xx)) as c FROM t1 GROUP BY a;
@@ -173,6 +173,22 @@ DROP FUNCTION fn;
--echo End of 5.0 tests.
+#
+# Bug#24736: UDF functions parsed as Stored Functions
+#
+
+select myfunc_double(3);
+select myfunc_double(3 AS three);
+select myfunc_double(abs(3));
+select myfunc_double(abs(3) AS named_param);
+select abs(myfunc_double(3));
+select abs(myfunc_double(3 AS three));
+
+-- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT
+select myfunc_double(abs(3 AS wrong));
+-- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT
+select abs(myfunc_double(3) AS wrong);
+
#
# Drop the example functions from udf_example
#
diff --git a/sql/item_create.cc b/sql/item_create.cc
index 7722ce28d4a..6f77cc0fa14 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -27,6 +27,37 @@
=============================================================================
*/
+/**
+ Adapter for native functions with a variable number of arguments.
+ The main use of this class is to discard the following calls:
+ foo(expr1 AS name1, expr2 AS name2, ...)
+ which are syntactically correct (the syntax can refer to a UDF),
+ but semantically invalid for native functions.
+*/
+
+class Create_native_func : public Create_func
+{
+public:
+ virtual Item* create(THD *thd, LEX_STRING name, List- *item_list);
+
+ /**
+ Builder method, with no arguments.
+ @param thd The current thread
+ @param name The native function name
+ @param item_list The function parameters, none of which are named
+ @return An item representing the function call
+ */
+ virtual Item* create_native(THD *thd, LEX_STRING name,
+ List
- *item_list) = 0;
+
+protected:
+ /** Constructor. */
+ Create_native_func() {}
+ /** Destructor. */
+ virtual ~Create_native_func() {}
+};
+
+
/**
Adapter for functions that takes exactly zero arguments.
*/
@@ -302,10 +333,10 @@ protected:
};
-class Create_func_atan : public Create_func
+class Create_func_atan : public Create_native_func
{
public:
- virtual Item* create(THD *thd, LEX_STRING name, List
- *item_list);
+ virtual Item* create_native(THD *thd, LEX_STRING name, List
- *item_list);
static Create_func_atan s_singleton;
@@ -434,10 +465,10 @@ protected:
};
-class Create_func_concat : public Create_func
+class Create_func_concat : public Create_native_func
{
public:
- virtual Item* create(THD *thd, LEX_STRING name, List
- *item_list);
+ virtual Item* create_native(THD *thd, LEX_STRING name, List
- *item_list);
static Create_func_concat s_singleton;
@@ -447,10 +478,10 @@ protected:
};
-class Create_func_concat_ws : public Create_func
+class Create_func_concat_ws : public Create_native_func
{
public:
- virtual Item* create(THD *thd, LEX_STRING name, List
- *item_list);
+ virtual Item* create_native(THD *thd, LEX_STRING name, List
- *item_list);
static Create_func_concat_ws s_singleton;
@@ -672,10 +703,10 @@ protected:
};
-class Create_func_des_decrypt : public Create_func
+class Create_func_des_decrypt : public Create_native_func
{
public:
- virtual Item* create(THD *thd, LEX_STRING name, List
- *item_list);
+ virtual Item* create_native(THD *thd, LEX_STRING name, List
- *item_list);
static Create_func_des_decrypt s_singleton;
@@ -685,10 +716,10 @@ protected:
};
-class Create_func_des_encrypt : public Create_func
+class Create_func_des_encrypt : public Create_native_func
{
public:
- virtual Item* create(THD *thd, LEX_STRING name, List
- *item_list);
+ virtual Item* create_native(THD *thd, LEX_STRING name, List
- *item_list);
static Create_func_des_encrypt s_singleton;
@@ -728,10 +759,10 @@ protected:
#endif
-class Create_func_elt : public Create_func
+class Create_func_elt : public Create_native_func
{
public:
- virtual Item* create(THD *thd, LEX_STRING name, List
- *item_list);
+ virtual Item* create_native(THD *thd, LEX_STRING name, List
- *item_list);
static Create_func_elt s_singleton;
@@ -754,10 +785,10 @@ protected:
};
-class Create_func_encrypt : public Create_func
+class Create_func_encrypt : public Create_native_func
{
public:
- virtual Item* create(THD *thd, LEX_STRING name, List
- *item_list);
+ virtual Item* create_native(THD *thd, LEX_STRING name, List
- *item_list);
static Create_func_encrypt s_singleton;
@@ -825,10 +856,10 @@ protected:
};
-class Create_func_export_set : public Create_func
+class Create_func_export_set : public Create_native_func
{
public:
- virtual Item* create(THD *thd, LEX_STRING name, List
- *item_list);
+ virtual Item* create_native(THD *thd, LEX_STRING name, List
- *item_list);
static Create_func_export_set s_singleton;
@@ -853,10 +884,10 @@ protected:
#endif
-class Create_func_field : public Create_func
+class Create_func_field : public Create_native_func
{
public:
- virtual Item* create(THD *thd, LEX_STRING name, List
- *item_list);
+ virtual Item* create_native(THD *thd, LEX_STRING name, List
- *item_list);
static Create_func_field s_singleton;
@@ -931,10 +962,10 @@ protected:
};
-class Create_func_from_unixtime : public Create_func
+class Create_func_from_unixtime : public Create_native_func
{
public:
- virtual Item* create(THD *thd, LEX_STRING name, List
- *item_list);
+ virtual Item* create_native(THD *thd, LEX_STRING name, List
- *item_list);
static Create_func_from_unixtime s_singleton;
@@ -945,10 +976,10 @@ protected:
#ifdef HAVE_SPATIAL
-class Create_func_geometry_from_text : public Create_func
+class Create_func_geometry_from_text : public Create_native_func
{
public:
- virtual Item* create(THD *thd, LEX_STRING name, List
- *item_list);
+ virtual Item* create_native(THD *thd, LEX_STRING name, List
- *item_list);
static Create_func_geometry_from_text s_singleton;
@@ -960,10 +991,10 @@ protected:
#ifdef HAVE_SPATIAL
-class Create_func_geometry_from_wkb : public Create_func
+class Create_func_geometry_from_wkb : public Create_native_func
{
public:
- virtual Item* create(THD *thd, LEX_STRING name, List
- *item_list);
+ virtual Item* create_native(THD *thd, LEX_STRING name, List
- *item_list);
static Create_func_geometry_from_wkb s_singleton;
@@ -1032,10 +1063,10 @@ protected:
#endif
-class Create_func_greatest : public Create_func
+class Create_func_greatest : public Create_native_func
{
public:
- virtual Item* create(THD *thd, LEX_STRING name, List
- *item_list);
+ virtual Item* create_native(THD *thd, LEX_STRING name, List
- *item_list);
static Create_func_greatest s_singleton;
@@ -1237,10 +1268,10 @@ protected:
};
-class Create_func_last_insert_id : public Create_func
+class Create_func_last_insert_id : public Create_native_func
{
public:
- virtual Item* create(THD *thd, LEX_STRING name, List
- *item_list);
+ virtual Item* create_native(THD *thd, LEX_STRING name, List
- *item_list);
static Create_func_last_insert_id s_singleton;
@@ -1263,10 +1294,10 @@ protected:
};
-class Create_func_least : public Create_func
+class Create_func_least : public Create_native_func
{
public:
- virtual Item* create(THD *thd, LEX_STRING name, List
- *item_list);
+ virtual Item* create_native(THD *thd, LEX_STRING name, List
- *item_list);
static Create_func_least s_singleton;
@@ -1315,10 +1346,10 @@ protected:
};
-class Create_func_locate : public Create_func
+class Create_func_locate : public Create_native_func
{
public:
- virtual Item* create(THD *thd, LEX_STRING name, List
- *item_list);
+ virtual Item* create_native(THD *thd, LEX_STRING name, List
- *item_list);
static Create_func_locate s_singleton;
@@ -1328,10 +1359,10 @@ protected:
};
-class Create_func_log : public Create_func
+class Create_func_log : public Create_native_func
{
public:
- virtual Item* create(THD *thd, LEX_STRING name, List
- *item_list);
+ virtual Item* create_native(THD *thd, LEX_STRING name, List
- *item_list);
static Create_func_log s_singleton;
@@ -1419,10 +1450,10 @@ protected:
};
-class Create_func_make_set : public Create_func
+class Create_func_make_set : public Create_native_func
{
public:
- virtual Item* create(THD *thd, LEX_STRING name, List
- *item_list);
+ virtual Item* create_native(THD *thd, LEX_STRING name, List
- *item_list);
static Create_func_make_set s_singleton;
@@ -1432,10 +1463,10 @@ protected:
};
-class Create_func_master_pos_wait : public Create_func
+class Create_func_master_pos_wait : public Create_native_func
{
public:
- virtual Item* create(THD *thd, LEX_STRING name, List
- *item_list);
+ virtual Item* create_native(THD *thd, LEX_STRING name, List
- *item_list);
static Create_func_master_pos_wait s_singleton;
@@ -1676,10 +1707,10 @@ protected:
};
-class Create_func_rand : public Create_func
+class Create_func_rand : public Create_native_func
{
public:
- virtual Item* create(THD *thd, LEX_STRING name, List
- *item_list);
+ virtual Item* create_native(THD *thd, LEX_STRING name, List
- *item_list);
static Create_func_rand s_singleton;
@@ -1715,10 +1746,10 @@ protected:
};
-class Create_func_round : public Create_func
+class Create_func_round : public Create_native_func
{
public:
- virtual Item* create(THD *thd, LEX_STRING name, List
- *item_list);
+ virtual Item* create_native(THD *thd, LEX_STRING name, List
- *item_list);
static Create_func_round s_singleton;
@@ -2085,10 +2116,10 @@ protected:
};
-class Create_func_unix_timestamp : public Create_func
+class Create_func_unix_timestamp : public Create_native_func
{
public:
- virtual Item* create(THD *thd, LEX_STRING name, List
- *item_list);
+ virtual Item* create_native(THD *thd, LEX_STRING name, List
- *item_list);
static Create_func_unix_timestamp s_singleton;
@@ -2221,10 +2252,10 @@ protected:
#endif
-class Create_func_year_week : public Create_func
+class Create_func_year_week : public Create_native_func
{
public:
- virtual Item* create(THD *thd, LEX_STRING name, List
- *item_list);
+ virtual Item* create_native(THD *thd, LEX_STRING name, List
- *item_list);
static Create_func_year_week s_singleton;
@@ -2240,6 +2271,29 @@ protected:
=============================================================================
*/
+/**
+ Checks if there are named parameters in a parameter list.
+ The syntax to name parameters in a function call is as follow:
+
foo(expr AS named, expr named, expr AS "named", expr "named")
+ @param params The parameter list, can be null
+ @return true if one or more parameter is named
+*/
+static bool has_named_parameters(List- *params)
+{
+ if (params)
+ {
+ Item *param;
+ List_iterator
- it(*params);
+ while ((param= it++))
+ {
+ if (! param->is_autogenerated_name)
+ return true;
+ }
+ }
+
+ return false;
+}
+
#ifndef HAVE_SPATIAL
Create_func_no_geom Create_func_no_geom::s_singleton;
@@ -2387,11 +2441,27 @@ Create_sp_func::create(THD *thd, LEX_STRING db, LEX_STRING name,
int arg_count= 0;
Item *func= NULL;
LEX *lex= thd->lex;
- sp_name *qname= new (thd->mem_root) sp_name(db, name);
+ sp_name *qname;
+
+ if (has_named_parameters(item_list))
+ {
+ /*
+ The syntax "db.foo(expr AS p1, expr AS p2, ...) is invalid,
+ and has been rejected during syntactic parsing already,
+ because a stored function call may not have named parameters.
+
+ The syntax "foo(expr AS p1, expr AS p2, ...)" is correct,
+ because it can refer to a User Defined Function call.
+ For a Stored Function however, this has no semantic.
+ */
+ my_error(ER_WRONG_PARAMETERS_TO_STORED_FCT, MYF(0), name.str);
+ return NULL;
+ }
if (item_list != NULL)
arg_count= item_list->elements;
+ qname= new (thd->mem_root) sp_name(db, name);
qname->init_qname(thd);
sp_add_used_routine(lex, thd, qname, TYPE_ENUM_FUNCTION);
@@ -2406,6 +2476,19 @@ Create_sp_func::create(THD *thd, LEX_STRING db, LEX_STRING name,
}
+Item*
+Create_native_func::create(THD *thd, LEX_STRING name, List
- *item_list)
+{
+ if (has_named_parameters(item_list))
+ {
+ my_error(ER_WRONG_PARAMETERS_TO_NATIVE_FCT, MYF(0), name.str);
+ return NULL;
+ }
+
+ return create_native(thd, name, item_list);
+}
+
+
Item*
Create_func_arg0::create(THD *thd, LEX_STRING name, List
- *item_list)
{
@@ -2439,6 +2522,13 @@ Create_func_arg1::create(THD *thd, LEX_STRING name, List
- *item_list)
}
Item *param_1= item_list->pop();
+
+ if (! param_1->is_autogenerated_name)
+ {
+ my_error(ER_WRONG_PARAMETERS_TO_NATIVE_FCT, MYF(0), name.str);
+ return NULL;
+ }
+
return create(thd, param_1);
}
@@ -2459,6 +2549,14 @@ Create_func_arg2::create(THD *thd, LEX_STRING name, List
- *item_list)
Item *param_1= item_list->pop();
Item *param_2= item_list->pop();
+
+ if ( (! param_1->is_autogenerated_name)
+ || (! param_2->is_autogenerated_name))
+ {
+ my_error(ER_WRONG_PARAMETERS_TO_NATIVE_FCT, MYF(0), name.str);
+ return NULL;
+ }
+
return create(thd, param_1, param_2);
}
@@ -2480,6 +2578,15 @@ Create_func_arg3::create(THD *thd, LEX_STRING name, List
- *item_list)
Item *param_1= item_list->pop();
Item *param_2= item_list->pop();
Item *param_3= item_list->pop();
+
+ if ( (! param_1->is_autogenerated_name)
+ || (! param_2->is_autogenerated_name)
+ || (! param_3->is_autogenerated_name))
+ {
+ my_error(ER_WRONG_PARAMETERS_TO_NATIVE_FCT, MYF(0), name.str);
+ return NULL;
+ }
+
return create(thd, param_1, param_2, param_3);
}
@@ -2574,7 +2681,8 @@ Create_func_asin::create(THD *thd, Item *arg1)
Create_func_atan Create_func_atan::s_singleton;
Item*
-Create_func_atan::create(THD *thd, LEX_STRING name, List
- *item_list)
+Create_func_atan::create_native(THD *thd, LEX_STRING name,
+ List
- *item_list)
{
Item* func= NULL;
int arg_count= 0;
@@ -2694,7 +2802,8 @@ Create_func_coercibility::create(THD *thd, Item *arg1)
Create_func_concat Create_func_concat::s_singleton;
Item*
-Create_func_concat::create(THD *thd, LEX_STRING name, List
- *item_list)
+Create_func_concat::create_native(THD *thd, LEX_STRING name,
+ List
- *item_list)
{
int arg_count= 0;
@@ -2714,7 +2823,8 @@ Create_func_concat::create(THD *thd, LEX_STRING name, List
- *item_list)
Create_func_concat_ws Create_func_concat_ws::s_singleton;
Item*
-Create_func_concat_ws::create(THD *thd, LEX_STRING name, List
- *item_list)
+Create_func_concat_ws::create_native(THD *thd, LEX_STRING name,
+ List
- *item_list)
{
int arg_count= 0;
@@ -2914,8 +3024,8 @@ Create_func_degrees::create(THD *thd, Item *arg1)
Create_func_des_decrypt Create_func_des_decrypt::s_singleton;
Item*
-Create_func_des_decrypt::create(THD *thd, LEX_STRING name,
- List
- *item_list)
+Create_func_des_decrypt::create_native(THD *thd, LEX_STRING name,
+ List
- *item_list)
{
Item *func= NULL;
int arg_count= 0;
@@ -2951,8 +3061,8 @@ Create_func_des_decrypt::create(THD *thd, LEX_STRING name,
Create_func_des_encrypt Create_func_des_encrypt::s_singleton;
Item*
-Create_func_des_encrypt::create(THD *thd, LEX_STRING name,
- List
- *item_list)
+Create_func_des_encrypt::create_native(THD *thd, LEX_STRING name,
+ List
- *item_list)
{
Item *func= NULL;
int arg_count= 0;
@@ -3011,7 +3121,8 @@ Create_func_disjoint::create(THD *thd, Item *arg1, Item *arg2)
Create_func_elt Create_func_elt::s_singleton;
Item*
-Create_func_elt::create(THD *thd, LEX_STRING name, List
- *item_list)
+Create_func_elt::create_native(THD *thd, LEX_STRING name,
+ List
- *item_list)
{
int arg_count= 0;
@@ -3050,7 +3161,8 @@ Create_func_encode::create(THD *thd, Item *arg1, Item *arg2)
Create_func_encrypt Create_func_encrypt::s_singleton;
Item*
-Create_func_encrypt::create(THD *thd, LEX_STRING name, List
- *item_list)
+Create_func_encrypt::create_native(THD *thd, LEX_STRING name,
+ List
- *item_list)
{
Item *func= NULL;
int arg_count= 0;
@@ -3131,7 +3243,8 @@ Create_func_exp::create(THD *thd, Item *arg1)
Create_func_export_set Create_func_export_set::s_singleton;
Item*
-Create_func_export_set::create(THD *thd, LEX_STRING name, List
- *item_list)
+Create_func_export_set::create_native(THD *thd, LEX_STRING name,
+ List
- *item_list)
{
Item *func= NULL;
int arg_count= 0;
@@ -3195,7 +3308,8 @@ Create_func_exteriorring::create(THD *thd, Item *arg1)
Create_func_field Create_func_field::s_singleton;
Item*
-Create_func_field::create(THD *thd, LEX_STRING name, List
- *item_list)
+Create_func_field::create_native(THD *thd, LEX_STRING name,
+ List
- *item_list)
{
int arg_count= 0;
@@ -3268,8 +3382,8 @@ Create_func_from_days::create(THD *thd, Item *arg1)
Create_func_from_unixtime Create_func_from_unixtime::s_singleton;
Item*
-Create_func_from_unixtime::create(THD *thd, LEX_STRING name,
- List
- *item_list)
+Create_func_from_unixtime::create_native(THD *thd, LEX_STRING name,
+ List
- *item_list)
{
Item *func= NULL;
int arg_count= 0;
@@ -3307,8 +3421,8 @@ Create_func_from_unixtime::create(THD *thd, LEX_STRING name,
Create_func_geometry_from_text Create_func_geometry_from_text::s_singleton;
Item*
-Create_func_geometry_from_text::create(THD *thd, LEX_STRING name,
- List
- *item_list)
+Create_func_geometry_from_text::create_native(THD *thd, LEX_STRING name,
+ List
- *item_list)
{
Item *func= NULL;
int arg_count= 0;
@@ -3347,8 +3461,8 @@ Create_func_geometry_from_text::create(THD *thd, LEX_STRING name,
Create_func_geometry_from_wkb Create_func_geometry_from_wkb::s_singleton;
Item*
-Create_func_geometry_from_wkb::create(THD *thd, LEX_STRING name,
- List
- *item_list)
+Create_func_geometry_from_wkb::create_native(THD *thd, LEX_STRING name,
+ List
- *item_list)
{
Item *func= NULL;
int arg_count= 0;
@@ -3430,7 +3544,8 @@ Create_func_glength::create(THD *thd, Item *arg1)
Create_func_greatest Create_func_greatest::s_singleton;
Item*
-Create_func_greatest::create(THD *thd, LEX_STRING name, List
- *item_list)
+Create_func_greatest::create_native(THD *thd, LEX_STRING name,
+ List
- *item_list)
{
int arg_count= 0;
@@ -3590,8 +3705,8 @@ Create_func_last_day::create(THD *thd, Item *arg1)
Create_func_last_insert_id Create_func_last_insert_id::s_singleton;
Item*
-Create_func_last_insert_id::create(THD *thd, LEX_STRING name,
- List
- *item_list)
+Create_func_last_insert_id::create_native(THD *thd, LEX_STRING name,
+ List
- *item_list)
{
Item *func= NULL;
int arg_count= 0;
@@ -3636,7 +3751,8 @@ Create_func_lcase::create(THD *thd, Item *arg1)
Create_func_least Create_func_least::s_singleton;
Item*
-Create_func_least::create(THD *thd, LEX_STRING name, List
- *item_list)
+Create_func_least::create_native(THD *thd, LEX_STRING name,
+ List
- *item_list)
{
int arg_count= 0;
@@ -3684,7 +3800,8 @@ Create_func_load_file::create(THD *thd, Item *arg1)
Create_func_locate Create_func_locate::s_singleton;
Item*
-Create_func_locate::create(THD *thd, LEX_STRING name, List
- *item_list)
+Create_func_locate::create_native(THD *thd, LEX_STRING name,
+ List
- *item_list)
{
Item *func= NULL;
int arg_count= 0;
@@ -3724,7 +3841,8 @@ Create_func_locate::create(THD *thd, LEX_STRING name, List
- *item_list)
Create_func_log Create_func_log::s_singleton;
Item*
-Create_func_log::create(THD *thd, LEX_STRING name, List
- *item_list)
+Create_func_log::create_native(THD *thd, LEX_STRING name,
+ List
- *item_list)
{
Item *func= NULL;
int arg_count= 0;
@@ -3814,7 +3932,8 @@ Create_func_maketime::create(THD *thd, Item *arg1, Item *arg2, Item *arg3)
Create_func_make_set Create_func_make_set::s_singleton;
Item*
-Create_func_make_set::create(THD *thd, LEX_STRING name, List
- *item_list)
+Create_func_make_set::create_native(THD *thd, LEX_STRING name,
+ List
- *item_list)
{
int arg_count= 0;
@@ -3835,8 +3954,8 @@ Create_func_make_set::create(THD *thd, LEX_STRING name, List
- *item_list)
Create_func_master_pos_wait Create_func_master_pos_wait::s_singleton;
Item*
-Create_func_master_pos_wait::create(THD *thd, LEX_STRING name,
- List
- *item_list)
+Create_func_master_pos_wait::create_native(THD *thd, LEX_STRING name,
+ List
- *item_list)
{
Item *func= NULL;
int arg_count= 0;
@@ -4044,7 +4163,8 @@ Create_func_radians::create(THD *thd, Item *arg1)
Create_func_rand Create_func_rand::s_singleton;
Item*
-Create_func_rand::create(THD *thd, LEX_STRING name, List
- *item_list)
+Create_func_rand::create_native(THD *thd, LEX_STRING name,
+ List
- *item_list)
{
Item *func= NULL;
int arg_count= 0;
@@ -4099,7 +4219,8 @@ Create_func_reverse::create(THD *thd, Item *arg1)
Create_func_round Create_func_round::s_singleton;
Item*
-Create_func_round::create(THD *thd, LEX_STRING name, List
- *item_list)
+Create_func_round::create_native(THD *thd, LEX_STRING name,
+ List
- *item_list)
{
Item *func= NULL;
int arg_count= 0;
@@ -4408,8 +4529,8 @@ Create_func_unhex::create(THD *thd, Item *arg1)
Create_func_unix_timestamp Create_func_unix_timestamp::s_singleton;
Item*
-Create_func_unix_timestamp::create(THD *thd, LEX_STRING name,
- List
- *item_list)
+Create_func_unix_timestamp::create_native(THD *thd, LEX_STRING name,
+ List
- *item_list)
{
Item *func= NULL;
int arg_count= 0;
@@ -4540,7 +4661,8 @@ Create_func_y::create(THD *thd, Item *arg1)
Create_func_year_week Create_func_year_week::s_singleton;
Item*
-Create_func_year_week::create(THD *thd, LEX_STRING name, List
- *item_list)
+Create_func_year_week::create_native(THD *thd, LEX_STRING name,
+ List
- *item_list)
{
Item *func= NULL;
int arg_count= 0;
diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt
index 3022967eeeb..6d7e4075e2c 100644
--- a/sql/share/errmsg.txt
+++ b/sql/share/errmsg.txt
@@ -6010,4 +6010,6 @@ ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT 42000
eng "Incorrect parameter count in the call to native function '%-.64s'"
ER_WRONG_PARAMETERS_TO_NATIVE_FCT 42000
eng "Incorrect parameters in the call to native function '%-.64s'"
+ER_WRONG_PARAMETERS_TO_STORED_FCT 42000
+ eng "Incorrect parameters in the call to stored function '%-.64s'"
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index ca40dc9013a..5c074cfc742 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -164,7 +164,6 @@ void lex_start(THD *thd, const uchar *buf, uint length)
lex->select_lex.ftfunc_list= &lex->select_lex.ftfunc_list_alloc;
lex->select_lex.group_list.empty();
lex->select_lex.order_list.empty();
- lex->select_lex.udf_list.empty();
lex->ignore_space=test(thd->variables.sql_mode & MODE_IGNORE_SPACE);
lex->sql_command= SQLCOM_END;
lex->duplicates= DUP_ERROR;
@@ -1176,7 +1175,6 @@ void st_select_lex::init_select()
braces= 0;
when_list.empty();
expr_list.empty();
- udf_list.empty();
interval_list.empty();
use_index.empty();
ftfunc_list_alloc.empty();
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index dd00018f5f8..21e1872d167 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -609,8 +609,6 @@ public:
/* exclude this select from check of unique_table() */
bool exclude_from_table_unique_test;
- List udf_list; /* udf function calls stack */
-
void init_query();
void init_select();
st_select_lex_unit* master_unit();
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index f5ad6f1e278..a6d9f5a15db 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -6375,7 +6375,7 @@ function_call_generic:
}
}
/* Temporary placing the result of find_udf in $3 */
- lex->current_select->udf_list.push_front(udf);
+ $$= udf;
#endif
}
udf_expr_list ')'
@@ -6403,10 +6403,10 @@ function_call_generic:
{
#ifdef HAVE_DLOPEN
/* Retrieving the result of find_udf */
- udf_func *udf;
+ udf_func *udf= $3;
LEX *lex= Lex;
- if (NULL != (udf= lex->current_select->udf_list.pop()))
+ if (udf)
{
if (udf->type == UDFTYPE_AGGREGATE)
{
@@ -6502,7 +6502,6 @@ udf_expr_list3:
udf_expr:
remember_name expr remember_end select_alias
{
- udf_func *udf= Select->udf_list.head();
/*
Use Item::name as a storage for the attribute value of user
defined function argument. It is safe to use Item::name
@@ -6511,20 +6510,10 @@ udf_expr:
*/
if ($4.str)
{
- if (!udf)
- {
- /*
- Disallow using AS to specify explicit names for the arguments
- of stored routine calls
- */
- yyerror(ER(ER_SYNTAX_ERROR));
- YYABORT;
- }
-
$2->is_autogenerated_name= FALSE;
$2->set_name($4.str, $4.length, system_charset_info);
}
- else if (udf)
+ else
$2->set_name($1, (uint) ($3 - $1), YYTHD->charset());
$$= $2;
}