mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
MDEV-32275 getting error 'Illegal parameter data types row and bigint for operation '+' ' when using ITERATE in a FOR..DO
An "ITERATE innerLoop" did not work properly inside a WHILE loop, which itself is inside an outer FOR loop: outerLoop: FOR ... innerLoop: WHILE ... ITERATE innerLoop; ... END WHILE; ... END FOR; It erroneously generated an integer increment code for the outer FOR loop. There were two problems: 1. "ITERATE innerLoop" worked like "ITERATE outerLoop" 2. It was always integer increment, even in case of FOR cursor loops. Background: - A FOR loop automatically creates a dedicated sp_pcontext stack entry, to put the iteration and bound variables on it. - Other loop types (LOOP, WHILE, REPEAT), do not generate a dedicated slack entry. The old code erroneously assumed that sp_pcontext::m_for_loop either describes the most inner loop (in case the inner loop is FOR), or is empty (in case the inner loop is not FOR). But in fact, sp_pcontext::m_for_loop is never empty inside a FOR loop: it describes the closest FOR loop, even if this FOR loop has nested non-FOR loops inside. So when we're near the ITERATE statement in the above script, sp_pcontext::m_for_loop is not empty - it stores information about the FOR loop labeled as "outrLoop:". Fix: - Adding a new member sp_pcontext::Lex_for_loop::m_start_label, to remember the explicit or the auto-generated label correspoding to the start of the FOR body. It's used during generation of "ITERATE loop_label" code to check if "loop_label" belongs to the current FOR loop pointed by sp_pcontext::m_for_loop, or belongs to a non-FOR nested loop. - Adding LEX methods sp_for_loop_intrange_iterate() and sp_for_loop_cursor_iterate() to reuse the code between methods handling: * ITERATE * END FOR - Adding a test for Lex_for_loop::is_for_loop_cursor() and generate a code either a cursor fetch, or for an integer increment. Before this change, it always erroneously generated an integer increment version. - Cleanup: Initialize Lex_for_loop_st::m_cursor_offset inside Lex_for_loop_st::init(), to avoid not initialized members. - Cleanup: Removing a redundant method: Lex_for_loop_st::init(const Lex_for_loop_st &other) Using Lex_for_loop_st::operator(const Lex_for_loop_st &other) instead.
This commit is contained in:
@ -4158,7 +4158,7 @@ public:
|
||||
const LEX_CSTRING *index,
|
||||
const Lex_for_loop_bounds_st &bounds);
|
||||
bool sp_for_loop_intrange_condition_test(THD *thd, const Lex_for_loop_st &loop);
|
||||
bool sp_for_loop_intrange_finalize(THD *thd, const Lex_for_loop_st &loop);
|
||||
bool sp_for_loop_intrange_iterate(THD *thd, const Lex_for_loop_st &loop);
|
||||
|
||||
/* Cursor FOR LOOP methods */
|
||||
bool sp_for_loop_cursor_declarations(THD *thd, Lex_for_loop_st *loop,
|
||||
@ -4174,7 +4174,7 @@ public:
|
||||
Lex_for_loop_bounds_st *bounds,
|
||||
sp_lex_cursor *cur);
|
||||
bool sp_for_loop_cursor_condition_test(THD *thd, const Lex_for_loop_st &loop);
|
||||
bool sp_for_loop_cursor_finalize(THD *thd, const Lex_for_loop_st &);
|
||||
bool sp_for_loop_cursor_iterate(THD *thd, const Lex_for_loop_st &);
|
||||
|
||||
/* Generic FOR LOOP methods*/
|
||||
|
||||
@ -4232,9 +4232,12 @@ public:
|
||||
*/
|
||||
bool sp_for_loop_finalize(THD *thd, const Lex_for_loop_st &loop)
|
||||
{
|
||||
return loop.is_for_loop_cursor() ?
|
||||
sp_for_loop_cursor_finalize(thd, loop) :
|
||||
sp_for_loop_intrange_finalize(thd, loop);
|
||||
if (loop.is_for_loop_cursor() ?
|
||||
sp_for_loop_cursor_iterate(thd, loop) :
|
||||
sp_for_loop_intrange_iterate(thd, loop))
|
||||
return true;
|
||||
// Generate a jump to the beginning of the loop
|
||||
return sp_while_loop_finalize(thd);
|
||||
}
|
||||
bool sp_for_loop_outer_block_finalize(THD *thd, const Lex_for_loop_st &loop);
|
||||
|
||||
|
Reference in New Issue
Block a user