summaryrefslogtreecommitdiff
path: root/sql/sp_head.cc
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.org>2017-03-22 18:10:33 +0400
committerAlexander Barkov <bar@mariadb.org>2017-04-05 15:03:00 +0400
commitec19e48021e408edac2e875cfeeef8f496a04d22 (patch)
tree2e0e035a36bb4ccaf5bb3918dc9a5362afc4e42b /sql/sp_head.cc
parente0451941ccb6adc11490099cdb7b1564af62ee68 (diff)
downloadmariadb-git-ec19e48021e408edac2e875cfeeef8f496a04d22.tar.gz
MDEV-12314 Implicit cursor FOR LOOP for cursors with parameters
Diffstat (limited to 'sql/sp_head.cc')
-rw-r--r--sql/sp_head.cc40
1 files changed, 37 insertions, 3 deletions
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 16dfbe9b700..20a0467be71 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -4612,14 +4612,16 @@ Item *sp_head::adjust_assignment_source(THD *thd, Item *val, Item *val2)
bool
sp_head::set_local_variable(THD *thd, sp_pcontext *spcont,
- sp_variable *spv, Item *val, LEX *lex)
+ sp_variable *spv, Item *val, LEX *lex,
+ bool responsible_to_free_lex)
{
if (!(val= adjust_assignment_source(thd, val, spv->default_value)))
return true;
sp_instr_set *sp_set= new (thd->mem_root)
sp_instr_set(instructions(), spcont,
- spv->offset, val, lex, true);
+ spv->offset, val, lex,
+ responsible_to_free_lex);
return sp_set == NULL || add_instr(sp_set);
}
@@ -4689,8 +4691,15 @@ bool sp_head::add_open_cursor(THD *thd, sp_pcontext *spcont, uint offset,
bool sp_head::add_for_loop_open_cursor(THD *thd, sp_pcontext *spcont,
sp_variable *index,
- const sp_pcursor *pcursor, uint coffset)
+ const sp_pcursor *pcursor, uint coffset,
+ sp_assignment_lex *param_lex,
+ Item_args *parameters)
{
+ if (parameters &&
+ add_set_for_loop_cursor_param_variables(thd, pcursor->param_context(),
+ param_lex, parameters))
+ return true;
+
sp_instr *instr_copy_struct=
new (thd->mem_root) sp_instr_cursor_copy_struct(instructions(),
spcont, pcursor->lex(),
@@ -4711,3 +4720,28 @@ bool sp_head::add_for_loop_open_cursor(THD *thd, sp_pcontext *spcont,
instr_cfetch->add_to_varlist(index);
return false;
}
+
+
+bool
+sp_head::add_set_for_loop_cursor_param_variables(THD *thd,
+ sp_pcontext *param_spcont,
+ sp_assignment_lex *param_lex,
+ Item_args *parameters)
+{
+ DBUG_ASSERT(param_spcont->context_var_count() == parameters->argument_count());
+ for (uint idx= 0; idx < parameters->argument_count(); idx ++)
+ {
+ /*
+ param_lex is shared between multiple items (cursor parameters).
+ Only the last sp_instr_set is responsible for freeing param_lex.
+ See more comments in LEX::sp_for_loop_cursor_declarations in sql_lex.cc.
+ */
+ bool last= idx + 1 == parameters->argument_count();
+ sp_variable *spvar= param_spcont->find_context_variable(idx);
+ if (set_local_variable(thd, param_spcont,
+ spvar, parameters->arguments()[idx],
+ param_lex, last))
+ return true;
+ }
+ return false;
+}