summaryrefslogtreecommitdiff
path: root/sql/sp_head.cc
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.com>2019-03-06 17:36:30 +0400
committerAlexander Barkov <bar@mariadb.com>2019-03-07 18:48:15 +0400
commit5f34513c2a2dd5f8431cf03f6ba083c42f233dca (patch)
treea4314e0b0762a0401de604a5e23fa20d3a8551b8 /sql/sp_head.cc
parenta71d185a9a84c4c5f5d251e43aaaaf6efa0aa8d9 (diff)
downloadmariadb-git-5f34513c2a2dd5f8431cf03f6ba083c42f233dca.tar.gz
MDEV-18813 PROCEDURE and anonymous blocks silently ignore FETCH GROUP NEXT ROW
Part#2 (final): rewritting the code to pass the correct enum_sp_aggregate_type to the sp_head constructor, so sp_head never changes its aggregation type later on. The grammar has been simplified and defragmented. This allowed to check aggregate specific instructions right after a routine body has been scanned, by calling new LEX methods: sp_body_finalize_{procedure|function|trigger|event}() Moving some C++ code from *.yy to a few new helper methods in LEX.
Diffstat (limited to 'sql/sp_head.cc')
-rw-r--r--sql/sp_head.cc47
1 files changed, 45 insertions, 2 deletions
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 8ea0b19c378..f2d3a01b953 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -489,7 +489,8 @@ sp_head::operator delete(void *ptr, size_t size) throw()
}
-sp_head::sp_head(sp_package *parent, const Sp_handler *sph)
+sp_head::sp_head(sp_package *parent, const Sp_handler *sph,
+ enum_sp_aggregate_type agg_type)
:Query_arena(&main_mem_root, STMT_INITIALIZED_FOR_SP),
Database_qualified_name(&null_clex_str, &null_clex_str),
m_parent(parent),
@@ -522,6 +523,7 @@ sp_head::sp_head(sp_package *parent, const Sp_handler *sph)
m_pcont(new (&main_mem_root) sp_pcontext()),
m_cont_level(0)
{
+ set_chistics_agg_type(agg_type);
m_first_instance= this;
m_first_free_instance= this;
m_last_cached_sp= this;
@@ -547,7 +549,7 @@ sp_head::sp_head(sp_package *parent, const Sp_handler *sph)
sp_package::sp_package(LEX *top_level_lex,
const sp_name *name,
const Sp_handler *sph)
- :sp_head(NULL, sph),
+ :sp_head(NULL, sph, DEFAULT_AGGREGATE),
m_current_routine(NULL),
m_top_level_lex(top_level_lex),
m_rcontext(NULL),
@@ -2681,6 +2683,17 @@ sp_head::set_chistics(const st_sp_chistics &chistics)
m_chistics.comment.length);
}
+
+void
+sp_head::set_c_chistics(const st_sp_chistics &chistics)
+{
+ // Set all chistics but preserve agg_type.
+ enum_sp_aggregate_type save_agg_type= agg_type();
+ set_chistics(chistics);
+ set_chistics_agg_type(save_agg_type);
+}
+
+
void
sp_head::set_info(longlong created, longlong modified,
const st_sp_chistics &chistics, sql_mode_t sql_mode)
@@ -5134,6 +5147,36 @@ bool sp_head::spvar_fill_table_rowtype_reference(THD *thd,
}
+bool sp_head::check_group_aggregate_instructions_forbid() const
+{
+ if (unlikely(m_flags & sp_head::HAS_AGGREGATE_INSTR))
+ {
+ my_error(ER_NOT_AGGREGATE_FUNCTION, MYF(0));
+ return true;
+ }
+ return false;
+}
+
+
+bool sp_head::check_group_aggregate_instructions_require() const
+{
+ if (unlikely(!(m_flags & HAS_AGGREGATE_INSTR)))
+ {
+ my_error(ER_INVALID_AGGREGATE_FUNCTION, MYF(0));
+ return true;
+ }
+ return false;
+}
+
+
+bool sp_head::check_group_aggregate_instructions_function() const
+{
+ return agg_type() == GROUP_AGGREGATE ?
+ check_group_aggregate_instructions_require() :
+ check_group_aggregate_instructions_forbid();
+}
+
+
/*
In Oracle mode stored routines have an optional name
at the end of a declaration: