diff options
author | halfspawn <j.brauge@qualiac.com> | 2017-02-14 14:43:11 +0100 |
---|---|---|
committer | Alexander Barkov <bar@mariadb.org> | 2017-04-05 15:02:57 +0400 |
commit | af7f287b3b53742e32dd489c8e7187f336a222a9 (patch) | |
tree | 55e6e237c398763cdab7468313054db87e48990f /sql/sp_pcontext.cc | |
parent | d836f52be520c3d9cf6c7041aa332cb8c43e3d79 (diff) | |
download | mariadb-git-af7f287b3b53742e32dd489c8e7187f336a222a9.tar.gz |
MDEV-10697 GOTO statement
Diffstat (limited to 'sql/sp_pcontext.cc')
-rw-r--r-- | sql/sp_pcontext.cc | 61 |
1 files changed, 58 insertions, 3 deletions
diff --git a/sql/sp_pcontext.cc b/sql/sp_pcontext.cc index 06c51642d68..628c79a880b 100644 --- a/sql/sp_pcontext.cc +++ b/sql/sp_pcontext.cc @@ -87,6 +87,7 @@ void sp_pcontext::init(uint var_offset, m_num_case_exprs= num_case_expressions; m_labels.empty(); + m_goto_labels.empty(); } @@ -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() { m_parent->m_max_var_index+= m_max_var_index; @@ -140,6 +147,18 @@ sp_pcontext *sp_pcontext::pop_context() if (m_num_case_exprs > m_parent->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; } @@ -227,9 +246,9 @@ sp_variable *sp_pcontext::add_variable(THD *thd, LEX_STRING name) return m_vars.append(p) ? NULL : p; } - 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= 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, if (!label) return NULL; - m_labels.push_front(label, thd->mem_root); + list->push_front(label, thd->mem_root); 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) { |