summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.org>2016-08-15 21:46:22 +0400
committerAlexander Barkov <bar@mariadb.org>2017-04-05 15:02:43 +0400
commitd2b007d6bc8458d3451bb28cc7319e39dae00e7d (patch)
treec0193e697ab858d722f2687363aa722d1e3bd135 /sql
parent4940a91a5f57da21714b04dce77c425c2db6195c (diff)
downloadmariadb-git-d2b007d6bc8458d3451bb28cc7319e39dae00e7d.tar.gz
Optimization for MDEV-10411 Providing compatibility for basic PL/SQL constructs
When processing an SP body: CREATE PROCEDURE p1 (parameters) AS [ declarations ] BEGIN statements [ EXCEPTION exceptions ] END; the parser generates two "jump" instructions: - from the end of "declarations" to the beginning of EXCEPTION - from the end of EXCEPTION to "statements" These jumps are useless if EXCEPTION does not exist. This patch makes sure that these two "jump" instructions are generated only if EXCEPTION really exists.
Diffstat (limited to 'sql')
-rw-r--r--sql/sp_head.cc28
-rw-r--r--sql/sp_head.h2
-rw-r--r--sql/sql_lex.cc14
-rw-r--r--sql/sql_lex.h3
-rw-r--r--sql/sql_yacc_ora.yy2
5 files changed, 46 insertions, 3 deletions
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 7951ef538bc..1ecbc1b2e5f 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -2582,6 +2582,34 @@ bool sp_head::add_instr_jump_forward_with_backpatch(THD *thd,
}
+/*
+ Replace an instruction at position to "no operation".
+
+ @param thd - use mem_root of this THD for "new".
+ @param ip - position of the operation
+ @returns - true on error, false on success
+
+ When we need to remove an instruction that during compilation
+ appeared to be useless (typically as useless jump), we replace
+ it to a jump to exactly the next instruction.
+ Such jumps are later removed during sp_head::optimize().
+
+ QQ: Perhaps we need a dedicated sp_instr_nop for this purpose.
+*/
+bool sp_head::replace_instr_to_nop(THD *thd, uint ip)
+{
+ sp_instr *instr= get_instr(ip);
+ sp_instr_jump *nop= new (thd->mem_root) sp_instr_jump(instr->m_ip,
+ instr->m_ctx,
+ instr->m_ip + 1);
+ if (!nop)
+ return true;
+ delete instr;
+ set_dynamic(&m_instr, (uchar *) &nop, ip);
+ return false;
+}
+
+
/**
Do some minimal optimization of the code:
-# Mark used instructions
diff --git a/sql/sp_head.h b/sql/sp_head.h
index eb2f47ae2d8..b4c3cdaac6c 100644
--- a/sql/sp_head.h
+++ b/sql/sp_head.h
@@ -367,6 +367,8 @@ public:
return i;
}
+ bool replace_instr_to_nop(THD *thd, uint ip);
+
/*
Resets lex in 'thd' and keeps a copy of the old one.
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 9c66aea04d9..fec4e309d3f 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -5428,8 +5428,20 @@ LEX::sp_block_with_exceptions_finalize_executable_section(THD *thd,
bool
LEX::sp_block_with_exceptions_finalize_exceptions(THD *thd,
- uint executable_section_ip)
+ uint executable_section_ip,
+ uint exception_count)
{
+ if (!exception_count)
+ {
+ /*
+ The jump from the end of DECLARE section to
+ the beginning of the EXCEPTION section that we added in
+ sp_block_with_exceptions_finalize_declarations() is useless
+ if there were no exceptions.
+ Replace it to "no operation".
+ */
+ return sphead->replace_instr_to_nop(thd, executable_section_ip - 1);
+ }
/*
Generate a jump from the end of the EXCEPTION code
to the executable section.
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 538cec38d43..ac76dddffcb 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -3149,7 +3149,8 @@ public:
bool sp_block_with_exceptions_finalize_executable_section(THD *thd,
uint executable_section_ip);
bool sp_block_with_exceptions_finalize_exceptions(THD *thd,
- uint executable_section_ip);
+ uint executable_section_ip,
+ uint exception_count);
// Check if "KEY IF NOT EXISTS name" used outside of ALTER context
bool check_add_key(DDL_options_st ddl)
{
diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy
index 99e7ee41827..d322770857d 100644
--- a/sql/sql_yacc_ora.yy
+++ b/sql/sql_yacc_ora.yy
@@ -3489,7 +3489,7 @@ sp_block_statements_and_exceptions:
}
opt_exception_clause
{
- if (Lex->sp_block_with_exceptions_finalize_exceptions(thd, $1))
+ if (Lex->sp_block_with_exceptions_finalize_exceptions(thd, $1, $4))
MYSQL_YYABORT;
$$= $4;
}