Commit 189ec0e0 authored by unknown's avatar unknown

A fix for Bug#32007 select udf_function() doesn't return an error if error

during udf initialization. The bug is spotted while working on Bug 12713.

If a user-defined function was used in a SELECT statement, and an
error would occur during UDF initialization, this error would not terminate
execution of the SELECT, but rather would be converted to a warning.

The fix is to use a stack buffer to store the message from udf_init instead
of private my_error() buffer.


mysql-test/r/udf.result:
  Update the result to reflect the fix for Bug#32007 select udf_function() 
  doesn't return an error if error during udf initialization
mysql-test/t/udf.test:
  Update the test to reflect the fix for Bug #32007 select udf_function() 
  doesn't return an error if error during udf initialization
sql/item_func.cc:
  A fix for Bug#32007.
  
  net.last_error buffer was used to store the temporary message from udf_init.
  Then, when my_error() was called, net.last_error was not empty so 
  my_error() would conclude that there is already an error in the error stack, 
  and not "overwrite" it.
  However, thd->net.report_error was not set, so the the 
  SELECT was not aborted.
  
  The fix is to use a stack buffer instead of thd->net.last_error
  to store the message from udf_init. The message will end up in
  thd->net.last_error anyway after a call to my_error.
parent c2dadab1
...@@ -11,7 +11,7 @@ RETURNS STRING SONAME "UDF_EXAMPLE_LIB"; ...@@ -11,7 +11,7 @@ RETURNS STRING SONAME "UDF_EXAMPLE_LIB";
CREATE AGGREGATE FUNCTION avgcost CREATE AGGREGATE FUNCTION avgcost
RETURNS REAL SONAME "UDF_EXAMPLE_LIB"; RETURNS REAL SONAME "UDF_EXAMPLE_LIB";
select myfunc_double(); select myfunc_double();
ERROR HY000: myfunc_double must have at least one argument ERROR HY000: Can't initialize function 'myfunc_double'; myfunc_double must have at least one argument
select myfunc_double(1); select myfunc_double(1);
myfunc_double(1) myfunc_double(1)
49.00 49.00
...@@ -24,26 +24,26 @@ select myfunc_int(); ...@@ -24,26 +24,26 @@ select myfunc_int();
myfunc_int() myfunc_int()
0 0
select lookup(); select lookup();
ERROR HY000: Wrong arguments to lookup; Use the source ERROR HY000: Can't initialize function 'lookup'; Wrong arguments to lookup; Use the source
select lookup("127.0.0.1"); select lookup("127.0.0.1");
lookup("127.0.0.1") lookup("127.0.0.1")
127.0.0.1 127.0.0.1
select lookup(127,0,0,1); select lookup(127,0,0,1);
ERROR HY000: Wrong arguments to lookup; Use the source ERROR HY000: Can't initialize function 'lookup'; Wrong arguments to lookup; Use the source
select lookup("localhost"); select lookup("localhost");
lookup("localhost") lookup("localhost")
127.0.0.1 127.0.0.1
select reverse_lookup(); select reverse_lookup();
ERROR HY000: Wrong number of arguments to reverse_lookup; Use the source ERROR HY000: Can't initialize function 'reverse_lookup'; Wrong number of arguments to reverse_lookup; Use the source
select reverse_lookup("127.0.0.1"); select reverse_lookup("127.0.0.1");
select reverse_lookup(127,0,0,1); select reverse_lookup(127,0,0,1);
select reverse_lookup("localhost"); select reverse_lookup("localhost");
reverse_lookup("localhost") reverse_lookup("localhost")
NULL NULL
select avgcost(); select avgcost();
ERROR HY000: wrong number of arguments: AVGCOST() requires two arguments ERROR HY000: Can't initialize function 'avgcost'; wrong number of arguments: AVGCOST() requires two arguments
select avgcost(100,23.76); select avgcost(100,23.76);
ERROR HY000: wrong argument type: AVGCOST() requires an INT and a REAL ERROR HY000: Can't initialize function 'avgcost'; wrong argument type: AVGCOST() requires an INT and a REAL
create table t1(sum int, price float(24)); create table t1(sum int, price float(24));
insert into t1 values(100, 50.00), (100, 100.00); insert into t1 values(100, 50.00), (100, 100.00);
select avgcost(sum, price) from t1; select avgcost(sum, price) from t1;
......
...@@ -35,20 +35,20 @@ eval CREATE FUNCTION reverse_lookup ...@@ -35,20 +35,20 @@ eval CREATE FUNCTION reverse_lookup
eval CREATE AGGREGATE FUNCTION avgcost eval CREATE AGGREGATE FUNCTION avgcost
RETURNS REAL SONAME "$UDF_EXAMPLE_LIB"; RETURNS REAL SONAME "$UDF_EXAMPLE_LIB";
--error 0 --error ER_CANT_INITIALIZE_UDF
select myfunc_double(); select myfunc_double();
select myfunc_double(1); select myfunc_double(1);
select myfunc_double(78654); select myfunc_double(78654);
--error 1305 --error 1305
select myfunc_nonexist(); select myfunc_nonexist();
select myfunc_int(); select myfunc_int();
--error 0 --error ER_CANT_INITIALIZE_UDF
select lookup(); select lookup();
select lookup("127.0.0.1"); select lookup("127.0.0.1");
--error 0 --error ER_CANT_INITIALIZE_UDF
select lookup(127,0,0,1); select lookup(127,0,0,1);
select lookup("localhost"); select lookup("localhost");
--error 0 --error ER_CANT_INITIALIZE_UDF
select reverse_lookup(); select reverse_lookup();
# These two functions should return "localhost", but it's # These two functions should return "localhost", but it's
...@@ -59,9 +59,9 @@ select reverse_lookup(127,0,0,1); ...@@ -59,9 +59,9 @@ select reverse_lookup(127,0,0,1);
--enable_result_log --enable_result_log
select reverse_lookup("localhost"); select reverse_lookup("localhost");
--error 0 --error ER_CANT_INITIALIZE_UDF
select avgcost(); select avgcost();
--error 0 --error ER_CANT_INITIALIZE_UDF
select avgcost(100,23.76); select avgcost(100,23.76);
create table t1(sum int, price float(24)); create table t1(sum int, price float(24));
insert into t1 values(100, 50.00), (100, 100.00); insert into t1 values(100, 50.00), (100, 100.00);
......
...@@ -2897,6 +2897,7 @@ udf_handler::fix_fields(THD *thd, Item_result_field *func, ...@@ -2897,6 +2897,7 @@ udf_handler::fix_fields(THD *thd, Item_result_field *func,
if (u_d->func_init) if (u_d->func_init)
{ {
char init_msg_buff[MYSQL_ERRMSG_SIZE];
char *to=num_buffer; char *to=num_buffer;
for (uint i=0; i < arg_count; i++) for (uint i=0; i < arg_count; i++)
{ {
...@@ -2949,10 +2950,10 @@ udf_handler::fix_fields(THD *thd, Item_result_field *func, ...@@ -2949,10 +2950,10 @@ udf_handler::fix_fields(THD *thd, Item_result_field *func,
} }
thd->net.last_error[0]=0; thd->net.last_error[0]=0;
Udf_func_init init= u_d->func_init; Udf_func_init init= u_d->func_init;
if ((error=(uchar) init(&initid, &f_args, thd->net.last_error))) if ((error=(uchar) init(&initid, &f_args, init_msg_buff)))
{ {
my_error(ER_CANT_INITIALIZE_UDF, MYF(0), my_error(ER_CANT_INITIALIZE_UDF, MYF(0),
u_d->name.str, thd->net.last_error); u_d->name.str, init_msg_buff);
free_udf(u_d); free_udf(u_d);
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
} }
......
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