mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
MDEV-17253 Oracle compatibility: The REVERSE key word for FOR loop behaves incorrectly
This commit is contained in:
@ -1020,8 +1020,8 @@ i
|
||||
SHOW PROCEDURE CODE p1;
|
||||
Pos Instruction
|
||||
0 set i@0 1
|
||||
1 set [upper_bound]@1 3
|
||||
2 jump_if_not 6(6) i@0 <= [upper_bound]@1
|
||||
1 set [target_bound]@1 3
|
||||
2 jump_if_not 6(6) i@0 <= [target_bound]@1
|
||||
3 stmt 0 "SELECT i"
|
||||
4 set i@0 i@0 + 1
|
||||
5 jump 2
|
||||
@ -1058,11 +1058,11 @@ i j
|
||||
SHOW PROCEDURE CODE p1;
|
||||
Pos Instruction
|
||||
0 set i@0 1
|
||||
1 set [upper_bound]@1 3
|
||||
2 jump_if_not 17(17) i@0 <= [upper_bound]@1
|
||||
1 set [target_bound]@1 3
|
||||
2 jump_if_not 17(17) i@0 <= [target_bound]@1
|
||||
3 set j@2 1
|
||||
4 set [upper_bound]@3 3
|
||||
5 jump_if_not 13(13) j@2 <= [upper_bound]@3
|
||||
4 set [target_bound]@3 3
|
||||
5 jump_if_not 13(13) j@2 <= [target_bound]@3
|
||||
6 jump_if_not 8(8) i@0 = 3
|
||||
7 jump 17
|
||||
8 jump_if_not 10(10) j@2 = 3
|
||||
|
@ -80,7 +80,7 @@ CREATE FUNCTION f1 (a INT, b INT) RETURNS INT
|
||||
BEGIN
|
||||
DECLARE total INT DEFAULT 0;
|
||||
fori:
|
||||
FOR i IN REVERSE a..1
|
||||
FOR i IN REVERSE 1..a
|
||||
DO
|
||||
SET total= total + i;
|
||||
IF i = b THEN
|
||||
|
@ -86,7 +86,7 @@ CREATE FUNCTION f1 (a INT, b INT) RETURNS INT
|
||||
BEGIN
|
||||
DECLARE total INT DEFAULT 0;
|
||||
fori:
|
||||
FOR i IN REVERSE a..1
|
||||
FOR i IN REVERSE 1..a
|
||||
DO
|
||||
SET total= total + i;
|
||||
IF i = b THEN
|
||||
|
@ -579,8 +579,8 @@ SHOW FUNCTION CODE f1;
|
||||
Pos Instruction
|
||||
0 set total@2 0
|
||||
1 set i@3 1
|
||||
2 set [upper_bound]@4 a@0
|
||||
3 jump_if_not 9(9) i@3 <= [upper_bound]@4
|
||||
2 set [target_bound]@4 a@0
|
||||
3 jump_if_not 9(9) i@3 <= [target_bound]@4
|
||||
4 set total@2 total@2 + i@3
|
||||
5 jump_if_not 7(7) i@3 = b@1
|
||||
6 jump 9
|
||||
@ -598,7 +598,7 @@ CREATE FUNCTION f1 (a INT, b INT) RETURN INT
|
||||
AS
|
||||
total INT := 0;
|
||||
BEGIN
|
||||
FOR i IN REVERSE a..1
|
||||
FOR i IN REVERSE 1..a
|
||||
LOOP
|
||||
total:= total + i;
|
||||
IF i = b THEN
|
||||
@ -612,8 +612,8 @@ SHOW FUNCTION CODE f1;
|
||||
Pos Instruction
|
||||
0 set total@2 0
|
||||
1 set i@3 a@0
|
||||
2 set [upper_bound]@4 1
|
||||
3 jump_if_not 9(9) i@3 >= [upper_bound]@4
|
||||
2 set [target_bound]@4 1
|
||||
3 jump_if_not 9(9) i@3 >= [target_bound]@4
|
||||
4 set total@2 total@2 + i@3
|
||||
5 jump_if_not 7(7) i@3 = b@1
|
||||
6 jump 9
|
||||
@ -651,12 +651,12 @@ SHOW FUNCTION CODE f1;
|
||||
Pos Instruction
|
||||
0 set total@4 0
|
||||
1 set ia@5 1
|
||||
2 set [upper_bound]@6 a@0
|
||||
3 jump_if_not 17(17) ia@5 <= [upper_bound]@6
|
||||
2 set [target_bound]@6 a@0
|
||||
3 jump_if_not 17(17) ia@5 <= [target_bound]@6
|
||||
4 set total@4 total@4 + 1000
|
||||
5 set ib@7 1
|
||||
6 set [upper_bound]@8 b@2
|
||||
7 jump_if_not 15(15) ib@7 <= [upper_bound]@8
|
||||
6 set [target_bound]@8 b@2
|
||||
7 jump_if_not 15(15) ib@7 <= [target_bound]@8
|
||||
8 set total@4 total@4 + 1
|
||||
9 jump_if_not 11(0) ib@7 = limitb@3
|
||||
10 jump 15
|
||||
@ -698,8 +698,8 @@ SHOW FUNCTION CODE f1;
|
||||
Pos Instruction
|
||||
0 set total@1 0
|
||||
1 set i@2 1
|
||||
2 set [upper_bound]@3 a@0
|
||||
3 jump_if_not 11(11) i@2 <= [upper_bound]@3
|
||||
2 set [target_bound]@3 a@0
|
||||
3 jump_if_not 11(11) i@2 <= [target_bound]@3
|
||||
4 set total@1 total@1 + 1000
|
||||
5 jump_if_not 8(8) i@2 = 5
|
||||
6 set i@2 i@2 + 1
|
||||
@ -735,11 +735,11 @@ SHOW FUNCTION CODE f1;
|
||||
Pos Instruction
|
||||
0 set total@1 0
|
||||
1 set i@2 1
|
||||
2 set [upper_bound]@3 a@0
|
||||
3 jump_if_not 16(16) i@2 <= [upper_bound]@3
|
||||
2 set [target_bound]@3 a@0
|
||||
3 jump_if_not 16(16) i@2 <= [target_bound]@3
|
||||
4 set j@4 1
|
||||
5 set [upper_bound]@5 2
|
||||
6 jump_if_not 14(14) j@4 <= [upper_bound]@5
|
||||
5 set [target_bound]@5 2
|
||||
6 jump_if_not 14(14) j@4 <= [target_bound]@5
|
||||
7 set total@1 total@1 + 1000
|
||||
8 jump_if_not 11(11) i@2 = 5
|
||||
9 set i@2 i@2 + 1
|
||||
@ -778,11 +778,11 @@ SHOW FUNCTION CODE f1;
|
||||
Pos Instruction
|
||||
0 set total@1 0
|
||||
1 set j@2 1
|
||||
2 set [upper_bound]@3 2
|
||||
3 jump_if_not 16(16) j@2 <= [upper_bound]@3
|
||||
2 set [target_bound]@3 2
|
||||
3 jump_if_not 16(16) j@2 <= [target_bound]@3
|
||||
4 set i@4 1
|
||||
5 set [upper_bound]@5 a@0
|
||||
6 jump_if_not 14(14) i@4 <= [upper_bound]@5
|
||||
5 set [target_bound]@5 a@0
|
||||
6 jump_if_not 14(14) i@4 <= [target_bound]@5
|
||||
7 set total@1 total@1 + 1000
|
||||
8 jump_if_not 11(11) i@4 = 5
|
||||
9 set i@4 i@4 + 1
|
||||
@ -814,8 +814,8 @@ SHOW FUNCTION CODE f1;
|
||||
Pos Instruction
|
||||
0 set total@1 0
|
||||
1 set i@2 1
|
||||
2 set [upper_bound]@3 a@0
|
||||
3 jump_if_not 10(10) i@2 <= [upper_bound]@3
|
||||
2 set [target_bound]@3 a@0
|
||||
3 jump_if_not 10(10) i@2 <= [target_bound]@3
|
||||
4 jump_if_not 7(0) i@2 = 5
|
||||
5 set i@2 i@2 + 1
|
||||
6 jump 3
|
||||
|
@ -843,7 +843,7 @@ CREATE FUNCTION f1 (a INT, b INT) RETURN INT
|
||||
AS
|
||||
total INT := 0;
|
||||
BEGIN
|
||||
FOR i IN REVERSE a..1
|
||||
FOR i IN REVERSE 1..a
|
||||
LOOP
|
||||
total:= total + i;
|
||||
IF i = b THEN
|
||||
@ -2502,3 +2502,61 @@ BEGIN
|
||||
SELECT 'a' IN ('b',v);
|
||||
END $$
|
||||
ERROR HY000: Illegal parameter data types varchar and row for operation 'in'
|
||||
#
|
||||
# MDEV-17253 Oracle compatibility: The REVERSE key word for FOR loop behaves incorrectly
|
||||
#
|
||||
DECLARE
|
||||
totalprice DECIMAL(12,2):=NULL;
|
||||
loop_start INTEGER := 1;
|
||||
BEGIN
|
||||
FOR idx IN REVERSE loop_start..10 LOOP
|
||||
SELECT idx;
|
||||
END LOOP;
|
||||
END;
|
||||
$$
|
||||
idx
|
||||
10
|
||||
idx
|
||||
9
|
||||
idx
|
||||
8
|
||||
idx
|
||||
7
|
||||
idx
|
||||
6
|
||||
idx
|
||||
5
|
||||
idx
|
||||
4
|
||||
idx
|
||||
3
|
||||
idx
|
||||
2
|
||||
idx
|
||||
1
|
||||
CREATE PROCEDURE p1 AS
|
||||
loop_start INTEGER := 1;
|
||||
BEGIN
|
||||
FOR idx IN REVERSE 3..loop_start LOOP
|
||||
SELECT idx;
|
||||
END LOOP;
|
||||
END;
|
||||
$$
|
||||
CALL p1();
|
||||
DROP PROCEDURE p1;
|
||||
CREATE PROCEDURE p1 AS
|
||||
loop_start INTEGER := 1;
|
||||
BEGIN
|
||||
FOR idx IN REVERSE loop_start..3 LOOP
|
||||
SELECT idx;
|
||||
END LOOP;
|
||||
END;
|
||||
$$
|
||||
CALL p1();
|
||||
idx
|
||||
3
|
||||
idx
|
||||
2
|
||||
idx
|
||||
1
|
||||
DROP PROCEDURE p1;
|
||||
|
@ -470,7 +470,7 @@ CREATE FUNCTION f1 (a INT, b INT) RETURN INT
|
||||
AS
|
||||
total INT := 0;
|
||||
BEGIN
|
||||
FOR i IN REVERSE a..1
|
||||
FOR i IN REVERSE 1..a
|
||||
LOOP
|
||||
total:= total + i;
|
||||
IF i = b THEN
|
||||
|
@ -918,7 +918,7 @@ CREATE FUNCTION f1 (a INT, b INT) RETURN INT
|
||||
AS
|
||||
total INT := 0;
|
||||
BEGIN
|
||||
FOR i IN REVERSE a..1
|
||||
FOR i IN REVERSE 1..a
|
||||
LOOP
|
||||
total:= total + i;
|
||||
IF i = b THEN
|
||||
@ -2352,3 +2352,46 @@ BEGIN
|
||||
END $$
|
||||
DELIMITER ;$$
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-17253 Oracle compatibility: The REVERSE key word for FOR loop behaves incorrectly
|
||||
--echo #
|
||||
|
||||
DELIMITER $$;
|
||||
DECLARE
|
||||
totalprice DECIMAL(12,2):=NULL;
|
||||
loop_start INTEGER := 1;
|
||||
BEGIN
|
||||
FOR idx IN REVERSE loop_start..10 LOOP
|
||||
SELECT idx;
|
||||
END LOOP;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PROCEDURE p1 AS
|
||||
loop_start INTEGER := 1;
|
||||
BEGIN
|
||||
FOR idx IN REVERSE 3..loop_start LOOP
|
||||
SELECT idx;
|
||||
END LOOP;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL p1();
|
||||
DROP PROCEDURE p1;
|
||||
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PROCEDURE p1 AS
|
||||
loop_start INTEGER := 1;
|
||||
BEGIN
|
||||
FOR idx IN REVERSE loop_start..3 LOOP
|
||||
SELECT idx;
|
||||
END LOOP;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL p1();
|
||||
DROP PROCEDURE p1;
|
||||
|
@ -5695,7 +5695,7 @@ bool LEX::sp_for_loop_implicit_cursor_statement(THD *thd,
|
||||
return true;
|
||||
DBUG_ASSERT(thd->lex == this);
|
||||
bounds->m_direction= 1;
|
||||
bounds->m_upper_bound= NULL;
|
||||
bounds->m_target_bound= NULL;
|
||||
bounds->m_implicit_cursor= true;
|
||||
return false;
|
||||
}
|
||||
@ -5739,7 +5739,7 @@ bool LEX::sp_for_loop_condition(THD *thd, const Lex_for_loop_st &loop)
|
||||
Item_splocal *args[2];
|
||||
for (uint i= 0 ; i < 2; i++)
|
||||
{
|
||||
sp_variable *src= i == 0 ? loop.m_index : loop.m_upper_bound;
|
||||
sp_variable *src= i == 0 ? loop.m_index : loop.m_target_bound;
|
||||
args[i]= new (thd->mem_root)
|
||||
Item_splocal(thd, &sp_rcontext_handler_local,
|
||||
&src->name, src->offset, src->type_handler());
|
||||
@ -5800,11 +5800,11 @@ bool LEX::sp_for_loop_intrange_declarations(THD *thd, Lex_for_loop_st *loop,
|
||||
sp_add_for_loop_variable(thd, index,
|
||||
bounds.m_index->get_item()))))
|
||||
return true;
|
||||
if (unlikely(!(loop->m_upper_bound=
|
||||
bounds.m_upper_bound->
|
||||
sp_add_for_loop_upper_bound(thd,
|
||||
if (unlikely(!(loop->m_target_bound=
|
||||
bounds.m_target_bound->
|
||||
sp_add_for_loop_target_bound(thd,
|
||||
bounds.
|
||||
m_upper_bound->get_item()))))
|
||||
m_target_bound->get_item()))))
|
||||
return true;
|
||||
loop->m_direction= bounds.m_direction;
|
||||
loop->m_implicit_cursor= 0;
|
||||
@ -5867,7 +5867,7 @@ bool LEX::sp_for_loop_cursor_declarations(THD *thd,
|
||||
bounds.m_index,
|
||||
item_func_sp)))
|
||||
return true;
|
||||
loop->m_upper_bound= NULL;
|
||||
loop->m_target_bound= NULL;
|
||||
loop->m_direction= bounds.m_direction;
|
||||
loop->m_cursor_offset= coffs;
|
||||
loop->m_implicit_cursor= bounds.m_implicit_cursor;
|
||||
|
@ -3736,9 +3736,9 @@ public:
|
||||
/* Integer range FOR LOOP methods */
|
||||
sp_variable *sp_add_for_loop_variable(THD *thd, const LEX_CSTRING *name,
|
||||
Item *value);
|
||||
sp_variable *sp_add_for_loop_upper_bound(THD *thd, Item *value)
|
||||
sp_variable *sp_add_for_loop_target_bound(THD *thd, Item *value)
|
||||
{
|
||||
LEX_CSTRING name= { STRING_WITH_LEN("[upper_bound]") };
|
||||
LEX_CSTRING name= { STRING_WITH_LEN("[target_bound]") };
|
||||
return sp_add_for_loop_variable(thd, &name, value);
|
||||
}
|
||||
bool sp_for_loop_intrange_declarations(THD *thd, Lex_for_loop_st *loop,
|
||||
|
@ -4769,16 +4769,13 @@ sp_for_loop_bounds:
|
||||
IN_SYM opt_sp_for_loop_direction for_loop_bound_expr
|
||||
DOT_DOT_SYM for_loop_bound_expr
|
||||
{
|
||||
$$.m_direction= $2;
|
||||
$$.m_index= $3;
|
||||
$$.m_upper_bound= $5;
|
||||
$$.m_implicit_cursor= false;
|
||||
$$= Lex_for_loop_bounds_intrange($2, $3, $5);
|
||||
}
|
||||
| IN_SYM opt_sp_for_loop_direction for_loop_bound_expr
|
||||
{
|
||||
$$.m_direction= $2;
|
||||
$$.m_index= $3;
|
||||
$$.m_upper_bound= NULL;
|
||||
$$.m_target_bound= NULL;
|
||||
$$.m_implicit_cursor= false;
|
||||
}
|
||||
| IN_SYM opt_sp_for_loop_direction '(' sp_cursor_stmt ')'
|
||||
|
@ -4615,16 +4615,13 @@ sp_for_loop_bounds:
|
||||
IN_SYM opt_sp_for_loop_direction for_loop_bound_expr
|
||||
DOT_DOT_SYM for_loop_bound_expr
|
||||
{
|
||||
$$.m_direction= $2;
|
||||
$$.m_index= $3;
|
||||
$$.m_upper_bound= $5;
|
||||
$$.m_implicit_cursor= false;
|
||||
$$= Lex_for_loop_bounds_intrange($2, $3, $5);
|
||||
}
|
||||
| IN_SYM opt_sp_for_loop_direction for_loop_bound_expr
|
||||
{
|
||||
$$.m_direction= $2;
|
||||
$$.m_index= $3;
|
||||
$$.m_upper_bound= NULL;
|
||||
$$.m_target_bound= NULL;
|
||||
$$.m_implicit_cursor= false;
|
||||
}
|
||||
| IN_SYM opt_sp_for_loop_direction '(' sp_cursor_stmt ')'
|
||||
|
@ -692,26 +692,41 @@ public:
|
||||
struct Lex_for_loop_bounds_st
|
||||
{
|
||||
public:
|
||||
class sp_assignment_lex *m_index;
|
||||
class sp_assignment_lex *m_upper_bound;
|
||||
class sp_assignment_lex *m_index; // The first iteration value (or cursor)
|
||||
class sp_assignment_lex *m_target_bound; // The last iteration value
|
||||
int8 m_direction;
|
||||
bool m_implicit_cursor;
|
||||
bool is_for_loop_cursor() const { return m_upper_bound == NULL; }
|
||||
bool is_for_loop_cursor() const { return m_target_bound == NULL; }
|
||||
};
|
||||
|
||||
|
||||
class Lex_for_loop_bounds_intrange: public Lex_for_loop_bounds_st
|
||||
{
|
||||
public:
|
||||
Lex_for_loop_bounds_intrange(int8 direction,
|
||||
class sp_assignment_lex *left_expr,
|
||||
class sp_assignment_lex *right_expr)
|
||||
{
|
||||
m_direction= direction;
|
||||
m_index= direction > 0 ? left_expr : right_expr;
|
||||
m_target_bound= direction > 0 ? right_expr : left_expr;
|
||||
m_implicit_cursor= false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct Lex_for_loop_st
|
||||
{
|
||||
public:
|
||||
class sp_variable *m_index;
|
||||
class sp_variable *m_upper_bound;
|
||||
class sp_variable *m_index; // The first iteration value (or cursor)
|
||||
class sp_variable *m_target_bound; // The last iteration value
|
||||
int m_cursor_offset;
|
||||
int8 m_direction;
|
||||
bool m_implicit_cursor;
|
||||
void init()
|
||||
{
|
||||
m_index= 0;
|
||||
m_upper_bound= 0;
|
||||
m_target_bound= 0;
|
||||
m_direction= 0;
|
||||
m_implicit_cursor= false;
|
||||
}
|
||||
@ -719,7 +734,7 @@ public:
|
||||
{
|
||||
*this= other;
|
||||
}
|
||||
bool is_for_loop_cursor() const { return m_upper_bound == NULL; }
|
||||
bool is_for_loop_cursor() const { return m_target_bound == NULL; }
|
||||
bool is_for_loop_explicit_cursor() const
|
||||
{
|
||||
return is_for_loop_cursor() && !m_implicit_cursor;
|
||||
|
Reference in New Issue
Block a user