Commit f8d26221 authored by malff@lambda.hsd1.co.comcast.net's avatar malff@lambda.hsd1.co.comcast.net

Merge malff@bk-internal.mysql.com:/home/bk/mysql-5.0-runtime

into  lambda.hsd1.co.comcast.net.:/home/malff/TREE/mysql-5.0-28318-rework
parents f721a6f6 a9c6ed46
...@@ -1211,7 +1211,7 @@ ERROR 42S02: Unknown table 'c' in field list ...@@ -1211,7 +1211,7 @@ ERROR 42S02: Unknown table 'c' in field list
drop procedure bug15091; drop procedure bug15091;
drop function if exists bug16896; drop function if exists bug16896;
create aggregate function bug16896() returns int return 1; create aggregate function bug16896() returns int return 1;
ERROR 42000: AGGREGATE is not supported for stored functions 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 '() returns int return 1' at line 1
DROP PROCEDURE IF EXISTS bug14702; DROP PROCEDURE IF EXISTS bug14702;
CREATE IF NOT EXISTS PROCEDURE bug14702() CREATE IF NOT EXISTS PROCEDURE bug14702()
BEGIN BEGIN
...@@ -1457,7 +1457,7 @@ CREATE DATABASE mysqltest; ...@@ -1457,7 +1457,7 @@ CREATE DATABASE mysqltest;
USE mysqltest; USE mysqltest;
DROP DATABASE mysqltest; DROP DATABASE mysqltest;
SELECT inexistent(), 1 + ,; SELECT inexistent(), 1 + ,;
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 '' at line 1 ERROR 42000: FUNCTION inexistent does not exist
SELECT inexistent(); SELECT inexistent();
ERROR 42000: FUNCTION inexistent does not exist ERROR 42000: FUNCTION inexistent does not exist
SELECT .inexistent(); SELECT .inexistent();
......
...@@ -6563,6 +6563,21 @@ f1() ...@@ -6563,6 +6563,21 @@ f1()
DROP TABLE t1; DROP TABLE t1;
DROP FUNCTION f1; DROP FUNCTION f1;
DROP PROCEDURE IF EXISTS db28318_a.t1;
DROP PROCEDURE IF EXISTS db28318_b.t2;
DROP DATABASE IF EXISTS db28318_a;
DROP DATABASE IF EXISTS db28318_b;
CREATE DATABASE db28318_a;
CREATE DATABASE db28318_b;
CREATE PROCEDURE db28318_a.t1() SELECT "db28318_a.t1";
CREATE PROCEDURE db28318_b.t2() CALL t1();
use db28318_a;
CALL db28318_b.t2();
ERROR 42000: PROCEDURE db28318_b.t1 does not exist
DROP PROCEDURE db28318_a.t1;
DROP PROCEDURE db28318_b.t2;
DROP DATABASE db28318_a;
DROP DATABASE db28318_b;
# ------------------------------------------------------------------ # ------------------------------------------------------------------
# -- End of 5.0 tests # -- End of 5.0 tests
# ------------------------------------------------------------------ # ------------------------------------------------------------------
...@@ -95,10 +95,10 @@ FR ...@@ -95,10 +95,10 @@ FR
DROP TABLE bug19904; DROP TABLE bug19904;
CREATE DEFINER=CURRENT_USER() FUNCTION should_not_parse CREATE DEFINER=CURRENT_USER() FUNCTION should_not_parse
RETURNS STRING SONAME "should_not_parse.so"; RETURNS STRING SONAME "should_not_parse.so";
ERROR HY000: Incorrect usage of SONAME and DEFINER 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 'RETURNS STRING SONAME "should_not_parse.so"' at line 2
CREATE DEFINER=someone@somewhere FUNCTION should_not_parse CREATE DEFINER=someone@somewhere FUNCTION should_not_parse
RETURNS STRING SONAME "should_not_parse.so"; RETURNS STRING SONAME "should_not_parse.so";
ERROR HY000: Incorrect usage of SONAME and DEFINER 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 'RETURNS STRING SONAME "should_not_parse.so"' at line 2
create table t1(f1 int); create table t1(f1 int);
insert into t1 values(1),(2); insert into t1 values(1),(2);
explain select myfunc_int(f1) from t1 order by 1; explain select myfunc_int(f1) from t1 order by 1;
......
...@@ -1744,7 +1744,7 @@ drop procedure bug15091; ...@@ -1744,7 +1744,7 @@ drop procedure bug15091;
drop function if exists bug16896; drop function if exists bug16896;
--enable_warnings --enable_warnings
--error ER_SP_NO_AGGREGATE --error ER_PARSE_ERROR
create aggregate function bug16896() returns int return 1; create aggregate function bug16896() returns int return 1;
...@@ -2099,7 +2099,10 @@ DROP DATABASE IF EXISTS mysqltest; ...@@ -2099,7 +2099,10 @@ DROP DATABASE IF EXISTS mysqltest;
CREATE DATABASE mysqltest; CREATE DATABASE mysqltest;
USE mysqltest; USE mysqltest;
DROP DATABASE mysqltest; DROP DATABASE mysqltest;
--error ER_PARSE_ERROR # Both ER_SP_DOES_NOT_EXIST and ER_PARSE_ERROR are valid here,
# the result is implementation dependent:
# See Bug#29816 for details
--error ER_SP_DOES_NOT_EXIST
SELECT inexistent(), 1 + ,; SELECT inexistent(), 1 + ,;
--error ER_SP_DOES_NOT_EXIST --error ER_SP_DOES_NOT_EXIST
SELECT inexistent(); SELECT inexistent();
......
...@@ -7671,6 +7671,35 @@ DROP FUNCTION f1; ...@@ -7671,6 +7671,35 @@ DROP FUNCTION f1;
########################################################################### ###########################################################################
#
# Bug#28318 (CREATE FUNCTION (UDF) requires a schema)
#
--disable_warnings
DROP PROCEDURE IF EXISTS db28318_a.t1;
DROP PROCEDURE IF EXISTS db28318_b.t2;
DROP DATABASE IF EXISTS db28318_a;
DROP DATABASE IF EXISTS db28318_b;
--enable_warnings
CREATE DATABASE db28318_a;
CREATE DATABASE db28318_b;
CREATE PROCEDURE db28318_a.t1() SELECT "db28318_a.t1";
CREATE PROCEDURE db28318_b.t2() CALL t1();
use db28318_a;
# In db28318_b.t2, t1 refers to db28318_b.t1
--error ER_SP_DOES_NOT_EXIST
CALL db28318_b.t2();
DROP PROCEDURE db28318_a.t1;
DROP PROCEDURE db28318_b.t2;
DROP DATABASE db28318_a;
DROP DATABASE db28318_b;
--echo # ------------------------------------------------------------------ --echo # ------------------------------------------------------------------
--echo # -- End of 5.0 tests --echo # -- End of 5.0 tests
--echo # ------------------------------------------------------------------ --echo # ------------------------------------------------------------------
...@@ -113,11 +113,11 @@ DROP TABLE bug19904; ...@@ -113,11 +113,11 @@ DROP TABLE bug19904;
# Bug#21269: DEFINER-clause is allowed for UDF-functions # Bug#21269: DEFINER-clause is allowed for UDF-functions
# #
--error ER_WRONG_USAGE --error ER_PARSE_ERROR
CREATE DEFINER=CURRENT_USER() FUNCTION should_not_parse CREATE DEFINER=CURRENT_USER() FUNCTION should_not_parse
RETURNS STRING SONAME "should_not_parse.so"; RETURNS STRING SONAME "should_not_parse.so";
--error ER_WRONG_USAGE --error ER_PARSE_ERROR
CREATE DEFINER=someone@somewhere FUNCTION should_not_parse CREATE DEFINER=someone@somewhere FUNCTION should_not_parse
RETURNS STRING SONAME "should_not_parse.so"; RETURNS STRING SONAME "should_not_parse.so";
# #
......
...@@ -4016,12 +4016,6 @@ end_with_restore_list: ...@@ -4016,12 +4016,6 @@ end_with_restore_list:
if (check_access(thd,INSERT_ACL,"mysql",0,1,0,0)) if (check_access(thd,INSERT_ACL,"mysql",0,1,0,0))
break; break;
#ifdef HAVE_DLOPEN #ifdef HAVE_DLOPEN
if (sp_find_routine(thd, TYPE_ENUM_FUNCTION, lex->spname,
&thd->sp_func_cache, FALSE))
{
my_error(ER_UDF_EXISTS, MYF(0), lex->spname->m_name.str);
goto error;
}
if (!(res = mysql_create_function(thd, &lex->udf))) if (!(res = mysql_create_function(thd, &lex->udf)))
send_ok(thd); send_ok(thd);
#else #else
......
...@@ -426,14 +426,14 @@ int mysql_create_function(THD *thd,udf_func *udf) ...@@ -426,14 +426,14 @@ int mysql_create_function(THD *thd,udf_func *udf)
} }
if (udf->name.length > NAME_LEN) if (udf->name.length > NAME_LEN)
{ {
my_error(ER_TOO_LONG_IDENT, MYF(0), udf->name); my_error(ER_TOO_LONG_IDENT, MYF(0), udf->name.str);
DBUG_RETURN(1); DBUG_RETURN(1);
} }
rw_wrlock(&THR_LOCK_udf); rw_wrlock(&THR_LOCK_udf);
if ((hash_search(&udf_hash,(byte*) udf->name.str, udf->name.length))) if ((hash_search(&udf_hash,(byte*) udf->name.str, udf->name.length)))
{ {
my_error(ER_UDF_EXISTS, MYF(0), udf->name); my_error(ER_UDF_EXISTS, MYF(0), udf->name.str);
goto err; goto err;
} }
if (!(dl = find_udf_dl(udf->dl))) if (!(dl = find_udf_dl(udf->dl)))
......
...@@ -1121,8 +1121,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); ...@@ -1121,8 +1121,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%type <cast_type> cast_type %type <cast_type> cast_type
%type <udf_type> udf_func_type
%type <symbol> FUNC_ARG0 FUNC_ARG1 FUNC_ARG2 FUNC_ARG3 keyword keyword_sp %type <symbol> FUNC_ARG0 FUNC_ARG1 FUNC_ARG2 FUNC_ARG3 keyword keyword_sp
%type <lex_user> user grant_user %type <lex_user> user grant_user
...@@ -1181,11 +1179,12 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); ...@@ -1181,11 +1179,12 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
statement sp_suid statement sp_suid
sp_c_chistics sp_a_chistics sp_chistic sp_c_chistic xa sp_c_chistics sp_a_chistics sp_chistic sp_c_chistic xa
load_data opt_field_or_var_spec fields_or_vars opt_load_data_set_spec load_data opt_field_or_var_spec fields_or_vars opt_load_data_set_spec
definer view_replace_or_algorithm view_replace view_algorithm_opt view_replace_or_algorithm view_replace view_algorithm_opt
view_algorithm view_or_trigger_or_sp view_or_trigger_or_sp_tail view_algorithm view_or_trigger_or_sp definer_tail
view_suid view_tail view_list_opt view_list view_select view_suid view_tail view_list_opt view_list view_select
view_check_option trigger_tail sp_tail view_check_option trigger_tail sp_tail sf_tail udf_tail
case_stmt_specification simple_case_stmt searched_case_stmt case_stmt_specification simple_case_stmt searched_case_stmt
definer_opt no_definer definer
END_OF_INPUT END_OF_INPUT
%type <NONE> call sp_proc_stmts sp_proc_stmts1 sp_proc_stmt %type <NONE> call sp_proc_stmts sp_proc_stmts1 sp_proc_stmt
...@@ -1570,15 +1569,14 @@ sp_name: ...@@ -1570,15 +1569,14 @@ sp_name:
| ident | ident
{ {
LEX *lex= Lex; LEX *lex= Lex;
LEX_STRING db= {0,0}; LEX_STRING db;
THD *thd= YYTHD;
if (check_routine_name($1)) if (check_routine_name($1))
{ {
my_error(ER_SP_WRONG_NAME, MYF(0), $1.str); my_error(ER_SP_WRONG_NAME, MYF(0), $1.str);
MYSQL_YYABORT; MYSQL_YYABORT;
} }
if (thd->db && thd->copy_db_to(&db.str, &db.length)) if (lex->copy_db_to(&db.str, &db.length))
MYSQL_YYABORT; MYSQL_YYABORT;
$$= new sp_name(db, $1, false); $$= new sp_name(db, $1, false);
if ($$) if ($$)
...@@ -1586,131 +1584,6 @@ sp_name: ...@@ -1586,131 +1584,6 @@ sp_name:
} }
; ;
create_function_tail:
RETURNS_SYM udf_type UDF_SONAME_SYM TEXT_STRING_sys
{
LEX *lex=Lex;
if (lex->definer != NULL)
{
/*
DEFINER is a concept meaningful when interpreting SQL code.
UDF functions are compiled.
Using DEFINER with UDF has therefore no semantic,
and is considered a parsing error.
*/
my_error(ER_WRONG_USAGE, MYF(0), "SONAME", "DEFINER");
MYSQL_YYABORT;
}
lex->sql_command = SQLCOM_CREATE_FUNCTION;
lex->udf.name = lex->spname->m_name;
lex->udf.returns=(Item_result) $2;
lex->udf.dl=$4.str;
}
| '('
{
THD *thd= YYTHD;
LEX *lex= thd->lex;
Lex_input_stream *lip= thd->m_lip;
sp_head *sp;
/*
First check if AGGREGATE was used, in that case it's a
syntax error.
*/
if (lex->udf.type == UDFTYPE_AGGREGATE)
{
my_error(ER_SP_NO_AGGREGATE, MYF(0));
MYSQL_YYABORT;
}
if (lex->sphead)
{
my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "FUNCTION");
MYSQL_YYABORT;
}
if (!lex->spname->m_db.length)
{
my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
MYSQL_YYABORT;
}
/* Order is important here: new - reset - init */
sp= new sp_head();
sp->reset_thd_mem_root(thd);
sp->init(lex);
sp->init_sp_name(thd, lex->spname);
sp->m_type= TYPE_ENUM_FUNCTION;
lex->sphead= sp;
/*
* We have to turn of CLIENT_MULTI_QUERIES while parsing a
* stored procedure, otherwise yylex will chop it into pieces
* at each ';'.
*/
sp->m_old_cmq= thd->client_capabilities & CLIENT_MULTI_QUERIES;
thd->client_capabilities &= ~CLIENT_MULTI_QUERIES;
lex->sphead->m_param_begin= lip->tok_start+1;
}
sp_fdparam_list ')'
{
THD *thd= YYTHD;
LEX *lex= thd->lex;
Lex_input_stream *lip= thd->m_lip;
lex->sphead->m_param_end= lip->tok_start;
}
RETURNS_SYM
{
LEX *lex= Lex;
lex->charset= NULL;
lex->length= lex->dec= NULL;
lex->interval_list.empty();
lex->type= 0;
}
type
{
LEX *lex= Lex;
sp_head *sp= lex->sphead;
if (sp->fill_field_definition(YYTHD, lex,
(enum enum_field_types) $8,
&sp->m_return_field_def))
MYSQL_YYABORT;
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
}
sp_c_chistics
{
THD *thd= YYTHD;
LEX *lex= thd->lex;
Lex_input_stream *lip= thd->m_lip;
lex->sphead->m_chistics= &lex->sp_chistics;
lex->sphead->m_body_begin= lip->tok_start;
}
sp_proc_stmt
{
LEX *lex= Lex;
sp_head *sp= lex->sphead;
if (sp->is_not_allowed_in_function("function"))
MYSQL_YYABORT;
lex->sql_command= SQLCOM_CREATE_SPFUNCTION;
sp->init_strings(YYTHD, lex);
if (!(sp->m_flags & sp_head::HAS_RETURN))
{
my_error(ER_SP_NORETURN, MYF(0), sp->m_qname.str);
MYSQL_YYABORT;
}
/* Restore flag if it was cleared above */
if (sp->m_old_cmq)
YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES;
sp->restore_thd_mem_root(YYTHD);
}
;
sp_a_chistics: sp_a_chistics:
/* Empty */ {} /* Empty */ {}
| sp_a_chistics sp_chistic {} | sp_a_chistics sp_chistic {}
...@@ -3011,10 +2884,6 @@ opt_select_from: ...@@ -3011,10 +2884,6 @@ opt_select_from:
opt_limit_clause {} opt_limit_clause {}
| select_from select_lock_type; | select_from select_lock_type;
udf_func_type:
/* empty */ { $$ = UDFTYPE_FUNCTION; }
| AGGREGATE_SYM { $$ = UDFTYPE_AGGREGATE; };
udf_type: udf_type:
STRING_SYM {$$ = (int) STRING_RESULT; } STRING_SYM {$$ = (int) STRING_RESULT; }
| REAL {$$ = (int) REAL_RESULT; } | REAL {$$ = (int) REAL_RESULT; }
...@@ -3678,7 +3547,7 @@ alter: ...@@ -3678,7 +3547,7 @@ alter:
lex->sql_command= SQLCOM_ALTER_FUNCTION; lex->sql_command= SQLCOM_ALTER_FUNCTION;
lex->spname= $3; lex->spname= $3;
} }
| ALTER view_algorithm_opt definer view_suid | ALTER view_algorithm_opt definer_opt view_suid
VIEW_SYM table_ident VIEW_SYM table_ident
{ {
THD *thd= YYTHD; THD *thd= YYTHD;
...@@ -5204,9 +5073,31 @@ simple_expr: ...@@ -5204,9 +5073,31 @@ simple_expr:
#endif /* HAVE_DLOPEN */ #endif /* HAVE_DLOPEN */
{ {
THD *thd= lex->thd; THD *thd= lex->thd;
LEX_STRING db= {0,0}; LEX_STRING db;
if (thd->db && thd->copy_db_to(&db.str, &db.length)) if (! thd->db && ! lex->sphead)
{
/*
The proper error message should be in the lines of:
Can't resolve <name>() to a function call,
because this function:
- is not a native function,
- is not a user defined function,
- can not match a stored function since no database is selected.
Reusing ER_SP_DOES_NOT_EXIST have a message consistent with
the case when a default database exist, see below.
*/
my_error(ER_SP_DOES_NOT_EXIST, MYF(0),
"FUNCTION", $1);
MYSQL_YYABORT; MYSQL_YYABORT;
}
if (lex->copy_db_to(&db.str, &db.length))
MYSQL_YYABORT;
/*
From here, the parser assumes <name>() is a stored function,
as a last choice. This later can lead to ER_SP_DOES_NOT_EXIST.
*/
sp_name *name= new sp_name(db, $1, false); sp_name *name= new sp_name(db, $1, false);
if (name) if (name)
name->init_qname(thd); name->init_qname(thd);
...@@ -6508,9 +6399,11 @@ drop: ...@@ -6508,9 +6399,11 @@ drop:
lex->drop_if_exists=$3; lex->drop_if_exists=$3;
lex->name=$4.str; lex->name=$4.str;
} }
| DROP FUNCTION_SYM if_exists sp_name | DROP FUNCTION_SYM if_exists ident '.' ident
{ {
LEX *lex=Lex; THD *thd= YYTHD;
LEX *lex= thd->lex;
sp_name *spname;
if (lex->sphead) if (lex->sphead)
{ {
my_error(ER_SP_NO_DROP_SP, MYF(0), "FUNCTION"); my_error(ER_SP_NO_DROP_SP, MYF(0), "FUNCTION");
...@@ -6518,7 +6411,28 @@ drop: ...@@ -6518,7 +6411,28 @@ drop:
} }
lex->sql_command = SQLCOM_DROP_FUNCTION; lex->sql_command = SQLCOM_DROP_FUNCTION;
lex->drop_if_exists= $3; lex->drop_if_exists= $3;
lex->spname= $4; spname= new sp_name($4, $6, true);
spname->init_qname(thd);
lex->spname= spname;
}
| DROP FUNCTION_SYM if_exists ident
{
THD *thd= YYTHD;
LEX *lex= thd->lex;
LEX_STRING db= {0, 0};
sp_name *spname;
if (lex->sphead)
{
my_error(ER_SP_NO_DROP_SP, MYF(0), "FUNCTION");
MYSQL_YYABORT;
}
if (thd->db && lex->copy_db_to(&db.str, &db.length))
MYSQL_YYABORT;
lex->sql_command = SQLCOM_DROP_FUNCTION;
lex->drop_if_exists= $3;
spname= new sp_name(db, $4, false);
spname->init_qname(thd);
lex->spname= spname;
} }
| DROP PROCEDURE if_exists sp_name | DROP PROCEDURE if_exists sp_name
{ {
...@@ -9567,19 +9481,27 @@ subselect_end: ...@@ -9567,19 +9481,27 @@ subselect_end:
**************************************************************************/ **************************************************************************/
view_or_trigger_or_sp: view_or_trigger_or_sp:
definer view_or_trigger_or_sp_tail definer definer_tail
{} {}
| view_replace_or_algorithm definer view_tail | no_definer no_definer_tail
{} {}
| view_replace_or_algorithm definer_opt view_tail
{}
; ;
view_or_trigger_or_sp_tail: definer_tail:
view_tail view_tail
{}
| trigger_tail | trigger_tail
{}
| sp_tail | sp_tail
{} | sf_tail
;
no_definer_tail:
view_tail
| trigger_tail
| sp_tail
| sf_tail
| udf_tail
; ;
/************************************************************************** /**************************************************************************
...@@ -9588,23 +9510,31 @@ view_or_trigger_or_sp_tail: ...@@ -9588,23 +9510,31 @@ view_or_trigger_or_sp_tail:
**************************************************************************/ **************************************************************************/
definer_opt:
no_definer
| definer
;
no_definer:
/* empty */
{
/*
We have to distinguish missing DEFINER-clause from case when
CURRENT_USER specified as definer explicitly in order to properly
handle CREATE TRIGGER statements which come to replication thread
from older master servers (i.e. to create non-suid trigger in this
case).
*/
YYTHD->lex->definer= 0;
}
;
definer: definer:
/* empty */ DEFINER_SYM EQ user
{ {
/* YYTHD->lex->definer= get_current_user(YYTHD, $3);
We have to distinguish missing DEFINER-clause from case when }
CURRENT_USER specified as definer explicitly in order to properly ;
handle CREATE TRIGGER statements which come to replication thread
from older master servers (i.e. to create non-suid trigger in this
case).
*/
YYTHD->lex->definer= 0;
}
| DEFINER_SYM EQ user
{
YYTHD->lex->definer= get_current_user(YYTHD, $3);
}
;
/************************************************************************** /**************************************************************************
...@@ -9755,12 +9685,6 @@ trigger_tail: ...@@ -9755,12 +9685,6 @@ trigger_tail:
MYSQL_YYABORT; MYSQL_YYABORT;
} }
if (!$3->m_db.length)
{
my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
MYSQL_YYABORT;
}
if (!(sp= new sp_head())) if (!(sp= new sp_head()))
MYSQL_YYABORT; MYSQL_YYABORT;
sp->reset_thd_mem_root(thd); sp->reset_thd_mem_root(thd);
...@@ -9822,17 +9746,131 @@ trigger_tail: ...@@ -9822,17 +9746,131 @@ trigger_tail:
**************************************************************************/ **************************************************************************/
udf_tail:
AGGREGATE_SYM remember_name FUNCTION_SYM ident
RETURNS_SYM udf_type UDF_SONAME_SYM TEXT_STRING_sys
{
LEX *lex=Lex;
lex->sql_command = SQLCOM_CREATE_FUNCTION;
lex->udf.type= UDFTYPE_AGGREGATE;
lex->stmt_definition_begin= $2;
lex->udf.name = $4;
lex->udf.returns=(Item_result) $6;
lex->udf.dl=$8.str;
}
| remember_name FUNCTION_SYM ident
RETURNS_SYM udf_type UDF_SONAME_SYM TEXT_STRING_sys
{
LEX *lex=Lex;
lex->sql_command = SQLCOM_CREATE_FUNCTION;
lex->udf.type= UDFTYPE_FUNCTION;
lex->stmt_definition_begin= $1;
lex->udf.name = $3;
lex->udf.returns=(Item_result) $5;
lex->udf.dl=$7.str;
}
;
sf_tail:
remember_name /* $1 */
FUNCTION_SYM /* $2 */
sp_name /* $3 */
'(' /* 44 */
{ /* $5 */
THD *thd= YYTHD;
LEX *lex= thd->lex;
Lex_input_stream *lip= thd->m_lip;
sp_head *sp;
lex->stmt_definition_begin= $1;
lex->spname= $3;
if (lex->sphead)
{
my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "FUNCTION");
MYSQL_YYABORT;
}
/* Order is important here: new - reset - init */
sp= new sp_head();
sp->reset_thd_mem_root(thd);
sp->init(lex);
sp->init_sp_name(thd, lex->spname);
sp->m_type= TYPE_ENUM_FUNCTION;
lex->sphead= sp;
/*
* We have to turn of CLIENT_MULTI_QUERIES while parsing a
* stored procedure, otherwise yylex will chop it into pieces
* at each ';'.
*/
sp->m_old_cmq= thd->client_capabilities & CLIENT_MULTI_QUERIES;
thd->client_capabilities &= ~CLIENT_MULTI_QUERIES;
lex->sphead->m_param_begin= lip->tok_start+1;
}
sp_fdparam_list /* $6 */
')' /* $7 */
{ /* $8 */
THD *thd= YYTHD;
LEX *lex= thd->lex;
Lex_input_stream *lip= thd->m_lip;
lex->sphead->m_param_end= lip->tok_start;
}
RETURNS_SYM /* $9 */
{ /* $10 */
LEX *lex= Lex;
lex->charset= NULL;
lex->length= lex->dec= NULL;
lex->interval_list.empty();
lex->type= 0;
}
type /* $11 */
{ /* $12 */
LEX *lex= Lex;
sp_head *sp= lex->sphead;
if (sp->fill_field_definition(YYTHD, lex,
(enum enum_field_types) $11,
&sp->m_return_field_def))
MYSQL_YYABORT;
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
}
sp_c_chistics /* $13 */
{ /* $14 */
THD *thd= YYTHD;
LEX *lex= thd->lex;
Lex_input_stream *lip= thd->m_lip;
lex->sphead->m_chistics= &lex->sp_chistics;
lex->sphead->m_body_begin= lip->tok_start;
}
sp_proc_stmt /* $15 */
{
LEX *lex= Lex;
sp_head *sp= lex->sphead;
if (sp->is_not_allowed_in_function("function"))
MYSQL_YYABORT;
lex->sql_command= SQLCOM_CREATE_SPFUNCTION;
sp->init_strings(YYTHD, lex);
if (!(sp->m_flags & sp_head::HAS_RETURN))
{
my_error(ER_SP_NORETURN, MYF(0), sp->m_qname.str);
MYSQL_YYABORT;
}
/* Restore flag if it was cleared above */
if (sp->m_old_cmq)
YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES;
sp->restore_thd_mem_root(YYTHD);
}
;
sp_tail: sp_tail:
udf_func_type remember_name FUNCTION_SYM sp_name PROCEDURE remember_name sp_name
{
LEX *lex=Lex;
lex->udf.type= $1;
lex->stmt_definition_begin= $2;
lex->spname= $4;
}
create_function_tail
{}
| PROCEDURE remember_name sp_name
{ {
LEX *lex= Lex; LEX *lex= Lex;
sp_head *sp; sp_head *sp;
...@@ -9843,12 +9881,6 @@ sp_tail: ...@@ -9843,12 +9881,6 @@ sp_tail:
MYSQL_YYABORT; MYSQL_YYABORT;
} }
if (!$3->m_db.length)
{
my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
MYSQL_YYABORT;
}
lex->stmt_definition_begin= $2; lex->stmt_definition_begin= $2;
/* Order is important here: new - reset - init */ /* Order is important here: new - reset - init */
......
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