Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
MariaDB
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
af7f287b
Commit
af7f287b
authored
Feb 14, 2017
by
halfspawn
Committed by
Alexander Barkov
Apr 05, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
MDEV-10697 GOTO statement
parent
d836f52b
Changes
11
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
2092 additions
and
41 deletions
+2092
-41
mysql-test/suite/compat/oracle/r/sp-goto.result
mysql-test/suite/compat/oracle/r/sp-goto.result
+834
-0
mysql-test/suite/compat/oracle/t/sp-goto.test
mysql-test/suite/compat/oracle/t/sp-goto.test
+872
-0
sql/lex.h
sql/lex.h
+1
-0
sql/sp_head.cc
sql/sp_head.cc
+133
-2
sql/sp_head.h
sql/sp_head.h
+29
-0
sql/sp_pcontext.cc
sql/sp_pcontext.cc
+58
-3
sql/sp_pcontext.h
sql/sp_pcontext.h
+49
-6
sql/sql_lex.cc
sql/sql_lex.cc
+48
-0
sql/sql_lex.h
sql/sql_lex.h
+2
-0
sql/sql_yacc.yy
sql/sql_yacc.yy
+2
-0
sql/sql_yacc_ora.yy
sql/sql_yacc_ora.yy
+64
-30
No files found.
mysql-test/suite/compat/oracle/r/sp-goto.result
0 → 100644
View file @
af7f287b
This diff is collapsed.
Click to expand it.
mysql-test/suite/compat/oracle/t/sp-goto.test
0 → 100644
View file @
af7f287b
This diff is collapsed.
Click to expand it.
sql/lex.h
View file @
af7f287b
...
@@ -261,6 +261,7 @@ static SYMBOL symbols[] = {
...
@@ -261,6 +261,7 @@ static SYMBOL symbols[] = {
{
"GET_FORMAT"
,
SYM
(
GET_FORMAT
)},
{
"GET_FORMAT"
,
SYM
(
GET_FORMAT
)},
{
"GET"
,
SYM
(
GET_SYM
)},
{
"GET"
,
SYM
(
GET_SYM
)},
{
"GLOBAL"
,
SYM
(
GLOBAL_SYM
)},
{
"GLOBAL"
,
SYM
(
GLOBAL_SYM
)},
{
"GOTO"
,
SYM
(
GOTO_SYM
)},
{
"GRANT"
,
SYM
(
GRANT
)},
{
"GRANT"
,
SYM
(
GRANT
)},
{
"GRANTS"
,
SYM
(
GRANTS
)},
{
"GRANTS"
,
SYM
(
GRANTS
)},
{
"GROUP"
,
SYM
(
GROUP_SYM
)},
{
"GROUP"
,
SYM
(
GROUP_SYM
)},
...
...
sql/sp_head.cc
View file @
af7f287b
...
@@ -556,6 +556,7 @@ sp_head::sp_head()
...
@@ -556,6 +556,7 @@ sp_head::sp_head()
DBUG_ENTER
(
"sp_head::sp_head"
);
DBUG_ENTER
(
"sp_head::sp_head"
);
m_backpatch
.
empty
();
m_backpatch
.
empty
();
m_backpatch_goto
.
empty
();
m_cont_backpatch
.
empty
();
m_cont_backpatch
.
empty
();
m_lex
.
empty
();
m_lex
.
empty
();
my_hash_init
(
&
m_sptabs
,
system_charset_info
,
0
,
0
,
0
,
sp_table_key
,
0
,
0
);
my_hash_init
(
&
m_sptabs
,
system_charset_info
,
0
,
0
,
0
,
sp_table_key
,
0
,
0
);
...
@@ -2212,7 +2213,8 @@ sp_head::merge_lex(THD *thd, LEX *oldlex, LEX *sublex)
...
@@ -2212,7 +2213,8 @@ sp_head::merge_lex(THD *thd, LEX *oldlex, LEX *sublex)
Put the instruction on the backpatch list, associated with the label.
Put the instruction on the backpatch list, associated with the label.
*/
*/
int
int
sp_head
::
push_backpatch
(
THD
*
thd
,
sp_instr
*
i
,
sp_label
*
lab
)
sp_head
::
push_backpatch
(
THD
*
thd
,
sp_instr
*
i
,
sp_label
*
lab
,
List
<
bp_t
>
*
list
,
backpatch_instr_type
itype
)
{
{
bp_t
*
bp
=
(
bp_t
*
)
thd
->
alloc
(
sizeof
(
bp_t
));
bp_t
*
bp
=
(
bp_t
*
)
thd
->
alloc
(
sizeof
(
bp_t
));
...
@@ -2220,7 +2222,45 @@ sp_head::push_backpatch(THD *thd, sp_instr *i, sp_label *lab)
...
@@ -2220,7 +2222,45 @@ sp_head::push_backpatch(THD *thd, sp_instr *i, sp_label *lab)
return
1
;
return
1
;
bp
->
lab
=
lab
;
bp
->
lab
=
lab
;
bp
->
instr
=
i
;
bp
->
instr
=
i
;
return
m_backpatch
.
push_front
(
bp
);
bp
->
instr_type
=
itype
;
return
list
->
push_front
(
bp
);
}
int
sp_head
::
push_backpatch
(
THD
*
thd
,
sp_instr
*
i
,
sp_label
*
lab
)
{
return
push_backpatch
(
thd
,
i
,
lab
,
&
m_backpatch
,
GOTO
);
}
int
sp_head
::
push_backpatch_goto
(
THD
*
thd
,
sp_pcontext
*
ctx
,
sp_label
*
lab
)
{
uint
ip
=
instructions
();
/*
Add cpop/hpop : they will be removed or updated later if target is in
the same block or not
*/
sp_instr_hpop
*
hpop
=
new
(
thd
->
mem_root
)
sp_instr_hpop
(
ip
++
,
ctx
,
0
);
if
(
hpop
==
NULL
||
add_instr
(
hpop
))
return
true
;
if
(
push_backpatch
(
thd
,
hpop
,
lab
,
&
m_backpatch_goto
,
HPOP
))
return
true
;
sp_instr_cpop
*
cpop
=
new
(
thd
->
mem_root
)
sp_instr_cpop
(
ip
++
,
ctx
,
0
);
if
(
cpop
==
NULL
||
add_instr
(
cpop
))
return
true
;
if
(
push_backpatch
(
thd
,
cpop
,
lab
,
&
m_backpatch_goto
,
CPOP
))
return
true
;
// Add jump with ip=0. IP will be updated when label is found.
sp_instr_jump
*
i
=
new
(
thd
->
mem_root
)
sp_instr_jump
(
ip
,
ctx
);
if
(
i
==
NULL
||
add_instr
(
i
))
return
true
;
if
(
push_backpatch
(
thd
,
i
,
lab
,
&
m_backpatch_goto
,
GOTO
))
return
true
;
return
false
;
}
}
/**
/**
...
@@ -2247,6 +2287,97 @@ sp_head::backpatch(sp_label *lab)
...
@@ -2247,6 +2287,97 @@ sp_head::backpatch(sp_label *lab)
DBUG_VOID_RETURN
;
DBUG_VOID_RETURN
;
}
}
void
sp_head
::
backpatch_goto
(
THD
*
thd
,
sp_label
*
lab
,
sp_label
*
lab_begin_block
)
{
bp_t
*
bp
;
uint
dest
=
instructions
();
List_iterator
<
bp_t
>
li
(
m_backpatch_goto
);
DBUG_ENTER
(
"sp_head::backpatch_goto"
);
while
((
bp
=
li
++
))
{
if
(
bp
->
instr
->
m_ip
<
lab_begin_block
->
ip
||
bp
->
instr
->
m_ip
>
lab
->
ip
)
{
/*
Update only jump target from the beginning of the block where the
label is defined.
*/
continue
;
}
if
(
my_strcasecmp
(
system_charset_info
,
bp
->
lab
->
name
.
str
,
lab
->
name
.
str
)
==
0
)
{
if
(
bp
->
instr_type
==
GOTO
)
{
DBUG_PRINT
(
"info"
,
(
"backpatch_goto: (m_ip %d, label 0x%lx <%s>) to dest %d"
,
bp
->
instr
->
m_ip
,
(
ulong
)
lab
,
lab
->
name
.
str
,
dest
));
bp
->
instr
->
backpatch
(
dest
,
lab
->
ctx
);
// Jump resolved, remove from the list
li
.
remove
();
continue
;
}
if
(
bp
->
instr_type
==
CPOP
)
{
int
n
=
lab
->
ctx
->
diff_cursors
(
lab_begin_block
->
ctx
,
true
);
if
(
n
==
0
)
{
// Remove cpop instr
replace_instr_to_nop
(
thd
,
bp
->
instr
->
m_ip
);
}
else
{
// update count of cpop
static_cast
<
sp_instr_cpop
*>
(
bp
->
instr
)
->
update_count
(
n
);
n
=
1
;
}
li
.
remove
();
continue
;
}
if
(
bp
->
instr_type
==
HPOP
)
{
int
n
=
lab
->
ctx
->
diff_handlers
(
lab_begin_block
->
ctx
,
true
);
if
(
n
==
0
)
{
// Remove hpop instr
replace_instr_to_nop
(
thd
,
bp
->
instr
->
m_ip
);
}
else
{
// update count of cpop
static_cast
<
sp_instr_hpop
*>
(
bp
->
instr
)
->
update_count
(
n
);
n
=
1
;
}
li
.
remove
();
continue
;
}
}
}
DBUG_VOID_RETURN
;
}
bool
sp_head
::
check_unresolved_goto
()
{
DBUG_ENTER
(
"sp_head::check_unresolved_goto"
);
bool
has_unresolved_label
=
false
;
if
(
m_backpatch_goto
.
elements
>
0
)
{
List_iterator_fast
<
bp_t
>
li
(
m_backpatch_goto
);
bp_t
*
bp
;
while
((
bp
=
li
++
))
{
if
((
bp
->
instr_type
==
GOTO
))
{
my_error
(
ER_SP_LILABEL_MISMATCH
,
MYF
(
0
),
"GOTO"
,
bp
->
lab
->
name
);
has_unresolved_label
=
true
;
}
}
}
DBUG_RETURN
(
has_unresolved_label
);
}
int
int
sp_head
::
new_cont_backpatch
(
sp_instr_opt_meta
*
i
)
sp_head
::
new_cont_backpatch
(
sp_instr_opt_meta
*
i
)
...
...
sql/sp_head.h
View file @
af7f287b
...
@@ -516,11 +516,19 @@ class sp_head :private Query_arena,
...
@@ -516,11 +516,19 @@ class sp_head :private Query_arena,
/// Put the instruction on the backpatch list, associated with the label.
/// Put the instruction on the backpatch list, associated with the label.
int
int
push_backpatch
(
THD
*
thd
,
sp_instr
*
,
sp_label
*
);
push_backpatch
(
THD
*
thd
,
sp_instr
*
,
sp_label
*
);
int
push_backpatch_goto
(
THD
*
thd
,
sp_pcontext
*
ctx
,
sp_label
*
lab
);
/// Update all instruction with this label in the backpatch list to
/// Update all instruction with this label in the backpatch list to
/// the current position.
/// the current position.
void
void
backpatch
(
sp_label
*
);
backpatch
(
sp_label
*
);
void
backpatch_goto
(
THD
*
thd
,
sp_label
*
,
sp_label
*
);
/// Check for unresolved goto label
bool
check_unresolved_goto
();
/// Start a new cont. backpatch level. If 'i' is NULL, the level is just incr.
/// Start a new cont. backpatch level. If 'i' is NULL, the level is just incr.
int
int
...
@@ -695,12 +703,17 @@ class sp_head :private Query_arena,
...
@@ -695,12 +703,17 @@ class sp_head :private Query_arena,
sp_pcontext
*
m_pcont
;
///< Parse context
sp_pcontext
*
m_pcont
;
///< Parse context
List
<
LEX
>
m_lex
;
///< Temp. store for the other lex
List
<
LEX
>
m_lex
;
///< Temp. store for the other lex
DYNAMIC_ARRAY
m_instr
;
///< The "instructions"
DYNAMIC_ARRAY
m_instr
;
///< The "instructions"
enum
backpatch_instr_type
{
GOTO
,
CPOP
,
HPOP
};
typedef
struct
typedef
struct
{
{
sp_label
*
lab
;
sp_label
*
lab
;
sp_instr
*
instr
;
sp_instr
*
instr
;
backpatch_instr_type
instr_type
;
}
bp_t
;
}
bp_t
;
List
<
bp_t
>
m_backpatch
;
///< Instructions needing backpatching
List
<
bp_t
>
m_backpatch
;
///< Instructions needing backpatching
List
<
bp_t
>
m_backpatch_goto
;
// Instructions needing backpatching (for goto)
/**
/**
We need a special list for backpatching of instructions with a continue
We need a special list for backpatching of instructions with a continue
destination (in the case of a continue handler catching an error in
destination (in the case of a continue handler catching an error in
...
@@ -738,6 +751,12 @@ class sp_head :private Query_arena,
...
@@ -738,6 +751,12 @@ class sp_head :private Query_arena,
by routine.
by routine.
*/
*/
bool
merge_table_list
(
THD
*
thd
,
TABLE_LIST
*
table
,
LEX
*
lex_for_tmp_check
);
bool
merge_table_list
(
THD
*
thd
,
TABLE_LIST
*
table
,
LEX
*
lex_for_tmp_check
);
/// Put the instruction on the a backpatch list, associated with the label.
int
push_backpatch
(
THD
*
thd
,
sp_instr
*
,
sp_label
*
,
List
<
bp_t
>
*
list
,
backpatch_instr_type
itype
);
}
;
// class sp_head : public Sql_alloc
}
;
// class sp_head : public Sql_alloc
...
@@ -1359,6 +1378,11 @@ class sp_instr_hpop : public sp_instr
...
@@ -1359,6 +1378,11 @@ class sp_instr_hpop : public sp_instr
virtual
~
sp_instr_hpop
()
virtual
~
sp_instr_hpop
()
{}
{}
void
update_count
(
uint
count
)
{
m_count
=
count
;
}
virtual
int
execute
(
THD
*
thd
,
uint
*
nextp
);
virtual
int
execute
(
THD
*
thd
,
uint
*
nextp
);
virtual
void
print
(
String
*
str
);
virtual
void
print
(
String
*
str
);
...
@@ -1451,6 +1475,11 @@ class sp_instr_cpop : public sp_instr
...
@@ -1451,6 +1475,11 @@ class sp_instr_cpop : public sp_instr
virtual
~
sp_instr_cpop
()
virtual
~
sp_instr_cpop
()
{}
{}
void
update_count
(
uint
count
)
{
m_count
=
count
;
}
virtual
int
execute
(
THD
*
thd
,
uint
*
nextp
);
virtual
int
execute
(
THD
*
thd
,
uint
*
nextp
);
virtual
void
print
(
String
*
str
);
virtual
void
print
(
String
*
str
);
...
...
sql/sp_pcontext.cc
View file @
af7f287b
...
@@ -87,6 +87,7 @@ void sp_pcontext::init(uint var_offset,
...
@@ -87,6 +87,7 @@ void sp_pcontext::init(uint var_offset,
m_num_case_exprs
=
num_case_expressions
;
m_num_case_exprs
=
num_case_expressions
;
m_labels
.
empty
();
m_labels
.
empty
();
m_goto_labels
.
empty
();
}
}
...
@@ -129,6 +130,12 @@ sp_pcontext *sp_pcontext::push_context(THD *thd, sp_pcontext::enum_scope scope)
...
@@ -129,6 +130,12 @@ sp_pcontext *sp_pcontext::push_context(THD *thd, sp_pcontext::enum_scope scope)
}
}
bool
cmp_labels
(
sp_label
*
a
,
sp_label
*
b
)
{
return
(
my_strcasecmp
(
system_charset_info
,
a
->
name
.
str
,
b
->
name
.
str
)
==
0
&&
a
->
type
==
b
->
type
);
}
sp_pcontext
*
sp_pcontext
::
pop_context
()
sp_pcontext
*
sp_pcontext
::
pop_context
()
{
{
m_parent
->
m_max_var_index
+=
m_max_var_index
;
m_parent
->
m_max_var_index
+=
m_max_var_index
;
...
@@ -140,6 +147,18 @@ sp_pcontext *sp_pcontext::pop_context()
...
@@ -140,6 +147,18 @@ sp_pcontext *sp_pcontext::pop_context()
if
(
m_num_case_exprs
>
m_parent
->
m_num_case_exprs
)
if
(
m_num_case_exprs
>
m_parent
->
m_num_case_exprs
)
m_parent
->
m_num_case_exprs
=
m_num_case_exprs
;
m_parent
->
m_num_case_exprs
=
m_num_case_exprs
;
/*
** Push unresolved goto label to parent context
*/
sp_label
*
label
;
List_iterator_fast
<
sp_label
>
li
(
m_goto_labels
);
while
((
label
=
li
++
))
{
if
(
label
->
ip
==
0
)
{
m_parent
->
m_goto_labels
.
add_unique
(
label
,
&
cmp_labels
);
}
}
return
m_parent
;
return
m_parent
;
}
}
...
@@ -227,9 +246,9 @@ sp_variable *sp_pcontext::add_variable(THD *thd, LEX_STRING name)
...
@@ -227,9 +246,9 @@ sp_variable *sp_pcontext::add_variable(THD *thd, LEX_STRING name)
return
m_vars
.
append
(
p
)
?
NULL
:
p
;
return
m_vars
.
append
(
p
)
?
NULL
:
p
;
}
}
sp_label
*
sp_pcontext
::
push_label
(
THD
*
thd
,
LEX_STRING
name
,
uint
ip
,
sp_label
*
sp_pcontext
::
push_label
(
THD
*
thd
,
LEX_STRING
name
,
uint
ip
,
sp_label
::
enum_type
type
)
sp_label
::
enum_type
type
,
List
<
sp_label
>
*
list
)
{
{
sp_label
*
label
=
sp_label
*
label
=
new
(
thd
->
mem_root
)
sp_label
(
name
,
ip
,
type
,
this
);
new
(
thd
->
mem_root
)
sp_label
(
name
,
ip
,
type
,
this
);
...
@@ -237,11 +256,47 @@ sp_label *sp_pcontext::push_label(THD *thd, LEX_STRING name, uint ip,
...
@@ -237,11 +256,47 @@ sp_label *sp_pcontext::push_label(THD *thd, LEX_STRING name, uint ip,
if
(
!
label
)
if
(
!
label
)
return
NULL
;
return
NULL
;
m_labels
.
push_front
(
label
,
thd
->
mem_root
);
list
->
push_front
(
label
,
thd
->
mem_root
);
return
label
;
return
label
;
}
}
sp_label
*
sp_pcontext
::
find_goto_label
(
const
LEX_STRING
name
,
bool
recusive
)
{
List_iterator_fast
<
sp_label
>
li
(
m_goto_labels
);
sp_label
*
lab
;
while
((
lab
=
li
++
))
{
if
(
my_strcasecmp
(
system_charset_info
,
name
.
str
,
lab
->
name
.
str
)
==
0
)
return
lab
;
}
if
(
!
recusive
)
return
NULL
;
/*
Note about exception handlers.
See SQL:2003 SQL/PSM (ISO/IEC 9075-4:2003),
section 13.1 <compound statement>,
syntax rule 4.
In short, a DECLARE HANDLER block can not refer
to labels from the parent context, as they are out of scope.
*/
if
(
m_scope
==
HANDLER_SCOPE
&&
m_parent
)
{
if
(
m_parent
->
m_parent
)
{
// Skip the parent context
return
m_parent
->
m_parent
->
find_goto_label
(
name
);
}
}
return
m_parent
&&
(
m_scope
==
REGULAR_SCOPE
)
?
m_parent
->
find_goto_label
(
name
)
:
NULL
;
}
sp_label
*
sp_pcontext
::
find_label
(
const
LEX_STRING
name
)
sp_label
*
sp_pcontext
::
find_label
(
const
LEX_STRING
name
)
{
{
...
...
sql/sp_pcontext.h
View file @
af7f287b
...
@@ -94,6 +94,7 @@ class sp_variable : public Sql_alloc
...
@@ -94,6 +94,7 @@ class sp_variable : public Sql_alloc
/// IF/WHILE/REPEAT/LOOP, when such statement is rewritten into a
/// IF/WHILE/REPEAT/LOOP, when such statement is rewritten into a
/// combination of low-level jump/jump_if instructions and labels.
/// combination of low-level jump/jump_if instructions and labels.
class
sp_label
:
public
Sql_alloc
class
sp_label
:
public
Sql_alloc
{
{
public:
public:
...
@@ -106,7 +107,10 @@ class sp_label : public Sql_alloc
...
@@ -106,7 +107,10 @@ class sp_label : public Sql_alloc
BEGIN
,
BEGIN
,
/// Label at iteration control
/// Label at iteration control
ITERATION
ITERATION
,
/// Label for jump
GOTO
};
};
/// Name of the label.
/// Name of the label.
...
@@ -132,6 +136,7 @@ class sp_label : public Sql_alloc
...
@@ -132,6 +136,7 @@ class sp_label : public Sql_alloc
{
}
{
}
};
};
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
/// This class represents condition-value term in DECLARE CONDITION or
/// This class represents condition-value term in DECLARE CONDITION or
...
@@ -507,15 +512,29 @@ class sp_pcontext : public Sql_alloc
...
@@ -507,15 +512,29 @@ class sp_pcontext : public Sql_alloc
/////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////
sp_label
*
push_label
(
THD
*
thd
,
const
LEX_STRING
name
,
uint
ip
,
sp_label
*
push_label
(
THD
*
thd
,
const
LEX_STRING
name
,
uint
ip
,
sp_label
::
enum_type
type
);
sp_label
::
enum_type
type
,
List
<
sp_label
>
*
list
);
sp_label
*
push_label
(
THD
*
thd
,
LEX_STRING
name
,
uint
ip
,
sp_label
::
enum_type
type
)
{
return
push_label
(
thd
,
name
,
ip
,
type
,
&
m_labels
);
}
sp_label
*
push_goto_label
(
THD
*
thd
,
LEX_STRING
name
,
uint
ip
,
sp_label
::
enum_type
type
)
{
return
push_label
(
thd
,
name
,
ip
,
type
,
&
m_goto_labels
);
}
sp_label
*
push_label
(
THD
*
thd
,
const
LEX_STRING
name
,
uint
ip
)
sp_label
*
push_label
(
THD
*
thd
,
const
LEX_STRING
name
,
uint
ip
)
{
{
return
push_label
(
thd
,
name
,
ip
,
sp_label
::
IMPLICIT
);
}
return
push_label
(
thd
,
name
,
ip
,
sp_label
::
IMPLICIT
);
}
sp_label
*
push_goto_label
(
THD
*
thd
,
const
LEX_STRING
name
,
uint
ip
)
{
return
push_goto_label
(
thd
,
name
,
ip
,
sp_label
::
GOTO
);
}
sp_label
*
find_label
(
const
LEX_STRING
name
);
sp_label
*
find_label
(
const
LEX_STRING
name
);
sp_label
*
find_goto_label
(
const
LEX_STRING
name
,
bool
recusive
);
sp_label
*
find_goto_label
(
const
LEX_STRING
name
)
{
return
find_goto_label
(
name
,
true
);
}
sp_label
*
find_label_current_loop_start
();
sp_label
*
find_label_current_loop_start
();
sp_label
*
last_label
()
sp_label
*
last_label
()
...
@@ -528,6 +547,11 @@ class sp_pcontext : public Sql_alloc
...
@@ -528,6 +547,11 @@ class sp_pcontext : public Sql_alloc
return
label
;
return
label
;
}
}
sp_label
*
last_goto_label
()
{
return
m_goto_labels
.
head
();
}
sp_label
*
pop_label
()
sp_label
*
pop_label
()
{
return
m_labels
.
pop
();
}
{
return
m_labels
.
pop
();
}
...
@@ -697,8 +721,27 @@ class sp_pcontext : public Sql_alloc
...
@@ -697,8 +721,27 @@ class sp_pcontext : public Sql_alloc
/// Stack of SQL-handlers.
/// Stack of SQL-handlers.
Dynamic_array
<
sp_handler
*>
m_handlers
;
Dynamic_array
<
sp_handler
*>
m_handlers
;
/// List of labels.
/*
In the below example the label <<lab>> has two meanings:
- GOTO lab : must go before the beginning of the loop
- CONTINUE lab : must go to the beginning of the loop
We solve this by storing block labels and goto labels into separate lists.
BEGIN
<<lab>>
FOR i IN a..10 LOOP
...
GOTO lab;
...
CONTINUE lab;
...
END LOOP;
END;
*/
/// List of block labels
List
<
sp_label
>
m_labels
;
List
<
sp_label
>
m_labels
;
/// List of goto labels
List
<
sp_label
>
m_goto_labels
;
/// Children contexts, used for destruction.
/// Children contexts, used for destruction.
Dynamic_array
<
sp_pcontext
*>
m_children
;
Dynamic_array
<
sp_pcontext
*>
m_children
;
...
...
sql/sql_lex.cc
View file @
af7f287b
...
@@ -5704,6 +5704,54 @@ bool LEX::sp_leave_statement(THD *thd, const LEX_STRING label_name)
...
@@ -5704,6 +5704,54 @@ bool LEX::sp_leave_statement(THD *thd, const LEX_STRING label_name)
return
sp_exit_block
(
thd
,
lab
,
NULL
);
return
sp_exit_block
(
thd
,
lab
,
NULL
);
}
}
bool
LEX
::
sp_goto_statement
(
THD
*
thd
,
const
LEX_STRING
label_name
)
{
sp_label
*
lab
=
spcont
->
find_goto_label
(
label_name
);
if
(
!
lab
||
lab
->
ip
==
0
)
{
sp_label
*
delayedlabel
;
if
(
!
lab
)
{
// Label not found --> add forward jump to an unknown label
spcont
->
push_goto_label
(
thd
,
label_name
,
0
,
sp_label
::
GOTO
);
delayedlabel
=
spcont
->
last_goto_label
();
}
else
{
delayedlabel
=
lab
;
}
return
sphead
->
push_backpatch_goto
(
thd
,
spcont
,
delayedlabel
);
}
else
{
// Label found (backward goto)
return
sp_change_context
(
thd
,
lab
->
ctx
,
false
)
||
sphead
->
add_instr_jump
(
thd
,
spcont
,
lab
->
ip
);
/* Jump back */
}
return
false
;
}
bool
LEX
::
sp_push_goto_label
(
THD
*
thd
,
const
LEX_STRING
label_name
)
{
sp_label
*
lab
=
spcont
->
find_goto_label
(
label_name
,
false
);
if
(
lab
)
{
if
(
lab
->
ip
!=
0
)
{
my_error
(
ER_SP_LABEL_REDEFINE
,
MYF
(
0
),
label_name
.
str
);
return
true
;
}
lab
->
ip
=
sphead
->
instructions
();
sp_label
*
beginblocklabel
=
spcont
->
find_label
(
empty_lex_str
);
sphead
->
backpatch_goto
(
thd
,
lab
,
beginblocklabel
);
}
else
{
spcont
->
push_goto_label
(
thd
,
label_name
,
sphead
->
instructions
());
}
return
false
;
}
bool
LEX
::
sp_exit_block
(
THD
*
thd
,
sp_label
*
lab
)
bool
LEX
::
sp_exit_block
(
THD
*
thd
,
sp_label
*
lab
)
{
{
...
...
sql/sql_lex.h
View file @
af7f287b
...
@@ -3317,6 +3317,7 @@ struct LEX: public Query_tables_list
...
@@ -3317,6 +3317,7 @@ struct LEX: public Query_tables_list
bool
sp_exit_statement
(
THD
*
thd
,
Item
*
when
);
bool
sp_exit_statement
(
THD
*
thd
,
Item
*
when
);
bool
sp_exit_statement
(
THD
*
thd
,
const
LEX_STRING
label_name
,
Item
*
item
);
bool
sp_exit_statement
(
THD
*
thd
,
const
LEX_STRING
label_name
,
Item
*
item
);
bool
sp_leave_statement
(
THD
*
thd
,
const
LEX_STRING
label_name
);
bool
sp_leave_statement
(
THD
*
thd
,
const
LEX_STRING
label_name
);
bool
sp_goto_statement
(
THD
*
thd
,
const
LEX_STRING
label_name
);
bool
sp_continue_statement
(
THD
*
thd
,
Item
*
when
);
bool
sp_continue_statement
(
THD
*
thd
,
Item
*
when
);
bool
sp_continue_statement
(
THD
*
thd
,
const
LEX_STRING
label_name
,
Item
*
when
);
bool
sp_continue_statement
(
THD
*
thd
,
const
LEX_STRING
label_name
,
Item
*
when
);
...
@@ -3329,6 +3330,7 @@ struct LEX: public Query_tables_list
...
@@ -3329,6 +3330,7 @@ struct LEX: public Query_tables_list
void
sp_pop_loop_empty_label
(
THD
*
thd
);
void
sp_pop_loop_empty_label
(
THD
*
thd
);
bool
sp_while_loop_expression
(
THD
*
thd
,
Item
*
expr
);
bool
sp_while_loop_expression
(
THD
*
thd
,
Item
*
expr
);
bool
sp_while_loop_finalize
(
THD
*
thd
);
bool
sp_while_loop_finalize
(
THD
*
thd
);
bool
sp_push_goto_label
(
THD
*
thd
,
LEX_STRING
label_name
);
Item_param
*
add_placeholder
(
THD
*
thd
,
char
*
name
,
Item_param
*
add_placeholder
(
THD
*
thd
,
char
*
name
,
uint
pos_in_query
,
uint
len_in_query
);
uint
pos_in_query
,
uint
len_in_query
);
...
...
sql/sql_yacc.yy
View file @
af7f287b
...
@@ -1098,6 +1098,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
...
@@ -1098,6 +1098,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token GET_FORMAT /* MYSQL-FUNC */
%token GET_FORMAT /* MYSQL-FUNC */
%token GET_SYM /* SQL-2003-R */
%token GET_SYM /* SQL-2003-R */
%token GLOBAL_SYM /* SQL-2003-R */
%token GLOBAL_SYM /* SQL-2003-R */
%token GOTO_SYM /* Oracle, reserved in PL/SQL*/
%token GRANT /* SQL-2003-R */
%token GRANT /* SQL-2003-R */
%token GRANTS
%token GRANTS
%token GROUP_SYM /* SQL-2003-R */
%token GROUP_SYM /* SQL-2003-R */
...
@@ -14288,6 +14289,7 @@ keyword_sp:
...
@@ -14288,6 +14289,7 @@ keyword_sp:
| GET_FORMAT {}
| GET_FORMAT {}
| GRANTS {}
| GRANTS {}
| GLOBAL_SYM {}
| GLOBAL_SYM {}
| GOTO_SYM {}
| HASH_SYM {}
| HASH_SYM {}
| HARD_SYM {}
| HARD_SYM {}
| HOSTS_SYM {}
| HOSTS_SYM {}
...
...
sql/sql_yacc_ora.yy
View file @
af7f287b
...
@@ -516,6 +516,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
...
@@ -516,6 +516,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token GET_FORMAT /* MYSQL-FUNC */
%token GET_FORMAT /* MYSQL-FUNC */
%token GET_SYM /* SQL-2003-R */
%token GET_SYM /* SQL-2003-R */
%token GLOBAL_SYM /* SQL-2003-R */
%token GLOBAL_SYM /* SQL-2003-R */
%token GOTO_SYM /* Oracle, reserved in PL/SQL*/
%token GRANT /* SQL-2003-R */
%token GRANT /* SQL-2003-R */
%token GRANTS
%token GRANTS
%token GROUP_SYM /* SQL-2003-R */
%token GROUP_SYM /* SQL-2003-R */
...
@@ -1005,7 +1006,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
...
@@ -1005,7 +1006,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
opt_component key_cache_name
opt_component key_cache_name
sp_opt_label BIN_NUM label_ident TEXT_STRING_filesystem ident_or_empty
sp_opt_label BIN_NUM label_ident TEXT_STRING_filesystem ident_or_empty
opt_constraint constraint opt_ident
opt_constraint constraint opt_ident
label_declaration_oracle ident_directly_assignable
label_declaration_oracle labels_declaration_oracle
ident_directly_assignable
sp_decl_ident
sp_decl_ident
sp_block_label
sp_block_label
...
@@ -1307,15 +1309,16 @@ END_OF_INPUT
...
@@ -1307,15 +1309,16 @@ END_OF_INPUT
%type <NONE> call sp_proc_stmts sp_proc_stmts1 sp_proc_stmt
%type <NONE> call sp_proc_stmts sp_proc_stmts1 sp_proc_stmt
%type <NONE> sp_proc_stmt_statement sp_proc_stmt_return
%type <NONE> sp_proc_stmt_statement sp_proc_stmt_return
sp_proc_stmt_in_returns_clause
%type <NONE> sp_proc_stmt_compound_ok
%type <NONE> sp_proc_stmt_compound_ok
%type <NONE> sp_proc_stmt_if
%type <NONE> sp_proc_stmt_if
%type <NONE> sp_labeled_control sp_unlabeled_control
%type <NONE> sp_labeled_control sp_unlabeled_control
%type <NONE> sp_labeled_block sp_unlabeled_block
%type <NONE> sp_labeled_block sp_unlabeled_block
%type <NONE> sp_labelable_stmt
%type <NONE> sp_proc_stmt_continue
%type <NONE> sp_proc_stmt_continue
%type <NONE> sp_proc_stmt_exit
%type <NONE> sp_proc_stmt_exit
%type <NONE> sp_proc_stmt_leave
%type <NONE> sp_proc_stmt_leave
%type <NONE> sp_proc_stmt_iterate
%type <NONE> sp_proc_stmt_iterate
%type <NONE> sp_proc_stmt_goto
%type <NONE> sp_proc_stmt_open sp_proc_stmt_fetch sp_proc_stmt_close
%type <NONE> sp_proc_stmt_open sp_proc_stmt_fetch sp_proc_stmt_close
%type <NONE> case_stmt_specification
%type <NONE> case_stmt_specification
%type <NONE> loop_body while_body repeat_body
%type <NONE> loop_body while_body repeat_body
...
@@ -2425,6 +2428,17 @@ sp_proc_stmts1:
...
@@ -2425,6 +2428,17 @@ sp_proc_stmts1:
| sp_proc_stmts1 sp_proc_stmt ';'
| sp_proc_stmts1 sp_proc_stmt ';'
;
;
sp_proc_stmts1_implicit_block:
{
Lex->sp_block_init(thd);
}
sp_proc_stmts1
{
if (Lex->sp_block_finalize(thd))
MYSQL_YYABORT;
}
;
opt_sp_decl_body_list:
opt_sp_decl_body_list:
/* Empty */
/* Empty */
{
{
...
@@ -3034,32 +3048,28 @@ sp_opt_default:
...
@@ -3034,32 +3048,28 @@ sp_opt_default:
| SET_VAR expr { $$ = $2; }
| SET_VAR expr { $$ = $2; }
;
;
/*
sp_proc_stmt:
ps_proc_stmt_in_returns_clause is a statement that is allowed
sp_labeled_block
in the RETURNS clause of a stored function definition directly,
| sp_unlabeled_block
without the BEGIN..END block.
It should not include any syntax structures starting with '(', to avoid
shift/reduce conflicts with the rule "field_type" and its sub-rules
that scan an optional length, like CHAR(1) or YEAR(4).
See MDEV-9166.
*/
sp_proc_stmt_in_returns_clause:
sp_proc_stmt_return
| sp_labeled_block
| sp_labeled_control
| sp_labeled_control
| sp_proc_stmt_compound_ok
| sp_unlabeled_control
| sp_labelable_stmt
| labels_declaration_oracle sp_labelable_stmt {}
;
;
sp_proc_stmt:
sp_labelable_stmt:
sp_proc_stmt_in_returns_clause
sp_proc_stmt_statement
| sp_proc_stmt_statement
| sp_proc_stmt_continue
| sp_proc_stmt_continue
| sp_proc_stmt_exit
| sp_proc_stmt_exit
| sp_proc_stmt_leave
| sp_proc_stmt_leave
| sp_proc_stmt_iterate
| sp_proc_stmt_iterate
| sp_proc_stmt_goto
| sp_proc_stmt_open
| sp_proc_stmt_open
| sp_proc_stmt_fetch
| sp_proc_stmt_fetch
| sp_proc_stmt_close
| sp_proc_stmt_close
| sp_proc_stmt_return
| sp_proc_stmt_if
| case_stmt_specification
| NULL_SYM { }
| NULL_SYM { }
;
;
...
@@ -3245,6 +3255,15 @@ sp_proc_stmt_iterate:
...
@@ -3245,6 +3255,15 @@ sp_proc_stmt_iterate:
}
}
;
;
sp_proc_stmt_goto:
GOTO_SYM label_ident
{
if (Lex->sp_goto_statement(thd, $2))
MYSQL_YYABORT;
}
;
remember_lex:
remember_lex:
{
{
$$= thd->lex;
$$= thd->lex;
...
@@ -3396,7 +3415,7 @@ sp_if:
...
@@ -3396,7 +3415,7 @@ sp_if:
if (sp->restore_lex(thd))
if (sp->restore_lex(thd))
MYSQL_YYABORT;
MYSQL_YYABORT;
}
}
sp_proc_stmts1
sp_proc_stmts1
_implicit_block
{
{
sp_head *sp= Lex->sphead;
sp_head *sp= Lex->sphead;
sp_pcontext *ctx= Lex->spcont;
sp_pcontext *ctx= Lex->spcont;
...
@@ -3419,7 +3438,7 @@ sp_if:
...
@@ -3419,7 +3438,7 @@ sp_if:
sp_elseifs:
sp_elseifs:
/* Empty */
/* Empty */
| ELSIF_SYM sp_if
| ELSIF_SYM sp_if
| ELSE sp_proc_stmts1
| ELSE sp_proc_stmts1
_implicit_block
;
;
case_stmt_specification:
case_stmt_specification:
...
@@ -3535,7 +3554,7 @@ simple_when_clause:
...
@@ -3535,7 +3554,7 @@ simple_when_clause:
MYSQL_YYABORT;
MYSQL_YYABORT;
}
}
THEN_SYM
THEN_SYM
sp_proc_stmts1
sp_proc_stmts1
_implicit_block
{
{
if (Lex->case_stmt_action_then())
if (Lex->case_stmt_action_then())
MYSQL_YYABORT;
MYSQL_YYABORT;
...
@@ -3557,7 +3576,7 @@ searched_when_clause:
...
@@ -3557,7 +3576,7 @@ searched_when_clause:
MYSQL_YYABORT;
MYSQL_YYABORT;
}
}
THEN_SYM
THEN_SYM
sp_proc_stmts1
sp_proc_stmts1
_implicit_block
{
{
if (Lex->case_stmt_action_then())
if (Lex->case_stmt_action_then())
MYSQL_YYABORT;
MYSQL_YYABORT;
...
@@ -3576,7 +3595,7 @@ else_clause_opt:
...
@@ -3576,7 +3595,7 @@ else_clause_opt:
sp->add_instr(i))
sp->add_instr(i))
MYSQL_YYABORT;
MYSQL_YYABORT;
}
}
| ELSE sp_proc_stmts1
| ELSE sp_proc_stmts1
_implicit_block
;
;
sp_opt_label:
sp_opt_label:
...
@@ -3585,7 +3604,7 @@ sp_opt_label:
...
@@ -3585,7 +3604,7 @@ sp_opt_label:
;
;
sp_block_label:
sp_block_label:
label_declaration_oracle
label
s
_declaration_oracle
{
{
if (Lex->spcont->block_label_declare($1))
if (Lex->spcont->block_label_declare($1))
MYSQL_YYABORT;
MYSQL_YYABORT;
...
@@ -3819,14 +3838,14 @@ pop_sp_loop_label:
...
@@ -3819,14 +3838,14 @@ pop_sp_loop_label:
;
;
sp_labeled_control:
sp_labeled_control:
label_declaration_oracle LOOP_SYM
label
s
_declaration_oracle LOOP_SYM
{
{
if (Lex->sp_push_loop_label(thd, $1))
if (Lex->sp_push_loop_label(thd, $1))
MYSQL_YYABORT;
MYSQL_YYABORT;
}
}
loop_body pop_sp_loop_label
loop_body pop_sp_loop_label
{ }
{ }
| label_declaration_oracle WHILE_SYM
| label
s
_declaration_oracle WHILE_SYM
{
{
if (Lex->sp_push_loop_label(thd, $1))
if (Lex->sp_push_loop_label(thd, $1))
MYSQL_YYABORT;
MYSQL_YYABORT;
...
@@ -3834,7 +3853,7 @@ sp_labeled_control:
...
@@ -3834,7 +3853,7 @@ sp_labeled_control:
}
}
while_body pop_sp_loop_label
while_body pop_sp_loop_label
{ }
{ }
| label_declaration_oracle FOR_SYM
| label
s
_declaration_oracle FOR_SYM
{
{
// See "The FOR LOOP statement" comments in sql_lex.cc
// See "The FOR LOOP statement" comments in sql_lex.cc
Lex->sp_block_init(thd); // The outer DECLARE..BEGIN..END block
Lex->sp_block_init(thd); // The outer DECLARE..BEGIN..END block
...
@@ -3858,7 +3877,7 @@ sp_labeled_control:
...
@@ -3858,7 +3877,7 @@ sp_labeled_control:
if (Lex->sp_block_finalize(thd)) // The outer DECLARE..BEGIN..END
if (Lex->sp_block_finalize(thd)) // The outer DECLARE..BEGIN..END
MYSQL_YYABORT;
MYSQL_YYABORT;
}
}
| label_declaration_oracle REPEAT_SYM
| label
s
_declaration_oracle REPEAT_SYM
{
{
if (Lex->sp_push_loop_label(thd, $1))
if (Lex->sp_push_loop_label(thd, $1))
MYSQL_YYABORT;
MYSQL_YYABORT;
...
@@ -14188,8 +14207,18 @@ label_ident:
...
@@ -14188,8 +14207,18 @@ label_ident:
}
}
;
;
labels_declaration_oracle:
label_declaration_oracle { $$= $1; }
| labels_declaration_oracle label_declaration_oracle { $$= $2; }
;
label_declaration_oracle:
label_declaration_oracle:
SHIFT_LEFT label_ident SHIFT_RIGHT { $$= $2; }
SHIFT_LEFT label_ident SHIFT_RIGHT
{
if (Lex->sp_push_goto_label(thd, $2))
MYSQL_YYABORT;
$$= $2;
}
;
;
ident_or_text:
ident_or_text:
...
@@ -16434,6 +16463,8 @@ trigger_tail:
...
@@ -16434,6 +16463,8 @@ trigger_tail:
{ /* $21 */
{ /* $21 */
LEX *lex= Lex;
LEX *lex= Lex;
sp_head *sp= lex->sphead;
sp_head *sp= lex->sphead;
if (sp->check_unresolved_goto())
MYSQL_YYABORT;
lex->sql_command= SQLCOM_CREATE_TRIGGER;
lex->sql_command= SQLCOM_CREATE_TRIGGER;
sp->set_stmt_end(thd);
sp->set_stmt_end(thd);
...
@@ -16517,6 +16548,8 @@ sf_tail:
...
@@ -16517,6 +16548,8 @@ sf_tail:
{
{
LEX *lex= thd->lex;
LEX *lex= thd->lex;
sp_head *sp= lex->sphead;
sp_head *sp= lex->sphead;
if (sp->check_unresolved_goto())
MYSQL_YYABORT;
if (sp->is_not_allowed_in_function("function"))
if (sp->is_not_allowed_in_function("function"))
MYSQL_YYABORT;
MYSQL_YYABORT;
...
@@ -16549,7 +16582,8 @@ sp_tail:
...
@@ -16549,7 +16582,8 @@ sp_tail:
{
{
LEX *lex= Lex;
LEX *lex= Lex;
sp_head *sp= lex->sphead;
sp_head *sp= lex->sphead;
if (sp->check_unresolved_goto())
MYSQL_YYABORT;
sp->set_stmt_end(thd);
sp->set_stmt_end(thd);
lex->sql_command= SQLCOM_CREATE_PROCEDURE;
lex->sql_command= SQLCOM_CREATE_PROCEDURE;
sp->restore_thd_mem_root(thd);
sp->restore_thd_mem_root(thd);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment