Commit 365e0b31 authored by Alexander Barkov's avatar Alexander Barkov

sql_lex.yy / sql_yacc_ora.yy refactoring for MDEV-10411.

1. Adding const qualifiers into a few method parameters.

2. Adding methods:
- sp_label::block_label_declare()
- LEX::sp_block_init()
- LEX::sp_block_finalize()
  to share more code between the files sql_yacc.yy and sql_yacc_ora.yy,
  as well as between the rules sp_labeled_block, sp_unlabeled_block,
  sp_unlabeled_block_not_atomic.

3. sql_yacc.yy, sql_yacc_ora.yy changes:
- Removing sp_block_content
- Reorganizing the grammar so the rules sp_labeled_block,
  sp_unlabeled_block, sp_unlabeled_block_not_atomic now
  contain both BEGIN_SYM and END keywords. Previously,
  BEGIN_SYM and END resided in different rules.
  This change makes the grammar easier to read,
  as well as simplifies adding Oracle-style DECLARE section (coming soon):
    DECLARE
      ..
    BEGIN
      ..
    END;

  Good side effects:
  - SP block related grammar does not use Lex->name any more.
  - The "splabel" member was removed from %union
parent 36b80cae
...@@ -211,7 +211,7 @@ sp_label *sp_pcontext::push_label(THD *thd, LEX_STRING name, uint ip) ...@@ -211,7 +211,7 @@ sp_label *sp_pcontext::push_label(THD *thd, LEX_STRING name, uint ip)
} }
sp_label *sp_pcontext::find_label(LEX_STRING name) sp_label *sp_pcontext::find_label(const LEX_STRING name)
{ {
List_iterator_fast<sp_label> li(m_labels); List_iterator_fast<sp_label> li(m_labels);
sp_label *lab; sp_label *lab;
......
...@@ -108,7 +108,8 @@ class sp_label : public Sql_alloc ...@@ -108,7 +108,8 @@ class sp_label : public Sql_alloc
class sp_pcontext *ctx; class sp_pcontext *ctx;
public: public:
sp_label(LEX_STRING _name, uint _ip, enum_type _type, sp_pcontext *_ctx) sp_label(const LEX_STRING _name,
uint _ip, enum_type _type, sp_pcontext *_ctx)
:Sql_alloc(), :Sql_alloc(),
name(_name), name(_name),
ip(_ip), ip(_ip),
...@@ -401,9 +402,9 @@ class sp_pcontext : public Sql_alloc ...@@ -401,9 +402,9 @@ class sp_pcontext : public Sql_alloc
// Labels. // Labels.
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
sp_label *push_label(THD *thd, LEX_STRING name, uint ip); sp_label *push_label(THD *thd, const LEX_STRING name, uint ip);
sp_label *find_label(LEX_STRING name); sp_label *find_label(const LEX_STRING name);
sp_label *last_label() sp_label *last_label()
{ {
...@@ -418,6 +419,17 @@ class sp_pcontext : public Sql_alloc ...@@ -418,6 +419,17 @@ class sp_pcontext : public Sql_alloc
sp_label *pop_label() sp_label *pop_label()
{ return m_labels.pop(); } { return m_labels.pop(); }
bool block_label_declare(LEX_STRING label)
{
sp_label *lab= find_label(label);
if (lab)
{
my_error(ER_SP_LABEL_REDEFINE, MYF(0), label.str);
return true;
}
return false;
}
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// Conditions. // Conditions.
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
......
...@@ -5309,6 +5309,62 @@ bool LEX::sp_handler_declaration_finalize(THD *thd, int type) ...@@ -5309,6 +5309,62 @@ bool LEX::sp_handler_declaration_finalize(THD *thd, int type)
return false; return false;
} }
void LEX::sp_block_init(THD *thd, const LEX_STRING label)
{
sp_label *lab= spcont->push_label(thd, label, sphead->instructions());
lab->type= sp_label::BEGIN;
spcont= spcont->push_context(thd, sp_pcontext::REGULAR_SCOPE);
}
bool LEX::sp_block_finalize(THD *thd, const Lex_spblock_st spblock,
class sp_label **splabel)
{
sp_head *sp= sphead;
sp_pcontext *ctx= spcont;
sp_instr *i;
sp->backpatch(ctx->last_label()); /* We always have a label */
if (spblock.hndlrs)
{
i= new (thd->mem_root)
sp_instr_hpop(sp->instructions(), ctx, spblock.hndlrs);
if (i == NULL ||
sp->add_instr(i))
return true;
}
if (spblock.curs)
{
i= new (thd->mem_root)
sp_instr_cpop(sp->instructions(), ctx, spblock.curs);
if (i == NULL ||
sp->add_instr(i))
return true;
}
spcont= ctx->pop_context();
*splabel= spcont->pop_label();
return false;
}
bool LEX::sp_block_finalize(THD *thd, const Lex_spblock_st spblock,
const LEX_STRING end_label)
{
sp_label *splabel;
if (sp_block_finalize(thd, spblock, &splabel))
return true;
if (end_label.str &&
my_strcasecmp(system_charset_info,
end_label.str, splabel->name.str) != 0)
{
my_error(ER_SP_LABEL_MISMATCH, MYF(0), end_label.str);
return true;
}
return false;
}
#ifdef MYSQL_SERVER #ifdef MYSQL_SERVER
uint binlog_unsafe_map[256]; uint binlog_unsafe_map[256];
......
...@@ -2626,6 +2626,8 @@ struct LEX: public Query_tables_list ...@@ -2626,6 +2626,8 @@ struct LEX: public Query_tables_list
Query_arena_memroot *arena_for_set_stmt; Query_arena_memroot *arena_for_set_stmt;
MEM_ROOT *mem_root_for_set_stmt; MEM_ROOT *mem_root_for_set_stmt;
void parse_error(); void parse_error();
bool sp_block_finalize(THD *thd, const Lex_spblock_st spblock,
class sp_label **splabel);
public: public:
inline bool is_arena_for_set_stmt() {return arena_for_set_stmt != 0;} inline bool is_arena_for_set_stmt() {return arena_for_set_stmt != 0;}
bool set_arena_for_set_stmt(Query_arena *backup); bool set_arena_for_set_stmt(Query_arena *backup);
...@@ -3084,6 +3086,20 @@ struct LEX: public Query_tables_list ...@@ -3084,6 +3086,20 @@ struct LEX: public Query_tables_list
const char *start_in_q, const char *start_in_q,
const char *end_in_q); const char *end_in_q);
void sp_block_init(THD *thd, const LEX_STRING label);
void sp_block_init(THD *thd)
{
// Unlabeled blocks get an empty label
sp_block_init(thd, empty_lex_str);
}
public:
bool sp_block_finalize(THD *thd, const Lex_spblock_st spblock)
{
class sp_label *tmp;
return sp_block_finalize(thd, spblock, &tmp);
}
bool sp_block_finalize(THD *thd, const Lex_spblock_st spblock,
const LEX_STRING end_label);
// Check if "KEY IF NOT EXISTS name" used outside of ALTER context // Check if "KEY IF NOT EXISTS name" used outside of ALTER context
bool check_add_key(DDL_options_st ddl) bool check_add_key(DDL_options_st ddl)
{ {
......
...@@ -859,7 +859,7 @@ Virtual_column_info *add_virtual_expression(THD *thd, Item *expr) ...@@ -859,7 +859,7 @@ Virtual_column_info *add_virtual_expression(THD *thd, Item *expr)
LEX_SYMBOL symbol; LEX_SYMBOL symbol;
Lex_string_with_metadata_st lex_string_with_metadata; Lex_string_with_metadata_st lex_string_with_metadata;
struct sys_var_with_base variable; struct sys_var_with_base variable;
struct { int vars, conds, hndlrs, curs; } spblock; Lex_spblock_st spblock;
Lex_length_and_dec_st Lex_length_and_dec; Lex_length_and_dec_st Lex_length_and_dec;
Lex_cast_type_st Lex_cast_type; Lex_cast_type_st Lex_cast_type;
Lex_field_type_st Lex_field_type; Lex_field_type_st Lex_field_type;
...@@ -894,7 +894,6 @@ Virtual_column_info *add_virtual_expression(THD *thd, Item *expr) ...@@ -894,7 +894,6 @@ Virtual_column_info *add_virtual_expression(THD *thd, Item *expr)
class my_var *myvar; class my_var *myvar;
class sp_condition_value *spcondvalue; class sp_condition_value *spcondvalue;
class sp_head *sphead; class sp_head *sphead;
class sp_label *splabel;
class sp_name *spname; class sp_name *spname;
class sp_variable *spvar; class sp_variable *spvar;
class With_clause *with_clause; class With_clause *with_clause;
...@@ -1672,6 +1671,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); ...@@ -1672,6 +1671,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
opt_component key_cache_name opt_component key_cache_name
sp_opt_label BIN_NUM label_ident TEXT_STRING_filesystem ident_or_empty sp_opt_label BIN_NUM label_ident TEXT_STRING_filesystem ident_or_empty
opt_constraint constraint opt_ident opt_constraint constraint opt_ident
sp_block_label
%type <lex_string_with_metadata> %type <lex_string_with_metadata>
TEXT_STRING TEXT_STRING
...@@ -1952,7 +1952,6 @@ END_OF_INPUT ...@@ -1952,7 +1952,6 @@ END_OF_INPUT
%type <spblock> sp_decls sp_decl sp_decl_body %type <spblock> sp_decls sp_decl sp_decl_body
%type <lex> sp_cursor_stmt %type <lex> sp_cursor_stmt
%type <spname> sp_name %type <spname> sp_name
%type <splabel> sp_block_content
%type <spvar> sp_param_name sp_param_name_and_type %type <spvar> sp_param_name sp_param_name_and_type
%type <spvar_mode> sp_opt_inout %type <spvar_mode> sp_opt_inout
%type <index_hint> index_hint_type %type <index_hint> index_hint_type
...@@ -3987,34 +3986,43 @@ sp_opt_label: ...@@ -3987,34 +3986,43 @@ sp_opt_label:
| label_ident { $$= $1; } | label_ident { $$= $1; }
; ;
sp_labeled_block: sp_block_label:
label_ident ':' BEGIN_SYM label_ident ':'
{ {
LEX *lex= Lex; if (Lex->spcont->block_label_declare($1))
sp_pcontext *ctx= lex->spcont; MYSQL_YYABORT;
sp_label *lab= ctx->find_label($1); $$= $1;
}
;
if (lab) sp_labeled_block:
my_yyabort_error((ER_SP_LABEL_REDEFINE, MYF(0), $1.str)); sp_block_label
lex->name= $1; BEGIN_SYM
{
Lex->sp_block_init(thd, $1);
} }
sp_block_content sp_opt_label sp_decls
sp_proc_stmts
END
sp_opt_label
{ {
if ($6.str) if (Lex->sp_block_finalize(thd, $4, $7))
{ MYSQL_YYABORT;
if (my_strcasecmp(system_charset_info, $6.str, $5->name.str) != 0)
my_yyabort_error((ER_SP_LABEL_MISMATCH, MYF(0), $6.str));
}
} }
; ;
sp_unlabeled_block: sp_unlabeled_block:
BEGIN_SYM BEGIN_SYM
{ {
Lex->name= empty_lex_str; // Unlabeled blocks get an empty label Lex->sp_block_init(thd);
}
sp_decls
sp_proc_stmts
END
{
if (Lex->sp_block_finalize(thd, $3))
MYSQL_YYABORT;
} }
sp_block_content
{ }
; ;
sp_unlabeled_block_not_atomic: sp_unlabeled_block_not_atomic:
...@@ -4022,49 +4030,14 @@ sp_unlabeled_block_not_atomic: ...@@ -4022,49 +4030,14 @@ sp_unlabeled_block_not_atomic:
{ {
if (maybe_start_compound_statement(thd)) if (maybe_start_compound_statement(thd))
MYSQL_YYABORT; MYSQL_YYABORT;
Lex->name= empty_lex_str; // Unlabeled blocks get an empty label Lex->sp_block_init(thd);
}
sp_block_content
{ }
;
sp_block_content:
{
LEX *lex= Lex;
sp_label *lab= lex->spcont->push_label(thd, lex->name,
lex->sphead->instructions());
lab->type= sp_label::BEGIN;
lex->spcont= lex->spcont->push_context(thd,
sp_pcontext::REGULAR_SCOPE);
} }
sp_decls sp_decls
sp_proc_stmts sp_proc_stmts
END END
{ {
LEX *lex= Lex; if (Lex->sp_block_finalize(thd, $5))
sp_head *sp= lex->sphead; MYSQL_YYABORT;
sp_pcontext *ctx= lex->spcont;
sp_instr *i;
sp->backpatch(ctx->last_label()); /* We always have a label */
if ($2.hndlrs)
{
i= new (thd->mem_root)
sp_instr_hpop(sp->instructions(), ctx, $2.hndlrs);
if (i == NULL ||
sp->add_instr(i))
MYSQL_YYABORT;
}
if ($2.curs)
{
i= new (thd->mem_root)
sp_instr_cpop(sp->instructions(), ctx, $2.curs);
if (i == NULL ||
sp->add_instr(i))
MYSQL_YYABORT;
}
lex->spcont= ctx->pop_context();
$$ = lex->spcont->pop_label();
} }
; ;
......
...@@ -234,7 +234,7 @@ static bool push_sp_empty_label(THD *thd) ...@@ -234,7 +234,7 @@ static bool push_sp_empty_label(THD *thd)
LEX_SYMBOL symbol; LEX_SYMBOL symbol;
Lex_string_with_metadata_st lex_string_with_metadata; Lex_string_with_metadata_st lex_string_with_metadata;
struct sys_var_with_base variable; struct sys_var_with_base variable;
struct { int vars, conds, hndlrs, curs; } spblock; Lex_spblock_st spblock;
Lex_length_and_dec_st Lex_length_and_dec; Lex_length_and_dec_st Lex_length_and_dec;
Lex_cast_type_st Lex_cast_type; Lex_cast_type_st Lex_cast_type;
Lex_field_type_st Lex_field_type; Lex_field_type_st Lex_field_type;
...@@ -269,7 +269,6 @@ static bool push_sp_empty_label(THD *thd) ...@@ -269,7 +269,6 @@ static bool push_sp_empty_label(THD *thd)
class my_var *myvar; class my_var *myvar;
class sp_condition_value *spcondvalue; class sp_condition_value *spcondvalue;
class sp_head *sphead; class sp_head *sphead;
class sp_label *splabel;
class sp_name *spname; class sp_name *spname;
class sp_variable *spvar; class sp_variable *spvar;
class With_clause *with_clause; class With_clause *with_clause;
...@@ -1048,6 +1047,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); ...@@ -1048,6 +1047,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
sp_opt_label BIN_NUM label_ident TEXT_STRING_filesystem ident_or_empty sp_opt_label BIN_NUM label_ident TEXT_STRING_filesystem ident_or_empty
opt_constraint constraint opt_ident opt_constraint constraint opt_ident
label_declaration_oracle ident_directly_assignable label_declaration_oracle ident_directly_assignable
sp_block_label
%type <lex_string_with_metadata> %type <lex_string_with_metadata>
TEXT_STRING TEXT_STRING
...@@ -1332,7 +1332,6 @@ END_OF_INPUT ...@@ -1332,7 +1332,6 @@ END_OF_INPUT
%type <spblock> sp_decls sp_decl sp_decl_body %type <spblock> sp_decls sp_decl sp_decl_body
%type <lex> sp_cursor_stmt %type <lex> sp_cursor_stmt
%type <spname> sp_name %type <spname> sp_name
%type <splabel> sp_block_content
%type <spvar> sp_param_name sp_param_name_and_type %type <spvar> sp_param_name sp_param_name_and_type
%type <spvar_mode> sp_opt_inout %type <spvar_mode> sp_opt_inout
%type <index_hint> index_hint_type %type <index_hint> index_hint_type
...@@ -3373,34 +3372,43 @@ sp_opt_label: ...@@ -3373,34 +3372,43 @@ sp_opt_label:
| label_ident { $$= $1; } | label_ident { $$= $1; }
; ;
sp_labeled_block: sp_block_label:
label_declaration_oracle BEGIN_SYM label_declaration_oracle
{ {
LEX *lex= Lex; if (Lex->spcont->block_label_declare($1))
sp_pcontext *ctx= lex->spcont; MYSQL_YYABORT;
sp_label *lab= ctx->find_label($1); $$= $1;
}
;
if (lab) sp_labeled_block:
my_yyabort_error((ER_SP_LABEL_REDEFINE, MYF(0), $1.str)); sp_block_label
lex->name= $1; BEGIN_SYM
{
Lex->sp_block_init(thd, $1);
} }
sp_block_content sp_opt_label sp_decls
sp_proc_stmts
END
sp_opt_label
{ {
if ($5.str) if (Lex->sp_block_finalize(thd, $4, $7))
{ MYSQL_YYABORT;
if (my_strcasecmp(system_charset_info, $5.str, $4->name.str) != 0)
my_yyabort_error((ER_SP_LABEL_MISMATCH, MYF(0), $5.str));
}
} }
; ;
sp_unlabeled_block: sp_unlabeled_block:
BEGIN_SYM BEGIN_SYM
{ {
Lex->name= empty_lex_str; // Unlabeled blocks get an empty label Lex->sp_block_init(thd);
}
sp_decls
sp_proc_stmts
END
{
if (Lex->sp_block_finalize(thd, $3))
MYSQL_YYABORT;
} }
sp_block_content
{ }
; ;
sp_unlabeled_block_not_atomic: sp_unlabeled_block_not_atomic:
...@@ -3408,49 +3416,14 @@ sp_unlabeled_block_not_atomic: ...@@ -3408,49 +3416,14 @@ sp_unlabeled_block_not_atomic:
{ {
if (maybe_start_compound_statement(thd)) if (maybe_start_compound_statement(thd))
MYSQL_YYABORT; MYSQL_YYABORT;
Lex->name= empty_lex_str; // Unlabeled blocks get an empty label Lex->sp_block_init(thd);
}
sp_block_content
{ }
;
sp_block_content:
{
LEX *lex= Lex;
sp_label *lab= lex->spcont->push_label(thd, lex->name,
lex->sphead->instructions());
lab->type= sp_label::BEGIN;
lex->spcont= lex->spcont->push_context(thd,
sp_pcontext::REGULAR_SCOPE);
} }
sp_decls sp_decls
sp_proc_stmts sp_proc_stmts
END END
{ {
LEX *lex= Lex; if (Lex->sp_block_finalize(thd, $5))
sp_head *sp= lex->sphead; MYSQL_YYABORT;
sp_pcontext *ctx= lex->spcont;
sp_instr *i;
sp->backpatch(ctx->last_label()); /* We always have a label */
if ($2.hndlrs)
{
i= new (thd->mem_root)
sp_instr_hpop(sp->instructions(), ctx, $2.hndlrs);
if (i == NULL ||
sp->add_instr(i))
MYSQL_YYABORT;
}
if ($2.curs)
{
i= new (thd->mem_root)
sp_instr_cpop(sp->instructions(), ctx, $2.curs);
if (i == NULL ||
sp->add_instr(i))
MYSQL_YYABORT;
}
lex->spcont= ctx->pop_context();
$$ = lex->spcont->pop_label();
} }
; ;
......
...@@ -628,5 +628,14 @@ struct Lex_dyncol_type_st: public Lex_length_and_dec_st ...@@ -628,5 +628,14 @@ struct Lex_dyncol_type_st: public Lex_length_and_dec_st
int dyncol_type() const { return m_type; } int dyncol_type() const { return m_type; }
}; };
struct Lex_spblock_st
{
public:
int vars;
int conds;
int hndlrs;
int curs;
};
#endif /* STRUCTS_INCLUDED */ #endif /* STRUCTS_INCLUDED */
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