Skip to content

Commit

Permalink
sql_lex.yy / sql_yacc_ora.yy refactoring for MDEV-10411.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Alexander Barkov committed Apr 5, 2017
1 parent 36b80ca commit 365e0b3
Show file tree
Hide file tree
Showing 7 changed files with 159 additions and 120 deletions.
2 changes: 1 addition & 1 deletion sql/sp_pcontext.cc
Expand Up @@ -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;
Expand Down
18 changes: 15 additions & 3 deletions sql/sp_pcontext.h
Expand Up @@ -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),
Expand Down Expand Up @@ -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()
{
Expand All @@ -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.
/////////////////////////////////////////////////////////////////////////
Expand Down
56 changes: 56 additions & 0 deletions sql/sql_lex.cc
Expand Up @@ -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];

Expand Down
16 changes: 16 additions & 0 deletions sql/sql_lex.h
Expand Up @@ -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);
Expand Down Expand Up @@ -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)
{
Expand Down
89 changes: 31 additions & 58 deletions sql/sql_yacc.yy
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -3987,84 +3986,58 @@ 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:
BEGIN_SYM not ATOMIC_SYM /* TODO: BEGIN ATOMIC (not -> opt_not) */
{
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;
}
;

Expand Down

0 comments on commit 365e0b3

Please sign in to comment.