Skip to content

Commit

Permalink
Optimization for MDEV-10411 Providing compatibility for basic PL/SQL …
Browse files Browse the repository at this point in the history
…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.
  • Loading branch information
Alexander Barkov committed Apr 5, 2017
1 parent 4940a91 commit d2b007d
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 7 deletions.
7 changes: 3 additions & 4 deletions mysql-test/suite/compat/oracle/r/sp-code.result
Expand Up @@ -21,7 +21,7 @@ END;
/
SHOW PROCEDURE CODE p1;
Pos Instruction
0 jump 3
0 jump 2
CALL p1;
DROP PROCEDURE p1;
# No HANDLER declarations, no code, some exceptions
Expand Down Expand Up @@ -133,10 +133,9 @@ SHOW PROCEDURE CODE p1;
Pos Instruction
0 hpush_jump 3 1 EXIT
1 set v@0 123
2 hreturn 0 5
2 hreturn 0 4
3 set v@0 223
4 jump 5
5 hpop 1
4 hpop 1
set @v= 10;
CALL p1(@v);
SELECT @v;
Expand Down
28 changes: 28 additions & 0 deletions sql/sp_head.cc
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions sql/sp_head.h
Expand Up @@ -367,6 +367,8 @@ class sp_head :private Query_arena,
return i;
}

bool replace_instr_to_nop(THD *thd, uint ip);

/*
Resets lex in 'thd' and keeps a copy of the old one.
Expand Down
14 changes: 13 additions & 1 deletion sql/sql_lex.cc
Expand Up @@ -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.
Expand Down
3 changes: 2 additions & 1 deletion sql/sql_lex.h
Expand Up @@ -3149,7 +3149,8 @@ struct LEX: public Query_tables_list
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)
{
Expand Down
2 changes: 1 addition & 1 deletion sql/sql_yacc_ora.yy
Expand Up @@ -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;
}
Expand Down

0 comments on commit d2b007d

Please sign in to comment.