Commit 36b80cae authored by Alexander Barkov's avatar Alexander Barkov

Moving the code from *.yy to new methods to LEX and sp_context

Adding:
  LEX::sp_variable_declarations_init()
  LEX::sp_variable_declarations_finalize()
  LEX::sp_handler_declaration_init()
  LEX::sp_handler_declaration_finalize()
  LEX::sp_declare_cursor()
  sp_context::declare_condition()
parent 0281757e
......@@ -249,7 +249,7 @@ bool sp_pcontext::add_condition(THD *thd,
}
sp_condition_value *sp_pcontext::find_condition(LEX_STRING name,
sp_condition_value *sp_pcontext::find_condition(const LEX_STRING name,
bool current_scope_only) const
{
uint i= m_conditions.elements();
......@@ -415,7 +415,7 @@ sp_pcontext::find_handler(const char *sql_state,
}
bool sp_pcontext::add_cursor(LEX_STRING name)
bool sp_pcontext::add_cursor(const LEX_STRING name)
{
if (m_cursors.elements() == m_max_cursor_index)
++m_max_cursor_index;
......@@ -424,7 +424,7 @@ bool sp_pcontext::add_cursor(LEX_STRING name)
}
bool sp_pcontext::find_cursor(LEX_STRING name,
bool sp_pcontext::find_cursor(const LEX_STRING name,
uint *poff,
bool current_scope_only) const
{
......
......@@ -192,7 +192,7 @@ class sp_condition : public Sql_alloc
sp_condition_value *value;
public:
sp_condition(LEX_STRING _name, sp_condition_value *_value)
sp_condition(const LEX_STRING _name, sp_condition_value *_value)
:Sql_alloc(),
name(_name),
value(_value)
......@@ -422,11 +422,22 @@ class sp_pcontext : public Sql_alloc
// Conditions.
/////////////////////////////////////////////////////////////////////////
bool add_condition(THD *thd, LEX_STRING name, sp_condition_value *value);
bool add_condition(THD *thd, const LEX_STRING name,
sp_condition_value *value);
/// See comment for find_variable() above.
sp_condition_value *find_condition(LEX_STRING name,
sp_condition_value *find_condition(const LEX_STRING name,
bool current_scope_only) const;
bool declare_condition(THD *thd, const LEX_STRING name,
sp_condition_value *val)
{
if (find_condition(name, true))
{
my_error(ER_SP_DUP_COND, MYF(0), name.str);
return true;
}
return add_condition(thd, name, val);
}
/////////////////////////////////////////////////////////////////////////
// Handlers.
......@@ -467,10 +478,11 @@ class sp_pcontext : public Sql_alloc
// Cursors.
/////////////////////////////////////////////////////////////////////////
bool add_cursor(LEX_STRING name);
bool add_cursor(const LEX_STRING name);
/// See comment for find_variable() above.
bool find_cursor(LEX_STRING name, uint *poff, bool current_scope_only) const;
bool find_cursor(const LEX_STRING name,
uint *poff, bool current_scope_only) const;
/// Find cursor by offset (for debugging only).
const LEX_STRING *find_cursor(uint offset) const;
......
......@@ -5185,6 +5185,129 @@ bool LEX::init_default_internal_variable(struct sys_var_with_base *variable,
return false;
}
void LEX::sp_variable_declarations_init(THD *thd, int nvars)
{
// get the last variable:
uint num_vars= spcont->context_var_count();
uint var_idx= spcont->var_context2runtime(num_vars - 1);
sp_variable *spvar= spcont->find_variable(var_idx);
sphead->reset_lex(thd);
spcont->declare_var_boundary(nvars);
thd->lex->init_last_field(&spvar->field_def, spvar->name.str,
thd->variables.collation_database);
}
bool LEX::sp_variable_declarations_finalize(THD *thd, int nvars,
const Lex_field_type_st &type,
Item *dflt_value_item)
{
uint num_vars= spcont->context_var_count();
if (!dflt_value_item &&
!(dflt_value_item= new (thd->mem_root) Item_null(thd)))
return true;
/* QQ Set to the var_type with null_value? */
for (uint i= num_vars - nvars ; i < num_vars ; i++)
{
uint var_idx= spcont->var_context2runtime(i);
sp_variable *spvar= spcont->find_variable(var_idx);
bool last= i == num_vars - 1;
if (!spvar)
return true;
if (!last)
spvar->field_def= *last_field;
spvar->default_value= dflt_value_item;
spvar->field_def.field_name= spvar->name.str;
if (sphead->fill_field_definition(thd, &spvar->field_def))
return true;
spvar->field_def.pack_flag |= FIELDFLAG_MAYBE_NULL;
/* The last instruction is responsible for freeing LEX. */
sp_instr_set *is= new (this->thd->mem_root)
sp_instr_set(sphead->instructions(),
spcont, var_idx, dflt_value_item,
type.field_type(), this, last);
if (is == NULL || sphead->add_instr(is))
return true;
}
spcont->declare_var_boundary(0);
return sphead->restore_lex(thd);
}
bool LEX::sp_declare_cursor(THD *thd, const LEX_STRING name, LEX *cursor_stmt)
{
uint offp;
sp_instr_cpush *i;
if (spcont->find_cursor(name, &offp, true))
{
my_error(ER_SP_DUP_CURS, MYF(0), name.str);
return true;
}
i= new (thd->mem_root)
sp_instr_cpush(sphead->instructions(), spcont, cursor_stmt,
spcont->current_cursor_count());
return i == NULL || sphead->add_instr(i) || spcont->add_cursor(name);
}
bool LEX::sp_handler_declaration_init(THD *thd, int type)
{
sp_handler *h= spcont->add_handler(thd, (sp_handler::enum_type) type);
spcont= spcont->push_context(thd, sp_pcontext::HANDLER_SCOPE);
sp_instr_hpush_jump *i=
new (thd->mem_root) sp_instr_hpush_jump(sphead->instructions(), spcont, h);
if (i == NULL || sphead->add_instr(i))
return true;
/* For continue handlers, mark end of handler scope. */
if (type == sp_handler::CONTINUE &&
sphead->push_backpatch(thd, i, spcont->last_label()))
return true;
if (sphead->push_backpatch(thd, i, spcont->push_label(thd, empty_lex_str, 0)))
return true;
return false;
}
bool LEX::sp_handler_declaration_finalize(THD *thd, int type)
{
sp_label *hlab= spcont->pop_label(); /* After this hdlr */
sp_instr_hreturn *i;
if (type == sp_handler::CONTINUE)
{
i= new (thd->mem_root) sp_instr_hreturn(sphead->instructions(), spcont);
if (i == NULL ||
sphead->add_instr(i))
return true;
}
else
{ /* EXIT or UNDO handler, just jump to the end of the block */
i= new (thd->mem_root) sp_instr_hreturn(sphead->instructions(), spcont);
if (i == NULL ||
sphead->add_instr(i) ||
sphead->push_backpatch(thd, i, spcont->last_label())) /* Block end */
return true;
}
sphead->backpatch(hlab);
spcont= spcont->pop_context();
return false;
}
#ifdef MYSQL_SERVER
uint binlog_unsafe_map[256];
......
......@@ -3071,6 +3071,14 @@ struct LEX: public Query_tables_list
LEX_STRING dbname, LEX_STRING name);
bool init_default_internal_variable(struct sys_var_with_base *variable,
LEX_STRING name);
void sp_variable_declarations_init(THD *thd, int nvars);
bool sp_variable_declarations_finalize(THD *thd, int nvars,
const Lex_field_type_st &type,
Item *def);
bool sp_handler_declaration_init(THD *thd, int type);
bool sp_handler_declaration_finalize(THD *thd, int type);
bool sp_declare_cursor(THD *thd, const LEX_STRING name, LEX *cursor_stmt);
bool set_local_variable(sp_variable *spv, Item *val);
Item_splocal *create_item_for_sp_var(LEX_STRING name, sp_variable *spvar,
const char *start_in_q,
......
......@@ -1949,7 +1949,7 @@ END_OF_INPUT
%type <num> sp_decl_idents sp_handler_type sp_hcond_list
%type <spcondvalue> sp_cond sp_hcond sqlstate signal_value opt_signal_value
%type <spblock> sp_decls sp_decl
%type <spblock> sp_decls sp_decl sp_decl_body
%type <lex> sp_cursor_stmt
%type <spname> sp_name
%type <splabel> sp_block_content
......@@ -2997,161 +2997,44 @@ sp_decls:
;
sp_decl:
DECLARE_SYM sp_decl_idents
{
LEX *lex= Lex;
sp_pcontext *pctx= lex->spcont;
// get the last variable:
uint num_vars= pctx->context_var_count();
uint var_idx= pctx->var_context2runtime(num_vars - 1);
sp_variable *spvar= pctx->find_variable(var_idx);
DECLARE_SYM sp_decl_body { $$= $2; }
;
lex->sphead->reset_lex(thd);
pctx->declare_var_boundary($2);
thd->lex->init_last_field(&spvar->field_def, spvar->name.str,
thd->variables.collation_database);
sp_decl_body:
sp_decl_idents
{
Lex->sp_variable_declarations_init(thd, $1);
}
type_with_opt_collate
sp_opt_default
{
LEX *lex= Lex;
sp_pcontext *pctx= lex->spcont;
uint num_vars= pctx->context_var_count();
Item *dflt_value_item= $5;
if (!dflt_value_item)
{
dflt_value_item= new (thd->mem_root) Item_null(thd);
if (dflt_value_item == NULL)
if (Lex->sp_variable_declarations_finalize(thd, $1, $3, $4))
MYSQL_YYABORT;
/* QQ Set to the var_type with null_value? */
}
for (uint i = num_vars-$2 ; i < num_vars ; i++)
{
uint var_idx= pctx->var_context2runtime(i);
sp_variable *spvar= pctx->find_variable(var_idx);
bool last= i == num_vars - 1;
if (!spvar)
MYSQL_YYABORT;
if (!last)
spvar->field_def= *lex->last_field;
spvar->default_value= dflt_value_item;
spvar->field_def.field_name= spvar->name.str;
if (lex->sphead->fill_field_definition(thd, &spvar->field_def))
{
MYSQL_YYABORT;
}
spvar->field_def.pack_flag |= FIELDFLAG_MAYBE_NULL;
/* The last instruction is responsible for freeing LEX. */
sp_instr_set *is= new (lex->thd->mem_root)
sp_instr_set(lex->sphead->instructions(),
pctx, var_idx, dflt_value_item,
$4.field_type(), lex, last);
if (is == NULL || lex->sphead->add_instr(is))
MYSQL_YYABORT;
}
pctx->declare_var_boundary(0);
if (lex->sphead->restore_lex(thd))
MYSQL_YYABORT;
$$.vars= $2;
$$.vars= $1;
$$.conds= $$.hndlrs= $$.curs= 0;
}
| DECLARE_SYM ident CONDITION_SYM FOR_SYM sp_cond
| ident CONDITION_SYM FOR_SYM sp_cond
{
LEX *lex= Lex;
sp_pcontext *spc= lex->spcont;
if (spc->find_condition($2, TRUE))
my_yyabort_error((ER_SP_DUP_COND, MYF(0), $2.str));
if(spc->add_condition(thd, $2, $5))
if (Lex->spcont->declare_condition(thd, $1, $4))
MYSQL_YYABORT;
$$.vars= $$.hndlrs= $$.curs= 0;
$$.conds= 1;
}
| DECLARE_SYM sp_handler_type HANDLER_SYM FOR_SYM
| sp_handler_type HANDLER_SYM FOR_SYM
{
LEX *lex= Lex;
sp_head *sp= lex->sphead;
sp_handler *h= lex->spcont->add_handler(thd,
(sp_handler::enum_type) $2);
lex->spcont= lex->spcont->push_context(thd,
sp_pcontext::HANDLER_SCOPE);
sp_pcontext *ctx= lex->spcont;
sp_instr_hpush_jump *i=
new (thd->mem_root) sp_instr_hpush_jump(sp->instructions(),
ctx, h);
if (i == NULL || sp->add_instr(i))
MYSQL_YYABORT;
/* For continue handlers, mark end of handler scope. */
if ($2 == sp_handler::CONTINUE &&
sp->push_backpatch(thd, i, ctx->last_label()))
MYSQL_YYABORT;
if (sp->push_backpatch(thd, i, ctx->push_label(thd, empty_lex_str, 0)))
if (Lex->sp_handler_declaration_init(thd, $1))
MYSQL_YYABORT;
}
sp_hcond_list sp_proc_stmt
{
LEX *lex= Lex;
sp_head *sp= lex->sphead;
sp_pcontext *ctx= lex->spcont;
sp_label *hlab= lex->spcont->pop_label(); /* After this hdlr */
sp_instr_hreturn *i;
if ($2 == sp_handler::CONTINUE)
{
i= new (thd->mem_root)
sp_instr_hreturn(sp->instructions(), ctx);
if (i == NULL ||
sp->add_instr(i))
if (Lex->sp_handler_declaration_finalize(thd, $1))
MYSQL_YYABORT;
}
else
{ /* EXIT or UNDO handler, just jump to the end of the block */
i= new (thd->mem_root)
sp_instr_hreturn(sp->instructions(), ctx);
if (i == NULL ||
sp->add_instr(i) ||
sp->push_backpatch(thd, i, lex->spcont->last_label())) /* Block end */
MYSQL_YYABORT;
}
lex->sphead->backpatch(hlab);
lex->spcont= ctx->pop_context();
$$.vars= $$.conds= $$.curs= 0;
$$.hndlrs= 1;
}
| DECLARE_SYM ident CURSOR_SYM FOR_SYM sp_cursor_stmt
| ident CURSOR_SYM FOR_SYM sp_cursor_stmt
{
LEX *lex= Lex;
sp_head *sp= lex->sphead;
sp_pcontext *ctx= lex->spcont;
uint offp;
sp_instr_cpush *i;
if (ctx->find_cursor($2, &offp, TRUE))
my_yyabort_error((ER_SP_DUP_CURS, MYF(0), $2.str));
i= new (thd->mem_root)
sp_instr_cpush(sp->instructions(), ctx, $5,
ctx->current_cursor_count());
if (i == NULL || sp->add_instr(i) || ctx->add_cursor($2))
if (Lex->sp_declare_cursor(thd, $1, $4))
MYSQL_YYABORT;
$$.vars= $$.conds= $$.hndlrs= 0;
$$.curs= 1;
......
......@@ -1329,7 +1329,7 @@ END_OF_INPUT
%type <num> sp_decl_idents sp_handler_type sp_hcond_list
%type <spcondvalue> sp_cond sp_hcond sqlstate signal_value opt_signal_value
%type <spblock> sp_decls sp_decl
%type <spblock> sp_decls sp_decl sp_decl_body
%type <lex> sp_cursor_stmt
%type <spname> sp_name
%type <splabel> sp_block_content
......@@ -2383,161 +2383,44 @@ sp_decls:
;
sp_decl:
DECLARE_SYM sp_decl_idents
{
LEX *lex= Lex;
sp_pcontext *pctx= lex->spcont;
// get the last variable:
uint num_vars= pctx->context_var_count();
uint var_idx= pctx->var_context2runtime(num_vars - 1);
sp_variable *spvar= pctx->find_variable(var_idx);
DECLARE_SYM sp_decl_body { $$= $2; }
;
lex->sphead->reset_lex(thd);
pctx->declare_var_boundary($2);
thd->lex->init_last_field(&spvar->field_def, spvar->name.str,
thd->variables.collation_database);
sp_decl_body:
sp_decl_idents
{
Lex->sp_variable_declarations_init(thd, $1);
}
type_with_opt_collate
sp_opt_default
{
LEX *lex= Lex;
sp_pcontext *pctx= lex->spcont;
uint num_vars= pctx->context_var_count();
Item *dflt_value_item= $5;
if (!dflt_value_item)
{
dflt_value_item= new (thd->mem_root) Item_null(thd);
if (dflt_value_item == NULL)
MYSQL_YYABORT;
/* QQ Set to the var_type with null_value? */
}
for (uint i = num_vars-$2 ; i < num_vars ; i++)
{
uint var_idx= pctx->var_context2runtime(i);
sp_variable *spvar= pctx->find_variable(var_idx);
bool last= i == num_vars - 1;
if (!spvar)
MYSQL_YYABORT;
if (!last)
spvar->field_def= *lex->last_field;
spvar->default_value= dflt_value_item;
spvar->field_def.field_name= spvar->name.str;
if (lex->sphead->fill_field_definition(thd, &spvar->field_def))
{
if (Lex->sp_variable_declarations_finalize(thd, $1, $3, $4))
MYSQL_YYABORT;
}
spvar->field_def.pack_flag |= FIELDFLAG_MAYBE_NULL;
/* The last instruction is responsible for freeing LEX. */
sp_instr_set *is= new (lex->thd->mem_root)
sp_instr_set(lex->sphead->instructions(),
pctx, var_idx, dflt_value_item,
$4.field_type(), lex, last);
if (is == NULL || lex->sphead->add_instr(is))
MYSQL_YYABORT;
}
pctx->declare_var_boundary(0);
if (lex->sphead->restore_lex(thd))
MYSQL_YYABORT;
$$.vars= $2;
$$.vars= $1;
$$.conds= $$.hndlrs= $$.curs= 0;
}
| DECLARE_SYM ident CONDITION_SYM FOR_SYM sp_cond
| ident CONDITION_SYM FOR_SYM sp_cond
{
LEX *lex= Lex;
sp_pcontext *spc= lex->spcont;
if (spc->find_condition($2, TRUE))
my_yyabort_error((ER_SP_DUP_COND, MYF(0), $2.str));
if(spc->add_condition(thd, $2, $5))
if (Lex->spcont->declare_condition(thd, $1, $4))
MYSQL_YYABORT;
$$.vars= $$.hndlrs= $$.curs= 0;
$$.conds= 1;
}
| DECLARE_SYM sp_handler_type HANDLER_SYM FOR_SYM
| sp_handler_type HANDLER_SYM FOR_SYM
{
LEX *lex= Lex;
sp_head *sp= lex->sphead;
sp_handler *h= lex->spcont->add_handler(thd,
(sp_handler::enum_type) $2);
lex->spcont= lex->spcont->push_context(thd,
sp_pcontext::HANDLER_SCOPE);
sp_pcontext *ctx= lex->spcont;
sp_instr_hpush_jump *i=
new (thd->mem_root) sp_instr_hpush_jump(sp->instructions(),
ctx, h);
if (i == NULL || sp->add_instr(i))
MYSQL_YYABORT;
/* For continue handlers, mark end of handler scope. */
if ($2 == sp_handler::CONTINUE &&
sp->push_backpatch(thd, i, ctx->last_label()))
MYSQL_YYABORT;
if (sp->push_backpatch(thd, i, ctx->push_label(thd, empty_lex_str, 0)))
if (Lex->sp_handler_declaration_init(thd, $1))
MYSQL_YYABORT;
}
sp_hcond_list sp_proc_stmt
{
LEX *lex= Lex;
sp_head *sp= lex->sphead;
sp_pcontext *ctx= lex->spcont;
sp_label *hlab= lex->spcont->pop_label(); /* After this hdlr */
sp_instr_hreturn *i;
if ($2 == sp_handler::CONTINUE)
{
i= new (thd->mem_root)
sp_instr_hreturn(sp->instructions(), ctx);
if (i == NULL ||
sp->add_instr(i))
if (Lex->sp_handler_declaration_finalize(thd, $1))
MYSQL_YYABORT;
}
else
{ /* EXIT or UNDO handler, just jump to the end of the block */
i= new (thd->mem_root)
sp_instr_hreturn(sp->instructions(), ctx);
if (i == NULL ||
sp->add_instr(i) ||
sp->push_backpatch(thd, i, lex->spcont->last_label())) /* Block end */
MYSQL_YYABORT;
}
lex->sphead->backpatch(hlab);
lex->spcont= ctx->pop_context();
$$.vars= $$.conds= $$.curs= 0;
$$.hndlrs= 1;
}
| DECLARE_SYM ident CURSOR_SYM FOR_SYM sp_cursor_stmt
| ident CURSOR_SYM FOR_SYM sp_cursor_stmt
{
LEX *lex= Lex;
sp_head *sp= lex->sphead;
sp_pcontext *ctx= lex->spcont;
uint offp;
sp_instr_cpush *i;
if (ctx->find_cursor($2, &offp, TRUE))
my_yyabort_error((ER_SP_DUP_CURS, MYF(0), $2.str));
i= new (thd->mem_root)
sp_instr_cpush(sp->instructions(), ctx, $5,
ctx->current_cursor_count());
if (i == NULL || sp->add_instr(i) || ctx->add_cursor($2))
if (Lex->sp_declare_cursor(thd, $1, $4))
MYSQL_YYABORT;
$$.vars= $$.conds= $$.hndlrs= 0;
$$.curs= 1;
......
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