mirror of
https://github.com/MariaDB/server.git
synced 2026-01-06 05:22:24 +03:00
MDEV-10581 sql_mode=ORACLE: Explicit cursor FOR LOOP
MDEV-12098 sql_mode=ORACLE: Implicit cursor FOR loop
This commit is contained in:
145
sql/sql_lex.cc
145
sql/sql_lex.cc
@@ -5416,8 +5416,42 @@ sp_variable *LEX::sp_add_for_loop_variable(THD *thd, const LEX_STRING name,
|
||||
*/
|
||||
spvar->field_def.pack_flag= (FIELDFLAG_NUMBER |
|
||||
f_settype((uint) MYSQL_TYPE_LONGLONG));
|
||||
if (sp_variable_declarations_finalize(thd, 1, NULL, NULL, value))
|
||||
|
||||
if (!value && !(value= new (thd->mem_root) Item_null(thd)))
|
||||
return NULL;
|
||||
|
||||
spvar->default_value= value;
|
||||
sp_instr_set *is= new (this->thd->mem_root)
|
||||
sp_instr_set(sphead->instructions(),
|
||||
spcont, spvar->offset, value,
|
||||
this, true);
|
||||
if (is == NULL || sphead->add_instr(is))
|
||||
return NULL;
|
||||
spcont->declare_var_boundary(0);
|
||||
return spvar;
|
||||
}
|
||||
|
||||
|
||||
sp_variable *
|
||||
LEX::sp_add_for_loop_cursor_variable(THD *thd,
|
||||
const LEX_STRING name,
|
||||
const sp_pcursor *pcursor,
|
||||
uint coffset)
|
||||
{
|
||||
sp_variable *spvar= spcont->add_variable(thd, name);
|
||||
spcont->declare_var_boundary(1);
|
||||
spvar->field_def.field_name= spvar->name.str;
|
||||
spvar->default_value= new (thd->mem_root) Item_null(thd);
|
||||
|
||||
Cursor_rowtype *ref;
|
||||
if (!(ref= new (thd->mem_root) Cursor_rowtype(coffset)))
|
||||
return NULL;
|
||||
spvar->field_def.set_cursor_rowtype_ref(ref);
|
||||
|
||||
if (sphead->add_for_loop_open_cursor(thd, spcont, spvar, pcursor, coffset))
|
||||
return NULL;
|
||||
|
||||
spcont->declare_var_boundary(0);
|
||||
return spvar;
|
||||
}
|
||||
|
||||
@@ -5453,7 +5487,8 @@ bool LEX::sp_for_loop_condition(THD *thd, const Lex_for_loop_st &loop)
|
||||
/**
|
||||
Generate the FOR LOOP condition code in its own lex
|
||||
*/
|
||||
bool LEX::sp_for_loop_index_and_bounds(THD *thd, const Lex_for_loop_st &loop)
|
||||
bool LEX::sp_for_loop_intrange_condition_test(THD *thd,
|
||||
const Lex_for_loop_st &loop)
|
||||
{
|
||||
spcont->set_for_loop(loop);
|
||||
sphead->reset_lex(thd);
|
||||
@@ -5463,6 +5498,80 @@ bool LEX::sp_for_loop_index_and_bounds(THD *thd, const Lex_for_loop_st &loop)
|
||||
}
|
||||
|
||||
|
||||
bool LEX::sp_for_loop_cursor_condition_test(THD *thd,
|
||||
const Lex_for_loop_st &loop)
|
||||
{
|
||||
spcont->set_for_loop(loop);
|
||||
sphead->reset_lex(thd);
|
||||
const LEX_STRING *cursor_name= spcont->find_cursor(loop.m_cursor_offset);
|
||||
Item *expr= new (thd->mem_root) Item_func_cursor_found(thd, *cursor_name,
|
||||
loop.m_cursor_offset);
|
||||
if (thd->lex->sp_while_loop_expression(thd, expr))
|
||||
return true;
|
||||
return thd->lex->sphead->restore_lex(thd);
|
||||
}
|
||||
|
||||
|
||||
bool LEX::sp_for_loop_intrange_declarations(THD *thd, Lex_for_loop_st *loop,
|
||||
const LEX_STRING &index,
|
||||
const Lex_for_loop_bounds_st &bounds)
|
||||
{
|
||||
if (!(loop->m_index=
|
||||
bounds.m_index->sp_add_for_loop_variable(thd, index,
|
||||
bounds.m_index->get_item())))
|
||||
return true;
|
||||
if (!(loop->m_upper_bound=
|
||||
bounds.m_upper_bound->sp_add_for_loop_upper_bound(thd,
|
||||
bounds.m_upper_bound->get_item())))
|
||||
return true;
|
||||
loop->m_direction= bounds.m_direction;
|
||||
loop->m_implicit_cursor= 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool LEX::sp_for_loop_cursor_declarations(THD *thd,
|
||||
Lex_for_loop_st *loop,
|
||||
const LEX_STRING &index,
|
||||
const Lex_for_loop_bounds_st &bounds)
|
||||
{
|
||||
Item *item= bounds.m_index->get_item();
|
||||
Item_splocal *item_splocal;
|
||||
Item_field *item_field;
|
||||
LEX_STRING name;
|
||||
uint coffs;
|
||||
const sp_pcursor *pcursor;
|
||||
|
||||
if ((item_splocal= item->get_item_splocal()))
|
||||
{
|
||||
name= item_splocal->m_name;
|
||||
}
|
||||
else if ((item_field= item->type() == Item::FIELD_ITEM ?
|
||||
static_cast<Item_field *>(item) : NULL) &&
|
||||
item_field->table_name == NULL)
|
||||
{
|
||||
name.str= (char *) item_field->field_name;
|
||||
name.length= strlen(item_field->field_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
thd->parse_error();
|
||||
return true;
|
||||
}
|
||||
if (!(pcursor= spcont->find_cursor_with_error(name, &coffs, false)))
|
||||
return true;
|
||||
|
||||
if (!(loop->m_index= sp_add_for_loop_cursor_variable(thd, index,
|
||||
pcursor, coffs)))
|
||||
return true;
|
||||
loop->m_upper_bound= NULL;
|
||||
loop->m_direction= bounds.m_direction;
|
||||
loop->m_cursor_offset= coffs;
|
||||
loop->m_implicit_cursor= bounds.m_implicit_cursor;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Generate a code for a FOR loop index increment
|
||||
*/
|
||||
@@ -5487,7 +5596,7 @@ bool LEX::sp_for_loop_increment(THD *thd, const Lex_for_loop_st &loop)
|
||||
}
|
||||
|
||||
|
||||
bool LEX::sp_for_loop_finalize(THD *thd, const Lex_for_loop_st &loop)
|
||||
bool LEX::sp_for_loop_intrange_finalize(THD *thd, const Lex_for_loop_st &loop)
|
||||
{
|
||||
sphead->reset_lex(thd);
|
||||
|
||||
@@ -5503,6 +5612,18 @@ bool LEX::sp_for_loop_finalize(THD *thd, const Lex_for_loop_st &loop)
|
||||
}
|
||||
|
||||
|
||||
bool LEX::sp_for_loop_cursor_finalize(THD *thd, const Lex_for_loop_st &loop)
|
||||
{
|
||||
sp_instr_cfetch *instr=
|
||||
new (thd->mem_root) sp_instr_cfetch(sphead->instructions(),
|
||||
spcont, loop.m_cursor_offset);
|
||||
if (instr == NULL || sphead->add_instr(instr))
|
||||
return true;
|
||||
instr->add_to_varlist(loop.m_index);
|
||||
// Generate a jump to the beginning of the loop
|
||||
return sp_while_loop_finalize(thd);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
bool LEX::sp_declare_cursor(THD *thd, const LEX_STRING name,
|
||||
@@ -5517,6 +5638,7 @@ bool LEX::sp_declare_cursor(THD *thd, const LEX_STRING name,
|
||||
my_error(ER_SP_DUP_CURS, MYF(0), name.str);
|
||||
return true;
|
||||
}
|
||||
cursor_stmt->set_cursor_name(name);
|
||||
i= new (thd->mem_root)
|
||||
sp_instr_cpush(sphead->instructions(), spcont, cursor_stmt,
|
||||
spcont->current_cursor_count());
|
||||
@@ -5538,19 +5660,10 @@ bool LEX::sp_open_cursor(THD *thd, const LEX_STRING name,
|
||||
{
|
||||
uint offset;
|
||||
const sp_pcursor *pcursor;
|
||||
if (!(pcursor= spcont->find_cursor(name, &offset, false)))
|
||||
{
|
||||
my_error(ER_SP_CURSOR_MISMATCH, MYF(0), name.str);
|
||||
return true;
|
||||
}
|
||||
if ((pcursor->param_context() ?
|
||||
pcursor->param_context()->context_var_count() : 0) !=
|
||||
(parameters ? parameters->elements : 0))
|
||||
{
|
||||
my_error(ER_WRONG_PARAMCOUNT_TO_CURSOR, MYF(0), name.str);
|
||||
return true;
|
||||
}
|
||||
return sphead->add_open_cursor(thd, spcont, offset,
|
||||
uint param_count= parameters ? parameters->elements : 0;
|
||||
return !(pcursor= spcont->find_cursor_with_error(name, &offset, false)) ||
|
||||
pcursor->check_param_count_with_error(param_count) ||
|
||||
sphead->add_open_cursor(thd, spcont, offset,
|
||||
pcursor->param_context(), parameters);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user