diff options
author | Alexander Barkov <bar@mariadb.com> | 2019-03-06 17:36:30 +0400 |
---|---|---|
committer | Alexander Barkov <bar@mariadb.com> | 2019-03-07 18:48:15 +0400 |
commit | 5f34513c2a2dd5f8431cf03f6ba083c42f233dca (patch) | |
tree | a4314e0b0762a0401de604a5e23fa20d3a8551b8 /sql/sp_head.cc | |
parent | a71d185a9a84c4c5f5d251e43aaaaf6efa0aa8d9 (diff) | |
download | mariadb-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.cc | 47 |
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: |