summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <pem@mysql.comhem.se>2004-08-26 12:54:30 +0200
committerunknown <pem@mysql.comhem.se>2004-08-26 12:54:30 +0200
commit071651efbd5d910047f458121ca1222428d7aa58 (patch)
treee80e61a8c32e018499a7a29eacd653c2d0fd2fbd /sql
parentac06195caa5176a0245e635bb7678413c26cb7ab (diff)
downloadmariadb-git-071651efbd5d910047f458121ca1222428d7aa58.tar.gz
Major rehacking and cleanup of sp_pcontext.
This finishes (almost) WL#2002: Implement stored procedure GOTO. Only the syntax issue for free labels remains ("label L;" vs "L:"). include/mysqld_error.h: New error code for GOTO in SP handler. mysql-test/r/sp-error.result: New error test cases for GOTO. mysql-test/r/sp.result: New test cases for GOTO. Also removed some things that made it impossible to run the test in an external (debugged) mysqld. mysql-test/t/sp-error.test: New error test cases for GOTO. mysql-test/t/sp.test: New test cases for GOTO. Also removed some things that made it impossible to run the test in an external (debugged) mysqld. sql/share/czech/errmsg.txt: New error message for GOTO in SP handler. sql/share/danish/errmsg.txt: New error message for GOTO in SP handler. sql/share/dutch/errmsg.txt: New error message for GOTO in SP handler. sql/share/english/errmsg.txt: New error message for GOTO in SP handler. sql/share/estonian/errmsg.txt: New error message for GOTO in SP handler. sql/share/french/errmsg.txt: New error message for GOTO in SP handler. sql/share/german/errmsg.txt: New error message for GOTO in SP handler. sql/share/greek/errmsg.txt: New error message for GOTO in SP handler. sql/share/hungarian/errmsg.txt: New error message for GOTO in SP handler. sql/share/italian/errmsg.txt: New error message for GOTO in SP handler. sql/share/japanese/errmsg.txt: New error message for GOTO in SP handler. sql/share/korean/errmsg.txt: New error message for GOTO in SP handler. sql/share/norwegian-ny/errmsg.txt: New error message for GOTO in SP handler. sql/share/norwegian/errmsg.txt: New error message for GOTO in SP handler. sql/share/polish/errmsg.txt: New error message for GOTO in SP handler. sql/share/portuguese/errmsg.txt: New error message for GOTO in SP handler. sql/share/romanian/errmsg.txt: New error message for GOTO in SP handler. sql/share/russian/errmsg.txt: New error message for GOTO in SP handler. sql/share/serbian/errmsg.txt: New error message for GOTO in SP handler. sql/share/slovak/errmsg.txt: New error message for GOTO in SP handler. sql/share/spanish/errmsg.txt: New error message for GOTO in SP handler. sql/share/swedish/errmsg.txt: New error message for GOTO in SP handler. sql/share/ukrainian/errmsg.txt: New error message for GOTO in SP handler. sql/sp_head.cc: Code cleanup (renaming of pcontext methods), support goto, and fixed bug in jump shortcutting in the optimizer (detect infinite loops). sql/sp_head.h: Code cleanup (renaming of pcontext methods), support goto, and fixed bug in jump shortcutting in the optimizer (detect infinite loops). sql/sp_pcontext.cc: Major rehack and cleanup: - We now push and pop a chain of contexts during parsing (instead of having a single one). - Makes error detection for GOTO easier and enables some optmizations and debugger support. - Makes it a little trickier to keep track on variable and cursor indexes instead. - Renamed things to get a more consistent naming scheme too. sql/sp_pcontext.h: Major rehack and cleanup: - We now push and pop a chain of contexts during parsing (instead of having a single one). - Makes error detection for GOTO easier and enables some optmizations and debugger support. - Makes it a little trickier to keep track on variable and cursor indexes instead. - Renamed things to get a more consistent naming scheme too. sql/sql_yacc.yy: Changes to reflect the rework and renamings in sp_pcontext, and fixed some GOTO error checking.
Diffstat (limited to 'sql')
-rw-r--r--sql/share/czech/errmsg.txt1
-rw-r--r--sql/share/danish/errmsg.txt1
-rw-r--r--sql/share/dutch/errmsg.txt1
-rw-r--r--sql/share/english/errmsg.txt1
-rw-r--r--sql/share/estonian/errmsg.txt1
-rw-r--r--sql/share/french/errmsg.txt1
-rw-r--r--sql/share/german/errmsg.txt1
-rw-r--r--sql/share/greek/errmsg.txt1
-rw-r--r--sql/share/hungarian/errmsg.txt1
-rw-r--r--sql/share/italian/errmsg.txt1
-rw-r--r--sql/share/japanese/errmsg.txt1
-rw-r--r--sql/share/korean/errmsg.txt1
-rw-r--r--sql/share/norwegian-ny/errmsg.txt1
-rw-r--r--sql/share/norwegian/errmsg.txt1
-rw-r--r--sql/share/polish/errmsg.txt1
-rw-r--r--sql/share/portuguese/errmsg.txt1
-rw-r--r--sql/share/romanian/errmsg.txt1
-rw-r--r--sql/share/russian/errmsg.txt1
-rw-r--r--sql/share/serbian/errmsg.txt1
-rw-r--r--sql/share/slovak/errmsg.txt1
-rw-r--r--sql/share/spanish/errmsg.txt1
-rw-r--r--sql/share/swedish/errmsg.txt1
-rw-r--r--sql/share/ukrainian/errmsg.txt1
-rw-r--r--sql/sp_head.cc64
-rw-r--r--sql/sp_head.h111
-rw-r--r--sql/sp_pcontext.cc210
-rw-r--r--sql/sp_pcontext.h113
-rw-r--r--sql/sql_yacc.yy169
28 files changed, 337 insertions, 353 deletions
diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt
index 264bc38117a..9d1c429d5b6 100644
--- a/sql/share/czech/errmsg.txt
+++ b/sql/share/czech/errmsg.txt
@@ -369,3 +369,4 @@ character-set=latin2
"View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine"
+"GOTO is not allowed in a stored procedure handler"
diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt
index c0f915e0b53..b2d2fdf4d77 100644
--- a/sql/share/danish/errmsg.txt
+++ b/sql/share/danish/errmsg.txt
@@ -363,3 +363,4 @@ character-set=latin1
"View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine"
+"GOTO is not allowed in a stored procedure handler"
diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt
index 9bfca16ad54..85c0443869f 100644
--- a/sql/share/dutch/errmsg.txt
+++ b/sql/share/dutch/errmsg.txt
@@ -371,3 +371,4 @@ character-set=latin1
"View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine"
+"GOTO is not allowed in a stored procedure handler"
diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt
index c159e6b49c7..641f267d67e 100644
--- a/sql/share/english/errmsg.txt
+++ b/sql/share/english/errmsg.txt
@@ -360,3 +360,4 @@ character-set=latin1
"View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine"
+"GOTO is not allowed in a stored procedure handler"
diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt
index 4c679a2967a..e64c0c17e74 100644
--- a/sql/share/estonian/errmsg.txt
+++ b/sql/share/estonian/errmsg.txt
@@ -365,3 +365,4 @@ character-set=latin7
"View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine"
+"GOTO is not allowed in a stored procedure handler"
diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt
index 2f8cccbc6fb..f3443457346 100644
--- a/sql/share/french/errmsg.txt
+++ b/sql/share/french/errmsg.txt
@@ -360,3 +360,4 @@ character-set=latin1
"View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine"
+"GOTO is not allowed in a stored procedure handler"
diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt
index dc18cfa9b34..498a230faed 100644
--- a/sql/share/german/errmsg.txt
+++ b/sql/share/german/errmsg.txt
@@ -372,3 +372,4 @@ character-set=latin1
"View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine"
+"GOTO is not allowed in a stored procedure handler"
diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt
index b8cbe9b5a75..2827517ba9a 100644
--- a/sql/share/greek/errmsg.txt
+++ b/sql/share/greek/errmsg.txt
@@ -360,3 +360,4 @@ character-set=greek
"View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine"
+"GOTO is not allowed in a stored procedure handler"
diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt
index b7cc9fe34d7..fab0b156322 100644
--- a/sql/share/hungarian/errmsg.txt
+++ b/sql/share/hungarian/errmsg.txt
@@ -362,3 +362,4 @@ character-set=latin2
"View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine"
+"GOTO is not allowed in a stored procedure handler"
diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt
index 0c9576cab47..24634514a23 100644
--- a/sql/share/italian/errmsg.txt
+++ b/sql/share/italian/errmsg.txt
@@ -360,3 +360,4 @@ character-set=latin1
"View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine"
+"GOTO is not allowed in a stored procedure handler"
diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt
index d5ef9f22a56..68f2857aeca 100644
--- a/sql/share/japanese/errmsg.txt
+++ b/sql/share/japanese/errmsg.txt
@@ -362,3 +362,4 @@ character-set=ujis
"View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine"
+"GOTO is not allowed in a stored procedure handler"
diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt
index 4f03bedc717..70267c82364 100644
--- a/sql/share/korean/errmsg.txt
+++ b/sql/share/korean/errmsg.txt
@@ -360,3 +360,4 @@ character-set=euckr
"View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine"
+"GOTO is not allowed in a stored procedure handler"
diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt
index 821453e6119..1d84a3a5e5a 100644
--- a/sql/share/norwegian-ny/errmsg.txt
+++ b/sql/share/norwegian-ny/errmsg.txt
@@ -362,3 +362,4 @@ character-set=latin1
"View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine"
+"GOTO is not allowed in a stored procedure handler"
diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt
index 5a60042b19e..be881d54473 100644
--- a/sql/share/norwegian/errmsg.txt
+++ b/sql/share/norwegian/errmsg.txt
@@ -362,3 +362,4 @@ character-set=latin1
"View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine"
+"GOTO is not allowed in a stored procedure handler"
diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt
index 2f9f5b4bbce..8a576b5bf82 100644
--- a/sql/share/polish/errmsg.txt
+++ b/sql/share/polish/errmsg.txt
@@ -364,3 +364,4 @@ character-set=latin2
"View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine"
+"GOTO is not allowed in a stored procedure handler"
diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt
index 2a32c80138b..6794db726cc 100644
--- a/sql/share/portuguese/errmsg.txt
+++ b/sql/share/portuguese/errmsg.txt
@@ -361,3 +361,4 @@ character-set=latin1
"View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine"
+"GOTO is not allowed in a stored procedure handler"
diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt
index 211a0072934..9eaa4860b64 100644
--- a/sql/share/romanian/errmsg.txt
+++ b/sql/share/romanian/errmsg.txt
@@ -364,3 +364,4 @@ character-set=latin2
"View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine"
+"GOTO is not allowed in a stored procedure handler"
diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt
index 907cece485f..eec85d611fc 100644
--- a/sql/share/russian/errmsg.txt
+++ b/sql/share/russian/errmsg.txt
@@ -362,3 +362,4 @@ character-set=koi8r
"ïÂÎÏ×ÌÑÅÍÙÊ view ÎÅ ÓÏÄÅÒÖÉÔ ËÌÀÞÁ ÉÓÐÏÌØÚÏ×ÁÎÎÏÊ × ÎÅÍ ÔÁÂÌÉÃ(Ù)"
"View '%-.64s.%-.64s' ÓÓÙÌÁÅÔÓÑ ÎÁ ÎÅÓÕÝÅÓÔ×ÕÀÝÉÅ ÔÁÂÌÉÃÙ ÉÌÉ ÓÌÏÌÂÃÙ"
"Can't drop a %s from within another stored routine"
+"GOTO is not allowed in a stored procedure handler"
diff --git a/sql/share/serbian/errmsg.txt b/sql/share/serbian/errmsg.txt
index 5b74999a3cd..4039268f446 100644
--- a/sql/share/serbian/errmsg.txt
+++ b/sql/share/serbian/errmsg.txt
@@ -366,3 +366,4 @@ character-set=cp1250
"View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine"
+"GOTO is not allowed in a stored procedure handler"
diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt
index 5d7fce940e2..9be5ce01d6a 100644
--- a/sql/share/slovak/errmsg.txt
+++ b/sql/share/slovak/errmsg.txt
@@ -368,3 +368,4 @@ character-set=latin2
"View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine"
+"GOTO is not allowed in a stored procedure handler"
diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt
index 570da612be9..dc15f8b8d5e 100644
--- a/sql/share/spanish/errmsg.txt
+++ b/sql/share/spanish/errmsg.txt
@@ -362,3 +362,4 @@ character-set=latin1
"View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine"
+"GOTO is not allowed in a stored procedure handler"
diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt
index 4e97393b0b1..ee5436c3b80 100644
--- a/sql/share/swedish/errmsg.txt
+++ b/sql/share/swedish/errmsg.txt
@@ -360,3 +360,4 @@ character-set=latin1
"View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine"
+"GOTO is not allowed in a stored procedure handler"
diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt
index a043b6eb651..cb1d99e2fec 100644
--- a/sql/share/ukrainian/errmsg.txt
+++ b/sql/share/ukrainian/errmsg.txt
@@ -365,3 +365,4 @@ character-set=koi8u
"View, ÝÏ ÏÎÏ×ÌÀÅÔØÓÑ, ΊͦÓÔÉÔØ ÐÏ×ÎÏÇÏ ËÌÀÞÁ ÔÁÂÌÉæ(Ø), ÝÏ ×ÉËÏÒ¦ÓÔÁÎÁ × ÎØÀÏÍÕ"
"View '%-.64s.%-.64s' ÐÏÓÉÌÁ¤ÔÓÑ ÎÁ ÎŦÓÎÕÀÞ¦ ÔÁÂÌÉæ ÁÂÏ ÓÔÏ×Âæ"
"Can't drop a %s from within another stored routine"
+"GOTO is not allowed in a stored procedure handler"
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 5a58c32d2da..fd95767b7cd 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -257,7 +257,7 @@ sp_head::operator delete(void *ptr, size_t size)
sp_head::sp_head()
:Item_arena((bool)FALSE), m_returns_cs(NULL), m_has_return(FALSE),
- m_simple_case(FALSE), m_multi_results(FALSE)
+ m_simple_case(FALSE), m_multi_results(FALSE), m_in_handler(FALSE)
{
DBUG_ENTER("sp_head::sp_head");
@@ -272,7 +272,7 @@ sp_head::init(LEX *lex)
{
DBUG_ENTER("sp_head::init");
- lex->spcont= m_pcont= new sp_pcontext();
+ lex->spcont= m_pcont= new sp_pcontext(NULL);
my_init_dynamic_array(&m_instr, sizeof(sp_instr *), 16, 8);
m_param_begin= m_param_end= m_returns_begin= m_returns_end= m_body_begin= 0;
m_qname.str= m_db.str= m_name.str= m_params.str= m_retstr.str=
@@ -514,10 +514,10 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp)
{
DBUG_ENTER("sp_head::execute_function");
DBUG_PRINT("info", ("function %s", m_name.str));
- uint csize = m_pcont->max_framesize();
- uint params = m_pcont->params();
- uint hmax = m_pcont->handlers();
- uint cmax = m_pcont->cursors();
+ uint csize = m_pcont->max_pvars();
+ uint params = m_pcont->current_pvars();
+ uint hmax = m_pcont->max_handlers();
+ uint cmax = m_pcont->max_cursors();
sp_rcontext *octx = thd->spcont;
sp_rcontext *nctx = NULL;
uint i;
@@ -594,10 +594,10 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
DBUG_ENTER("sp_head::execute_procedure");
DBUG_PRINT("info", ("procedure %s", m_name.str));
int ret= 0;
- uint csize = m_pcont->max_framesize();
- uint params = m_pcont->params();
- uint hmax = m_pcont->handlers();
- uint cmax = m_pcont->cursors();
+ uint csize = m_pcont->max_pvars();
+ uint params = m_pcont->current_pvars();
+ uint hmax = m_pcont->max_handlers();
+ uint cmax = m_pcont->max_cursors();
sp_rcontext *octx = thd->spcont;
sp_rcontext *nctx = NULL;
my_bool tmp_octx = FALSE; // True if we have allocated a temporary octx
@@ -851,12 +851,18 @@ sp_head::backpatch(sp_label_t *lab)
(bp->lab->type == SP_LAB_REF &&
my_strcasecmp(system_charset_info, bp->lab->name, lab->name) == 0))
{
- sp_scope_t sdiff;
+ if (bp->lab->type != SP_LAB_REF)
+ bp->instr->backpatch(dest, lab->ctx);
+ else
+ {
+ sp_label_t *dstlab= bp->lab->ctx->find_label(lab->name);
- if (bp->lab->type == SP_LAB_REF)
- bp->lab= lab;
- m_pcont->diff_scopes(0, &sdiff);
- bp->instr->backpatch(dest, sdiff.hndlrs, sdiff.curs);
+ if (dstlab)
+ {
+ bp->lab= lab;
+ bp->instr->backpatch(dest, dstlab->ctx);
+ }
+ }
}
}
}
@@ -1236,7 +1242,7 @@ sp_instr_jump::print(String *str)
uint
sp_instr_jump::opt_mark(sp_head *sp)
{
- m_dest= opt_shortcut_jump(sp);
+ m_dest= opt_shortcut_jump(sp, this);
if (m_dest != m_ip+1) /* Jumping to following instruction? */
marked= 1;
m_optdest= sp->get_instr(m_dest);
@@ -1244,15 +1250,18 @@ sp_instr_jump::opt_mark(sp_head *sp)
}
uint
-sp_instr_jump::opt_shortcut_jump(sp_head *sp)
+sp_instr_jump::opt_shortcut_jump(sp_head *sp, sp_instr *start)
{
uint dest= m_dest;
sp_instr *i;
while ((i= sp->get_instr(dest)))
{
- uint ndest= i->opt_shortcut_jump(sp);
+ uint ndest;
+ if (start == i)
+ break;
+ ndest= i->opt_shortcut_jump(sp, start);
if (ndest == dest)
break;
dest= ndest;
@@ -1320,7 +1329,7 @@ sp_instr_jump_if::opt_mark(sp_head *sp)
marked= 1;
if ((i= sp->get_instr(m_dest)))
{
- m_dest= i->opt_shortcut_jump(sp);
+ m_dest= i->opt_shortcut_jump(sp, this);
m_optdest= sp->get_instr(m_dest);
}
sp->opt_mark(m_dest);
@@ -1377,7 +1386,7 @@ sp_instr_jump_if_not::opt_mark(sp_head *sp)
marked= 1;
if ((i= sp->get_instr(m_dest)))
{
- m_dest= i->opt_shortcut_jump(sp);
+ m_dest= i->opt_shortcut_jump(sp, this);
m_optdest= sp->get_instr(m_dest);
}
sp->opt_mark(m_dest);
@@ -1460,7 +1469,7 @@ sp_instr_hpush_jump::opt_mark(sp_head *sp)
marked= 1;
if ((i= sp->get_instr(m_dest)))
{
- m_dest= i->opt_shortcut_jump(sp);
+ m_dest= i->opt_shortcut_jump(sp, this);
m_optdest= sp->get_instr(m_dest);
}
sp->opt_mark(m_dest);
@@ -1487,6 +1496,13 @@ sp_instr_hpop::print(String *str)
str->qs_append(m_count);
}
+void
+sp_instr_hpop::backpatch(uint dest, sp_pcontext *dst_ctx)
+{
+ m_count= m_ctx->diff_handlers(dst_ctx);
+}
+
+
//
// sp_instr_hreturn
//
@@ -1551,6 +1567,12 @@ sp_instr_cpop::print(String *str)
str->qs_append(m_count);
}
+void
+sp_instr_cpop::backpatch(uint dest, sp_pcontext *dst_ctx)
+{
+ m_count= m_ctx->diff_cursors(dst_ctx);
+}
+
//
// sp_instr_copen
//
diff --git a/sql/sp_head.h b/sql/sp_head.h
index 9c29297180d..c0881661ad1 100644
--- a/sql/sp_head.h
+++ b/sql/sp_head.h
@@ -86,6 +86,7 @@ public:
my_bool m_has_return; // For FUNCTIONs only
my_bool m_simple_case; // TRUE if parsing simple case, FALSE otherwise
my_bool m_multi_results; // TRUE if a procedure with SELECT(s)
+ my_bool m_in_handler; // TRUE if parser in a handler body
uint m_old_cmq; // Old CLIENT_MULTI_QUERIES value
st_sp_chistics *m_chistics;
ulong m_sql_mode; // For SHOW CREATE
@@ -262,10 +263,11 @@ public:
uint marked;
Item *free_list; // My Items
uint m_ip; // My index
+ sp_pcontext *m_ctx; // My parse context
// Should give each a name or type code for debugging purposes?
- sp_instr(uint ip)
- :Sql_alloc(), marked(0), free_list(0), m_ip(ip)
+ sp_instr(uint ip, sp_pcontext *ctx)
+ :Sql_alloc(), marked(0), free_list(0), m_ip(ip), m_ctx(ctx)
{}
virtual ~sp_instr()
@@ -279,7 +281,7 @@ public:
virtual void print(String *str) = 0;
- virtual void backpatch(uint dest, uint hpop, uint cpop)
+ virtual void backpatch(uint dest, sp_pcontext *dst_ctx)
{}
virtual uint opt_mark(sp_head *sp)
@@ -288,7 +290,7 @@ public:
return m_ip+1;
}
- virtual uint opt_shortcut_jump(sp_head *sp)
+ virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start)
{
return m_ip;
}
@@ -311,8 +313,8 @@ class sp_instr_stmt : public sp_instr
public:
- sp_instr_stmt(uint ip)
- : sp_instr(ip), m_lex(NULL)
+ sp_instr_stmt(uint ip, sp_pcontext *ctx)
+ : sp_instr(ip, ctx), m_lex(NULL)
{}
virtual ~sp_instr_stmt();
@@ -353,8 +355,10 @@ public:
TABLE_LIST *tables;
- sp_instr_set(uint ip, uint offset, Item *val, enum enum_field_types type)
- : sp_instr(ip), tables(NULL), m_offset(offset), m_value(val), m_type(type)
+ sp_instr_set(uint ip, sp_pcontext *ctx,
+ uint offset, Item *val, enum enum_field_types type)
+ : sp_instr(ip, ctx),
+ tables(NULL), m_offset(offset), m_value(val), m_type(type)
{}
virtual ~sp_instr_set()
@@ -382,12 +386,12 @@ public:
uint m_dest; // Where we will go
- sp_instr_jump(uint ip)
- : sp_instr(ip), m_dest(0), m_optdest(0)
+ sp_instr_jump(uint ip, sp_pcontext *ctx)
+ : sp_instr(ip, ctx), m_dest(0), m_optdest(0)
{}
- sp_instr_jump(uint ip, uint dest)
- : sp_instr(ip), m_dest(dest), m_optdest(0)
+ sp_instr_jump(uint ip, sp_pcontext *ctx, uint dest)
+ : sp_instr(ip, ctx), m_dest(dest), m_optdest(0)
{}
virtual ~sp_instr_jump()
@@ -399,11 +403,11 @@ public:
virtual uint opt_mark(sp_head *sp);
- virtual uint opt_shortcut_jump(sp_head *sp);
+ virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start);
virtual void opt_move(uint dst, List<sp_instr> *ibp);
- virtual void backpatch(uint dest, uint hpop, uint cpop)
+ virtual void backpatch(uint dest, sp_pcontext *dst_ctx)
{
if (m_dest == 0) // Don't reset
m_dest= dest;
@@ -425,12 +429,12 @@ public:
TABLE_LIST *tables;
- sp_instr_jump_if(uint ip, Item *i)
- : sp_instr_jump(ip), tables(NULL), m_expr(i)
+ sp_instr_jump_if(uint ip, sp_pcontext *ctx, Item *i)
+ : sp_instr_jump(ip, ctx), tables(NULL), m_expr(i)
{}
- sp_instr_jump_if(uint ip, Item *i, uint dest)
- : sp_instr_jump(ip, dest), tables(NULL), m_expr(i)
+ sp_instr_jump_if(uint ip, sp_pcontext *ctx, Item *i, uint dest)
+ : sp_instr_jump(ip, ctx, dest), tables(NULL), m_expr(i)
{}
virtual ~sp_instr_jump_if()
@@ -442,7 +446,7 @@ public:
virtual uint opt_mark(sp_head *sp);
- virtual uint opt_shortcut_jump(sp_head *sp)
+ virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start)
{
return m_ip;
}
@@ -463,12 +467,12 @@ public:
TABLE_LIST *tables;
- sp_instr_jump_if_not(uint ip, Item *i)
- : sp_instr_jump(ip), tables(NULL), m_expr(i)
+ sp_instr_jump_if_not(uint ip, sp_pcontext *ctx, Item *i)
+ : sp_instr_jump(ip, ctx), tables(NULL), m_expr(i)
{}
- sp_instr_jump_if_not(uint ip, Item *i, uint dest)
- : sp_instr_jump(ip, dest), tables(NULL), m_expr(i)
+ sp_instr_jump_if_not(uint ip, sp_pcontext *ctx, Item *i, uint dest)
+ : sp_instr_jump(ip, ctx, dest), tables(NULL), m_expr(i)
{}
virtual ~sp_instr_jump_if_not()
@@ -480,7 +484,7 @@ public:
virtual uint opt_mark(sp_head *sp);
- virtual uint opt_shortcut_jump(sp_head *sp)
+ virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start)
{
return m_ip;
}
@@ -501,8 +505,9 @@ public:
TABLE_LIST *tables;
- sp_instr_freturn(uint ip, Item *val, enum enum_field_types type)
- : sp_instr(ip), tables(NULL), m_value(val), m_type(type)
+ sp_instr_freturn(uint ip, sp_pcontext *ctx,
+ Item *val, enum enum_field_types type)
+ : sp_instr(ip, ctx), tables(NULL), m_value(val), m_type(type)
{}
virtual ~sp_instr_freturn()
@@ -533,8 +538,8 @@ class sp_instr_hpush_jump : public sp_instr_jump
public:
- sp_instr_hpush_jump(uint ip, int htype, uint fp)
- : sp_instr_jump(ip), m_type(htype), m_frame(fp)
+ sp_instr_hpush_jump(uint ip, sp_pcontext *ctx, int htype, uint fp)
+ : sp_instr_jump(ip, ctx), m_type(htype), m_frame(fp)
{
m_handler= ip+1;
m_cond.empty();
@@ -551,7 +556,7 @@ public:
virtual uint opt_mark(sp_head *sp);
- virtual uint opt_shortcut_jump(sp_head *sp)
+ virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start)
{
return m_ip;
}
@@ -578,8 +583,8 @@ class sp_instr_hpop : public sp_instr
public:
- sp_instr_hpop(uint ip, uint count)
- : sp_instr(ip), m_count(count)
+ sp_instr_hpop(uint ip, sp_pcontext *ctx, uint count)
+ : sp_instr(ip, ctx), m_count(count)
{}
virtual ~sp_instr_hpop()
@@ -589,13 +594,7 @@ public:
virtual void print(String *str);
- virtual void backpatch(uint dest, uint hpop, uint cpop)
- {
- if (hpop > m_count)
- m_count= 0;
- else
- m_count-= hpop;
- }
+ virtual void backpatch(uint dest, sp_pcontext *dst_ctx);
virtual uint opt_mark(sp_head *sp)
{
@@ -618,8 +617,8 @@ class sp_instr_hreturn : public sp_instr
public:
- sp_instr_hreturn(uint ip, uint fp)
- : sp_instr(ip), m_frame(fp)
+ sp_instr_hreturn(uint ip, sp_pcontext *ctx, uint fp)
+ : sp_instr(ip, ctx), m_frame(fp)
{}
virtual ~sp_instr_hreturn()
@@ -649,8 +648,8 @@ class sp_instr_cpush : public sp_instr
public:
- sp_instr_cpush(uint ip, LEX *lex)
- : sp_instr(ip), m_lex(lex)
+ sp_instr_cpush(uint ip, sp_pcontext *ctx, LEX *lex)
+ : sp_instr(ip, ctx), m_lex(lex)
{}
virtual ~sp_instr_cpush();
@@ -673,8 +672,8 @@ class sp_instr_cpop : public sp_instr
public:
- sp_instr_cpop(uint ip, uint count)
- : sp_instr(ip), m_count(count)
+ sp_instr_cpop(uint ip, sp_pcontext *ctx, uint count)
+ : sp_instr(ip, ctx), m_count(count)
{}
virtual ~sp_instr_cpop()
@@ -684,13 +683,7 @@ public:
virtual void print(String *str);
- virtual void backpatch(uint dest, uint hpop, uint cpop)
- {
- if (cpop > m_count)
- m_count= 0;
- else
- m_count-= cpop;
- }
+ virtual void backpatch(uint dest, sp_pcontext *dst_ctx);
virtual uint opt_mark(sp_head *sp)
{
@@ -713,8 +706,8 @@ class sp_instr_copen : public sp_instr_stmt
public:
- sp_instr_copen(uint ip, uint c)
- : sp_instr_stmt(ip), m_cursor(c)
+ sp_instr_copen(uint ip, sp_pcontext *ctx, uint c)
+ : sp_instr_stmt(ip, ctx), m_cursor(c)
{}
virtual ~sp_instr_copen()
@@ -738,8 +731,8 @@ class sp_instr_cclose : public sp_instr
public:
- sp_instr_cclose(uint ip, uint c)
- : sp_instr(ip), m_cursor(c)
+ sp_instr_cclose(uint ip, sp_pcontext *ctx, uint c)
+ : sp_instr(ip, ctx), m_cursor(c)
{}
virtual ~sp_instr_cclose()
@@ -763,8 +756,8 @@ class sp_instr_cfetch : public sp_instr
public:
- sp_instr_cfetch(uint ip, uint c)
- : sp_instr(ip), m_cursor(c)
+ sp_instr_cfetch(uint ip, sp_pcontext *ctx, uint c)
+ : sp_instr(ip, ctx), m_cursor(c)
{
m_varlist.empty();
}
@@ -796,8 +789,8 @@ class sp_instr_error : public sp_instr
public:
- sp_instr_error(uint ip, int errcode)
- : sp_instr(ip), m_errcode(errcode)
+ sp_instr_error(uint ip, sp_pcontext *ctx, int errcode)
+ : sp_instr(ip, ctx), m_errcode(errcode)
{}
virtual ~sp_instr_error()
diff --git a/sql/sp_pcontext.cc b/sql/sp_pcontext.cc
index 6f999531e58..c83259c3926 100644
--- a/sql/sp_pcontext.cc
+++ b/sql/sp_pcontext.cc
@@ -26,79 +26,98 @@
#include "sp_pcontext.h"
#include "sp_head.h"
-sp_pcontext::sp_pcontext()
- : Sql_alloc(), m_params(0), m_framesize(0), m_handlers(0), m_cursmax(0),
- m_hndlrlev(0)
+sp_pcontext::sp_pcontext(sp_pcontext *prev)
+ : Sql_alloc(), m_psubsize(0), m_csubsize(0), m_hsubsize(0),
+ m_parent(prev), m_handlers(0)
{
VOID(my_init_dynamic_array(&m_pvar, sizeof(sp_pvar_t *), 16, 8));
VOID(my_init_dynamic_array(&m_cond, sizeof(sp_cond_type_t *), 16, 8));
VOID(my_init_dynamic_array(&m_cursor, sizeof(LEX_STRING), 16, 8));
- VOID(my_init_dynamic_array(&m_scopes, sizeof(sp_scope_t), 16, 8));
- VOID(my_init_dynamic_array(&m_glabel, sizeof(sp_label_t *), 16, 8));
m_label.empty();
+ m_children.empty();
+ if (!prev)
+ m_poffset= m_coffset= 0;
+ else
+ {
+ m_poffset= prev->current_pvars();
+ m_coffset= prev->current_cursors();
+ }
}
void
sp_pcontext::destroy()
{
+ List_iterator_fast<sp_pcontext> li(m_children);
+ sp_pcontext *child;
+
+ while ((child= li++))
+ child->destroy();
+
+ m_children.empty();
+ m_label.empty();
delete_dynamic(&m_pvar);
delete_dynamic(&m_cond);
delete_dynamic(&m_cursor);
- delete_dynamic(&m_scopes);
- delete_dynamic(&m_glabel);
- m_label.empty();
}
-void
-sp_pcontext::push_scope()
+sp_pcontext *
+sp_pcontext::push_context()
{
- sp_scope_t s;
-
- s.vars= m_pvar.elements;
- s.conds= m_cond.elements;
- s.hndlrs= m_hndlrlev;
- s.curs= m_cursor.elements;
- s.glab= m_glabel.elements;
- insert_dynamic(&m_scopes, (gptr)&s);
+ sp_pcontext *child= new sp_pcontext(this);
+
+ if (child)
+ m_children.push_back(child);
+ return child;
}
-void
-sp_pcontext::pop_scope(sp_scope_t *sp)
+sp_pcontext *
+sp_pcontext::pop_context()
{
- byte *p= pop_dynamic(&m_scopes);
-
- if (sp && p)
- memcpy(sp, p, sizeof(sp_scope_t));
+ uint submax= max_pvars();
+
+ if (submax > m_parent->m_psubsize)
+ m_parent->m_psubsize= submax;
+ submax= max_handlers();
+ if (submax > m_parent->m_hsubsize)
+ m_parent->m_hsubsize= submax;
+ submax= max_cursors();
+ if (submax > m_parent->m_csubsize)
+ m_parent->m_csubsize= submax;
+ return m_parent;
}
-void
-sp_pcontext::diff_scopes(uint sold, sp_scope_t *diffs)
+uint
+sp_pcontext::diff_handlers(sp_pcontext *ctx)
{
- uint snew= m_scopes.elements;
- sp_scope_t scope;
+ uint n= 0;
+ sp_pcontext *pctx= this;
- diffs->vars= diffs->conds= diffs->hndlrs= diffs->curs= diffs->glab= 0;
- while (snew-- > sold)
+ while (pctx && pctx != ctx)
{
- get_dynamic(&m_scopes, (gptr)&scope, snew);
- diffs->vars+= scope.vars;
- diffs->conds+= scope.conds;
- diffs->hndlrs+= scope.hndlrs;
- diffs->curs+= scope.curs;
- diffs->glab+= scope.glab;
+ n+= pctx->max_handlers();
+ pctx= pctx->parent_context();
}
- if (sold)
+ if (pctx)
+ return n;
+ return 0; // Didn't find ctx
+}
+
+uint
+sp_pcontext::diff_cursors(sp_pcontext *ctx)
+{
+ uint n= 0;
+ sp_pcontext *pctx= this;
+
+ while (pctx && pctx != ctx)
{
- get_dynamic(&m_scopes, (gptr)&scope, sold-1);
- diffs->vars-= scope.vars;
- diffs->conds-= scope.conds;
- diffs->hndlrs-= scope.hndlrs;
- diffs->curs-= scope.curs;
- diffs->glab-= scope.glab;
+ n+= pctx->max_cursors();
+ pctx= pctx->parent_context();
}
+ if (pctx)
+ return n;
+ return 0; // Didn't find ctx
}
-
/* This does a linear search (from newer to older variables, in case
** we have shadowed names).
** It's possible to have a more efficient allocation and search method,
@@ -109,20 +128,9 @@ sp_pcontext::diff_scopes(uint sold, sp_scope_t *diffs)
sp_pvar_t *
sp_pcontext::find_pvar(LEX_STRING *name, my_bool scoped)
{
- uint i = m_pvar.elements;
- uint limit;
-
- if (! scoped || m_scopes.elements == 0)
- limit= 0;
- else
- {
- sp_scope_t s;
+ uint i= m_pvar.elements;
- get_dynamic(&m_scopes, (gptr)&s, m_scopes.elements-1);
- limit= s.vars;
- }
-
- while (i-- > limit)
+ while (i--)
{
sp_pvar_t *p;
@@ -134,6 +142,8 @@ sp_pcontext::find_pvar(LEX_STRING *name, my_bool scoped)
return p;
}
}
+ if (!scoped && m_parent)
+ return m_parent->find_pvar(name, scoped);
return NULL;
}
@@ -145,13 +155,13 @@ sp_pcontext::push_pvar(LEX_STRING *name, enum enum_field_types type,
if (p)
{
- if (m_pvar.elements == m_framesize)
- m_framesize += 1;
+ if (m_pvar.elements == m_psubsize)
+ m_psubsize+= 1;
p->name.str= name->str;
p->name.length= name->length;
p->type= type;
p->mode= mode;
- p->offset= m_pvar.elements;
+ p->offset= current_pvars();
p->isset= (mode == sp_param_out ? FALSE : TRUE);
p->dflt= NULL;
insert_dynamic(&m_pvar, (gptr)&p);
@@ -168,7 +178,7 @@ sp_pcontext::push_label(char *name, uint ip)
lab->name= name;
lab->ip= ip;
lab->type= SP_LAB_GOTO;
- lab->scopes= 0;
+ lab->ctx= this;
m_label.push_front(lab);
}
return lab;
@@ -184,6 +194,8 @@ sp_pcontext::find_label(char *name)
if (my_strcasecmp(system_charset_info, name, lab->name) == 0)
return lab;
+ if (m_parent)
+ return m_parent->find_label(name);
return NULL;
}
@@ -207,20 +219,9 @@ sp_pcontext::push_cond(LEX_STRING *name, sp_cond_type_t *val)
sp_cond_type_t *
sp_pcontext::find_cond(LEX_STRING *name, my_bool scoped)
{
- uint i = m_cond.elements;
- uint limit;
+ uint i= m_cond.elements;
- if (! scoped || m_scopes.elements == 0)
- limit= 0;
- else
- {
- sp_scope_t s;
-
- get_dynamic(&m_scopes, (gptr)&s, m_scopes.elements-1);
- limit= s.conds;
- }
-
- while (i-- > limit)
+ while (i--)
{
sp_cond_t *p;
@@ -232,6 +233,8 @@ sp_pcontext::find_cond(LEX_STRING *name, my_bool scoped)
return p->val;
}
}
+ if (!scoped && m_parent)
+ return m_parent->find_cond(name, scoped);
return NULL;
}
@@ -240,11 +243,11 @@ sp_pcontext::push_cursor(LEX_STRING *name)
{
LEX_STRING n;
+ if (m_cursor.elements == m_csubsize)
+ m_csubsize+= 1;
n.str= name->str;
n.length= name->length;
insert_dynamic(&m_cursor, (gptr)&n);
- if (m_cursor.elements > m_cursmax)
- m_cursmax= m_cursor.elements;
}
/*
@@ -253,20 +256,9 @@ sp_pcontext::push_cursor(LEX_STRING *name)
my_bool
sp_pcontext::find_cursor(LEX_STRING *name, uint *poff, my_bool scoped)
{
- uint i = m_cursor.elements;
- uint limit;
+ uint i= m_cursor.elements;
- if (! scoped || m_scopes.elements == 0)
- limit= 0;
- else
- {
- sp_scope_t s;
-
- get_dynamic(&m_scopes, (gptr)&s, m_scopes.elements-1);
- limit= s.curs;
- }
-
- while (i-- > limit)
+ while (i--)
{
LEX_STRING n;
@@ -279,43 +271,7 @@ sp_pcontext::find_cursor(LEX_STRING *name, uint *poff, my_bool scoped)
return TRUE;
}
}
+ if (!scoped && m_parent)
+ return m_parent->find_cursor(name, poff, scoped);
return FALSE;
}
-
-sp_label_t *
-sp_pcontext::push_glabel(char *name, uint ip)
-{
- sp_label_t *lab = (sp_label_t *)sql_alloc(sizeof(sp_label_t));
-
- if (lab)
- {
- lab->name= name;
- lab->ip= ip;
- lab->type= SP_LAB_GOTO;
- lab->scopes= 0;
- insert_dynamic(&m_glabel, (gptr)&lab);
- }
- return lab;
-}
-
-sp_label_t *
-sp_pcontext::find_glabel(char *name)
-{
- uint i= m_glabel.elements;
-
- while (i--)
- {
- sp_label_t *lab;
-
- get_dynamic(&m_glabel, (gptr)&lab, i);
- if (my_strcasecmp(system_charset_info, name, lab->name) == 0)
- return lab;
- }
- return NULL;
-}
-
-void
-sp_pcontext::pop_glabel(uint count)
-{
- (void)pop_dynamic(&m_glabel);
-}
diff --git a/sql/sp_pcontext.h b/sql/sp_pcontext.h
index e3bdc41779a..6db62614aa5 100644
--- a/sql/sp_pcontext.h
+++ b/sql/sp_pcontext.h
@@ -50,7 +50,7 @@ typedef struct sp_label
char *name;
uint ip; // Instruction index
int type; // begin/iter or ref/free
- uint scopes; // No. of scopes at label
+ struct sp_pcontext *ctx; // The label's context
} sp_label_t;
typedef struct sp_cond_type
@@ -66,11 +66,6 @@ typedef struct sp_cond
sp_cond_type_t *val;
} sp_cond_t;
-typedef struct sp_scope
-{
- uint vars, conds, hndlrs, curs, glab;
-} sp_scope_t;
-
class sp_pcontext : public Sql_alloc
{
sp_pcontext(const sp_pcontext &); /* Prevent use of these */
@@ -78,28 +73,30 @@ class sp_pcontext : public Sql_alloc
public:
- sp_pcontext();
+ sp_pcontext(sp_pcontext *prev);
// Free memory
void
destroy();
- // For error checking of duplicate things
- void
- push_scope();
+ sp_pcontext *
+ push_context();
- void
- pop_scope(sp_scope_t *sp = 0);
+ // Returns the previous context, not the one we pop
+ sp_pcontext *
+ pop_context();
- uint
- scopes()
+ sp_pcontext *
+ parent_context()
{
- return m_scopes.elements;
+ return m_parent;
}
- // Sets '*diffs' to the differences between current scope index snew and sold
- void
- diff_scopes(uint sold, sp_scope_t *diffs);
+ uint
+ diff_handlers(sp_pcontext *ctx);
+
+ uint
+ diff_cursors(sp_pcontext *ctx);
//
@@ -107,28 +104,27 @@ class sp_pcontext : public Sql_alloc
//
inline uint
- max_framesize()
+ max_pvars()
{
- return m_framesize;
+ return m_psubsize + m_pvar.elements;
}
inline uint
- current_framesize()
+ current_pvars()
{
- return m_pvar.elements;
+ return m_poffset + m_pvar.elements;
}
inline uint
- params()
+ context_pvars()
{
- return m_params;
+ return m_pvar.elements;
}
- // Set the number of parameters to the current esize
- inline void
- set_params()
+ inline uint
+ pvar_context2index(uint i)
{
- m_params= m_pvar.elements;
+ return m_poffset + i;
}
inline void
@@ -199,7 +195,11 @@ class sp_pcontext : public Sql_alloc
inline sp_label_t *
last_label()
{
- return m_label.head();
+ sp_label_t *lab= m_label.head();
+
+ if (!lab && m_parent)
+ lab= m_parent->last_label();
+ return lab;
}
inline sp_label_t *
@@ -236,23 +236,17 @@ class sp_pcontext : public Sql_alloc
}
inline uint
- handlers()
+ max_handlers()
{
- return m_handlers;
+ return m_hsubsize + m_handlers;
}
inline void
- push_handlers(uint count)
+ push_handlers(uint n)
{
- m_hndlrlev+= count;
+ m_handlers+= n;
}
- inline void
- pop_handlers(uint count)
- {
- m_hndlrlev-= count;
- }
-
//
// Cursors
//
@@ -263,48 +257,41 @@ class sp_pcontext : public Sql_alloc
my_bool
find_cursor(LEX_STRING *name, uint *poff, my_bool scoped=0);
- inline void
- pop_cursor(uint num)
+ inline uint
+ max_cursors()
{
- while (num--)
- pop_dynamic(&m_cursor);
+ return m_csubsize + m_cursor.elements;
}
inline uint
- cursors()
+ current_cursors()
{
- return m_cursmax;
+ return m_coffset + m_cursor.elements;
}
- //
- // GOTO labels
- //
-
- sp_label_t *
- push_glabel(char *name, uint ip);
+protected:
- sp_label_t *
- find_glabel(char *name);
-
- void
- pop_glabel(uint count);
+ // The maximum sub context's framesizes
+ uint m_psubsize;
+ uint m_csubsize;
+ uint m_hsubsize;
private:
- uint m_params; // The number of parameters
- uint m_framesize; // The maximum framesize
- uint m_handlers; // The total number of handlers
- uint m_cursmax; // The maximum number of cursors
- uint m_hndlrlev; // Current number of active handlers
+ sp_pcontext *m_parent; // Parent context
+
+ uint m_poffset; // Variable offset for this context
+ uint m_coffset; // Cursor offset for this context
+ uint m_handlers; // No. of handlers in this context
DYNAMIC_ARRAY m_pvar; // Parameters/variables
DYNAMIC_ARRAY m_cond; // Conditions
DYNAMIC_ARRAY m_cursor; // Cursors
- DYNAMIC_ARRAY m_scopes; // For error checking
- DYNAMIC_ARRAY m_glabel; // Goto labels
List<sp_label_t> m_label; // The label list
+ List<sp_pcontext> m_children; // Children contexts, used for destruction
+
}; // class sp_pcontext : public Sql_alloc
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index a01abd9141b..1b15bc9a516 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -1169,7 +1169,6 @@ create:
LEX *lex= Lex;
lex->sphead->m_param_end= lex->tok_start;
- lex->spcont->set_params();
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
}
sp_c_chistics
@@ -1258,7 +1257,6 @@ create_function_tail:
{
LEX *lex= Lex;
- lex->spcont->set_params();
lex->sphead->m_param_end= lex->tok_start;
}
RETURNS_SYM
@@ -1470,25 +1468,28 @@ sp_decl:
DECLARE_SYM sp_decl_idents type sp_opt_default
{
LEX *lex= Lex;
- uint max= lex->spcont->current_framesize();
+ sp_pcontext *ctx= lex->spcont;
+ uint max= ctx->context_pvars();
enum enum_field_types type= (enum enum_field_types)$3;
Item *it= $4;
for (uint i = max-$2 ; i < max ; i++)
{
- lex->spcont->set_type(i, type);
+ ctx->set_type(i, type);
if (! it)
- lex->spcont->set_isset(i, FALSE);
+ ctx->set_isset(i, FALSE);
else
{
sp_instr_set *in= new sp_instr_set(lex->sphead->instructions(),
- i, it, type);
+ ctx,
+ ctx->pvar_context2index(i),
+ it, type);
in->tables= lex->query_tables;
lex->query_tables= 0;
lex->sphead->add_instr(in);
- lex->spcont->set_isset(i, TRUE);
- lex->spcont->set_default(i, it);
+ ctx->set_isset(i, TRUE);
+ ctx->set_default(i, it);
}
}
$$.vars= $2;
@@ -1514,30 +1515,33 @@ sp_decl:
sp_head *sp= lex->sphead;
sp_pcontext *ctx= lex->spcont;
sp_instr_hpush_jump *i=
- new sp_instr_hpush_jump(sp->instructions(), $2,
- ctx->current_framesize());
+ new sp_instr_hpush_jump(sp->instructions(), ctx, $2,
+ ctx->current_pvars());
sp->add_instr(i);
sp->push_backpatch(i, ctx->push_label((char *)"", 0));
ctx->add_handler();
+ sp->m_in_handler= TRUE;
}
sp_hcond_list sp_proc_stmt
{
LEX *lex= Lex;
sp_head *sp= lex->sphead;
+ sp_pcontext *ctx= lex->spcont;
sp_label_t *hlab= lex->spcont->pop_label(); /* After this hdlr */
if ($2 == SP_HANDLER_CONTINUE)
- sp->add_instr(new sp_instr_hreturn(sp->instructions(),
- lex->spcont->current_framesize()));
+ sp->add_instr(new sp_instr_hreturn(sp->instructions(), ctx,
+ ctx->current_pvars()));
else
{ /* EXIT or UNDO handler, just jump to the end of the block */
- sp_instr_jump *i= new sp_instr_jump(sp->instructions());
+ sp_instr_jump *i= new sp_instr_jump(sp->instructions(), ctx);
sp->add_instr(i);
sp->push_backpatch(i, lex->spcont->last_label()); /* Block end */
}
lex->sphead->backpatch(hlab);
+ sp->m_in_handler= FALSE;
$$.vars= $$.conds= $$.curs= 0;
$$.hndlrs= $6;
}
@@ -1545,19 +1549,19 @@ sp_decl:
{
LEX *lex= Lex;
sp_head *sp= lex->sphead;
- sp_pcontext *spc= lex->spcont;
+ sp_pcontext *ctx= lex->spcont;
uint offp;
sp_instr_cpush *i;
- if (spc->find_cursor(&$2, &offp, TRUE))
+ if (ctx->find_cursor(&$2, &offp, TRUE))
{
net_printf(YYTHD, ER_SP_DUP_CURS, $2.str);
delete $5;
YYABORT;
}
- i= new sp_instr_cpush(sp->instructions(), $5);
+ i= new sp_instr_cpush(sp->instructions(), ctx, $5);
sp->add_instr(i);
- lex->spcont->push_cursor(&$2);
+ ctx->push_cursor(&$2);
$$.vars= $$.conds= $$.hndlrs= 0;
$$.curs= 1;
}
@@ -1748,7 +1752,8 @@ sp_proc_stmt:
}
else
{
- sp_instr_stmt *i=new sp_instr_stmt(lex->sphead->instructions());
+ sp_instr_stmt *i=new sp_instr_stmt(lex->sphead->instructions(),
+ lex->spcont);
i->set_lex(lex);
lex->sphead->add_instr(i);
@@ -1776,6 +1781,7 @@ sp_proc_stmt:
YYABORT;
}
i= new sp_instr_freturn(lex->sphead->instructions(),
+ lex->spcont,
$2, lex->sphead->m_returns);
lex->sphead->add_instr(i);
lex->sphead->m_has_return= TRUE;
@@ -1794,8 +1800,9 @@ sp_proc_stmt:
at the same frame level, so we then know that it's the
top-most variable in the frame. */
LEX *lex= Lex;
- uint offset= lex->spcont->current_framesize();
+ uint offset= lex->spcont->current_pvars();
sp_instr_set *i = new sp_instr_set(lex->sphead->instructions(),
+ lex->spcont,
offset, $2, MYSQL_TYPE_STRING);
LEX_STRING dummy;
@@ -1839,19 +1846,17 @@ sp_proc_stmt:
else
{
uint ip= sp->instructions();
- sp_scope_t sdiff;
sp_instr_jump *i;
sp_instr_hpop *ih;
sp_instr_cpop *ic;
- ctx->diff_scopes(0, &sdiff);
- ih= new sp_instr_hpop(ip++, sdiff.hndlrs);
+ ih= new sp_instr_hpop(ip++, ctx, 0);
sp->push_backpatch(ih, lab);
sp->add_instr(ih);
- ic= new sp_instr_cpop(ip++, sdiff.curs);
+ ic= new sp_instr_cpop(ip++, ctx, 0);
sp->push_backpatch(ic, lab);
sp->add_instr(ic);
- i= new sp_instr_jump(ip);
+ i= new sp_instr_jump(ip, ctx);
sp->push_backpatch(i, lab); /* Jumping forward */
sp->add_instr(i);
}
@@ -1872,14 +1877,15 @@ sp_proc_stmt:
{
sp_instr_jump *i;
uint ip= sp->instructions();
- sp_scope_t sdiff;
-
- ctx->diff_scopes(lab->scopes, &sdiff);
- if (sdiff.hndlrs)
- sp->add_instr(new sp_instr_hpop(ip++, sdiff.hndlrs));
- if (sdiff.curs)
- sp->add_instr(new sp_instr_cpop(ip++, sdiff.curs));
- i= new sp_instr_jump(ip, lab->ip); /* Jump back */
+ uint n;
+
+ n= ctx->diff_handlers(lab->ctx);
+ if (n)
+ sp->add_instr(new sp_instr_hpop(ip++, ctx, n));
+ n= ctx->diff_cursors(lab->ctx);
+ if (n)
+ sp->add_instr(new sp_instr_cpop(ip++, ctx, n));
+ i= new sp_instr_jump(ip, ctx, lab->ip); /* Jump back */
sp->add_instr(i);
}
}
@@ -1890,8 +1896,6 @@ sp_proc_stmt:
sp_pcontext *ctx= lex->spcont;
sp_label_t *lab= ctx->find_label($2.str);
- if (! lab)
- lab= ctx->find_glabel($2.str);
if (lab)
{
net_printf(YYTHD, ER_SP_LABEL_REDEFINE, $2.str);
@@ -1899,9 +1903,9 @@ sp_proc_stmt:
}
else
{
- lab= ctx->push_glabel($2.str, sp->instructions());
+ lab= ctx->push_label($2.str, sp->instructions());
lab->type= SP_LAB_GOTO;
- lab->scopes= ctx->scopes();
+ lab->ctx= ctx;
sp->backpatch(lab);
}
}
@@ -1911,48 +1915,52 @@ sp_proc_stmt:
sp_head *sp= lex->sphead;
sp_pcontext *ctx= lex->spcont;
uint ip= lex->sphead->instructions();
- sp_label_t *lab= ctx->find_label($2.str);
- sp_scope_t sdiff;
+ sp_label_t *lab;
sp_instr_jump *i;
sp_instr_hpop *ih;
sp_instr_cpop *ic;
- if (! lab)
- lab= ctx->find_glabel($2.str);
-
+ if (sp->m_in_handler)
+ {
+ send_error(lex->thd, ER_SP_GOTO_IN_HNDLR);
+ YYABORT;
+ }
+ lab= ctx->find_label($2.str);
if (! lab)
{
lab= (sp_label_t *)YYTHD->alloc(sizeof(sp_label_t));
lab->name= $2.str;
lab->ip= 0;
lab->type= SP_LAB_REF;
- lab->scopes= 0;
+ lab->ctx= ctx;
- ctx->diff_scopes(0, &sdiff);
- ih= new sp_instr_hpop(ip++, sdiff.hndlrs);
+ ih= new sp_instr_hpop(ip++, ctx, 0);
sp->push_backpatch(ih, lab);
sp->add_instr(ih);
- ic= new sp_instr_cpop(ip++, sdiff.curs);
+ ic= new sp_instr_cpop(ip++, ctx, 0);
sp->add_instr(ic);
sp->push_backpatch(ic, lab);
- i= new sp_instr_jump(ip);
+ i= new sp_instr_jump(ip, ctx);
sp->push_backpatch(i, lab); /* Jumping forward */
sp->add_instr(i);
}
else
{
- ctx->diff_scopes(lab->scopes, &sdiff);
- if (sdiff.hndlrs)
+ uint n;
+
+ n= ctx->diff_handlers(lab->ctx);
+ if (n)
{
- ih= new sp_instr_hpop(ip++, sdiff.hndlrs);
+ ih= new sp_instr_hpop(ip++, ctx, n);
sp->add_instr(ih);
}
- if (sdiff.curs)
+ n= ctx->diff_cursors(lab->ctx);
+ if (n)
{
- ic= new sp_instr_cpop(ip++, sdiff.curs);
+ ic= new sp_instr_cpop(ip++, ctx, n);
sp->add_instr(ic);
}
- i= new sp_instr_jump(ip, lab->ip); /* Jump back */
+ i= new sp_instr_jump(ip, ctx, lab->ip); /* Jump back */
sp->add_instr(i);
}
}
@@ -1968,7 +1976,7 @@ sp_proc_stmt:
net_printf(YYTHD, ER_SP_CURSOR_MISMATCH, $2.str);
YYABORT;
}
- i= new sp_instr_copen(sp->instructions(), offset);
+ i= new sp_instr_copen(sp->instructions(), lex->spcont, offset);
sp->add_instr(i);
}
| FETCH_SYM ident INTO
@@ -1983,7 +1991,7 @@ sp_proc_stmt:
net_printf(YYTHD, ER_SP_CURSOR_MISMATCH, $2.str);
YYABORT;
}
- i= new sp_instr_cfetch(sp->instructions(), offset);
+ i= new sp_instr_cfetch(sp->instructions(), lex->spcont, offset);
sp->add_instr(i);
}
sp_fetch_list
@@ -2000,7 +2008,7 @@ sp_proc_stmt:
net_printf(YYTHD, ER_SP_CURSOR_MISMATCH, $2.str);
YYABORT;
}
- i= new sp_instr_cclose(sp->instructions(), offset);
+ i= new sp_instr_cclose(sp->instructions(), lex->spcont, offset);
sp->add_instr(i);
}
;
@@ -2056,7 +2064,7 @@ sp_if:
sp_head *sp= lex->sphead;
sp_pcontext *ctx= lex->spcont;
uint ip= sp->instructions();
- sp_instr_jump_if_not *i = new sp_instr_jump_if_not(ip, $1);
+ sp_instr_jump_if_not *i = new sp_instr_jump_if_not(ip, ctx, $1);
i->tables= lex->query_tables;
lex->query_tables= 0;
@@ -2068,7 +2076,7 @@ sp_if:
sp_head *sp= Lex->sphead;
sp_pcontext *ctx= Lex->spcont;
uint ip= sp->instructions();
- sp_instr_jump *i = new sp_instr_jump(ip);
+ sp_instr_jump *i = new sp_instr_jump(ip, ctx);
sp->add_instr(i);
sp->backpatch(ctx->pop_label());
@@ -2098,7 +2106,7 @@ sp_case:
sp_instr_jump_if_not *i;
if (! sp->m_simple_case)
- i= new sp_instr_jump_if_not(ip, $1);
+ i= new sp_instr_jump_if_not(ip, ctx, $1);
else
{ /* Simple case: <caseval> = <whenval> */
LEX_STRING ivar;
@@ -2106,10 +2114,10 @@ sp_case:
ivar.str= (char *)"_tmp_";
ivar.length= 5;
Item *var= (Item*) new Item_splocal(ivar,
- ctx->current_framesize()-1);
+ ctx->current_pvars()-1);
Item *expr= new Item_func_eq(var, $1);
- i= new sp_instr_jump_if_not(ip, expr);
+ i= new sp_instr_jump_if_not(ip, ctx, expr);
lex->variables_used= 1;
}
sp->push_backpatch(i, ctx->push_label((char *)"", 0));
@@ -2122,7 +2130,7 @@ sp_case:
sp_head *sp= Lex->sphead;
sp_pcontext *ctx= Lex->spcont;
uint ip= sp->instructions();
- sp_instr_jump *i = new sp_instr_jump(ip);
+ sp_instr_jump *i = new sp_instr_jump(ip, ctx);
sp->add_instr(i);
sp->backpatch(ctx->pop_label());
@@ -2141,7 +2149,8 @@ sp_whens:
{
sp_head *sp= Lex->sphead;
uint ip= sp->instructions();
- sp_instr_error *i= new sp_instr_error(ip, ER_SP_CASE_NOT_FOUND);
+ sp_instr_error *i= new sp_instr_error(ip, Lex->spcont,
+ ER_SP_CASE_NOT_FOUND);
sp->add_instr(i);
}
@@ -2166,7 +2175,6 @@ sp_labeled_control:
lab= lex->spcont->push_label($1.str,
lex->sphead->instructions());
lab->type= SP_LAB_ITER;
- lab->scopes= ctx->scopes();
}
}
sp_unlabeled_control sp_opt_label
@@ -2204,32 +2212,24 @@ sp_unlabeled_control:
sp_label_t *lab= lex->spcont->last_label();
lab->type= SP_LAB_BEGIN;
- /* Scope duplicate checking */
- lex->spcont->push_scope();
+ lex->spcont= lex->spcont->push_context();
}
sp_decls
- {
- Lex->spcont->push_handlers($3.hndlrs);
- }
sp_proc_stmts
END
{
LEX *lex= Lex;
sp_head *sp= lex->sphead;
sp_pcontext *ctx= lex->spcont;
- sp_scope_t scope;
sp->backpatch(ctx->last_label()); /* We always have a label */
- ctx->pop_pvar($3.vars);
- ctx->pop_cond($3.conds);
- ctx->pop_handlers($3.hndlrs);
- ctx->pop_cursor($3.curs);
if ($3.hndlrs)
- sp->add_instr(new sp_instr_hpop(sp->instructions(), $3.hndlrs));
+ sp->add_instr(new sp_instr_hpop(sp->instructions(), ctx,
+ $3.hndlrs));
if ($3.curs)
- sp->add_instr(new sp_instr_cpop(sp->instructions(), $3.curs));
- ctx->pop_scope(&scope);
- ctx->pop_glabel(scope.glab);
+ sp->add_instr(new sp_instr_cpop(sp->instructions(), ctx,
+ $3.curs));
+ lex->spcont= ctx->pop_context();
}
| LOOP_SYM
sp_proc_stmts END LOOP_SYM
@@ -2237,7 +2237,7 @@ sp_unlabeled_control:
LEX *lex= Lex;
uint ip= lex->sphead->instructions();
sp_label_t *lab= lex->spcont->last_label(); /* Jumping back */
- sp_instr_jump *i = new sp_instr_jump(ip, lab->ip);
+ sp_instr_jump *i = new sp_instr_jump(ip, lex->spcont, lab->ip);
lex->sphead->add_instr(i);
}
@@ -2246,7 +2246,8 @@ sp_unlabeled_control:
LEX *lex= Lex;
sp_head *sp= lex->sphead;
uint ip= sp->instructions();
- sp_instr_jump_if_not *i = new sp_instr_jump_if_not(ip, $2);
+ sp_instr_jump_if_not *i = new sp_instr_jump_if_not(ip, lex->spcont,
+ $2);
/* Jumping forward */
sp->push_backpatch(i, lex->spcont->last_label());
@@ -2259,7 +2260,7 @@ sp_unlabeled_control:
LEX *lex= Lex;
uint ip= lex->sphead->instructions();
sp_label_t *lab= lex->spcont->last_label(); /* Jumping back */
- sp_instr_jump *i = new sp_instr_jump(ip, lab->ip);
+ sp_instr_jump *i = new sp_instr_jump(ip, lex->spcont, lab->ip);
lex->sphead->add_instr(i);
}
@@ -2268,7 +2269,8 @@ sp_unlabeled_control:
LEX *lex= Lex;
uint ip= lex->sphead->instructions();
sp_label_t *lab= lex->spcont->last_label(); /* Jumping back */
- sp_instr_jump_if_not *i = new sp_instr_jump_if_not(ip, $4, lab->ip);
+ sp_instr_jump_if_not *i = new sp_instr_jump_if_not(ip, lex->spcont,
+ $4, lab->ip);
i->tables= lex->query_tables;
lex->query_tables= 0;
@@ -6786,11 +6788,12 @@ option_value:
}
else
{ /* An SP local variable */
+ sp_pcontext *ctx= lex->spcont;
sp_pvar_t *spv;
sp_instr_set *i;
Item *it;
- spv= lex->spcont->find_pvar(&$1.base_name);
+ spv= ctx->find_pvar(&$1.base_name);
if ($3)
it= $3;
@@ -6798,7 +6801,7 @@ option_value:
it= spv->dflt;
else
it= new Item_null();
- i= new sp_instr_set(lex->sphead->instructions(),
+ i= new sp_instr_set(lex->sphead->instructions(), ctx,
spv->offset, it, spv->type);
i->tables= lex->query_tables;
lex->query_tables= 0;