Commit f3a0df72 authored by Alexander Barkov's avatar Alexander Barkov

Reusing code: Adding LEX::make_sp_head() and LEX::make_sp_head_no_recursive()

parent dc292bc6
...@@ -35,8 +35,7 @@ ...@@ -35,8 +35,7 @@
#include <my_user.h> #include <my_user.h>
/* Used in error handling only */ /* Used in error handling only */
#define SP_TYPE_STRING(type) \ #define SP_TYPE_STRING(type) stored_procedure_type_to_str(type)
(type == TYPE_ENUM_FUNCTION ? "FUNCTION" : "PROCEDURE")
static int static int
db_load_routine(THD *thd, stored_procedure_type type, sp_name *name, db_load_routine(THD *thd, stored_procedure_type type, sp_name *name,
...@@ -1699,8 +1698,7 @@ sp_show_create_routine(THD *thd, stored_procedure_type type, sp_name *name) ...@@ -1699,8 +1698,7 @@ sp_show_create_routine(THD *thd, stored_procedure_type type, sp_name *name)
If we have insufficient privileges, pretend the routine If we have insufficient privileges, pretend the routine
does not exist. does not exist.
*/ */
my_error(ER_SP_DOES_NOT_EXIST, MYF(0), my_error(ER_SP_DOES_NOT_EXIST, MYF(0), stored_procedure_type_to_str(type),
type == TYPE_ENUM_FUNCTION ? "FUNCTION" : "PROCEDURE",
name->m_name.str); name->m_name.str);
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
} }
......
...@@ -48,6 +48,20 @@ enum stored_procedure_type ...@@ -48,6 +48,20 @@ enum stored_procedure_type
TYPE_ENUM_PROXY=4 TYPE_ENUM_PROXY=4
}; };
static inline const char *
stored_procedure_type_to_str(enum stored_procedure_type type)
{
switch (type) {
case TYPE_ENUM_PROCEDURE: return "PROCEDURE";
case TYPE_ENUM_FUNCTION: return "FUNCTION";
case TYPE_ENUM_TRIGGER: return "TRIGGER";
case TYPE_ENUM_PROXY: return "PROXY";
}
DBUG_ASSERT(0);
return "UNKNOWN_STORED_";
}
/* Tells what SP_DEFAULT_ACCESS should be mapped to */ /* Tells what SP_DEFAULT_ACCESS should be mapped to */
#define SP_DEFAULT_ACCESS_MAPPING SP_CONTAINS_SQL #define SP_DEFAULT_ACCESS_MAPPING SP_CONTAINS_SQL
......
...@@ -5365,6 +5365,29 @@ bool LEX::sp_block_finalize(THD *thd, const Lex_spblock_st spblock, ...@@ -5365,6 +5365,29 @@ bool LEX::sp_block_finalize(THD *thd, const Lex_spblock_st spblock,
} }
sp_head *LEX::make_sp_head(THD *thd, sp_name *name,
enum stored_procedure_type type)
{
sp_head *sp;
/* Order is important here: new - reset - init */
if ((sp= new sp_head()))
{
sp->reset_thd_mem_root(thd);
sp->init(this);
sp->m_type= type;
if (name)
sp->init_sp_name(thd, name);
sp->m_chistics= &sp_chistics;
sphead= sp;
}
bzero(&sp_chistics, sizeof(sp_chistics));
return sp;
}
#ifdef MYSQL_SERVER #ifdef MYSQL_SERVER
uint binlog_unsafe_map[256]; uint binlog_unsafe_map[256];
......
...@@ -30,6 +30,8 @@ ...@@ -30,6 +30,8 @@
#include "sql_alter.h" // Alter_info #include "sql_alter.h" // Alter_info
#include "sql_window.h" #include "sql_window.h"
#include "sql_trigger.h" #include "sql_trigger.h"
#include "sp.h" // enum stored_procedure_type
/* YACC and LEX Definitions */ /* YACC and LEX Definitions */
...@@ -3067,6 +3069,25 @@ struct LEX: public Query_tables_list ...@@ -3067,6 +3069,25 @@ struct LEX: public Query_tables_list
bool set_system_variable(struct sys_var_with_base *tmp, bool set_system_variable(struct sys_var_with_base *tmp,
enum enum_var_type var_type, Item *val); enum enum_var_type var_type, Item *val);
void set_stmt_init(); void set_stmt_init();
sp_head *make_sp_head(THD *thd, sp_name *name,
enum stored_procedure_type type);
sp_head *make_sp_head_no_recursive(THD *thd, sp_name *name,
enum stored_procedure_type type)
{
if (!sphead)
return make_sp_head(thd, name, type);
my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0),
stored_procedure_type_to_str(type));
return NULL;
}
sp_head *make_sp_head_no_recursive(THD *thd,
DDL_options_st options, sp_name *name,
enum stored_procedure_type type)
{
if (add_create_options_with_check(options))
return NULL;
return make_sp_head_no_recursive(thd, name, type);
}
bool init_internal_variable(struct sys_var_with_base *variable, bool init_internal_variable(struct sys_var_with_base *variable,
LEX_STRING name); LEX_STRING name);
bool init_internal_variable(struct sys_var_with_base *variable, bool init_internal_variable(struct sys_var_with_base *variable,
......
...@@ -172,32 +172,11 @@ void turn_parser_debug_on() ...@@ -172,32 +172,11 @@ void turn_parser_debug_on()
#endif #endif
static sp_head *make_sp_head(THD *thd, sp_name *name,
enum stored_procedure_type type)
{
LEX *lex= thd->lex;
sp_head *sp;
/* Order is important here: new - reset - init */
if ((sp= new sp_head()))
{
sp->reset_thd_mem_root(thd);
sp->init(lex);
sp->m_type= type;
if (name)
sp->init_sp_name(thd, name);
sp->m_chistics= &lex->sp_chistics;
lex->sphead= sp;
}
bzero(&lex->sp_chistics, sizeof(lex->sp_chistics));
return sp;
}
static bool maybe_start_compound_statement(THD *thd) static bool maybe_start_compound_statement(THD *thd)
{ {
if (!thd->lex->sphead) if (!thd->lex->sphead)
{ {
if (!make_sp_head(thd, NULL, TYPE_ENUM_PROCEDURE)) if (!thd->lex->make_sp_head(thd, NULL, TYPE_ENUM_PROCEDURE))
return 1; return 1;
Lex->sp_chistics.suid= SP_IS_NOT_SUID; Lex->sp_chistics.suid= SP_IS_NOT_SUID;
...@@ -2775,7 +2754,8 @@ ev_sql_stmt: ...@@ -2775,7 +2754,8 @@ ev_sql_stmt:
if (lex->sphead) if (lex->sphead)
my_yyabort_error((ER_EVENT_RECURSION_FORBIDDEN, MYF(0))); my_yyabort_error((ER_EVENT_RECURSION_FORBIDDEN, MYF(0)));
if (!make_sp_head(thd, lex->event_parse_data->identifier, TYPE_ENUM_PROCEDURE)) if (!lex->make_sp_head(thd, lex->event_parse_data->identifier,
TYPE_ENUM_PROCEDURE))
MYSQL_YYABORT; MYSQL_YYABORT;
lex->sp_chistics.suid= SP_IS_SUID; //always the definer! lex->sp_chistics.suid= SP_IS_SUID; //always the definer!
...@@ -16367,7 +16347,7 @@ trigger_tail: ...@@ -16367,7 +16347,7 @@ trigger_tail:
(*static_cast<st_trg_execution_order*>(&lex->trg_chistics))= ($18); (*static_cast<st_trg_execution_order*>(&lex->trg_chistics))= ($18);
lex->trg_chistics.ordering_clause_end= lip->get_cpp_ptr(); lex->trg_chistics.ordering_clause_end= lip->get_cpp_ptr();
if (!make_sp_head(thd, $5, TYPE_ENUM_TRIGGER)) if (!lex->make_sp_head(thd, $5, TYPE_ENUM_TRIGGER))
MYSQL_YYABORT; MYSQL_YYABORT;
lex->sphead->set_body_start(thd, lip->get_cpp_tok_start()); lex->sphead->set_body_start(thd, lip->get_cpp_tok_start());
...@@ -16429,50 +16409,45 @@ sf_tail: ...@@ -16429,50 +16409,45 @@ sf_tail:
FUNCTION_SYM /* $1 */ FUNCTION_SYM /* $1 */
opt_if_not_exists /* $2 */ opt_if_not_exists /* $2 */
sp_name /* $3 */ sp_name /* $3 */
'(' /* $4 */ {
{ /* $5 */ if (!Lex->make_sp_head_no_recursive(thd, $2, $3, TYPE_ENUM_FUNCTION))
MYSQL_YYABORT;
Lex->spname= $3;
}
'(' /* $5 */
{ /* $6 */
LEX *lex= Lex; LEX *lex= Lex;
Lex_input_stream *lip= YYLIP; Lex_input_stream *lip= YYLIP;
const char* tmp_param_begin; const char* tmp_param_begin;
if (lex->add_create_options_with_check($2))
MYSQL_YYABORT;
lex->spname= $3;
if (lex->sphead)
my_yyabort_error((ER_SP_NO_RECURSIVE_CREATE, MYF(0), "FUNCTION"));
if (!make_sp_head(thd, $3, TYPE_ENUM_FUNCTION))
MYSQL_YYABORT;
tmp_param_begin= lip->get_cpp_tok_start(); tmp_param_begin= lip->get_cpp_tok_start();
tmp_param_begin++; tmp_param_begin++;
lex->sphead->m_param_begin= tmp_param_begin; lex->sphead->m_param_begin= tmp_param_begin;
} }
sp_fdparam_list /* $6 */ sp_fdparam_list /* $7 */
')' /* $7 */ ')' /* $8 */
{ /* $8 */ { /* $9 */
Lex->sphead->m_param_end= YYLIP->get_cpp_tok_start(); Lex->sphead->m_param_end= YYLIP->get_cpp_tok_start();
} }
RETURNS_SYM /* $9 */ RETURNS_SYM /* $10 */
{ /* $10 */ { /* $11 */
LEX *lex= Lex; LEX *lex= Lex;
lex->init_last_field(&lex->sphead->m_return_field_def, NULL, lex->init_last_field(&lex->sphead->m_return_field_def, NULL,
thd->variables.collation_database); thd->variables.collation_database);
} }
type_with_opt_collate /* $11 */ type_with_opt_collate /* $12 */
{ /* $12 */ { /* $13 */
if (Lex->sphead->fill_field_definition(thd, Lex->last_field)) if (Lex->sphead->fill_field_definition(thd, Lex->last_field))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
sp_c_chistics /* $13 */ sp_c_chistics /* $14 */
{ /* $14 */ { /* $15 */
LEX *lex= thd->lex; LEX *lex= thd->lex;
Lex_input_stream *lip= YYLIP; Lex_input_stream *lip= YYLIP;
lex->sphead->set_body_start(thd, lip->get_cpp_tok_start()); lex->sphead->set_body_start(thd, lip->get_cpp_tok_start());
} }
sp_proc_stmt_in_returns_clause /* $15 */ sp_proc_stmt_in_returns_clause /* $16 */
{ {
LEX *lex= thd->lex; LEX *lex= thd->lex;
sp_head *sp= lex->sphead; sp_head *sp= lex->sphead;
...@@ -16493,13 +16468,8 @@ sf_tail: ...@@ -16493,13 +16468,8 @@ sf_tail:
sp_tail: sp_tail:
PROCEDURE_SYM opt_if_not_exists sp_name PROCEDURE_SYM opt_if_not_exists sp_name
{ {
if (Lex->add_create_options_with_check($2)) if (!Lex->make_sp_head_no_recursive(thd, $2, $3,
MYSQL_YYABORT; TYPE_ENUM_PROCEDURE))
if (Lex->sphead)
my_yyabort_error((ER_SP_NO_RECURSIVE_CREATE, MYF(0), "PROCEDURE"));
if (!make_sp_head(thd, $3, TYPE_ENUM_PROCEDURE))
MYSQL_YYABORT; MYSQL_YYABORT;
Lex->spname= $3; Lex->spname= $3;
} }
......
...@@ -151,32 +151,11 @@ void ORAerror(THD *thd, const char *s) ...@@ -151,32 +151,11 @@ void ORAerror(THD *thd, const char *s)
static sp_head *make_sp_head(THD *thd, sp_name *name,
enum stored_procedure_type type)
{
LEX *lex= thd->lex;
sp_head *sp;
/* Order is important here: new - reset - init */
if ((sp= new sp_head()))
{
sp->reset_thd_mem_root(thd);
sp->init(lex);
sp->m_type= type;
if (name)
sp->init_sp_name(thd, name);
sp->m_chistics= &lex->sp_chistics;
lex->sphead= sp;
}
bzero(&lex->sp_chistics, sizeof(lex->sp_chistics));
return sp;
}
static bool maybe_start_compound_statement(THD *thd) static bool maybe_start_compound_statement(THD *thd)
{ {
if (!thd->lex->sphead) if (!thd->lex->sphead)
{ {
if (!make_sp_head(thd, NULL, TYPE_ENUM_PROCEDURE)) if (!thd->lex->make_sp_head(thd, NULL, TYPE_ENUM_PROCEDURE))
return 1; return 1;
Lex->sp_chistics.suid= SP_IS_NOT_SUID; Lex->sp_chistics.suid= SP_IS_NOT_SUID;
...@@ -322,10 +301,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); ...@@ -322,10 +301,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%parse-param { THD *thd } %parse-param { THD *thd }
%lex-param { THD *thd } %lex-param { THD *thd }
/* /*
Currently there are 104 shift/reduce conflicts. Currently there are 102 shift/reduce conflicts.
We should not introduce new conflicts any more. We should not introduce new conflicts any more.
*/ */
%expect 104 %expect 102
/* /*
Comments for TOKENS. Comments for TOKENS.
...@@ -2157,7 +2136,8 @@ ev_sql_stmt: ...@@ -2157,7 +2136,8 @@ ev_sql_stmt:
if (lex->sphead) if (lex->sphead)
my_yyabort_error((ER_EVENT_RECURSION_FORBIDDEN, MYF(0))); my_yyabort_error((ER_EVENT_RECURSION_FORBIDDEN, MYF(0)));
if (!make_sp_head(thd, lex->event_parse_data->identifier, TYPE_ENUM_PROCEDURE)) if (!lex->make_sp_head(thd, lex->event_parse_data->identifier,
TYPE_ENUM_PROCEDURE))
MYSQL_YYABORT; MYSQL_YYABORT;
lex->sp_chistics.suid= SP_IS_SUID; //always the definer! lex->sp_chistics.suid= SP_IS_SUID; //always the definer!
...@@ -13834,7 +13814,6 @@ keyword_directly_assignable: ...@@ -13834,7 +13814,6 @@ keyword_directly_assignable:
| EXCLUDE_SYM {} | EXCLUDE_SYM {}
| EXECUTE_SYM {} | EXECUTE_SYM {}
| FLUSH_SYM {} | FLUSH_SYM {}
| FOLLOWS_SYM {}
| FOLLOWING_SYM {} | FOLLOWING_SYM {}
| FORMAT_SYM {} | FORMAT_SYM {}
| GET_SYM {} | GET_SYM {}
...@@ -13843,11 +13822,9 @@ keyword_directly_assignable: ...@@ -13843,11 +13822,9 @@ keyword_directly_assignable:
| INSTALL_SYM {} | INSTALL_SYM {}
| OPTION {} | OPTION {}
| OPTIONS_SYM {} | OPTIONS_SYM {}
| OTHERS_SYM {}
| OWNER_SYM {} | OWNER_SYM {}
| PARSER_SYM {} | PARSER_SYM {}
| PORT_SYM {} | PORT_SYM {}
| PRECEDES_SYM {}
| PRECEDING_SYM {} | PRECEDING_SYM {}
| PREPARE_SYM {} | PREPARE_SYM {}
| REMOVE_SYM {} | REMOVE_SYM {}
...@@ -13902,6 +13879,13 @@ keyword_directly_assignable: ...@@ -13902,6 +13879,13 @@ keyword_directly_assignable:
TODO: Allow these variables as SP lables when sql_mode=ORACLE. TODO: Allow these variables as SP lables when sql_mode=ORACLE.
TODO: Allow assigning of "SP characteristics" marked variables TODO: Allow assigning of "SP characteristics" marked variables
inside compound blocks. inside compound blocks.
TODO: Allow "follows" and "precedes" as variables in compound blocks:
BEGIN
follows := 10;
END;
as they conflict only with non-block FOR EACH ROW statement:
CREATE TRIGGER .. FOR EACH ROW follows:= 10;
CREATE TRIGGER .. FOR EACH ROW FOLLOWS tr1 a:= 10;
*/ */
keyword_directly_not_assignable: keyword_directly_not_assignable:
CONTAINS_SYM { /* SP characteristic */ } CONTAINS_SYM { /* SP characteristic */ }
...@@ -13917,6 +13901,8 @@ keyword_directly_not_assignable: ...@@ -13917,6 +13901,8 @@ keyword_directly_not_assignable:
| TRUNCATE_SYM { /* Verb clause. Reserved in Oracle */ } | TRUNCATE_SYM { /* Verb clause. Reserved in Oracle */ }
| BEGIN_SYM { /* Compound. Reserved in Oracle */ } | BEGIN_SYM { /* Compound. Reserved in Oracle */ }
| END { /* Compound. Reserved in Oracle */ } | END { /* Compound. Reserved in Oracle */ }
| FOLLOWS_SYM { /* Conflicts with assignment in FOR EACH */}
| PRECEDES_SYM { /* Conflicts with assignment in FOR EACH */}
; ;
/* /*
...@@ -15943,7 +15929,7 @@ trigger_tail: ...@@ -15943,7 +15929,7 @@ trigger_tail:
(*static_cast<st_trg_execution_order*>(&lex->trg_chistics))= ($18); (*static_cast<st_trg_execution_order*>(&lex->trg_chistics))= ($18);
lex->trg_chistics.ordering_clause_end= lip->get_cpp_ptr(); lex->trg_chistics.ordering_clause_end= lip->get_cpp_ptr();
if (!make_sp_head(thd, $5, TYPE_ENUM_TRIGGER)) if (!lex->make_sp_head(thd, $5, TYPE_ENUM_TRIGGER))
MYSQL_YYABORT; MYSQL_YYABORT;
lex->sphead->set_body_start(thd, lip->get_cpp_tok_start()); lex->sphead->set_body_start(thd, lip->get_cpp_tok_start());
...@@ -16005,51 +15991,46 @@ sf_tail: ...@@ -16005,51 +15991,46 @@ sf_tail:
FUNCTION_SYM /* $1 */ FUNCTION_SYM /* $1 */
opt_if_not_exists /* $2 */ opt_if_not_exists /* $2 */
sp_name /* $3 */ sp_name /* $3 */
'(' /* $4 */ {
{ /* $5 */ if (!Lex->make_sp_head_no_recursive(thd, $2, $3, TYPE_ENUM_FUNCTION))
MYSQL_YYABORT;
Lex->spname= $3;
}
'(' /* $5 */
{ /* $6 */
LEX *lex= Lex; LEX *lex= Lex;
Lex_input_stream *lip= YYLIP; Lex_input_stream *lip= YYLIP;
const char* tmp_param_begin; const char* tmp_param_begin;
if (lex->add_create_options_with_check($2))
MYSQL_YYABORT;
lex->spname= $3;
if (lex->sphead)
my_yyabort_error((ER_SP_NO_RECURSIVE_CREATE, MYF(0), "FUNCTION"));
if (!make_sp_head(thd, $3, TYPE_ENUM_FUNCTION))
MYSQL_YYABORT;
tmp_param_begin= lip->get_cpp_tok_start(); tmp_param_begin= lip->get_cpp_tok_start();
tmp_param_begin++; tmp_param_begin++;
lex->sphead->m_param_begin= tmp_param_begin; lex->sphead->m_param_begin= tmp_param_begin;
} }
sp_fdparam_list /* $6 */ sp_fdparam_list /* $7 */
')' /* $7 */ ')' /* $8 */
{ /* $8 */ { /* $9 */
Lex->sphead->m_param_end= YYLIP->get_cpp_tok_start(); Lex->sphead->m_param_end= YYLIP->get_cpp_tok_start();
} }
RETURNS_SYM /* $9 */ RETURNS_SYM /* $10 */
{ /* $10 */ { /* $11 */
LEX *lex= Lex; LEX *lex= Lex;
lex->init_last_field(&lex->sphead->m_return_field_def, NULL, lex->init_last_field(&lex->sphead->m_return_field_def, NULL,
thd->variables.collation_database); thd->variables.collation_database);
} }
type_with_opt_collate /* $11 */ type_with_opt_collate /* $12 */
{ /* $12 */ { /* $13 */
if (Lex->sphead->fill_field_definition(thd, Lex->last_field)) if (Lex->sphead->fill_field_definition(thd, Lex->last_field))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
sp_c_chistics /* $13 */ sp_c_chistics /* $14 */
{ /* $14 */ { /* $15 */
LEX *lex= thd->lex; LEX *lex= thd->lex;
Lex_input_stream *lip= YYLIP; Lex_input_stream *lip= YYLIP;
lex->sphead->set_body_start(thd, lip->get_cpp_tok_start()); lex->sphead->set_body_start(thd, lip->get_cpp_tok_start());
} }
sp_tail_is /* $15 */ sp_tail_is /* $16 */
sp_body /* $16 */ sp_body /* $17 */
{ {
LEX *lex= thd->lex; LEX *lex= thd->lex;
sp_head *sp= lex->sphead; sp_head *sp= lex->sphead;
...@@ -16070,13 +16051,8 @@ sf_tail: ...@@ -16070,13 +16051,8 @@ sf_tail:
sp_tail: sp_tail:
PROCEDURE_SYM opt_if_not_exists sp_name PROCEDURE_SYM opt_if_not_exists sp_name
{ {
if (Lex->add_create_options_with_check($2)) if (!Lex->make_sp_head_no_recursive(thd, $2, $3,
MYSQL_YYABORT; TYPE_ENUM_PROCEDURE))
if (Lex->sphead)
my_yyabort_error((ER_SP_NO_RECURSIVE_CREATE, MYF(0), "PROCEDURE"));
if (!make_sp_head(thd, $3, TYPE_ENUM_PROCEDURE))
MYSQL_YYABORT; MYSQL_YYABORT;
Lex->spname= $3; Lex->spname= $3;
} }
......
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