summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/sp.result116
-rw-r--r--mysql-test/r/sp_gis.result33
-rw-r--r--mysql-test/r/udf.result16
-rw-r--r--mysql-test/t/sp.test106
-rw-r--r--mysql-test/t/sp_gis.test35
-rw-r--r--mysql-test/t/udf.test36
-rw-r--r--sql/share/errmsg.txt2
-rw-r--r--sql/sql_lex.cc6
-rw-r--r--sql/sql_lex.h2
-rw-r--r--sql/sql_yacc.yy60
10 files changed, 409 insertions, 3 deletions
diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result
index aeccfd9c951..c53656c2546 100644
--- a/mysql-test/r/sp.result
+++ b/mysql-test/r/sp.result
@@ -2178,6 +2178,7 @@ set @stamped_time=in_time;
set x=2;
end if;
end|
+set time_zone='+03:00';
call bug3426(1000, @i)|
select @i, from_unixtime(@stamped_time, '%d-%m-%Y %h:%i:%s') as time|
@i time
@@ -5627,4 +5628,119 @@ Called B
drop procedure proc_21462_a|
drop procedure proc_21462_b|
End of 5.0 tests
+Begin of 5.1 tests
+drop function if exists pi;
+create function pi() returns varchar(50)
+return "pie, my favorite desert.";
+Warnings:
+Note 1578 This function 'pi' has the same name as a native function.
+SET @save_sql_mode=@@sql_mode;
+SET SQL_MODE='IGNORE_SPACE';
+select pi(), pi ();
+pi() pi ()
+3.141593 3.141593
+select test.pi(), test.pi ();
+test.pi() test.pi ()
+pie, my favorite desert. pie, my favorite desert.
+Warnings:
+Note 1578 This function 'pi' has the same name as a native function.
+SET SQL_MODE='';
+select pi(), pi ();
+pi() pi ()
+3.141593 3.141593
+select test.pi(), test.pi ();
+test.pi() test.pi ()
+pie, my favorite desert. pie, my favorite desert.
+SET @@sql_mode=@save_sql_mode;
+drop function pi;
+drop function if exists test.database;
+drop function if exists test.current_user;
+drop function if exists test.md5;
+create database nowhere;
+use nowhere;
+drop database nowhere;
+SET @save_sql_mode=@@sql_mode;
+SET SQL_MODE='IGNORE_SPACE';
+select database(), database ();
+database() database ()
+NULL NULL
+select current_user(), current_user ();
+current_user() current_user ()
+root@localhost root@localhost
+select md5("aaa"), md5 ("aaa");
+md5("aaa") md5 ("aaa")
+47bce5c74f589f4867dbd57e9ca9f808 47bce5c74f589f4867dbd57e9ca9f808
+SET SQL_MODE='';
+select database(), database ();
+database() database ()
+NULL NULL
+select current_user(), current_user ();
+current_user() current_user ()
+root@localhost root@localhost
+select md5("aaa"), md5 ("aaa");
+md5("aaa") md5 ("aaa")
+47bce5c74f589f4867dbd57e9ca9f808 47bce5c74f589f4867dbd57e9ca9f808
+use test;
+create function `database`() returns varchar(50)
+return "Stored function database";
+Warnings:
+Note 1578 This function 'database' has the same name as a native function.
+create function `current_user`() returns varchar(50)
+return "Stored function current_user";
+Warnings:
+Note 1578 This function 'current_user' has the same name as a native function.
+create function md5(x varchar(50)) returns varchar(50)
+return "Stored function md5";
+Warnings:
+Note 1578 This function 'md5' has the same name as a native function.
+SET SQL_MODE='IGNORE_SPACE';
+select database(), database ();
+database() database ()
+test test
+select current_user(), current_user ();
+current_user() current_user ()
+root@localhost root@localhost
+select md5("aaa"), md5 ("aaa");
+md5("aaa") md5 ("aaa")
+47bce5c74f589f4867dbd57e9ca9f808 47bce5c74f589f4867dbd57e9ca9f808
+select test.database(), test.database ();
+test.database() test.database ()
+Stored function database Stored function database
+Warnings:
+Note 1578 This function 'database' has the same name as a native function.
+select test.current_user(), test.current_user ();
+test.current_user() test.current_user ()
+Stored function current_user Stored function current_user
+Warnings:
+Note 1578 This function 'current_user' has the same name as a native function.
+select test.md5("aaa"), test.md5 ("aaa");
+test.md5("aaa") test.md5 ("aaa")
+Stored function md5 Stored function md5
+Warnings:
+Note 1578 This function 'md5' has the same name as a native function.
+SET SQL_MODE='';
+select database(), database ();
+database() database ()
+test test
+select current_user(), current_user ();
+current_user() current_user ()
+root@localhost root@localhost
+select md5("aaa"), md5 ("aaa");
+md5("aaa") md5 ("aaa")
+47bce5c74f589f4867dbd57e9ca9f808 47bce5c74f589f4867dbd57e9ca9f808
+select test.database(), test.database ();
+test.database() test.database ()
+Stored function database Stored function database
+select test.current_user(), test.current_user ();
+test.current_user() test.current_user ()
+Stored function current_user Stored function current_user
+select test.md5("aaa"), test.md5 ("aaa");
+test.md5("aaa") test.md5 ("aaa")
+Stored function md5 Stored function md5
+SET @@sql_mode=@save_sql_mode;
+drop function test.database;
+drop function test.current_user;
+drop function md5;
+use test;
+End of 5.1 tests
drop table t1,t2;
diff --git a/mysql-test/r/sp_gis.result b/mysql-test/r/sp_gis.result
new file mode 100644
index 00000000000..2d538b52279
--- /dev/null
+++ b/mysql-test/r/sp_gis.result
@@ -0,0 +1,33 @@
+use test;
+drop function if exists a;
+drop function if exists x;
+drop function if exists y;
+create function a() returns int
+return 1;
+create function x() returns int
+return 2;
+Warnings:
+Note 1578 This function 'x' has the same name as a native function.
+create function y() returns int
+return 3;
+Warnings:
+Note 1578 This function 'y' has the same name as a native function.
+select a();
+a()
+1
+select x();
+ERROR 42000: Incorrect parameter count in the call to native function 'x'
+select y();
+ERROR 42000: Incorrect parameter count in the call to native function 'y'
+select x(PointFromText("POINT(10 20)")), y(PointFromText("POINT(10 20)"));
+x(PointFromText("POINT(10 20)")) y(PointFromText("POINT(10 20)"))
+10 20
+select test.a(), test.x(), test.y();
+test.a() test.x() test.y()
+1 2 3
+Warnings:
+Note 1578 This function 'x' has the same name as a native function.
+Note 1578 This function 'y' has the same name as a native function.
+drop function a;
+drop function x;
+drop function y;
diff --git a/mysql-test/r/udf.result b/mysql-test/r/udf.result
index a552282fece..851818e7a79 100644
--- a/mysql-test/r/udf.result
+++ b/mysql-test/r/udf.result
@@ -106,6 +106,22 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using temporary; Using filesort
drop table t1;
End of 5.0 tests.
+drop function if exists pi;
+CREATE FUNCTION pi RETURNS STRING SONAME "should_not_parse.so";
+ERROR HY000: This function 'pi' has the same name as a native function.
+DROP FUNCTION IF EXISTS metaphon;
+CREATE FUNCTION metaphon(a int) RETURNS int
+return 0;
+CREATE FUNCTION metaphon RETURNS STRING SONAME "UDF_EXAMPLE_LIB";
+ERROR HY000: Function 'metaphon' already exists
+DROP FUNCTION metaphon;
+CREATE FUNCTION metaphon RETURNS STRING SONAME "UDF_EXAMPLE_LIB";
+CREATE FUNCTION metaphon(a int) RETURNS int
+return 0;
+ERROR HY000: Function 'metaphon' already exists
+CREATE FUNCTION test.metaphon(a int) RETURNS int
+return 0;
+ERROR HY000: Function 'metaphon' already exists
DROP FUNCTION metaphon;
DROP FUNCTION myfunc_double;
DROP FUNCTION myfunc_nonexist;
diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test
index 7c1fd59c50b..d65c4cb526f 100644
--- a/mysql-test/t/sp.test
+++ b/mysql-test/t/sp.test
@@ -11,6 +11,7 @@
# Tests that uses 'goto' to into sp-goto.test (currently disabled)
# Tests that destroys system tables (e.g. mysql.proc) for error testing
# go to sp-destruct.
+# Tests that require --with-geometry go into sp_gis.test
use test;
@@ -2584,6 +2585,9 @@ begin
end if;
end|
+# so that from_unixtime() has a deterministic result
+set time_zone='+03:00';
+
call bug3426(1000, @i)|
select @i, from_unixtime(@stamped_time, '%d-%m-%Y %h:%i:%s') as time|
call bug3426(NULL, @i)|
@@ -6585,6 +6589,108 @@ drop procedure proc_21462_b|
--echo End of 5.0 tests
+--echo Begin of 5.1 tests
+
+#
+# BUG#18239: Possible to overload internal functions with stored functions
+#
+
+delimiter ;|
+
+--disable_warnings
+drop function if exists pi;
+--enable_warnings
+
+create function pi() returns varchar(50)
+return "pie, my favorite desert.";
+
+SET @save_sql_mode=@@sql_mode;
+
+SET SQL_MODE='IGNORE_SPACE';
+
+select pi(), pi ();
+select test.pi(), test.pi ();
+
+SET SQL_MODE='';
+
+select pi(), pi ();
+select test.pi(), test.pi ();
+
+SET @@sql_mode=@save_sql_mode;
+
+drop function pi;
+# End of BUG#18239
+
+#
+# BUG#22619: Spaces considered harmful
+#
+
+--disable_warnings
+drop function if exists test.database;
+drop function if exists test.current_user;
+drop function if exists test.md5;
+--enable_warnings
+
+create database nowhere;
+use nowhere;
+drop database nowhere;
+
+SET @save_sql_mode=@@sql_mode;
+
+SET SQL_MODE='IGNORE_SPACE';
+
+select database(), database ();
+select current_user(), current_user ();
+select md5("aaa"), md5 ("aaa");
+
+SET SQL_MODE='';
+
+select database(), database ();
+select current_user(), current_user ();
+select md5("aaa"), md5 ("aaa");
+
+use test;
+
+create function `database`() returns varchar(50)
+return "Stored function database";
+
+create function `current_user`() returns varchar(50)
+return "Stored function current_user";
+
+create function md5(x varchar(50)) returns varchar(50)
+return "Stored function md5";
+
+SET SQL_MODE='IGNORE_SPACE';
+
+select database(), database ();
+select current_user(), current_user ();
+select md5("aaa"), md5 ("aaa");
+
+select test.database(), test.database ();
+select test.current_user(), test.current_user ();
+select test.md5("aaa"), test.md5 ("aaa");
+
+SET SQL_MODE='';
+
+select database(), database ();
+select current_user(), current_user ();
+select md5("aaa"), md5 ("aaa");
+
+select test.database(), test.database ();
+select test.current_user(), test.current_user ();
+select test.md5("aaa"), test.md5 ("aaa");
+
+SET @@sql_mode=@save_sql_mode;
+
+drop function test.database;
+drop function test.current_user;
+drop function md5;
+
+use test;
+delimiter |;
+# End of BUG#22619
+
+--echo End of 5.1 tests
#
# BUG#NNNN: New bug synopsis
diff --git a/mysql-test/t/sp_gis.test b/mysql-test/t/sp_gis.test
new file mode 100644
index 00000000000..f1d489e4cc5
--- /dev/null
+++ b/mysql-test/t/sp_gis.test
@@ -0,0 +1,35 @@
+-- source include/have_geometry.inc
+
+use test;
+
+#
+# BUG#21025: misleading error message when creating functions named 'x', or 'y'
+#
+
+--disable_warnings
+drop function if exists a;
+drop function if exists x;
+drop function if exists y;
+--enable_warnings
+
+create function a() returns int
+return 1;
+
+create function x() returns int
+return 2;
+
+create function y() returns int
+return 3;
+
+select a();
+--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT
+select x();
+--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT
+select y();
+select x(PointFromText("POINT(10 20)")), y(PointFromText("POINT(10 20)"));
+select test.a(), test.x(), test.y();
+
+drop function a;
+drop function x;
+drop function y;
+
diff --git a/mysql-test/t/udf.test b/mysql-test/t/udf.test
index 96e559f5c05..cab55fdb32a 100644
--- a/mysql-test/t/udf.test
+++ b/mysql-test/t/udf.test
@@ -130,6 +130,42 @@ drop table t1;
--echo End of 5.0 tests.
#
+# BUG#18239: Possible to overload internal functions with stored functions
+#
+
+--disable_warnings
+drop function if exists pi;
+--enable_warnings
+
+--error ER_NATIVE_FCT_NAME_COLLISION
+CREATE FUNCTION pi RETURNS STRING SONAME "should_not_parse.so";
+
+# Verify that Stored Functions and UDF are mutually exclusive
+DROP FUNCTION IF EXISTS metaphon;
+
+CREATE FUNCTION metaphon(a int) RETURNS int
+return 0;
+
+--replace_result $UDF_EXAMPLE_LIB UDF_EXAMPLE_LIB
+--error ER_UDF_EXISTS
+eval CREATE FUNCTION metaphon RETURNS STRING SONAME "$UDF_EXAMPLE_LIB";
+
+DROP FUNCTION metaphon;
+
+--replace_result $UDF_EXAMPLE_LIB UDF_EXAMPLE_LIB
+eval CREATE FUNCTION metaphon RETURNS STRING SONAME "$UDF_EXAMPLE_LIB";
+
+--error ER_UDF_EXISTS
+CREATE FUNCTION metaphon(a int) RETURNS int
+return 0;
+
+--error ER_UDF_EXISTS
+CREATE FUNCTION test.metaphon(a int) RETURNS int
+return 0;
+
+# End of Bug#18239
+
+#
# Drop the example functions from udf_example
#
diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt
index 3022967eeeb..5f9b9e6d563 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_NATIVE_FCT_NAME_COLLISION
+ eng "This function '%-.64s' has the same name as a native function."
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index c35ef4079d3..1c2d2cc1100 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -242,6 +242,12 @@ bool is_keyword(const char *name, uint len)
return get_hash_symbol(name,len,0)!=0;
}
+bool is_lex_native_function(const LEX_STRING *name)
+{
+ DBUG_ASSERT(name != NULL);
+ return (get_hash_symbol(name->str, name->length, 1) != 0);
+}
+
/* make a copy of token before ptr and set yytoklen */
static LEX_STRING get_token(LEX *lex,uint length)
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 7e09675cb0a..e8f275d5caf 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -1230,4 +1230,6 @@ extern void lex_end(LEX *lex);
extern int MYSQLlex(void *arg, void *yythd);
extern const uchar *skip_rear_comments(const uchar *ubegin, const uchar *uend);
+extern bool is_lex_native_function(const LEX_STRING *name);
+
#endif /* MYSQL_SERVER */
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index f2c72654473..d7e212bf737 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -97,6 +97,17 @@ void turn_parser_debug_on()
}
#endif
+static bool is_native_function(THD *thd, const LEX_STRING *name)
+{
+ if (find_native_function_builder(thd, *name))
+ return true;
+
+ if (is_lex_native_function(name))
+ return true;
+
+ return false;
+}
+
%}
%union {
int num;
@@ -1537,6 +1548,7 @@ sp_name:
create_function_tail:
RETURNS_SYM udf_type SONAME_SYM TEXT_STRING_sys
{
+ THD *thd= YYTHD;
LEX *lex=Lex;
if (lex->definer != NULL)
{
@@ -1549,6 +1561,12 @@ create_function_tail:
my_error(ER_WRONG_USAGE, MYF(0), "SONAME", "DEFINER");
YYABORT;
}
+ if (is_native_function(thd, & lex->spname->m_name))
+ {
+ my_error(ER_NATIVE_FCT_NAME_COLLISION, MYF(0),
+ lex->spname->m_name.str);
+ YYABORT;
+ }
lex->sql_command = SQLCOM_CREATE_FUNCTION;
lex->udf.name = lex->spname->m_name;
lex->udf.returns=(Item_result) $2;
@@ -1637,6 +1655,7 @@ create_function_tail:
}
sp_proc_stmt
{
+ THD *thd= YYTHD;
LEX *lex= Lex;
sp_head *sp= lex->sphead;
@@ -1644,15 +1663,50 @@ create_function_tail:
YYABORT;
lex->sql_command= SQLCOM_CREATE_SPFUNCTION;
- sp->init_strings(YYTHD, lex);
+ sp->init_strings(thd, lex);
if (!(sp->m_flags & sp_head::HAS_RETURN))
{
my_error(ER_SP_NORETURN, MYF(0), sp->m_qname.str);
YYABORT;
}
+ if (is_native_function(thd, & sp->m_name))
+ {
+ /*
+ This warning will be printed when
+ [1] A client query is parsed,
+ [2] A stored function is loaded by db_load_routine.
+ Printing the warning for [2] is intentional, to cover the
+ following scenario:
+ - A user define a SF 'foo' using MySQL 5.N
+ - An application uses select foo(), and works.
+ - MySQL 5.{N+1} defines a new native function 'foo', as
+ part of a new feature.
+ - MySQL 5.{N+1} documentation is updated, and should mention
+ that there is a potential incompatible change in case of
+ existing stored function named 'foo'.
+ - The user deploys 5.{N+1}. At this point, 'select foo()'
+ means something different, and the user code is most likely
+ broken (it's only safe if the code is 'select db.foo()').
+ With a warning printed when the SF is loaded (which has to occur
+ before the call), the warning will provide a hint explaining
+ the root cause of a later failure of 'select foo()'.
+ With no warning printed, the user code will fail with no
+ apparent reason.
+ Printing a warning each time db_load_routine is executed for
+ an ambiguous function is annoying, since that can happen a lot,
+ but in practice should not happen unless there *are* name
+ collisions.
+ If a collision exists, it should not be silenced but fixed.
+ */
+ push_warning_printf(thd,
+ MYSQL_ERROR::WARN_LEVEL_NOTE,
+ ER_NATIVE_FCT_NAME_COLLISION,
+ ER(ER_NATIVE_FCT_NAME_COLLISION),
+ sp->m_name.str);
+ }
/* Restore flag if it was cleared above */
- YYTHD->client_capabilities |= $<ulong_num>2;
- sp->restore_thd_mem_root(YYTHD);
+ thd->client_capabilities |= $<ulong_num>2;
+ sp->restore_thd_mem_root(thd);
}
;