summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <kostja@bodhi.(none)>2007-11-01 00:31:57 +0300
committerunknown <kostja@bodhi.(none)>2007-11-01 00:31:57 +0300
commit189ec0e0af2ab7d50340f66285ffecc4f06586c6 (patch)
treebcaa91f1539817a06d3c4e08a7e7caf42e152c40
parentc2dadab13649b036b910596382307ffeef2a1951 (diff)
downloadmariadb-git-189ec0e0af2ab7d50340f66285ffecc4f06586c6.tar.gz
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.
-rw-r--r--mysql-test/r/udf.result12
-rw-r--r--mysql-test/t/udf.test12
-rw-r--r--sql/item_func.cc5
3 files changed, 15 insertions, 14 deletions
diff --git a/mysql-test/r/udf.result b/mysql-test/r/udf.result
index da27a71c1a1..cb5afcf5f17 100644
--- a/mysql-test/r/udf.result
+++ b/mysql-test/r/udf.result
@@ -11,7 +11,7 @@ RETURNS STRING SONAME "UDF_EXAMPLE_LIB";
CREATE AGGREGATE FUNCTION avgcost
RETURNS REAL SONAME "UDF_EXAMPLE_LIB";
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);
myfunc_double(1)
49.00
@@ -24,26 +24,26 @@ select myfunc_int();
myfunc_int()
0
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");
lookup("127.0.0.1")
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");
lookup("localhost")
127.0.0.1
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("localhost");
reverse_lookup("localhost")
NULL
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);
-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));
insert into t1 values(100, 50.00), (100, 100.00);
select avgcost(sum, price) from t1;
diff --git a/mysql-test/t/udf.test b/mysql-test/t/udf.test
index 663dc08d72e..32cfca57546 100644
--- a/mysql-test/t/udf.test
+++ b/mysql-test/t/udf.test
@@ -35,20 +35,20 @@ eval CREATE FUNCTION reverse_lookup
eval CREATE AGGREGATE FUNCTION avgcost
RETURNS REAL SONAME "$UDF_EXAMPLE_LIB";
---error 0
+--error ER_CANT_INITIALIZE_UDF
select myfunc_double();
select myfunc_double(1);
select myfunc_double(78654);
--error 1305
select myfunc_nonexist();
select myfunc_int();
---error 0
+--error ER_CANT_INITIALIZE_UDF
select lookup();
select lookup("127.0.0.1");
---error 0
+--error ER_CANT_INITIALIZE_UDF
select lookup(127,0,0,1);
select lookup("localhost");
---error 0
+--error ER_CANT_INITIALIZE_UDF
select reverse_lookup();
# These two functions should return "localhost", but it's
@@ -59,9 +59,9 @@ select reverse_lookup(127,0,0,1);
--enable_result_log
select reverse_lookup("localhost");
---error 0
+--error ER_CANT_INITIALIZE_UDF
select avgcost();
---error 0
+--error ER_CANT_INITIALIZE_UDF
select avgcost(100,23.76);
create table t1(sum int, price float(24));
insert into t1 values(100, 50.00), (100, 100.00);
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 2d4d61de61b..ec0ecc89394 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -2897,6 +2897,7 @@ udf_handler::fix_fields(THD *thd, Item_result_field *func,
if (u_d->func_init)
{
+ char init_msg_buff[MYSQL_ERRMSG_SIZE];
char *to=num_buffer;
for (uint i=0; i < arg_count; i++)
{
@@ -2949,10 +2950,10 @@ udf_handler::fix_fields(THD *thd, Item_result_field *func,
}
thd->net.last_error[0]=0;
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),
- u_d->name.str, thd->net.last_error);
+ u_d->name.str, init_msg_buff);
free_udf(u_d);
DBUG_RETURN(TRUE);
}