Commit b92081cd authored by unknown's avatar unknown

Bug#24736: UDF functions parsed as Stored Functions

Before this fix, a call to a User Defined Function (UDF) could,
under some circumstances, be interpreted as a call to a Stored function
instead. This occurred if a native function was invoked in the parameters
for the UDF, as in "select my_udf(abs(x))".

The root cause of this defect is the introduction, by the fix for Bug 21809,
of st_select_lex::udf_list, and it's usage in the parser in sql_yacc.yy
in the rule function_call_generic (in 5.1).

While the fix itself for Bug 21809 is correct in 5.0, the code change
merged into the 5.1 release created the issue, because the calls in 5.1 to :
- lex->current_select->udf_list.push_front(udf)
- lex->current_select->udf_list.pop()
are not balanced in case of native functions, causing the udf_list,
which is really a stack, to be out of sync with the internal stack
maintained by the bison parser.

Instead of moving the call to udf_list.pop(), which would have fixed the
symptom, this patch goes further and removes the need for udf_list.

This is motivated by two reasons:

a) Maintaining a stack in the MySQL code in sync with the stack maintained
internally in sql_yacc.cc (not .yy) is extremely dependent of the
implementation of yacc/bison, and extremely difficult to maintain.
It's also totally dependent of the structure of the grammar, and has a risk
to break with regression defects each time the grammar itself is changed.

b) The previous code did report construct like "foo(expr AS name)" as
syntax errors (ER_PARSER_ERROR), which is incorrect, and misleading.
The syntax is perfectly valid, as this expression is valid when "foo" is
a UDF. Whether this syntax is legal or not depends of the semantic of "foo".

With this change:

a) There is only one stack (in bison), and no List<udf_func> to maintain.

b) "foo(expr AS name)", when used incorrectly, is reported as semantic error:
- ER_WRONG_PARAMETERS_TO_NATIVE_FCT (for native functions)
- ER_WRONG_PARAMETERS_TO_STORED_FCT (for stored functions)
This is achieved by the changes implemented in item_create.cc


mysql-test/r/parser.result:
  New tests
mysql-test/r/udf.result:
  New tests
mysql-test/t/parser.test:
  New tests
mysql-test/t/udf.test:
  New tests
sql/item_create.cc:
  Semantic checks for named parameters, as in "foo(expr AS name)".
sql/share/errmsg.txt:
  New error message
sql/sql_lex.cc:
  Remove usage of udf_list.
sql/sql_lex.h:
  Remove usage of udf_list.
sql/sql_yacc.yy:
  Remove usage of udf_list.
parent 06ac5d2f
......@@ -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'
......@@ -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;
......
......@@ -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);
......@@ -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
#
......
......@@ -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:
<code>foo(expr1 AS name1, expr2 AS name2, ...)</code>
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> *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> *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 @@ class Create_func_asin : public Create_func_arg1
};
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> *item_list);
virtual Item* create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_atan s_singleton;
......@@ -434,10 +465,10 @@ class Create_func_compress : public Create_func_arg1
};
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> *item_list);
virtual Item* create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_concat s_singleton;
......@@ -447,10 +478,10 @@ class Create_func_concat : public Create_func
};
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> *item_list);
virtual Item* create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_concat_ws s_singleton;
......@@ -672,10 +703,10 @@ class Create_func_degrees : public Create_func_arg1
};
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> *item_list);
virtual Item* create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_des_decrypt s_singleton;
......@@ -685,10 +716,10 @@ class Create_func_des_decrypt : public Create_func
};
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> *item_list);
virtual Item* create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_des_encrypt s_singleton;
......@@ -728,10 +759,10 @@ class Create_func_disjoint : public Create_func_arg2
#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> *item_list);
virtual Item* create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_elt s_singleton;
......@@ -754,10 +785,10 @@ class Create_func_encode : public Create_func_arg2
};
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> *item_list);
virtual Item* create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_encrypt s_singleton;
......@@ -825,10 +856,10 @@ class Create_func_exp : public Create_func_arg1
};
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> *item_list);
virtual Item* create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_export_set s_singleton;
......@@ -853,10 +884,10 @@ class Create_func_exteriorring : public Create_func_arg1
#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> *item_list);
virtual Item* create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_field s_singleton;
......@@ -931,10 +962,10 @@ class Create_func_from_days : public Create_func_arg1
};
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> *item_list);
virtual Item* create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_from_unixtime s_singleton;
......@@ -945,10 +976,10 @@ class Create_func_from_unixtime : public Create_func
#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> *item_list);
virtual Item* create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_geometry_from_text s_singleton;
......@@ -960,10 +991,10 @@ class Create_func_geometry_from_text : public Create_func
#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> *item_list);
virtual Item* create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_geometry_from_wkb s_singleton;
......@@ -1032,10 +1063,10 @@ class Create_func_glength : public Create_func_arg1
#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> *item_list);
virtual Item* create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_greatest s_singleton;
......@@ -1237,10 +1268,10 @@ class Create_func_last_day : public Create_func_arg1
};
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> *item_list);
virtual Item* create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_last_insert_id s_singleton;
......@@ -1263,10 +1294,10 @@ class Create_func_lcase : public Create_func_arg1
};
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> *item_list);
virtual Item* create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_least s_singleton;
......@@ -1315,10 +1346,10 @@ class Create_func_load_file : public Create_func_arg1
};
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> *item_list);
virtual Item* create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_locate s_singleton;
......@@ -1328,10 +1359,10 @@ class Create_func_locate : public Create_func
};
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> *item_list);
virtual Item* create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_log s_singleton;
......@@ -1419,10 +1450,10 @@ class Create_func_maketime : public Create_func_arg3
};
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> *item_list);
virtual Item* create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_make_set s_singleton;
......@@ -1432,10 +1463,10 @@ class Create_func_make_set : public Create_func
};
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> *item_list);
virtual Item* create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_master_pos_wait s_singleton;
......@@ -1676,10 +1707,10 @@ class Create_func_radians : public Create_func_arg1
};
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> *item_list);
virtual Item* create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_rand s_singleton;
......@@ -1715,10 +1746,10 @@ class Create_func_reverse : public Create_func_arg1
};
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> *item_list);
virtual Item* create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_round s_singleton;
......@@ -2085,10 +2116,10 @@ class Create_func_unhex : public Create_func_arg1
};
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> *item_list);
virtual Item* create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_unix_timestamp s_singleton;
......@@ -2221,10 +2252,10 @@ class Create_func_y : public Create_func_arg1
#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> *item_list);
virtual Item* create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_year_week s_singleton;
......@@ -2240,6 +2271,29 @@ class Create_func_year_week : public Create_func
=============================================================================
*/
/**
Checks if there are named parameters in a parameter list.
The syntax to name parameters in a function call is as follow:
<code>foo(expr AS named, expr named, expr AS "named", expr "named")</code>
@param params The parameter list, can be null
@return true if one or more parameter is named
*/
static bool has_named_parameters(List<Item> *params)
{
if (params)
{
Item *param;
List_iterator<Item> 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> *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> *item_list)
{
......@@ -2439,6 +2522,13 @@ Create_func_arg1::create(THD *thd, LEX_STRING name, List<Item> *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> *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> *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> *item_list)
Create_func_atan::create_native(THD *thd, LEX_STRING name,
List<Item> *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> *item_list)
Create_func_concat::create_native(THD *thd, LEX_STRING name,
List<Item> *item_list)
{
int arg_count= 0;
......@@ -2714,7 +2823,8 @@ Create_func_concat::create(THD *thd, LEX_STRING name, List<Item> *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> *item_list)
Create_func_concat_ws::create_native(THD *thd, LEX_STRING name,
List<Item> *item_list)
{
int arg_count= 0;
......@@ -2914,7 +3024,7 @@ 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,
Create_func_des_decrypt::create_native(THD *thd, LEX_STRING name,
List<Item> *item_list)
{
Item *func= NULL;
......@@ -2951,7 +3061,7 @@ 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,
Create_func_des_encrypt::create_native(THD *thd, LEX_STRING name,
List<Item> *item_list)
{
Item *func= NULL;
......@@ -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> *item_list)
Create_func_elt::create_native(THD *thd, LEX_STRING name,
List<Item> *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> *item_list)
Create_func_encrypt::create_native(THD *thd, LEX_STRING name,
List<Item> *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> *item_list)
Create_func_export_set::create_native(THD *thd, LEX_STRING name,
List<Item> *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> *item_list)
Create_func_field::create_native(THD *thd, LEX_STRING name,
List<Item> *item_list)
{
int arg_count= 0;
......@@ -3268,7 +3382,7 @@ 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,
Create_func_from_unixtime::create_native(THD *thd, LEX_STRING name,
List<Item> *item_list)
{
Item *func= NULL;
......@@ -3307,7 +3421,7 @@ 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,
Create_func_geometry_from_text::create_native(THD *thd, LEX_STRING name,
List<Item> *item_list)
{
Item *func= NULL;
......@@ -3347,7 +3461,7 @@ 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,
Create_func_geometry_from_wkb::create_native(THD *thd, LEX_STRING name,
List<Item> *item_list)
{
Item *func= NULL;
......@@ -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> *item_list)
Create_func_greatest::create_native(THD *thd, LEX_STRING name,
List<Item> *item_list)
{
int arg_count= 0;
......@@ -3590,7 +3705,7 @@ 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,
Create_func_last_insert_id::create_native(THD *thd, LEX_STRING name,
List<Item> *item_list)
{
Item *func= NULL;
......@@ -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> *item_list)
Create_func_least::create_native(THD *thd, LEX_STRING name,
List<Item> *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> *item_list)
Create_func_locate::create_native(THD *thd, LEX_STRING name,
List<Item> *item_list)
{
Item *func= NULL;
int arg_count= 0;
......@@ -3724,7 +3841,8 @@ Create_func_locate::create(THD *thd, LEX_STRING name, List<Item> *item_list)
Create_func_log Create_func_log::s_singleton;
Item*
Create_func_log::create(THD *thd, LEX_STRING name, List<Item> *item_list)
Create_func_log::create_native(THD *thd, LEX_STRING name,
List<Item> *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> *item_list)
Create_func_make_set::create_native(THD *thd, LEX_STRING name,
List<Item> *item_list)
{
int arg_count= 0;
......@@ -3835,7 +3954,7 @@ Create_func_make_set::create(THD *thd, LEX_STRING name, List<Item> *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,
Create_func_master_pos_wait::create_native(THD *thd, LEX_STRING name,
List<Item> *item_list)
{
Item *func= NULL;
......@@ -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> *item_list)
Create_func_rand::create_native(THD *thd, LEX_STRING name,
List<Item> *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> *item_list)
Create_func_round::create_native(THD *thd, LEX_STRING name,
List<Item> *item_list)
{
Item *func= NULL;
int arg_count= 0;
......@@ -4408,7 +4529,7 @@ 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,
Create_func_unix_timestamp::create_native(THD *thd, LEX_STRING name,
List<Item> *item_list)
{
Item *func= NULL;
......@@ -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> *item_list)
Create_func_year_week::create_native(THD *thd, LEX_STRING name,
List<Item> *item_list)
{
Item *func= NULL;
int arg_count= 0;
......
......@@ -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'"
......@@ -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();
......
......@@ -609,8 +609,6 @@ class st_select_lex: public st_select_lex_node
/* exclude this select from check of unique_table() */
bool exclude_from_table_unique_test;
List<udf_func> udf_list; /* udf function calls stack */
void init_query();
void init_select();
st_select_lex_unit* master_unit();
......
......@@ -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>$= 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= $<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;
}
......
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