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)
}
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);
sp_label *lab;
......
......@@ -108,7 +108,8 @@ class sp_label : public Sql_alloc
class sp_pcontext *ctx;
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(),
name(_name),
ip(_ip),
......@@ -401,9 +402,9 @@ class sp_pcontext : public Sql_alloc
// 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()
{
......@@ -418,6 +419,17 @@ class sp_pcontext : public Sql_alloc
sp_label *pop_label()
{ 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.
/////////////////////////////////////////////////////////////////////////
......
......@@ -5309,6 +5309,62 @@ bool LEX::sp_handler_declaration_finalize(THD *thd, int type)
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
uint binlog_unsafe_map[256];
......
......@@ -2626,6 +2626,8 @@ struct LEX: public Query_tables_list
Query_arena_memroot *arena_for_set_stmt;
MEM_ROOT *mem_root_for_set_stmt;
void parse_error();
bool sp_block_finalize(THD *thd, const Lex_spblock_st spblock,
class sp_label **splabel);
public:
inline bool is_arena_for_set_stmt() {return arena_for_set_stmt != 0;}
bool set_arena_for_set_stmt(Query_arena *backup);
......@@ -3084,6 +3086,20 @@ struct LEX: public Query_tables_list
const char *start_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
bool check_add_key(DDL_options_st ddl)
{
......
......@@ -859,7 +859,7 @@ Virtual_column_info *add_virtual_expression(THD *thd, Item *expr)
LEX_SYMBOL symbol;
Lex_string_with_metadata_st lex_string_with_metadata;
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_cast_type_st Lex_cast_type;
Lex_field_type_st Lex_field_type;
......@@ -894,7 +894,6 @@ Virtual_column_info *add_virtual_expression(THD *thd, Item *expr)
class my_var *myvar;
class sp_condition_value *spcondvalue;
class sp_head *sphead;
class sp_label *splabel;
class sp_name *spname;
class sp_variable *spvar;
class With_clause *with_clause;
......@@ -1672,6 +1671,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
opt_component key_cache_name
sp_opt_label BIN_NUM label_ident TEXT_STRING_filesystem ident_or_empty
opt_constraint constraint opt_ident
sp_block_label
%type <lex_string_with_metadata>
TEXT_STRING
......@@ -1952,7 +1952,6 @@ END_OF_INPUT
%type <spblock> sp_decls sp_decl sp_decl_body
%type <lex> sp_cursor_stmt
%type <spname> sp_name
%type <splabel> sp_block_content
%type <spvar> sp_param_name sp_param_name_and_type
%type <spvar_mode> sp_opt_inout
%type <index_hint> index_hint_type
......@@ -3987,34 +3986,43 @@ sp_opt_label:
| label_ident { $$= $1; }
;
sp_labeled_block:
label_ident ':' BEGIN_SYM
sp_block_label:
label_ident ':'
{
LEX *lex= Lex;
sp_pcontext *ctx= lex->spcont;
sp_label *lab= ctx->find_label($1);
if (Lex->spcont->block_label_declare($1))
MYSQL_YYABORT;
$$= $1;
}
;
if (lab)
my_yyabort_error((ER_SP_LABEL_REDEFINE, MYF(0), $1.str));
lex->name= $1;
sp_labeled_block:
sp_block_label
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 (my_strcasecmp(system_charset_info, $6.str, $5->name.str) != 0)
my_yyabort_error((ER_SP_LABEL_MISMATCH, MYF(0), $6.str));
}
if (Lex->sp_block_finalize(thd, $4, $7))
MYSQL_YYABORT;
}
;
sp_unlabeled_block:
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:
......@@ -4022,49 +4030,14 @@ sp_unlabeled_block_not_atomic:
{
if (maybe_start_compound_statement(thd))
MYSQL_YYABORT;
Lex->name= empty_lex_str; // Unlabeled blocks get an empty label
}
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);
Lex->sp_block_init(thd);
}
sp_decls
sp_proc_stmts
END
{
LEX *lex= Lex;
sp_head *sp= lex->sphead;
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();
if (Lex->sp_block_finalize(thd, $5))
MYSQL_YYABORT;
}
;
......
......@@ -234,7 +234,7 @@ static bool push_sp_empty_label(THD *thd)
LEX_SYMBOL symbol;
Lex_string_with_metadata_st lex_string_with_metadata;
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_cast_type_st Lex_cast_type;
Lex_field_type_st Lex_field_type;
......@@ -269,7 +269,6 @@ static bool push_sp_empty_label(THD *thd)
class my_var *myvar;
class sp_condition_value *spcondvalue;
class sp_head *sphead;
class sp_label *splabel;
class sp_name *spname;
class sp_variable *spvar;
class With_clause *with_clause;
......@@ -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
opt_constraint constraint opt_ident
label_declaration_oracle ident_directly_assignable
sp_block_label
%type <lex_string_with_metadata>
TEXT_STRING
......@@ -1332,7 +1332,6 @@ END_OF_INPUT
%type <spblock> sp_decls sp_decl sp_decl_body
%type <lex> sp_cursor_stmt
%type <spname> sp_name
%type <splabel> sp_block_content
%type <spvar> sp_param_name sp_param_name_and_type
%type <spvar_mode> sp_opt_inout
%type <index_hint> index_hint_type
......@@ -3373,34 +3372,43 @@ sp_opt_label:
| label_ident { $$= $1; }
;
sp_labeled_block:
label_declaration_oracle BEGIN_SYM
sp_block_label:
label_declaration_oracle
{
LEX *lex= Lex;
sp_pcontext *ctx= lex->spcont;
sp_label *lab= ctx->find_label($1);
if (Lex->spcont->block_label_declare($1))
MYSQL_YYABORT;
$$= $1;
}
;
if (lab)
my_yyabort_error((ER_SP_LABEL_REDEFINE, MYF(0), $1.str));
lex->name= $1;
sp_labeled_block:
sp_block_label
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 (my_strcasecmp(system_charset_info, $5.str, $4->name.str) != 0)
my_yyabort_error((ER_SP_LABEL_MISMATCH, MYF(0), $5.str));
}
if (Lex->sp_block_finalize(thd, $4, $7))
MYSQL_YYABORT;
}
;
sp_unlabeled_block:
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:
......@@ -3408,49 +3416,14 @@ sp_unlabeled_block_not_atomic:
{
if (maybe_start_compound_statement(thd))
MYSQL_YYABORT;
Lex->name= empty_lex_str; // Unlabeled blocks get an empty label
}
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);
Lex->sp_block_init(thd);
}
sp_decls
sp_proc_stmts
END
{
LEX *lex= Lex;
sp_head *sp= lex->sphead;
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();
if (Lex->sp_block_finalize(thd, $5))
MYSQL_YYABORT;
}
;
......
......@@ -628,5 +628,14 @@ struct Lex_dyncol_type_st: public Lex_length_and_dec_st
int dyncol_type() const { return m_type; }
};
struct Lex_spblock_st
{
public:
int vars;
int conds;
int hndlrs;
int curs;
};
#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