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 @@
#include <my_user.h>
/* Used in error handling only */
#define SP_TYPE_STRING(type) \
(type == TYPE_ENUM_FUNCTION ? "FUNCTION" : "PROCEDURE")
#define SP_TYPE_STRING(type) stored_procedure_type_to_str(type)
static int
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)
If we have insufficient privileges, pretend the routine
does not exist.
*/
my_error(ER_SP_DOES_NOT_EXIST, MYF(0),
type == TYPE_ENUM_FUNCTION ? "FUNCTION" : "PROCEDURE",
my_error(ER_SP_DOES_NOT_EXIST, MYF(0), stored_procedure_type_to_str(type),
name->m_name.str);
DBUG_RETURN(TRUE);
}
......
......@@ -48,6 +48,20 @@ enum stored_procedure_type
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 */
#define SP_DEFAULT_ACCESS_MAPPING SP_CONTAINS_SQL
......
......@@ -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
uint binlog_unsafe_map[256];
......
......@@ -30,6 +30,8 @@
#include "sql_alter.h" // Alter_info
#include "sql_window.h"
#include "sql_trigger.h"
#include "sp.h" // enum stored_procedure_type
/* YACC and LEX Definitions */
......@@ -3067,6 +3069,25 @@ struct LEX: public Query_tables_list
bool set_system_variable(struct sys_var_with_base *tmp,
enum enum_var_type var_type, Item *val);
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,
LEX_STRING name);
bool init_internal_variable(struct sys_var_with_base *variable,
......
......@@ -172,32 +172,11 @@ void turn_parser_debug_on()
#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)
{
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;
Lex->sp_chistics.suid= SP_IS_NOT_SUID;
......@@ -2775,7 +2754,8 @@ ev_sql_stmt:
if (lex->sphead)
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;
lex->sp_chistics.suid= SP_IS_SUID; //always the definer!
......@@ -16367,7 +16347,7 @@ trigger_tail:
(*static_cast<st_trg_execution_order*>(&lex->trg_chistics))= ($18);
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;
lex->sphead->set_body_start(thd, lip->get_cpp_tok_start());
......@@ -16429,50 +16409,45 @@ sf_tail:
FUNCTION_SYM /* $1 */
opt_if_not_exists /* $2 */
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_input_stream *lip= YYLIP;
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++;
lex->sphead->m_param_begin= tmp_param_begin;
}
sp_fdparam_list /* $6 */
')' /* $7 */
{ /* $8 */
sp_fdparam_list /* $7 */
')' /* $8 */
{ /* $9 */
Lex->sphead->m_param_end= YYLIP->get_cpp_tok_start();
}
RETURNS_SYM /* $9 */
{ /* $10 */
RETURNS_SYM /* $10 */
{ /* $11 */
LEX *lex= Lex;
lex->init_last_field(&lex->sphead->m_return_field_def, NULL,
thd->variables.collation_database);
}
type_with_opt_collate /* $11 */
{ /* $12 */
type_with_opt_collate /* $12 */
{ /* $13 */
if (Lex->sphead->fill_field_definition(thd, Lex->last_field))
MYSQL_YYABORT;
}
sp_c_chistics /* $13 */
{ /* $14 */
sp_c_chistics /* $14 */
{ /* $15 */
LEX *lex= thd->lex;
Lex_input_stream *lip= YYLIP;
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;
sp_head *sp= lex->sphead;
......@@ -16493,13 +16468,8 @@ sf_tail:
sp_tail:
PROCEDURE_SYM opt_if_not_exists sp_name
{
if (Lex->add_create_options_with_check($2))
MYSQL_YYABORT;
if (Lex->sphead)
my_yyabort_error((ER_SP_NO_RECURSIVE_CREATE, MYF(0), "PROCEDURE"));
if (!make_sp_head(thd, $3, TYPE_ENUM_PROCEDURE))
if (!Lex->make_sp_head_no_recursive(thd, $2, $3,
TYPE_ENUM_PROCEDURE))
MYSQL_YYABORT;
Lex->spname= $3;
}
......
......@@ -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)
{
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;
Lex->sp_chistics.suid= SP_IS_NOT_SUID;
......@@ -322,10 +301,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%parse-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.
*/
%expect 104
%expect 102
/*
Comments for TOKENS.
......@@ -2157,7 +2136,8 @@ ev_sql_stmt:
if (lex->sphead)
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;
lex->sp_chistics.suid= SP_IS_SUID; //always the definer!
......@@ -13834,7 +13814,6 @@ keyword_directly_assignable:
| EXCLUDE_SYM {}
| EXECUTE_SYM {}
| FLUSH_SYM {}
| FOLLOWS_SYM {}
| FOLLOWING_SYM {}
| FORMAT_SYM {}
| GET_SYM {}
......@@ -13843,11 +13822,9 @@ keyword_directly_assignable:
| INSTALL_SYM {}
| OPTION {}
| OPTIONS_SYM {}
| OTHERS_SYM {}
| OWNER_SYM {}
| PARSER_SYM {}
| PORT_SYM {}
| PRECEDES_SYM {}
| PRECEDING_SYM {}
| PREPARE_SYM {}
| REMOVE_SYM {}
......@@ -13902,6 +13879,13 @@ keyword_directly_assignable:
TODO: Allow these variables as SP lables when sql_mode=ORACLE.
TODO: Allow assigning of "SP characteristics" marked variables
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:
CONTAINS_SYM { /* SP characteristic */ }
......@@ -13917,6 +13901,8 @@ keyword_directly_not_assignable:
| TRUNCATE_SYM { /* Verb clause. Reserved in Oracle */ }
| BEGIN_SYM { /* 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:
(*static_cast<st_trg_execution_order*>(&lex->trg_chistics))= ($18);
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;
lex->sphead->set_body_start(thd, lip->get_cpp_tok_start());
......@@ -16005,51 +15991,46 @@ sf_tail:
FUNCTION_SYM /* $1 */
opt_if_not_exists /* $2 */
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_input_stream *lip= YYLIP;
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++;
lex->sphead->m_param_begin= tmp_param_begin;
}
sp_fdparam_list /* $6 */
')' /* $7 */
{ /* $8 */
sp_fdparam_list /* $7 */
')' /* $8 */
{ /* $9 */
Lex->sphead->m_param_end= YYLIP->get_cpp_tok_start();
}
RETURNS_SYM /* $9 */
{ /* $10 */
RETURNS_SYM /* $10 */
{ /* $11 */
LEX *lex= Lex;
lex->init_last_field(&lex->sphead->m_return_field_def, NULL,
thd->variables.collation_database);
}
type_with_opt_collate /* $11 */
{ /* $12 */
type_with_opt_collate /* $12 */
{ /* $13 */
if (Lex->sphead->fill_field_definition(thd, Lex->last_field))
MYSQL_YYABORT;
}
sp_c_chistics /* $13 */
{ /* $14 */
sp_c_chistics /* $14 */
{ /* $15 */
LEX *lex= thd->lex;
Lex_input_stream *lip= YYLIP;
lex->sphead->set_body_start(thd, lip->get_cpp_tok_start());
}
sp_tail_is /* $15 */
sp_body /* $16 */
sp_tail_is /* $16 */
sp_body /* $17 */
{
LEX *lex= thd->lex;
sp_head *sp= lex->sphead;
......@@ -16070,13 +16051,8 @@ sf_tail:
sp_tail:
PROCEDURE_SYM opt_if_not_exists sp_name
{
if (Lex->add_create_options_with_check($2))
MYSQL_YYABORT;
if (Lex->sphead)
my_yyabort_error((ER_SP_NO_RECURSIVE_CREATE, MYF(0), "PROCEDURE"));
if (!make_sp_head(thd, $3, TYPE_ENUM_PROCEDURE))
if (!Lex->make_sp_head_no_recursive(thd, $2, $3,
TYPE_ENUM_PROCEDURE))
MYSQL_YYABORT;
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