2023-07-19 12:43:31 +02:00
|
|
|
#ifndef _SP_INSTR_H_
|
|
|
|
#define _SP_INSTR_H_
|
|
|
|
|
|
|
|
#include "mariadb.h"
|
|
|
|
|
|
|
|
#include "sql_alloc.h" // Sql_alloc
|
|
|
|
#include "sql_class.h" // THD, Query_arena
|
|
|
|
#include "sql_lex.h" // class sp_lex_local
|
|
|
|
#include "sp_pcontext.h" // class sp_pcontext
|
|
|
|
#include "sp_head.h" // class sp_head
|
|
|
|
|
|
|
|
/*
|
|
|
|
Sufficient max length of frame offsets.
|
|
|
|
*/
|
|
|
|
static const int SP_INSTR_UINT_MAXLEN= 8;
|
|
|
|
|
|
|
|
class sp_lex_cursor: public sp_lex_local, public Query_arena
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
sp_lex_cursor(THD *thd, const LEX *oldlex, MEM_ROOT *mem_root_arg)
|
|
|
|
: sp_lex_local(thd, oldlex),
|
2023-07-19 12:53:55 +02:00
|
|
|
Query_arena(mem_root_arg, STMT_INITIALIZED_FOR_SP),
|
|
|
|
m_expr_str(empty_clex_str)
|
2023-07-19 12:43:31 +02:00
|
|
|
{}
|
|
|
|
|
|
|
|
sp_lex_cursor(THD *thd, const LEX *oldlex)
|
|
|
|
: sp_lex_local(thd, oldlex),
|
|
|
|
Query_arena(thd->lex->sphead->get_main_mem_root(),
|
2023-07-19 12:53:55 +02:00
|
|
|
STMT_INITIALIZED_FOR_SP),
|
|
|
|
m_expr_str(empty_clex_str)
|
2023-07-19 12:43:31 +02:00
|
|
|
{}
|
|
|
|
|
|
|
|
~sp_lex_cursor() { free_items(); }
|
|
|
|
|
|
|
|
bool cleanup_stmt(bool /*restore_set_statement_vars*/) override
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
Query_arena *query_arena() override
|
|
|
|
{
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool validate()
|
|
|
|
{
|
|
|
|
DBUG_ASSERT(sql_command == SQLCOM_SELECT);
|
|
|
|
if (result)
|
|
|
|
{
|
|
|
|
my_error(ER_SP_BAD_CURSOR_SELECT, MYF(0));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool stmt_finalize(THD *thd)
|
|
|
|
{
|
|
|
|
if (validate())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
sp_lex_in_use= true;
|
|
|
|
free_list= thd->free_list;
|
|
|
|
thd->free_list= nullptr;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
2023-07-19 12:53:55 +02:00
|
|
|
|
|
|
|
void set_expr_str(const LEX_CSTRING &expr_str)
|
|
|
|
{
|
|
|
|
m_expr_str= expr_str;
|
|
|
|
}
|
|
|
|
|
|
|
|
const LEX_CSTRING &get_expr_str() const
|
|
|
|
{
|
|
|
|
return m_expr_str;
|
|
|
|
}
|
|
|
|
|
2023-07-19 13:17:19 +02:00
|
|
|
sp_lex_cursor* get_lex_for_cursor() override
|
|
|
|
{
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2023-07-19 12:53:55 +02:00
|
|
|
private:
|
|
|
|
LEX_CSTRING m_expr_str;
|
2023-07-19 12:43:31 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// "Instructions"...
|
|
|
|
//
|
|
|
|
|
2023-07-19 12:48:31 +02:00
|
|
|
// Forward declaration for use in the method sp_instr::opt_move().
|
|
|
|
class sp_instr_opt_meta;
|
|
|
|
|
2023-07-19 12:43:31 +02:00
|
|
|
class sp_instr :public Query_arena, public Sql_alloc
|
|
|
|
{
|
|
|
|
sp_instr(const sp_instr &); /**< Prevent use of these */
|
|
|
|
void operator=(sp_instr &);
|
|
|
|
|
|
|
|
public:
|
|
|
|
uint marked;
|
|
|
|
uint m_ip; ///< My index
|
|
|
|
sp_pcontext *m_ctx; ///< My parse context
|
|
|
|
uint m_lineno;
|
|
|
|
|
|
|
|
/// Should give each a name or type code for debugging purposes?
|
|
|
|
sp_instr(uint ip, sp_pcontext *ctx)
|
|
|
|
: Query_arena(0, STMT_INITIALIZED_FOR_SP),
|
|
|
|
marked(0),
|
|
|
|
m_ip(ip),
|
|
|
|
m_ctx(ctx),
|
|
|
|
m_lineno(0)
|
|
|
|
{}
|
|
|
|
|
|
|
|
virtual ~sp_instr()
|
|
|
|
{
|
|
|
|
free_items();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
Execute this instruction
|
|
|
|
|
|
|
|
|
|
|
|
@param thd Thread handle
|
|
|
|
@param[out] nextp index of the next instruction to execute. (For most
|
|
|
|
instructions this will be the instruction following this
|
|
|
|
one). Note that this parameter is undefined in case of
|
|
|
|
errors, use get_cont_dest() to find the continuation
|
|
|
|
instruction for CONTINUE error handlers.
|
|
|
|
|
|
|
|
@retval 0 on success,
|
|
|
|
@retval other if some error occurred
|
|
|
|
*/
|
|
|
|
virtual int execute(THD *thd, uint *nextp) = 0;
|
|
|
|
|
|
|
|
/**
|
|
|
|
Execute <code>open_and_lock_tables()</code> for this statement.
|
|
|
|
Open and lock the tables used by this statement, as a pre-requisite
|
|
|
|
to execute the core logic of this instruction with
|
|
|
|
<code>exec_core()</code>.
|
|
|
|
@param thd the current thread
|
|
|
|
@param tables the list of tables to open and lock
|
|
|
|
@return zero on success, non zero on failure.
|
|
|
|
*/
|
|
|
|
int exec_open_and_lock_tables(THD *thd, TABLE_LIST *tables);
|
|
|
|
|
|
|
|
/**
|
|
|
|
Get the continuation destination of this instruction.
|
|
|
|
@return the continuation destination
|
|
|
|
*/
|
|
|
|
virtual uint get_cont_dest() const;
|
|
|
|
|
|
|
|
/*
|
|
|
|
Execute core function of instruction after all preparations (e.g.
|
|
|
|
setting of proper LEX, saving part of the thread context have been
|
|
|
|
done).
|
|
|
|
|
|
|
|
Should be implemented for instructions using expressions or whole
|
|
|
|
statements (thus having to have own LEX). Used in concert with
|
|
|
|
sp_lex_keeper class and its descendants (there are none currently).
|
|
|
|
*/
|
|
|
|
virtual int exec_core(THD *thd, uint *nextp);
|
|
|
|
|
|
|
|
virtual void print(String *str) = 0;
|
|
|
|
|
|
|
|
virtual void backpatch(uint dest, sp_pcontext *dst_ctx)
|
|
|
|
{}
|
|
|
|
|
|
|
|
/**
|
|
|
|
Mark this instruction as reachable during optimization and return the
|
|
|
|
index to the next instruction. Jump instruction will add their
|
|
|
|
destination to the leads list.
|
|
|
|
*/
|
|
|
|
virtual uint opt_mark(sp_head *sp, List<sp_instr> *leads)
|
|
|
|
{
|
|
|
|
marked= 1;
|
|
|
|
return m_ip+1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
Short-cut jumps to jumps during optimization. This is used by the
|
|
|
|
jump instructions' opt_mark() methods. 'start' is the starting point,
|
|
|
|
used to prevent the mark sweep from looping for ever. Return the
|
|
|
|
end destination.
|
|
|
|
*/
|
|
|
|
virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start)
|
|
|
|
{
|
|
|
|
return m_ip;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
Inform the instruction that it has been moved during optimization.
|
|
|
|
Most instructions will simply update its index, but jump instructions
|
|
|
|
must also take care of their destination pointers. Forward jumps get
|
|
|
|
pushed to the backpatch list 'ibp'.
|
|
|
|
*/
|
2023-07-19 12:48:31 +02:00
|
|
|
virtual void opt_move(uint dst, List<sp_instr_opt_meta> *ibp)
|
2023-07-19 12:43:31 +02:00
|
|
|
{
|
|
|
|
m_ip= dst;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual PSI_statement_info* get_psi_info() = 0;
|
|
|
|
|
2023-07-19 13:00:13 +02:00
|
|
|
virtual SQL_I_List<Item_trigger_field>* get_instr_trig_field_list()
|
|
|
|
{
|
|
|
|
return nullptr;
|
|
|
|
}
|
2023-07-19 12:43:31 +02:00
|
|
|
}; // class sp_instr : public Sql_alloc
|
|
|
|
|
|
|
|
|
2023-07-19 12:57:13 +02:00
|
|
|
class sp_instr;
|
|
|
|
class sp_lex_instr;
|
|
|
|
|
2023-07-19 12:43:31 +02:00
|
|
|
/**
|
|
|
|
Auxilary class to which instructions delegate responsibility
|
|
|
|
for handling LEX and preparations before executing statement
|
|
|
|
or calculating complex expression.
|
|
|
|
|
|
|
|
Exist mainly to avoid having double hierarchy between instruction
|
|
|
|
classes.
|
|
|
|
|
|
|
|
@todo
|
|
|
|
Add ability to not store LEX and do any preparations if
|
|
|
|
expression used is simple.
|
|
|
|
*/
|
|
|
|
|
|
|
|
class sp_lex_keeper final
|
|
|
|
{
|
|
|
|
/** Prevent use of these */
|
|
|
|
sp_lex_keeper(const sp_lex_keeper &);
|
|
|
|
void operator=(sp_lex_keeper &);
|
|
|
|
|
|
|
|
public:
|
|
|
|
sp_lex_keeper(LEX *lex, bool lex_resp)
|
|
|
|
: m_lex(lex),
|
|
|
|
m_lex_resp(lex_resp),
|
|
|
|
prelocking_tables(nullptr),
|
2023-07-19 12:57:13 +02:00
|
|
|
lex_query_tables_own_last(nullptr),
|
|
|
|
m_first_execution(true)
|
2023-07-19 12:43:31 +02:00
|
|
|
{
|
|
|
|
lex->sp_lex_in_use= true;
|
|
|
|
}
|
|
|
|
|
|
|
|
~sp_lex_keeper()
|
|
|
|
{
|
|
|
|
if (m_lex_resp)
|
|
|
|
{
|
|
|
|
/* Prevent endless recursion. */
|
|
|
|
m_lex->sphead= nullptr;
|
|
|
|
lex_end(m_lex);
|
|
|
|
delete m_lex;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
Prepare execution of instruction using LEX, if requested check whenever
|
|
|
|
we have read access to tables used and open/lock them, call instruction's
|
|
|
|
exec_core() method, perform cleanup afterwards.
|
|
|
|
|
|
|
|
@todo Conflicting comment in sp_head.cc
|
|
|
|
*/
|
|
|
|
int reset_lex_and_exec_core(THD *thd, uint *nextp, bool open_tables,
|
|
|
|
sp_instr* instr);
|
|
|
|
|
2023-07-19 12:57:13 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
Do several attempts to execute an instruction.
|
|
|
|
|
|
|
|
This method installs Reprepare_observer to catch possible metadata changes
|
|
|
|
on depending database objects, then calls reset_lex_and_exec_core()
|
|
|
|
to execute the instruction. If execution of the instruction fails, does
|
|
|
|
re-parsing of the instruction and re-execute it.
|
|
|
|
|
|
|
|
@param thd Thread context.
|
|
|
|
@param[out] nextp Pointer for storing a next instruction to execute
|
|
|
|
@param open_tables Flag to specify if the function should check read
|
|
|
|
access to tables in LEX's table list and open and
|
|
|
|
lock them (used in instructions which need to
|
|
|
|
calculate some expression and don't execute
|
|
|
|
complete statement).
|
|
|
|
@param instr instruction which we prepare context and run.
|
|
|
|
|
|
|
|
@return 0 on success, 1 on error
|
|
|
|
*/
|
|
|
|
int validate_lex_and_exec_core(THD *thd, uint *nextp, bool open_tables,
|
|
|
|
sp_lex_instr* instr);
|
|
|
|
|
2023-07-19 12:43:31 +02:00
|
|
|
int cursor_reset_lex_and_exec_core(THD *thd, uint *nextp, bool open_tables,
|
MDEV-5816: Stored programs: validation of stored program statements
Added re-parsing of a failing cursor body. Re-parsing of a failing
SP statement is implemented by the method validate_lex_and_exec_core(),
therefore invocation of the method reset_lex_and_exec_core() inside
sp_lex_keeper::cursor_reset_lex_and_exec_core
was replaced by the method validate_lex_and_exec_core().
Re-parsing of a failed SP statement is relied upon interface provided
by the class sp_lex_instr (the methods used for this goal are
is_invalid(), parse_expr(), invalidate(), get_query(), get_expr_query()).
To provide access to these methods on opening a cursor, the signature of
the method
sp_lex_keeper::cursor_reset_lex_and_exec_core
was changed to accept a pointer to the class sp_lex_instr instead of
the class sp_instr, and the new method get_push_instr() was added
into the class sp_cursor. This method is to get access to an instance
of the class sp_instr_cpush on opening a cursor (on handling the statement
OPEN cursors_name).
Default implementation of this method just returns NULL pointer of
the type sp_instr_cpush. This method is overridden in the class
sp_instr_cpush with trivial implementation
{ return this; }
On handling the statement DECLARE CURSOR FOR the new instruction of
the type sp_instr_cpush is added into sp_head. The class sp_instr_cpush
holds a text of SELECT query referencing by a cursor declaration.
When a cursor is being opened (on handling the statement 'OPEN cur_name')
a pointer to sp_instr_cpush is returned by the method
sp_cursor::get_push_instr()
and this pointer is passed to the method
sp_lex_keeper::cursor_reset_lex_and_exec_core
in order to open a cursor and provide access to an interface required
for SP statement re-parsing in case metadata changes took place.
Since real access to a lex object is required on handling instruction
sp_instr_cpush (an instance of this class is created during parsing of
cursor declaration statement), calling of the method sp_cursor::open
is moved from the method
sp_instr_copen::exec_core
into the method
sp_instr_cpush::exec_core.
Additionally, updated the methods get_query/get_expr_query in the classes
sp_instr_cpush, sp_instr_cursor_copy_struct in order to return correct text of
cursor's body taking into account that lexer treated the clause CURSOR FOR/
CURSOR IS as two different tokens following one after another. So, to return
a correct text of SELECT statement specified in CURSOR declaration statement,
the token FOR/IS should be skipped and text following it should be returned as
a text of cursors's query.
2023-07-19 13:14:00 +02:00
|
|
|
sp_lex_instr *instr);
|
2023-07-19 12:43:31 +02:00
|
|
|
|
2023-07-19 12:57:13 +02:00
|
|
|
/**
|
|
|
|
(Re-)parse the query corresponding to this instruction and return a new
|
|
|
|
LEX-object.
|
|
|
|
|
|
|
|
@param thd Thread context.
|
|
|
|
@param sp The stored program.
|
|
|
|
|
|
|
|
@return new LEX-object or NULL in case of failure.
|
|
|
|
*/
|
|
|
|
LEX *parse_expr(THD *thd, const sp_head *sp);
|
|
|
|
|
2023-07-19 12:43:31 +02:00
|
|
|
inline uint sql_command() const
|
|
|
|
{
|
|
|
|
return (uint)m_lex->sql_command;
|
|
|
|
}
|
|
|
|
|
|
|
|
void disable_query_cache()
|
|
|
|
{
|
|
|
|
m_lex->safe_to_cache_query= 0;
|
|
|
|
}
|
|
|
|
|
2023-07-19 12:57:13 +02:00
|
|
|
private:
|
|
|
|
/**
|
|
|
|
Clean up and destroy owned LEX object.
|
|
|
|
*/
|
|
|
|
void free_lex(THD *thd);
|
|
|
|
|
|
|
|
/**
|
|
|
|
Set LEX object.
|
|
|
|
|
|
|
|
@param lex LEX-object
|
|
|
|
*/
|
2023-07-19 13:17:19 +02:00
|
|
|
void set_lex(LEX *lex);
|
2023-07-19 12:57:13 +02:00
|
|
|
|
2023-07-19 12:43:31 +02:00
|
|
|
private:
|
|
|
|
LEX *m_lex;
|
|
|
|
|
|
|
|
/**
|
|
|
|
Indicates whenever this sp_lex_keeper instance responsible
|
|
|
|
for LEX deletion.
|
|
|
|
*/
|
|
|
|
bool m_lex_resp;
|
|
|
|
|
|
|
|
/*
|
|
|
|
Support for being able to execute this statement in two modes:
|
|
|
|
a) inside prelocked mode set by the calling procedure or its ancestor.
|
|
|
|
b) outside of prelocked mode, when this statement enters/leaves
|
|
|
|
prelocked mode itself.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
List of additional tables this statement needs to lock when it
|
|
|
|
enters/leaves prelocked mode on its own.
|
|
|
|
*/
|
|
|
|
TABLE_LIST *prelocking_tables;
|
|
|
|
|
|
|
|
/**
|
|
|
|
The value m_lex->query_tables_own_last should be set to this when the
|
|
|
|
statement enters/leaves prelocked mode on its own.
|
|
|
|
*/
|
|
|
|
TABLE_LIST **lex_query_tables_own_last;
|
2023-07-19 12:57:13 +02:00
|
|
|
|
|
|
|
bool m_first_execution;
|
2023-07-19 12:43:31 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
MDEV-5816: Stored programs: validation of stored program statements
This is the prerequisite patch introducing the class sp_lex_instr
that encapsulates access to an instance of the class sp_lex_keeper.
Every SP instruction that need to get access to a LEX object on its
processing should inherit this class and implement two abstract methods:
is_invalid(),
invalidate().
These methods will be used in subsequent patches to implement recompilation of
SP instructions on failure.
Currently, the following instructions are derived from the class sp_lex_instr:
sp_instr_stmt,
sp_instr_set,
sp_instr_set_trigger_field,
sp_instr_jump_if_not,
sp_instr_freturn,
sp_instr_cpush,
sp_instr_cursor_copy_struct,
sp_instr_set_case_expr
Additionally, this patch converts the class sp_instr_opt_meta
to a base abstract class (that is, not inherited from the class
sp_instr). Since this class originally was designed to provide a way
for opimizer to update a destination address for jump SP-instructions,
the only useful method at the interface of this class is set_destination
and therefore inheritance from the class sp_instr is meaningless.
Every jump SP instruction now must be inherited directly from
the class sp_instr_opt_meta and additionally from either the class
sp_lex_instr or sp_instr depending on whether this SP instruction
need to get access to a LEX object or not.
Moreover, the class sp_cursor doesn't own a data member of
the class sp_lex_keeper any more. Instead, the virtual method
get_lex_keeper() has been added to the class sp_cursor() that
returns nullptr and this method is overridden in the derived class
sp_instr_cpush to provide a pointer to a real instance of
the class sp_lex_keeper. Doing this way we exclude duplication
of a data member of the type sp_lex_keeper at the class sp_instr_cpush
since it is derived both from sp_lex_instr and sp_cursor, and sp_lex_instr
already encapsulates a data member of the class sp_lex_keeper.
2023-07-19 12:50:47 +02:00
|
|
|
The base class for any stored program instruction that need to get access
|
|
|
|
to a LEX object on execution.
|
2023-07-19 12:43:31 +02:00
|
|
|
*/
|
|
|
|
|
MDEV-5816: Stored programs: validation of stored program statements
This is the prerequisite patch introducing the class sp_lex_instr
that encapsulates access to an instance of the class sp_lex_keeper.
Every SP instruction that need to get access to a LEX object on its
processing should inherit this class and implement two abstract methods:
is_invalid(),
invalidate().
These methods will be used in subsequent patches to implement recompilation of
SP instructions on failure.
Currently, the following instructions are derived from the class sp_lex_instr:
sp_instr_stmt,
sp_instr_set,
sp_instr_set_trigger_field,
sp_instr_jump_if_not,
sp_instr_freturn,
sp_instr_cpush,
sp_instr_cursor_copy_struct,
sp_instr_set_case_expr
Additionally, this patch converts the class sp_instr_opt_meta
to a base abstract class (that is, not inherited from the class
sp_instr). Since this class originally was designed to provide a way
for opimizer to update a destination address for jump SP-instructions,
the only useful method at the interface of this class is set_destination
and therefore inheritance from the class sp_instr is meaningless.
Every jump SP instruction now must be inherited directly from
the class sp_instr_opt_meta and additionally from either the class
sp_lex_instr or sp_instr depending on whether this SP instruction
need to get access to a LEX object or not.
Moreover, the class sp_cursor doesn't own a data member of
the class sp_lex_keeper any more. Instead, the virtual method
get_lex_keeper() has been added to the class sp_cursor() that
returns nullptr and this method is overridden in the derived class
sp_instr_cpush to provide a pointer to a real instance of
the class sp_lex_keeper. Doing this way we exclude duplication
of a data member of the type sp_lex_keeper at the class sp_instr_cpush
since it is derived both from sp_lex_instr and sp_cursor, and sp_lex_instr
already encapsulates a data member of the class sp_lex_keeper.
2023-07-19 12:50:47 +02:00
|
|
|
class sp_lex_instr : public sp_instr
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
sp_lex_instr(uint ip, sp_pcontext *ctx, LEX *lex, bool is_lex_owner)
|
|
|
|
: sp_instr(ip, ctx),
|
|
|
|
m_lex_keeper(lex, is_lex_owner)
|
|
|
|
{}
|
|
|
|
|
|
|
|
virtual bool is_invalid() const = 0;
|
|
|
|
|
|
|
|
virtual void invalidate() = 0;
|
|
|
|
|
2023-07-19 12:53:55 +02:00
|
|
|
/**
|
|
|
|
Return the query string, which can be passed to the parser,
|
|
|
|
that is a valid SQL-statement.
|
|
|
|
|
|
|
|
@param[out] sql_query SQL-statement query string.
|
|
|
|
*/
|
|
|
|
virtual void get_query(String *sql_query) const;
|
|
|
|
|
2023-07-19 12:57:13 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
(Re-)parse the query corresponding to this instruction and return a new
|
|
|
|
LEX-object.
|
|
|
|
|
|
|
|
@param thd Thread context.
|
|
|
|
@param sp The stored program.
|
2023-07-19 13:17:19 +02:00
|
|
|
@param lex SP instruction's lex
|
2023-07-19 12:57:13 +02:00
|
|
|
|
|
|
|
@return new LEX-object or NULL in case of failure.
|
|
|
|
*/
|
2023-07-19 13:17:19 +02:00
|
|
|
LEX *parse_expr(THD *thd, sp_head *sp, LEX *lex);
|
2023-07-19 12:57:13 +02:00
|
|
|
|
2023-07-19 13:00:13 +02:00
|
|
|
SQL_I_List<Item_trigger_field>* get_instr_trig_field_list() override
|
|
|
|
{
|
|
|
|
return &m_cur_trigger_stmt_items;
|
|
|
|
}
|
|
|
|
|
MDEV-5816: Stored programs: validation of stored program statements
This is the prerequisite patch introducing the class sp_lex_instr
that encapsulates access to an instance of the class sp_lex_keeper.
Every SP instruction that need to get access to a LEX object on its
processing should inherit this class and implement two abstract methods:
is_invalid(),
invalidate().
These methods will be used in subsequent patches to implement recompilation of
SP instructions on failure.
Currently, the following instructions are derived from the class sp_lex_instr:
sp_instr_stmt,
sp_instr_set,
sp_instr_set_trigger_field,
sp_instr_jump_if_not,
sp_instr_freturn,
sp_instr_cpush,
sp_instr_cursor_copy_struct,
sp_instr_set_case_expr
Additionally, this patch converts the class sp_instr_opt_meta
to a base abstract class (that is, not inherited from the class
sp_instr). Since this class originally was designed to provide a way
for opimizer to update a destination address for jump SP-instructions,
the only useful method at the interface of this class is set_destination
and therefore inheritance from the class sp_instr is meaningless.
Every jump SP instruction now must be inherited directly from
the class sp_instr_opt_meta and additionally from either the class
sp_lex_instr or sp_instr depending on whether this SP instruction
need to get access to a LEX object or not.
Moreover, the class sp_cursor doesn't own a data member of
the class sp_lex_keeper any more. Instead, the virtual method
get_lex_keeper() has been added to the class sp_cursor() that
returns nullptr and this method is overridden in the derived class
sp_instr_cpush to provide a pointer to a real instance of
the class sp_lex_keeper. Doing this way we exclude duplication
of a data member of the type sp_lex_keeper at the class sp_instr_cpush
since it is derived both from sp_lex_instr and sp_cursor, and sp_lex_instr
already encapsulates a data member of the class sp_lex_keeper.
2023-07-19 12:50:47 +02:00
|
|
|
protected:
|
2023-07-19 12:53:55 +02:00
|
|
|
/**
|
|
|
|
@return the expression query string. This string can't be passed directly
|
|
|
|
to the parser as it is most likely not a valid SQL-statement.
|
|
|
|
*/
|
|
|
|
virtual LEX_CSTRING get_expr_query() const = 0;
|
|
|
|
|
2023-07-19 12:57:13 +02:00
|
|
|
/**
|
|
|
|
Some expressions may be re-parsed as SELECT statements.
|
|
|
|
This method is overridden in derived classes for instructions
|
|
|
|
those SQL command should be adjusted.
|
|
|
|
*/
|
|
|
|
virtual void adjust_sql_command(LEX *)
|
|
|
|
{}
|
|
|
|
|
|
|
|
/**
|
|
|
|
Callback method which is called after an expression string successfully
|
|
|
|
parsed and the thread context has not been switched to the outer context.
|
|
|
|
The thread context contains new LEX-object corresponding to the parsed
|
|
|
|
expression string.
|
|
|
|
|
|
|
|
@param thd Thread context.
|
|
|
|
|
|
|
|
@return Error flag.
|
|
|
|
*/
|
|
|
|
virtual bool on_after_expr_parsing(THD *)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
MDEV-5816: Stored programs: validation of stored program statements
This is the prerequisite patch introducing the class sp_lex_instr
that encapsulates access to an instance of the class sp_lex_keeper.
Every SP instruction that need to get access to a LEX object on its
processing should inherit this class and implement two abstract methods:
is_invalid(),
invalidate().
These methods will be used in subsequent patches to implement recompilation of
SP instructions on failure.
Currently, the following instructions are derived from the class sp_lex_instr:
sp_instr_stmt,
sp_instr_set,
sp_instr_set_trigger_field,
sp_instr_jump_if_not,
sp_instr_freturn,
sp_instr_cpush,
sp_instr_cursor_copy_struct,
sp_instr_set_case_expr
Additionally, this patch converts the class sp_instr_opt_meta
to a base abstract class (that is, not inherited from the class
sp_instr). Since this class originally was designed to provide a way
for opimizer to update a destination address for jump SP-instructions,
the only useful method at the interface of this class is set_destination
and therefore inheritance from the class sp_instr is meaningless.
Every jump SP instruction now must be inherited directly from
the class sp_instr_opt_meta and additionally from either the class
sp_lex_instr or sp_instr depending on whether this SP instruction
need to get access to a LEX object or not.
Moreover, the class sp_cursor doesn't own a data member of
the class sp_lex_keeper any more. Instead, the virtual method
get_lex_keeper() has been added to the class sp_cursor() that
returns nullptr and this method is overridden in the derived class
sp_instr_cpush to provide a pointer to a real instance of
the class sp_lex_keeper. Doing this way we exclude duplication
of a data member of the type sp_lex_keeper at the class sp_instr_cpush
since it is derived both from sp_lex_instr and sp_cursor, and sp_lex_instr
already encapsulates a data member of the class sp_lex_keeper.
2023-07-19 12:50:47 +02:00
|
|
|
sp_lex_keeper m_lex_keeper;
|
2023-07-19 12:57:13 +02:00
|
|
|
|
|
|
|
private:
|
2023-07-19 13:00:13 +02:00
|
|
|
/**
|
|
|
|
List of Item_trigger_field objects created on parsing of a SQL statement
|
|
|
|
corresponding to this SP-instruction.
|
|
|
|
*/
|
|
|
|
SQL_I_List<Item_trigger_field> m_cur_trigger_stmt_items;
|
|
|
|
|
2023-07-19 12:57:13 +02:00
|
|
|
/**
|
|
|
|
Clean up items previously created on behalf of the current instruction.
|
|
|
|
*/
|
2023-07-19 13:00:13 +02:00
|
|
|
void cleanup_before_parsing(enum_sp_type sp_type);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
Set up field object for every NEW/OLD item of the trigger and
|
|
|
|
move the list of Item_trigger_field objects, created on parsing the current
|
|
|
|
trigger's instruction, from sp_head to trigger's SP instruction object.
|
|
|
|
|
|
|
|
@param thd current thread
|
|
|
|
@param sp sp_head object of the trigger
|
|
|
|
@param next_trig_items_list pointer to the next list of Item_trigger_field
|
|
|
|
objects that used as a link between lists
|
|
|
|
to support list of lists structure.
|
|
|
|
|
|
|
|
@return false on success, true on failure
|
|
|
|
*/
|
|
|
|
|
|
|
|
bool setup_table_fields_for_trigger(
|
|
|
|
THD *thd, sp_head *sp,
|
|
|
|
SQL_I_List<Item_trigger_field> *next_trig_items_list);
|
MDEV-5816: Stored programs: validation of stored program statements
This is the prerequisite patch introducing the class sp_lex_instr
that encapsulates access to an instance of the class sp_lex_keeper.
Every SP instruction that need to get access to a LEX object on its
processing should inherit this class and implement two abstract methods:
is_invalid(),
invalidate().
These methods will be used in subsequent patches to implement recompilation of
SP instructions on failure.
Currently, the following instructions are derived from the class sp_lex_instr:
sp_instr_stmt,
sp_instr_set,
sp_instr_set_trigger_field,
sp_instr_jump_if_not,
sp_instr_freturn,
sp_instr_cpush,
sp_instr_cursor_copy_struct,
sp_instr_set_case_expr
Additionally, this patch converts the class sp_instr_opt_meta
to a base abstract class (that is, not inherited from the class
sp_instr). Since this class originally was designed to provide a way
for opimizer to update a destination address for jump SP-instructions,
the only useful method at the interface of this class is set_destination
and therefore inheritance from the class sp_instr is meaningless.
Every jump SP instruction now must be inherited directly from
the class sp_instr_opt_meta and additionally from either the class
sp_lex_instr or sp_instr depending on whether this SP instruction
need to get access to a LEX object or not.
Moreover, the class sp_cursor doesn't own a data member of
the class sp_lex_keeper any more. Instead, the virtual method
get_lex_keeper() has been added to the class sp_cursor() that
returns nullptr and this method is overridden in the derived class
sp_instr_cpush to provide a pointer to a real instance of
the class sp_lex_keeper. Doing this way we exclude duplication
of a data member of the type sp_lex_keeper at the class sp_instr_cpush
since it is derived both from sp_lex_instr and sp_cursor, and sp_lex_instr
already encapsulates a data member of the class sp_lex_keeper.
2023-07-19 12:50:47 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
The class sp_instr_stmt represents almost all conventional SQL-statements.
|
|
|
|
*/
|
|
|
|
|
|
|
|
class sp_instr_stmt : public sp_lex_instr
|
2023-07-19 12:43:31 +02:00
|
|
|
{
|
|
|
|
sp_instr_stmt(const sp_instr_stmt &); /**< Prevent use of these */
|
|
|
|
void operator=(sp_instr_stmt &);
|
|
|
|
|
MDEV-5816: Stored programs: validation of stored program statements
This is the prerequisite patch introducing the class sp_lex_instr
that encapsulates access to an instance of the class sp_lex_keeper.
Every SP instruction that need to get access to a LEX object on its
processing should inherit this class and implement two abstract methods:
is_invalid(),
invalidate().
These methods will be used in subsequent patches to implement recompilation of
SP instructions on failure.
Currently, the following instructions are derived from the class sp_lex_instr:
sp_instr_stmt,
sp_instr_set,
sp_instr_set_trigger_field,
sp_instr_jump_if_not,
sp_instr_freturn,
sp_instr_cpush,
sp_instr_cursor_copy_struct,
sp_instr_set_case_expr
Additionally, this patch converts the class sp_instr_opt_meta
to a base abstract class (that is, not inherited from the class
sp_instr). Since this class originally was designed to provide a way
for opimizer to update a destination address for jump SP-instructions,
the only useful method at the interface of this class is set_destination
and therefore inheritance from the class sp_instr is meaningless.
Every jump SP instruction now must be inherited directly from
the class sp_instr_opt_meta and additionally from either the class
sp_lex_instr or sp_instr depending on whether this SP instruction
need to get access to a LEX object or not.
Moreover, the class sp_cursor doesn't own a data member of
the class sp_lex_keeper any more. Instead, the virtual method
get_lex_keeper() has been added to the class sp_cursor() that
returns nullptr and this method is overridden in the derived class
sp_instr_cpush to provide a pointer to a real instance of
the class sp_lex_keeper. Doing this way we exclude duplication
of a data member of the type sp_lex_keeper at the class sp_instr_cpush
since it is derived both from sp_lex_instr and sp_cursor, and sp_lex_instr
already encapsulates a data member of the class sp_lex_keeper.
2023-07-19 12:50:47 +02:00
|
|
|
/**
|
|
|
|
Flag to tell whether a metadata this instruction depends on
|
|
|
|
has been changed and a LEX object should be reinitialized.
|
|
|
|
*/
|
|
|
|
bool m_valid;
|
|
|
|
|
2023-07-19 12:43:31 +02:00
|
|
|
LEX_STRING m_query; ///< For thd->query
|
|
|
|
|
2023-07-19 12:53:55 +02:00
|
|
|
public:
|
|
|
|
sp_instr_stmt(uint ip, sp_pcontext *ctx, LEX *lex, const LEX_STRING& query)
|
MDEV-5816: Stored programs: validation of stored program statements
This is the prerequisite patch introducing the class sp_lex_instr
that encapsulates access to an instance of the class sp_lex_keeper.
Every SP instruction that need to get access to a LEX object on its
processing should inherit this class and implement two abstract methods:
is_invalid(),
invalidate().
These methods will be used in subsequent patches to implement recompilation of
SP instructions on failure.
Currently, the following instructions are derived from the class sp_lex_instr:
sp_instr_stmt,
sp_instr_set,
sp_instr_set_trigger_field,
sp_instr_jump_if_not,
sp_instr_freturn,
sp_instr_cpush,
sp_instr_cursor_copy_struct,
sp_instr_set_case_expr
Additionally, this patch converts the class sp_instr_opt_meta
to a base abstract class (that is, not inherited from the class
sp_instr). Since this class originally was designed to provide a way
for opimizer to update a destination address for jump SP-instructions,
the only useful method at the interface of this class is set_destination
and therefore inheritance from the class sp_instr is meaningless.
Every jump SP instruction now must be inherited directly from
the class sp_instr_opt_meta and additionally from either the class
sp_lex_instr or sp_instr depending on whether this SP instruction
need to get access to a LEX object or not.
Moreover, the class sp_cursor doesn't own a data member of
the class sp_lex_keeper any more. Instead, the virtual method
get_lex_keeper() has been added to the class sp_cursor() that
returns nullptr and this method is overridden in the derived class
sp_instr_cpush to provide a pointer to a real instance of
the class sp_lex_keeper. Doing this way we exclude duplication
of a data member of the type sp_lex_keeper at the class sp_instr_cpush
since it is derived both from sp_lex_instr and sp_cursor, and sp_lex_instr
already encapsulates a data member of the class sp_lex_keeper.
2023-07-19 12:50:47 +02:00
|
|
|
: sp_lex_instr(ip, ctx, lex, true),
|
2023-07-19 12:53:55 +02:00
|
|
|
m_valid(true),
|
|
|
|
m_query(query)
|
|
|
|
{}
|
2023-07-19 12:43:31 +02:00
|
|
|
|
|
|
|
virtual ~sp_instr_stmt() = default;
|
|
|
|
|
|
|
|
int execute(THD *thd, uint *nextp) override;
|
|
|
|
|
|
|
|
int exec_core(THD *thd, uint *nextp) override;
|
|
|
|
|
|
|
|
void print(String *str) override;
|
|
|
|
|
MDEV-5816: Stored programs: validation of stored program statements
This is the prerequisite patch introducing the class sp_lex_instr
that encapsulates access to an instance of the class sp_lex_keeper.
Every SP instruction that need to get access to a LEX object on its
processing should inherit this class and implement two abstract methods:
is_invalid(),
invalidate().
These methods will be used in subsequent patches to implement recompilation of
SP instructions on failure.
Currently, the following instructions are derived from the class sp_lex_instr:
sp_instr_stmt,
sp_instr_set,
sp_instr_set_trigger_field,
sp_instr_jump_if_not,
sp_instr_freturn,
sp_instr_cpush,
sp_instr_cursor_copy_struct,
sp_instr_set_case_expr
Additionally, this patch converts the class sp_instr_opt_meta
to a base abstract class (that is, not inherited from the class
sp_instr). Since this class originally was designed to provide a way
for opimizer to update a destination address for jump SP-instructions,
the only useful method at the interface of this class is set_destination
and therefore inheritance from the class sp_instr is meaningless.
Every jump SP instruction now must be inherited directly from
the class sp_instr_opt_meta and additionally from either the class
sp_lex_instr or sp_instr depending on whether this SP instruction
need to get access to a LEX object or not.
Moreover, the class sp_cursor doesn't own a data member of
the class sp_lex_keeper any more. Instead, the virtual method
get_lex_keeper() has been added to the class sp_cursor() that
returns nullptr and this method is overridden in the derived class
sp_instr_cpush to provide a pointer to a real instance of
the class sp_lex_keeper. Doing this way we exclude duplication
of a data member of the type sp_lex_keeper at the class sp_instr_cpush
since it is derived both from sp_lex_instr and sp_cursor, and sp_lex_instr
already encapsulates a data member of the class sp_lex_keeper.
2023-07-19 12:50:47 +02:00
|
|
|
bool is_invalid() const override
|
|
|
|
{
|
|
|
|
return !m_valid;
|
|
|
|
}
|
|
|
|
|
|
|
|
void invalidate() override
|
|
|
|
{
|
|
|
|
m_valid= false;
|
|
|
|
}
|
2023-07-19 12:43:31 +02:00
|
|
|
|
2023-07-19 12:53:55 +02:00
|
|
|
void get_query(String *sql_query) const override
|
|
|
|
{
|
|
|
|
sql_query->append(get_expr_query());
|
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
LEX_CSTRING get_expr_query() const override
|
|
|
|
{
|
|
|
|
return LEX_CSTRING{m_query.str, m_query.length};
|
|
|
|
}
|
|
|
|
|
2023-07-19 12:57:13 +02:00
|
|
|
bool on_after_expr_parsing(THD *) override
|
|
|
|
{
|
|
|
|
m_valid= true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-07-19 12:43:31 +02:00
|
|
|
public:
|
|
|
|
PSI_statement_info* get_psi_info() override { return & psi_info; }
|
|
|
|
static PSI_statement_info psi_info;
|
MDEV-5816: Stored programs: validation of stored program statements
This is the prerequisite patch introducing the class sp_lex_instr
that encapsulates access to an instance of the class sp_lex_keeper.
Every SP instruction that need to get access to a LEX object on its
processing should inherit this class and implement two abstract methods:
is_invalid(),
invalidate().
These methods will be used in subsequent patches to implement recompilation of
SP instructions on failure.
Currently, the following instructions are derived from the class sp_lex_instr:
sp_instr_stmt,
sp_instr_set,
sp_instr_set_trigger_field,
sp_instr_jump_if_not,
sp_instr_freturn,
sp_instr_cpush,
sp_instr_cursor_copy_struct,
sp_instr_set_case_expr
Additionally, this patch converts the class sp_instr_opt_meta
to a base abstract class (that is, not inherited from the class
sp_instr). Since this class originally was designed to provide a way
for opimizer to update a destination address for jump SP-instructions,
the only useful method at the interface of this class is set_destination
and therefore inheritance from the class sp_instr is meaningless.
Every jump SP instruction now must be inherited directly from
the class sp_instr_opt_meta and additionally from either the class
sp_lex_instr or sp_instr depending on whether this SP instruction
need to get access to a LEX object or not.
Moreover, the class sp_cursor doesn't own a data member of
the class sp_lex_keeper any more. Instead, the virtual method
get_lex_keeper() has been added to the class sp_cursor() that
returns nullptr and this method is overridden in the derived class
sp_instr_cpush to provide a pointer to a real instance of
the class sp_lex_keeper. Doing this way we exclude duplication
of a data member of the type sp_lex_keeper at the class sp_instr_cpush
since it is derived both from sp_lex_instr and sp_cursor, and sp_lex_instr
already encapsulates a data member of the class sp_lex_keeper.
2023-07-19 12:50:47 +02:00
|
|
|
}; // class sp_instr_stmt : public sp_lex_instr
|
2023-07-19 12:43:31 +02:00
|
|
|
|
|
|
|
|
MDEV-5816: Stored programs: validation of stored program statements
This is the prerequisite patch introducing the class sp_lex_instr
that encapsulates access to an instance of the class sp_lex_keeper.
Every SP instruction that need to get access to a LEX object on its
processing should inherit this class and implement two abstract methods:
is_invalid(),
invalidate().
These methods will be used in subsequent patches to implement recompilation of
SP instructions on failure.
Currently, the following instructions are derived from the class sp_lex_instr:
sp_instr_stmt,
sp_instr_set,
sp_instr_set_trigger_field,
sp_instr_jump_if_not,
sp_instr_freturn,
sp_instr_cpush,
sp_instr_cursor_copy_struct,
sp_instr_set_case_expr
Additionally, this patch converts the class sp_instr_opt_meta
to a base abstract class (that is, not inherited from the class
sp_instr). Since this class originally was designed to provide a way
for opimizer to update a destination address for jump SP-instructions,
the only useful method at the interface of this class is set_destination
and therefore inheritance from the class sp_instr is meaningless.
Every jump SP instruction now must be inherited directly from
the class sp_instr_opt_meta and additionally from either the class
sp_lex_instr or sp_instr depending on whether this SP instruction
need to get access to a LEX object or not.
Moreover, the class sp_cursor doesn't own a data member of
the class sp_lex_keeper any more. Instead, the virtual method
get_lex_keeper() has been added to the class sp_cursor() that
returns nullptr and this method is overridden in the derived class
sp_instr_cpush to provide a pointer to a real instance of
the class sp_lex_keeper. Doing this way we exclude duplication
of a data member of the type sp_lex_keeper at the class sp_instr_cpush
since it is derived both from sp_lex_instr and sp_cursor, and sp_lex_instr
already encapsulates a data member of the class sp_lex_keeper.
2023-07-19 12:50:47 +02:00
|
|
|
class sp_instr_set : public sp_lex_instr
|
2023-07-19 12:43:31 +02:00
|
|
|
{
|
|
|
|
sp_instr_set(const sp_instr_set &); /**< Prevent use of these */
|
|
|
|
void operator=(sp_instr_set &);
|
|
|
|
|
|
|
|
public:
|
|
|
|
sp_instr_set(uint ip, sp_pcontext *ctx,
|
|
|
|
const Sp_rcontext_handler *rh,
|
|
|
|
uint offset, Item *val,
|
2023-07-19 12:53:55 +02:00
|
|
|
LEX *lex, bool lex_resp,
|
|
|
|
const LEX_CSTRING &expr_str)
|
MDEV-5816: Stored programs: validation of stored program statements
This is the prerequisite patch introducing the class sp_lex_instr
that encapsulates access to an instance of the class sp_lex_keeper.
Every SP instruction that need to get access to a LEX object on its
processing should inherit this class and implement two abstract methods:
is_invalid(),
invalidate().
These methods will be used in subsequent patches to implement recompilation of
SP instructions on failure.
Currently, the following instructions are derived from the class sp_lex_instr:
sp_instr_stmt,
sp_instr_set,
sp_instr_set_trigger_field,
sp_instr_jump_if_not,
sp_instr_freturn,
sp_instr_cpush,
sp_instr_cursor_copy_struct,
sp_instr_set_case_expr
Additionally, this patch converts the class sp_instr_opt_meta
to a base abstract class (that is, not inherited from the class
sp_instr). Since this class originally was designed to provide a way
for opimizer to update a destination address for jump SP-instructions,
the only useful method at the interface of this class is set_destination
and therefore inheritance from the class sp_instr is meaningless.
Every jump SP instruction now must be inherited directly from
the class sp_instr_opt_meta and additionally from either the class
sp_lex_instr or sp_instr depending on whether this SP instruction
need to get access to a LEX object or not.
Moreover, the class sp_cursor doesn't own a data member of
the class sp_lex_keeper any more. Instead, the virtual method
get_lex_keeper() has been added to the class sp_cursor() that
returns nullptr and this method is overridden in the derived class
sp_instr_cpush to provide a pointer to a real instance of
the class sp_lex_keeper. Doing this way we exclude duplication
of a data member of the type sp_lex_keeper at the class sp_instr_cpush
since it is derived both from sp_lex_instr and sp_cursor, and sp_lex_instr
already encapsulates a data member of the class sp_lex_keeper.
2023-07-19 12:50:47 +02:00
|
|
|
: sp_lex_instr(ip, ctx, lex, lex_resp),
|
2023-07-19 12:43:31 +02:00
|
|
|
m_rcontext_handler(rh),
|
|
|
|
m_offset(offset),
|
2023-07-19 12:53:55 +02:00
|
|
|
m_value(val),
|
|
|
|
m_expr_str(expr_str)
|
2023-07-19 12:43:31 +02:00
|
|
|
{}
|
|
|
|
|
|
|
|
virtual ~sp_instr_set() = default;
|
|
|
|
|
|
|
|
int execute(THD *thd, uint *nextp) override;
|
|
|
|
|
|
|
|
int exec_core(THD *thd, uint *nextp) override;
|
|
|
|
|
|
|
|
void print(String *str) override;
|
|
|
|
|
MDEV-5816: Stored programs: validation of stored program statements
This is the prerequisite patch introducing the class sp_lex_instr
that encapsulates access to an instance of the class sp_lex_keeper.
Every SP instruction that need to get access to a LEX object on its
processing should inherit this class and implement two abstract methods:
is_invalid(),
invalidate().
These methods will be used in subsequent patches to implement recompilation of
SP instructions on failure.
Currently, the following instructions are derived from the class sp_lex_instr:
sp_instr_stmt,
sp_instr_set,
sp_instr_set_trigger_field,
sp_instr_jump_if_not,
sp_instr_freturn,
sp_instr_cpush,
sp_instr_cursor_copy_struct,
sp_instr_set_case_expr
Additionally, this patch converts the class sp_instr_opt_meta
to a base abstract class (that is, not inherited from the class
sp_instr). Since this class originally was designed to provide a way
for opimizer to update a destination address for jump SP-instructions,
the only useful method at the interface of this class is set_destination
and therefore inheritance from the class sp_instr is meaningless.
Every jump SP instruction now must be inherited directly from
the class sp_instr_opt_meta and additionally from either the class
sp_lex_instr or sp_instr depending on whether this SP instruction
need to get access to a LEX object or not.
Moreover, the class sp_cursor doesn't own a data member of
the class sp_lex_keeper any more. Instead, the virtual method
get_lex_keeper() has been added to the class sp_cursor() that
returns nullptr and this method is overridden in the derived class
sp_instr_cpush to provide a pointer to a real instance of
the class sp_lex_keeper. Doing this way we exclude duplication
of a data member of the type sp_lex_keeper at the class sp_instr_cpush
since it is derived both from sp_lex_instr and sp_cursor, and sp_lex_instr
already encapsulates a data member of the class sp_lex_keeper.
2023-07-19 12:50:47 +02:00
|
|
|
bool is_invalid() const override
|
|
|
|
{
|
|
|
|
return m_value == nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void invalidate() override
|
|
|
|
{
|
|
|
|
m_value= nullptr;
|
|
|
|
}
|
|
|
|
|
2023-07-19 12:43:31 +02:00
|
|
|
protected:
|
2023-07-19 12:53:55 +02:00
|
|
|
LEX_CSTRING get_expr_query() const override
|
|
|
|
{
|
|
|
|
return m_expr_str;
|
|
|
|
}
|
|
|
|
|
2023-07-19 12:57:13 +02:00
|
|
|
void adjust_sql_command(LEX *lex) override
|
|
|
|
{
|
|
|
|
DBUG_ASSERT(lex->sql_command == SQLCOM_SELECT);
|
|
|
|
lex->sql_command= SQLCOM_SET_OPTION;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool on_after_expr_parsing(THD *thd) override
|
|
|
|
{
|
|
|
|
DBUG_ASSERT(thd->lex->current_select->item_list.elements == 1);
|
|
|
|
|
|
|
|
m_value= thd->lex->current_select->item_list.head();
|
|
|
|
DBUG_ASSERT(m_value != nullptr);
|
|
|
|
|
|
|
|
// Return error in release version if m_value == nullptr
|
|
|
|
return m_value == nullptr;
|
|
|
|
}
|
|
|
|
|
2023-07-19 12:43:31 +02:00
|
|
|
sp_rcontext *get_rcontext(THD *thd) const;
|
|
|
|
const Sp_rcontext_handler *m_rcontext_handler;
|
|
|
|
uint m_offset; ///< Frame offset
|
|
|
|
Item *m_value;
|
|
|
|
|
2023-07-19 12:53:55 +02:00
|
|
|
private:
|
|
|
|
LEX_CSTRING m_expr_str;
|
|
|
|
|
2023-07-19 12:43:31 +02:00
|
|
|
public:
|
|
|
|
PSI_statement_info* get_psi_info() override { return & psi_info; }
|
|
|
|
static PSI_statement_info psi_info;
|
MDEV-5816: Stored programs: validation of stored program statements
This is the prerequisite patch introducing the class sp_lex_instr
that encapsulates access to an instance of the class sp_lex_keeper.
Every SP instruction that need to get access to a LEX object on its
processing should inherit this class and implement two abstract methods:
is_invalid(),
invalidate().
These methods will be used in subsequent patches to implement recompilation of
SP instructions on failure.
Currently, the following instructions are derived from the class sp_lex_instr:
sp_instr_stmt,
sp_instr_set,
sp_instr_set_trigger_field,
sp_instr_jump_if_not,
sp_instr_freturn,
sp_instr_cpush,
sp_instr_cursor_copy_struct,
sp_instr_set_case_expr
Additionally, this patch converts the class sp_instr_opt_meta
to a base abstract class (that is, not inherited from the class
sp_instr). Since this class originally was designed to provide a way
for opimizer to update a destination address for jump SP-instructions,
the only useful method at the interface of this class is set_destination
and therefore inheritance from the class sp_instr is meaningless.
Every jump SP instruction now must be inherited directly from
the class sp_instr_opt_meta and additionally from either the class
sp_lex_instr or sp_instr depending on whether this SP instruction
need to get access to a LEX object or not.
Moreover, the class sp_cursor doesn't own a data member of
the class sp_lex_keeper any more. Instead, the virtual method
get_lex_keeper() has been added to the class sp_cursor() that
returns nullptr and this method is overridden in the derived class
sp_instr_cpush to provide a pointer to a real instance of
the class sp_lex_keeper. Doing this way we exclude duplication
of a data member of the type sp_lex_keeper at the class sp_instr_cpush
since it is derived both from sp_lex_instr and sp_cursor, and sp_lex_instr
already encapsulates a data member of the class sp_lex_keeper.
2023-07-19 12:50:47 +02:00
|
|
|
}; // class sp_instr_set : public sp_lex_instr
|
2023-07-19 12:43:31 +02:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
This class handles assignments of a ROW fields:
|
|
|
|
DECLARE rec ROW (a INT,b INT);
|
|
|
|
SET rec.a= 10;
|
|
|
|
*/
|
|
|
|
|
|
|
|
class sp_instr_set_row_field : public sp_instr_set
|
|
|
|
{
|
|
|
|
sp_instr_set_row_field(const sp_instr_set_row_field &); // Prevent use of this
|
|
|
|
void operator=(sp_instr_set_row_field &);
|
|
|
|
uint m_field_offset;
|
|
|
|
|
|
|
|
public:
|
|
|
|
sp_instr_set_row_field(uint ip, sp_pcontext *ctx,
|
|
|
|
const Sp_rcontext_handler *rh,
|
|
|
|
uint offset, uint field_offset,
|
|
|
|
Item *val,
|
2023-07-19 12:53:55 +02:00
|
|
|
LEX *lex, bool lex_resp,
|
|
|
|
const LEX_CSTRING &value_query)
|
|
|
|
: sp_instr_set(ip, ctx, rh, offset, val, lex, lex_resp, value_query),
|
2023-07-19 12:43:31 +02:00
|
|
|
m_field_offset(field_offset)
|
|
|
|
{}
|
|
|
|
|
|
|
|
virtual ~sp_instr_set_row_field() = default;
|
|
|
|
|
|
|
|
int exec_core(THD *thd, uint *nextp) override;
|
|
|
|
|
|
|
|
void print(String *str) override;
|
|
|
|
}; // class sp_instr_set_field : public sp_instr_set
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
This class handles assignment instructions like this:
|
|
|
|
DECLARE
|
|
|
|
CURSOR cur IS SELECT * FROM t1;
|
|
|
|
rec cur%ROWTYPE;
|
|
|
|
BEGIN
|
|
|
|
rec.column1:= 10; -- This instruction
|
|
|
|
END;
|
|
|
|
|
|
|
|
The idea is that during sp_rcontext::create() we do not know the extact
|
|
|
|
structure of "rec". It gets resolved at run time, during the corresponding
|
|
|
|
sp_instr_cursor_copy_struct::exec_core().
|
|
|
|
|
|
|
|
So sp_instr_set_row_field_by_name searches for ROW fields by name,
|
|
|
|
while sp_instr_set_row_field (see above) searches for ROW fields by index.
|
|
|
|
*/
|
|
|
|
|
|
|
|
class sp_instr_set_row_field_by_name : public sp_instr_set
|
|
|
|
{
|
|
|
|
// Prevent use of this
|
|
|
|
sp_instr_set_row_field_by_name(const sp_instr_set_row_field &);
|
|
|
|
void operator=(sp_instr_set_row_field_by_name &);
|
|
|
|
const LEX_CSTRING m_field_name;
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
sp_instr_set_row_field_by_name(uint ip, sp_pcontext *ctx,
|
|
|
|
const Sp_rcontext_handler *rh,
|
|
|
|
uint offset, const LEX_CSTRING &field_name,
|
|
|
|
Item *val,
|
2023-07-19 12:53:55 +02:00
|
|
|
LEX *lex, bool lex_resp,
|
|
|
|
const LEX_CSTRING &value_query)
|
|
|
|
: sp_instr_set(ip, ctx, rh, offset, val, lex, lex_resp, value_query),
|
2023-07-19 12:43:31 +02:00
|
|
|
m_field_name(field_name)
|
|
|
|
{}
|
|
|
|
|
|
|
|
virtual ~sp_instr_set_row_field_by_name() = default;
|
|
|
|
|
|
|
|
int exec_core(THD *thd, uint *nextp) override;
|
|
|
|
|
|
|
|
void print(String *str) override;
|
|
|
|
}; // class sp_instr_set_field_by_name : public sp_instr_set
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
Set NEW/OLD row field value instruction. Used in triggers.
|
|
|
|
*/
|
|
|
|
|
MDEV-5816: Stored programs: validation of stored program statements
This is the prerequisite patch introducing the class sp_lex_instr
that encapsulates access to an instance of the class sp_lex_keeper.
Every SP instruction that need to get access to a LEX object on its
processing should inherit this class and implement two abstract methods:
is_invalid(),
invalidate().
These methods will be used in subsequent patches to implement recompilation of
SP instructions on failure.
Currently, the following instructions are derived from the class sp_lex_instr:
sp_instr_stmt,
sp_instr_set,
sp_instr_set_trigger_field,
sp_instr_jump_if_not,
sp_instr_freturn,
sp_instr_cpush,
sp_instr_cursor_copy_struct,
sp_instr_set_case_expr
Additionally, this patch converts the class sp_instr_opt_meta
to a base abstract class (that is, not inherited from the class
sp_instr). Since this class originally was designed to provide a way
for opimizer to update a destination address for jump SP-instructions,
the only useful method at the interface of this class is set_destination
and therefore inheritance from the class sp_instr is meaningless.
Every jump SP instruction now must be inherited directly from
the class sp_instr_opt_meta and additionally from either the class
sp_lex_instr or sp_instr depending on whether this SP instruction
need to get access to a LEX object or not.
Moreover, the class sp_cursor doesn't own a data member of
the class sp_lex_keeper any more. Instead, the virtual method
get_lex_keeper() has been added to the class sp_cursor() that
returns nullptr and this method is overridden in the derived class
sp_instr_cpush to provide a pointer to a real instance of
the class sp_lex_keeper. Doing this way we exclude duplication
of a data member of the type sp_lex_keeper at the class sp_instr_cpush
since it is derived both from sp_lex_instr and sp_cursor, and sp_lex_instr
already encapsulates a data member of the class sp_lex_keeper.
2023-07-19 12:50:47 +02:00
|
|
|
class sp_instr_set_trigger_field : public sp_lex_instr
|
2023-07-19 12:43:31 +02:00
|
|
|
{
|
|
|
|
sp_instr_set_trigger_field(const sp_instr_set_trigger_field &);
|
|
|
|
void operator=(sp_instr_set_trigger_field &);
|
|
|
|
|
|
|
|
public:
|
|
|
|
sp_instr_set_trigger_field(uint ip, sp_pcontext *ctx,
|
|
|
|
Item_trigger_field *trg_fld,
|
2023-07-19 12:53:55 +02:00
|
|
|
Item *val, LEX *lex,
|
|
|
|
const LEX_CSTRING &value_query)
|
MDEV-5816: Stored programs: validation of stored program statements
This is the prerequisite patch introducing the class sp_lex_instr
that encapsulates access to an instance of the class sp_lex_keeper.
Every SP instruction that need to get access to a LEX object on its
processing should inherit this class and implement two abstract methods:
is_invalid(),
invalidate().
These methods will be used in subsequent patches to implement recompilation of
SP instructions on failure.
Currently, the following instructions are derived from the class sp_lex_instr:
sp_instr_stmt,
sp_instr_set,
sp_instr_set_trigger_field,
sp_instr_jump_if_not,
sp_instr_freturn,
sp_instr_cpush,
sp_instr_cursor_copy_struct,
sp_instr_set_case_expr
Additionally, this patch converts the class sp_instr_opt_meta
to a base abstract class (that is, not inherited from the class
sp_instr). Since this class originally was designed to provide a way
for opimizer to update a destination address for jump SP-instructions,
the only useful method at the interface of this class is set_destination
and therefore inheritance from the class sp_instr is meaningless.
Every jump SP instruction now must be inherited directly from
the class sp_instr_opt_meta and additionally from either the class
sp_lex_instr or sp_instr depending on whether this SP instruction
need to get access to a LEX object or not.
Moreover, the class sp_cursor doesn't own a data member of
the class sp_lex_keeper any more. Instead, the virtual method
get_lex_keeper() has been added to the class sp_cursor() that
returns nullptr and this method is overridden in the derived class
sp_instr_cpush to provide a pointer to a real instance of
the class sp_lex_keeper. Doing this way we exclude duplication
of a data member of the type sp_lex_keeper at the class sp_instr_cpush
since it is derived both from sp_lex_instr and sp_cursor, and sp_lex_instr
already encapsulates a data member of the class sp_lex_keeper.
2023-07-19 12:50:47 +02:00
|
|
|
: sp_lex_instr(ip, ctx, lex, true),
|
2023-07-19 12:43:31 +02:00
|
|
|
trigger_field(trg_fld),
|
2023-07-19 12:53:55 +02:00
|
|
|
value(val),
|
|
|
|
m_expr_str(value_query)
|
2023-07-19 12:57:13 +02:00
|
|
|
{
|
|
|
|
m_trigger_field_name=
|
|
|
|
LEX_CSTRING{strdup_root(current_thd->mem_root, trg_fld->field_name.str),
|
|
|
|
trg_fld->field_name.length};
|
|
|
|
}
|
2023-07-19 12:43:31 +02:00
|
|
|
|
|
|
|
virtual ~sp_instr_set_trigger_field() = default;
|
|
|
|
|
|
|
|
int execute(THD *thd, uint *nextp) override;
|
|
|
|
|
|
|
|
int exec_core(THD *thd, uint *nextp) override;
|
|
|
|
|
|
|
|
void print(String *str) override;
|
|
|
|
|
MDEV-5816: Stored programs: validation of stored program statements
This is the prerequisite patch introducing the class sp_lex_instr
that encapsulates access to an instance of the class sp_lex_keeper.
Every SP instruction that need to get access to a LEX object on its
processing should inherit this class and implement two abstract methods:
is_invalid(),
invalidate().
These methods will be used in subsequent patches to implement recompilation of
SP instructions on failure.
Currently, the following instructions are derived from the class sp_lex_instr:
sp_instr_stmt,
sp_instr_set,
sp_instr_set_trigger_field,
sp_instr_jump_if_not,
sp_instr_freturn,
sp_instr_cpush,
sp_instr_cursor_copy_struct,
sp_instr_set_case_expr
Additionally, this patch converts the class sp_instr_opt_meta
to a base abstract class (that is, not inherited from the class
sp_instr). Since this class originally was designed to provide a way
for opimizer to update a destination address for jump SP-instructions,
the only useful method at the interface of this class is set_destination
and therefore inheritance from the class sp_instr is meaningless.
Every jump SP instruction now must be inherited directly from
the class sp_instr_opt_meta and additionally from either the class
sp_lex_instr or sp_instr depending on whether this SP instruction
need to get access to a LEX object or not.
Moreover, the class sp_cursor doesn't own a data member of
the class sp_lex_keeper any more. Instead, the virtual method
get_lex_keeper() has been added to the class sp_cursor() that
returns nullptr and this method is overridden in the derived class
sp_instr_cpush to provide a pointer to a real instance of
the class sp_lex_keeper. Doing this way we exclude duplication
of a data member of the type sp_lex_keeper at the class sp_instr_cpush
since it is derived both from sp_lex_instr and sp_cursor, and sp_lex_instr
already encapsulates a data member of the class sp_lex_keeper.
2023-07-19 12:50:47 +02:00
|
|
|
bool is_invalid() const override
|
|
|
|
{
|
|
|
|
return value == nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void invalidate() override
|
|
|
|
{
|
|
|
|
value= nullptr;
|
|
|
|
}
|
|
|
|
|
2023-07-19 12:53:55 +02:00
|
|
|
protected:
|
|
|
|
LEX_CSTRING get_expr_query() const override
|
|
|
|
{
|
|
|
|
return m_expr_str;
|
|
|
|
}
|
|
|
|
|
2023-07-19 12:57:13 +02:00
|
|
|
bool on_after_expr_parsing(THD *thd) override;
|
|
|
|
|
2023-07-19 12:43:31 +02:00
|
|
|
private:
|
|
|
|
Item_trigger_field *trigger_field;
|
|
|
|
Item *value;
|
2023-07-19 12:53:55 +02:00
|
|
|
/**
|
|
|
|
SQL clause corresponding to the expression value.
|
|
|
|
*/
|
|
|
|
LEX_CSTRING m_expr_str;
|
2023-07-19 12:43:31 +02:00
|
|
|
|
2023-07-19 12:57:13 +02:00
|
|
|
LEX_CSTRING m_trigger_field_name;
|
|
|
|
|
2023-07-19 12:43:31 +02:00
|
|
|
public:
|
|
|
|
PSI_statement_info* get_psi_info() override { return & psi_info; }
|
|
|
|
static PSI_statement_info psi_info;
|
MDEV-5816: Stored programs: validation of stored program statements
This is the prerequisite patch introducing the class sp_lex_instr
that encapsulates access to an instance of the class sp_lex_keeper.
Every SP instruction that need to get access to a LEX object on its
processing should inherit this class and implement two abstract methods:
is_invalid(),
invalidate().
These methods will be used in subsequent patches to implement recompilation of
SP instructions on failure.
Currently, the following instructions are derived from the class sp_lex_instr:
sp_instr_stmt,
sp_instr_set,
sp_instr_set_trigger_field,
sp_instr_jump_if_not,
sp_instr_freturn,
sp_instr_cpush,
sp_instr_cursor_copy_struct,
sp_instr_set_case_expr
Additionally, this patch converts the class sp_instr_opt_meta
to a base abstract class (that is, not inherited from the class
sp_instr). Since this class originally was designed to provide a way
for opimizer to update a destination address for jump SP-instructions,
the only useful method at the interface of this class is set_destination
and therefore inheritance from the class sp_instr is meaningless.
Every jump SP instruction now must be inherited directly from
the class sp_instr_opt_meta and additionally from either the class
sp_lex_instr or sp_instr depending on whether this SP instruction
need to get access to a LEX object or not.
Moreover, the class sp_cursor doesn't own a data member of
the class sp_lex_keeper any more. Instead, the virtual method
get_lex_keeper() has been added to the class sp_cursor() that
returns nullptr and this method is overridden in the derived class
sp_instr_cpush to provide a pointer to a real instance of
the class sp_lex_keeper. Doing this way we exclude duplication
of a data member of the type sp_lex_keeper at the class sp_instr_cpush
since it is derived both from sp_lex_instr and sp_cursor, and sp_lex_instr
already encapsulates a data member of the class sp_lex_keeper.
2023-07-19 12:50:47 +02:00
|
|
|
}; // class sp_instr_trigger_field : public sp_lex_instr
|
2023-07-19 12:43:31 +02:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
An abstract class for all instructions with destinations that
|
|
|
|
needs to be updated by the optimizer.
|
|
|
|
|
|
|
|
Even if not all subclasses will use both the normal destination and
|
|
|
|
the continuation destination, we put them both here for simplicity.
|
|
|
|
*/
|
|
|
|
|
MDEV-5816: Stored programs: validation of stored program statements
This is the prerequisite patch introducing the class sp_lex_instr
that encapsulates access to an instance of the class sp_lex_keeper.
Every SP instruction that need to get access to a LEX object on its
processing should inherit this class and implement two abstract methods:
is_invalid(),
invalidate().
These methods will be used in subsequent patches to implement recompilation of
SP instructions on failure.
Currently, the following instructions are derived from the class sp_lex_instr:
sp_instr_stmt,
sp_instr_set,
sp_instr_set_trigger_field,
sp_instr_jump_if_not,
sp_instr_freturn,
sp_instr_cpush,
sp_instr_cursor_copy_struct,
sp_instr_set_case_expr
Additionally, this patch converts the class sp_instr_opt_meta
to a base abstract class (that is, not inherited from the class
sp_instr). Since this class originally was designed to provide a way
for opimizer to update a destination address for jump SP-instructions,
the only useful method at the interface of this class is set_destination
and therefore inheritance from the class sp_instr is meaningless.
Every jump SP instruction now must be inherited directly from
the class sp_instr_opt_meta and additionally from either the class
sp_lex_instr or sp_instr depending on whether this SP instruction
need to get access to a LEX object or not.
Moreover, the class sp_cursor doesn't own a data member of
the class sp_lex_keeper any more. Instead, the virtual method
get_lex_keeper() has been added to the class sp_cursor() that
returns nullptr and this method is overridden in the derived class
sp_instr_cpush to provide a pointer to a real instance of
the class sp_lex_keeper. Doing this way we exclude duplication
of a data member of the type sp_lex_keeper at the class sp_instr_cpush
since it is derived both from sp_lex_instr and sp_cursor, and sp_lex_instr
already encapsulates a data member of the class sp_lex_keeper.
2023-07-19 12:50:47 +02:00
|
|
|
class sp_instr_opt_meta
|
2023-07-19 12:43:31 +02:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
uint m_dest; ///< Where we will go
|
|
|
|
uint m_cont_dest; ///< Where continue handlers will go
|
|
|
|
|
MDEV-5816: Stored programs: validation of stored program statements
This is the prerequisite patch introducing the class sp_lex_instr
that encapsulates access to an instance of the class sp_lex_keeper.
Every SP instruction that need to get access to a LEX object on its
processing should inherit this class and implement two abstract methods:
is_invalid(),
invalidate().
These methods will be used in subsequent patches to implement recompilation of
SP instructions on failure.
Currently, the following instructions are derived from the class sp_lex_instr:
sp_instr_stmt,
sp_instr_set,
sp_instr_set_trigger_field,
sp_instr_jump_if_not,
sp_instr_freturn,
sp_instr_cpush,
sp_instr_cursor_copy_struct,
sp_instr_set_case_expr
Additionally, this patch converts the class sp_instr_opt_meta
to a base abstract class (that is, not inherited from the class
sp_instr). Since this class originally was designed to provide a way
for opimizer to update a destination address for jump SP-instructions,
the only useful method at the interface of this class is set_destination
and therefore inheritance from the class sp_instr is meaningless.
Every jump SP instruction now must be inherited directly from
the class sp_instr_opt_meta and additionally from either the class
sp_lex_instr or sp_instr depending on whether this SP instruction
need to get access to a LEX object or not.
Moreover, the class sp_cursor doesn't own a data member of
the class sp_lex_keeper any more. Instead, the virtual method
get_lex_keeper() has been added to the class sp_cursor() that
returns nullptr and this method is overridden in the derived class
sp_instr_cpush to provide a pointer to a real instance of
the class sp_lex_keeper. Doing this way we exclude duplication
of a data member of the type sp_lex_keeper at the class sp_instr_cpush
since it is derived both from sp_lex_instr and sp_cursor, and sp_lex_instr
already encapsulates a data member of the class sp_lex_keeper.
2023-07-19 12:50:47 +02:00
|
|
|
explicit sp_instr_opt_meta(uint dest)
|
|
|
|
: m_dest(dest),
|
2023-07-19 12:43:31 +02:00
|
|
|
m_cont_dest(0),
|
|
|
|
m_optdest(0),
|
|
|
|
m_cont_optdest(0)
|
|
|
|
{}
|
|
|
|
|
|
|
|
virtual ~sp_instr_opt_meta() = default;
|
|
|
|
|
|
|
|
virtual void set_destination(uint old_dest, uint new_dest) = 0;
|
|
|
|
|
|
|
|
protected:
|
|
|
|
sp_instr *m_optdest; ///< Used during optimization
|
|
|
|
sp_instr *m_cont_optdest; ///< Used during optimization
|
MDEV-5816: Stored programs: validation of stored program statements
This is the prerequisite patch introducing the class sp_lex_instr
that encapsulates access to an instance of the class sp_lex_keeper.
Every SP instruction that need to get access to a LEX object on its
processing should inherit this class and implement two abstract methods:
is_invalid(),
invalidate().
These methods will be used in subsequent patches to implement recompilation of
SP instructions on failure.
Currently, the following instructions are derived from the class sp_lex_instr:
sp_instr_stmt,
sp_instr_set,
sp_instr_set_trigger_field,
sp_instr_jump_if_not,
sp_instr_freturn,
sp_instr_cpush,
sp_instr_cursor_copy_struct,
sp_instr_set_case_expr
Additionally, this patch converts the class sp_instr_opt_meta
to a base abstract class (that is, not inherited from the class
sp_instr). Since this class originally was designed to provide a way
for opimizer to update a destination address for jump SP-instructions,
the only useful method at the interface of this class is set_destination
and therefore inheritance from the class sp_instr is meaningless.
Every jump SP instruction now must be inherited directly from
the class sp_instr_opt_meta and additionally from either the class
sp_lex_instr or sp_instr depending on whether this SP instruction
need to get access to a LEX object or not.
Moreover, the class sp_cursor doesn't own a data member of
the class sp_lex_keeper any more. Instead, the virtual method
get_lex_keeper() has been added to the class sp_cursor() that
returns nullptr and this method is overridden in the derived class
sp_instr_cpush to provide a pointer to a real instance of
the class sp_lex_keeper. Doing this way we exclude duplication
of a data member of the type sp_lex_keeper at the class sp_instr_cpush
since it is derived both from sp_lex_instr and sp_cursor, and sp_lex_instr
already encapsulates a data member of the class sp_lex_keeper.
2023-07-19 12:50:47 +02:00
|
|
|
}; // class sp_instr_opt_meta
|
2023-07-19 12:43:31 +02:00
|
|
|
|
|
|
|
|
MDEV-5816: Stored programs: validation of stored program statements
This is the prerequisite patch introducing the class sp_lex_instr
that encapsulates access to an instance of the class sp_lex_keeper.
Every SP instruction that need to get access to a LEX object on its
processing should inherit this class and implement two abstract methods:
is_invalid(),
invalidate().
These methods will be used in subsequent patches to implement recompilation of
SP instructions on failure.
Currently, the following instructions are derived from the class sp_lex_instr:
sp_instr_stmt,
sp_instr_set,
sp_instr_set_trigger_field,
sp_instr_jump_if_not,
sp_instr_freturn,
sp_instr_cpush,
sp_instr_cursor_copy_struct,
sp_instr_set_case_expr
Additionally, this patch converts the class sp_instr_opt_meta
to a base abstract class (that is, not inherited from the class
sp_instr). Since this class originally was designed to provide a way
for opimizer to update a destination address for jump SP-instructions,
the only useful method at the interface of this class is set_destination
and therefore inheritance from the class sp_instr is meaningless.
Every jump SP instruction now must be inherited directly from
the class sp_instr_opt_meta and additionally from either the class
sp_lex_instr or sp_instr depending on whether this SP instruction
need to get access to a LEX object or not.
Moreover, the class sp_cursor doesn't own a data member of
the class sp_lex_keeper any more. Instead, the virtual method
get_lex_keeper() has been added to the class sp_cursor() that
returns nullptr and this method is overridden in the derived class
sp_instr_cpush to provide a pointer to a real instance of
the class sp_lex_keeper. Doing this way we exclude duplication
of a data member of the type sp_lex_keeper at the class sp_instr_cpush
since it is derived both from sp_lex_instr and sp_cursor, and sp_lex_instr
already encapsulates a data member of the class sp_lex_keeper.
2023-07-19 12:50:47 +02:00
|
|
|
class sp_instr_jump : public sp_instr, public sp_instr_opt_meta
|
2023-07-19 12:43:31 +02:00
|
|
|
{
|
|
|
|
sp_instr_jump(const sp_instr_jump &); /**< Prevent use of these */
|
|
|
|
void operator=(sp_instr_jump &);
|
|
|
|
|
|
|
|
public:
|
|
|
|
sp_instr_jump(uint ip, sp_pcontext *ctx)
|
MDEV-5816: Stored programs: validation of stored program statements
This is the prerequisite patch introducing the class sp_lex_instr
that encapsulates access to an instance of the class sp_lex_keeper.
Every SP instruction that need to get access to a LEX object on its
processing should inherit this class and implement two abstract methods:
is_invalid(),
invalidate().
These methods will be used in subsequent patches to implement recompilation of
SP instructions on failure.
Currently, the following instructions are derived from the class sp_lex_instr:
sp_instr_stmt,
sp_instr_set,
sp_instr_set_trigger_field,
sp_instr_jump_if_not,
sp_instr_freturn,
sp_instr_cpush,
sp_instr_cursor_copy_struct,
sp_instr_set_case_expr
Additionally, this patch converts the class sp_instr_opt_meta
to a base abstract class (that is, not inherited from the class
sp_instr). Since this class originally was designed to provide a way
for opimizer to update a destination address for jump SP-instructions,
the only useful method at the interface of this class is set_destination
and therefore inheritance from the class sp_instr is meaningless.
Every jump SP instruction now must be inherited directly from
the class sp_instr_opt_meta and additionally from either the class
sp_lex_instr or sp_instr depending on whether this SP instruction
need to get access to a LEX object or not.
Moreover, the class sp_cursor doesn't own a data member of
the class sp_lex_keeper any more. Instead, the virtual method
get_lex_keeper() has been added to the class sp_cursor() that
returns nullptr and this method is overridden in the derived class
sp_instr_cpush to provide a pointer to a real instance of
the class sp_lex_keeper. Doing this way we exclude duplication
of a data member of the type sp_lex_keeper at the class sp_instr_cpush
since it is derived both from sp_lex_instr and sp_cursor, and sp_lex_instr
already encapsulates a data member of the class sp_lex_keeper.
2023-07-19 12:50:47 +02:00
|
|
|
: sp_instr(ip, ctx),
|
|
|
|
sp_instr_opt_meta(0)
|
2023-07-19 12:43:31 +02:00
|
|
|
{}
|
|
|
|
|
|
|
|
sp_instr_jump(uint ip, sp_pcontext *ctx, uint dest)
|
MDEV-5816: Stored programs: validation of stored program statements
This is the prerequisite patch introducing the class sp_lex_instr
that encapsulates access to an instance of the class sp_lex_keeper.
Every SP instruction that need to get access to a LEX object on its
processing should inherit this class and implement two abstract methods:
is_invalid(),
invalidate().
These methods will be used in subsequent patches to implement recompilation of
SP instructions on failure.
Currently, the following instructions are derived from the class sp_lex_instr:
sp_instr_stmt,
sp_instr_set,
sp_instr_set_trigger_field,
sp_instr_jump_if_not,
sp_instr_freturn,
sp_instr_cpush,
sp_instr_cursor_copy_struct,
sp_instr_set_case_expr
Additionally, this patch converts the class sp_instr_opt_meta
to a base abstract class (that is, not inherited from the class
sp_instr). Since this class originally was designed to provide a way
for opimizer to update a destination address for jump SP-instructions,
the only useful method at the interface of this class is set_destination
and therefore inheritance from the class sp_instr is meaningless.
Every jump SP instruction now must be inherited directly from
the class sp_instr_opt_meta and additionally from either the class
sp_lex_instr or sp_instr depending on whether this SP instruction
need to get access to a LEX object or not.
Moreover, the class sp_cursor doesn't own a data member of
the class sp_lex_keeper any more. Instead, the virtual method
get_lex_keeper() has been added to the class sp_cursor() that
returns nullptr and this method is overridden in the derived class
sp_instr_cpush to provide a pointer to a real instance of
the class sp_lex_keeper. Doing this way we exclude duplication
of a data member of the type sp_lex_keeper at the class sp_instr_cpush
since it is derived both from sp_lex_instr and sp_cursor, and sp_lex_instr
already encapsulates a data member of the class sp_lex_keeper.
2023-07-19 12:50:47 +02:00
|
|
|
: sp_instr(ip, ctx),
|
|
|
|
sp_instr_opt_meta(dest)
|
2023-07-19 12:43:31 +02:00
|
|
|
{}
|
|
|
|
|
|
|
|
virtual ~sp_instr_jump() = default;
|
|
|
|
|
|
|
|
int execute(THD *thd, uint *nextp) override;
|
|
|
|
|
|
|
|
void print(String *str) override;
|
|
|
|
|
|
|
|
uint opt_mark(sp_head *sp, List<sp_instr> *leads) override;
|
|
|
|
|
|
|
|
uint opt_shortcut_jump(sp_head *sp, sp_instr *start) override;
|
|
|
|
|
2023-07-19 12:48:31 +02:00
|
|
|
void opt_move(uint dst, List<sp_instr_opt_meta> *ibp) override;
|
2023-07-19 12:43:31 +02:00
|
|
|
|
|
|
|
void backpatch(uint dest, sp_pcontext *dst_ctx) override
|
|
|
|
{
|
|
|
|
/* Calling backpatch twice is a logic flaw in jump resolution. */
|
|
|
|
DBUG_ASSERT(m_dest == 0);
|
|
|
|
m_dest= dest;
|
|
|
|
}
|
|
|
|
|
MDEV-5816: Stored programs: validation of stored program statements
This is the prerequisite patch introducing the class sp_lex_instr
that encapsulates access to an instance of the class sp_lex_keeper.
Every SP instruction that need to get access to a LEX object on its
processing should inherit this class and implement two abstract methods:
is_invalid(),
invalidate().
These methods will be used in subsequent patches to implement recompilation of
SP instructions on failure.
Currently, the following instructions are derived from the class sp_lex_instr:
sp_instr_stmt,
sp_instr_set,
sp_instr_set_trigger_field,
sp_instr_jump_if_not,
sp_instr_freturn,
sp_instr_cpush,
sp_instr_cursor_copy_struct,
sp_instr_set_case_expr
Additionally, this patch converts the class sp_instr_opt_meta
to a base abstract class (that is, not inherited from the class
sp_instr). Since this class originally was designed to provide a way
for opimizer to update a destination address for jump SP-instructions,
the only useful method at the interface of this class is set_destination
and therefore inheritance from the class sp_instr is meaningless.
Every jump SP instruction now must be inherited directly from
the class sp_instr_opt_meta and additionally from either the class
sp_lex_instr or sp_instr depending on whether this SP instruction
need to get access to a LEX object or not.
Moreover, the class sp_cursor doesn't own a data member of
the class sp_lex_keeper any more. Instead, the virtual method
get_lex_keeper() has been added to the class sp_cursor() that
returns nullptr and this method is overridden in the derived class
sp_instr_cpush to provide a pointer to a real instance of
the class sp_lex_keeper. Doing this way we exclude duplication
of a data member of the type sp_lex_keeper at the class sp_instr_cpush
since it is derived both from sp_lex_instr and sp_cursor, and sp_lex_instr
already encapsulates a data member of the class sp_lex_keeper.
2023-07-19 12:50:47 +02:00
|
|
|
uint get_cont_dest() const override
|
|
|
|
{
|
|
|
|
return m_cont_dest;
|
|
|
|
}
|
|
|
|
|
2023-07-19 12:43:31 +02:00
|
|
|
/**
|
|
|
|
Update the destination; used by the optimizer.
|
|
|
|
*/
|
|
|
|
void set_destination(uint old_dest, uint new_dest) override
|
|
|
|
{
|
|
|
|
if (m_dest == old_dest)
|
|
|
|
m_dest= new_dest;
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
PSI_statement_info* get_psi_info() override { return & psi_info; }
|
|
|
|
static PSI_statement_info psi_info;
|
MDEV-5816: Stored programs: validation of stored program statements
This is the prerequisite patch introducing the class sp_lex_instr
that encapsulates access to an instance of the class sp_lex_keeper.
Every SP instruction that need to get access to a LEX object on its
processing should inherit this class and implement two abstract methods:
is_invalid(),
invalidate().
These methods will be used in subsequent patches to implement recompilation of
SP instructions on failure.
Currently, the following instructions are derived from the class sp_lex_instr:
sp_instr_stmt,
sp_instr_set,
sp_instr_set_trigger_field,
sp_instr_jump_if_not,
sp_instr_freturn,
sp_instr_cpush,
sp_instr_cursor_copy_struct,
sp_instr_set_case_expr
Additionally, this patch converts the class sp_instr_opt_meta
to a base abstract class (that is, not inherited from the class
sp_instr). Since this class originally was designed to provide a way
for opimizer to update a destination address for jump SP-instructions,
the only useful method at the interface of this class is set_destination
and therefore inheritance from the class sp_instr is meaningless.
Every jump SP instruction now must be inherited directly from
the class sp_instr_opt_meta and additionally from either the class
sp_lex_instr or sp_instr depending on whether this SP instruction
need to get access to a LEX object or not.
Moreover, the class sp_cursor doesn't own a data member of
the class sp_lex_keeper any more. Instead, the virtual method
get_lex_keeper() has been added to the class sp_cursor() that
returns nullptr and this method is overridden in the derived class
sp_instr_cpush to provide a pointer to a real instance of
the class sp_lex_keeper. Doing this way we exclude duplication
of a data member of the type sp_lex_keeper at the class sp_instr_cpush
since it is derived both from sp_lex_instr and sp_cursor, and sp_lex_instr
already encapsulates a data member of the class sp_lex_keeper.
2023-07-19 12:50:47 +02:00
|
|
|
}; // class sp_instr_jump : public sp_instr, public sp_instr_opt_meta
|
2023-07-19 12:43:31 +02:00
|
|
|
|
|
|
|
|
MDEV-5816: Stored programs: validation of stored program statements
This is the prerequisite patch introducing the class sp_lex_instr
that encapsulates access to an instance of the class sp_lex_keeper.
Every SP instruction that need to get access to a LEX object on its
processing should inherit this class and implement two abstract methods:
is_invalid(),
invalidate().
These methods will be used in subsequent patches to implement recompilation of
SP instructions on failure.
Currently, the following instructions are derived from the class sp_lex_instr:
sp_instr_stmt,
sp_instr_set,
sp_instr_set_trigger_field,
sp_instr_jump_if_not,
sp_instr_freturn,
sp_instr_cpush,
sp_instr_cursor_copy_struct,
sp_instr_set_case_expr
Additionally, this patch converts the class sp_instr_opt_meta
to a base abstract class (that is, not inherited from the class
sp_instr). Since this class originally was designed to provide a way
for opimizer to update a destination address for jump SP-instructions,
the only useful method at the interface of this class is set_destination
and therefore inheritance from the class sp_instr is meaningless.
Every jump SP instruction now must be inherited directly from
the class sp_instr_opt_meta and additionally from either the class
sp_lex_instr or sp_instr depending on whether this SP instruction
need to get access to a LEX object or not.
Moreover, the class sp_cursor doesn't own a data member of
the class sp_lex_keeper any more. Instead, the virtual method
get_lex_keeper() has been added to the class sp_cursor() that
returns nullptr and this method is overridden in the derived class
sp_instr_cpush to provide a pointer to a real instance of
the class sp_lex_keeper. Doing this way we exclude duplication
of a data member of the type sp_lex_keeper at the class sp_instr_cpush
since it is derived both from sp_lex_instr and sp_cursor, and sp_lex_instr
already encapsulates a data member of the class sp_lex_keeper.
2023-07-19 12:50:47 +02:00
|
|
|
class sp_instr_jump_if_not : public sp_lex_instr, public sp_instr_opt_meta
|
2023-07-19 12:43:31 +02:00
|
|
|
{
|
|
|
|
/**< Prevent use of these */
|
|
|
|
sp_instr_jump_if_not(const sp_instr_jump_if_not &);
|
|
|
|
void operator=(sp_instr_jump_if_not &);
|
|
|
|
|
|
|
|
public:
|
2023-07-19 12:53:55 +02:00
|
|
|
sp_instr_jump_if_not(uint ip, sp_pcontext *ctx, Item *i, LEX *lex,
|
|
|
|
const LEX_CSTRING &expr_query)
|
MDEV-5816: Stored programs: validation of stored program statements
This is the prerequisite patch introducing the class sp_lex_instr
that encapsulates access to an instance of the class sp_lex_keeper.
Every SP instruction that need to get access to a LEX object on its
processing should inherit this class and implement two abstract methods:
is_invalid(),
invalidate().
These methods will be used in subsequent patches to implement recompilation of
SP instructions on failure.
Currently, the following instructions are derived from the class sp_lex_instr:
sp_instr_stmt,
sp_instr_set,
sp_instr_set_trigger_field,
sp_instr_jump_if_not,
sp_instr_freturn,
sp_instr_cpush,
sp_instr_cursor_copy_struct,
sp_instr_set_case_expr
Additionally, this patch converts the class sp_instr_opt_meta
to a base abstract class (that is, not inherited from the class
sp_instr). Since this class originally was designed to provide a way
for opimizer to update a destination address for jump SP-instructions,
the only useful method at the interface of this class is set_destination
and therefore inheritance from the class sp_instr is meaningless.
Every jump SP instruction now must be inherited directly from
the class sp_instr_opt_meta and additionally from either the class
sp_lex_instr or sp_instr depending on whether this SP instruction
need to get access to a LEX object or not.
Moreover, the class sp_cursor doesn't own a data member of
the class sp_lex_keeper any more. Instead, the virtual method
get_lex_keeper() has been added to the class sp_cursor() that
returns nullptr and this method is overridden in the derived class
sp_instr_cpush to provide a pointer to a real instance of
the class sp_lex_keeper. Doing this way we exclude duplication
of a data member of the type sp_lex_keeper at the class sp_instr_cpush
since it is derived both from sp_lex_instr and sp_cursor, and sp_lex_instr
already encapsulates a data member of the class sp_lex_keeper.
2023-07-19 12:50:47 +02:00
|
|
|
: sp_lex_instr(ip, ctx, lex, true),
|
|
|
|
sp_instr_opt_meta(0),
|
2023-07-19 12:53:55 +02:00
|
|
|
m_expr(i),
|
|
|
|
m_expr_str(expr_query)
|
2023-07-19 12:43:31 +02:00
|
|
|
{}
|
|
|
|
|
2023-07-19 12:53:55 +02:00
|
|
|
sp_instr_jump_if_not(uint ip, sp_pcontext *ctx, Item *i, uint dest, LEX *lex,
|
|
|
|
const LEX_CSTRING &expr_query)
|
MDEV-5816: Stored programs: validation of stored program statements
This is the prerequisite patch introducing the class sp_lex_instr
that encapsulates access to an instance of the class sp_lex_keeper.
Every SP instruction that need to get access to a LEX object on its
processing should inherit this class and implement two abstract methods:
is_invalid(),
invalidate().
These methods will be used in subsequent patches to implement recompilation of
SP instructions on failure.
Currently, the following instructions are derived from the class sp_lex_instr:
sp_instr_stmt,
sp_instr_set,
sp_instr_set_trigger_field,
sp_instr_jump_if_not,
sp_instr_freturn,
sp_instr_cpush,
sp_instr_cursor_copy_struct,
sp_instr_set_case_expr
Additionally, this patch converts the class sp_instr_opt_meta
to a base abstract class (that is, not inherited from the class
sp_instr). Since this class originally was designed to provide a way
for opimizer to update a destination address for jump SP-instructions,
the only useful method at the interface of this class is set_destination
and therefore inheritance from the class sp_instr is meaningless.
Every jump SP instruction now must be inherited directly from
the class sp_instr_opt_meta and additionally from either the class
sp_lex_instr or sp_instr depending on whether this SP instruction
need to get access to a LEX object or not.
Moreover, the class sp_cursor doesn't own a data member of
the class sp_lex_keeper any more. Instead, the virtual method
get_lex_keeper() has been added to the class sp_cursor() that
returns nullptr and this method is overridden in the derived class
sp_instr_cpush to provide a pointer to a real instance of
the class sp_lex_keeper. Doing this way we exclude duplication
of a data member of the type sp_lex_keeper at the class sp_instr_cpush
since it is derived both from sp_lex_instr and sp_cursor, and sp_lex_instr
already encapsulates a data member of the class sp_lex_keeper.
2023-07-19 12:50:47 +02:00
|
|
|
: sp_lex_instr(ip, ctx, lex, true),
|
|
|
|
sp_instr_opt_meta(dest),
|
2023-07-19 12:53:55 +02:00
|
|
|
m_expr(i),
|
|
|
|
m_expr_str(expr_query)
|
2023-07-19 12:43:31 +02:00
|
|
|
{}
|
|
|
|
|
|
|
|
virtual ~sp_instr_jump_if_not() = default;
|
|
|
|
|
|
|
|
int execute(THD *thd, uint *nextp) override;
|
|
|
|
|
|
|
|
int exec_core(THD *thd, uint *nextp) override;
|
|
|
|
|
|
|
|
void print(String *str) override;
|
|
|
|
|
|
|
|
uint opt_mark(sp_head *sp, List<sp_instr> *leads) override;
|
|
|
|
|
|
|
|
/** Override sp_instr_jump's shortcut; we stop here */
|
|
|
|
uint opt_shortcut_jump(sp_head *sp, sp_instr *start) override
|
|
|
|
{
|
|
|
|
return m_ip;
|
|
|
|
}
|
|
|
|
|
2023-07-19 12:48:31 +02:00
|
|
|
void opt_move(uint dst, List<sp_instr_opt_meta> *ibp) override;
|
2023-07-19 12:43:31 +02:00
|
|
|
|
MDEV-5816: Stored programs: validation of stored program statements
This is the prerequisite patch introducing the class sp_lex_instr
that encapsulates access to an instance of the class sp_lex_keeper.
Every SP instruction that need to get access to a LEX object on its
processing should inherit this class and implement two abstract methods:
is_invalid(),
invalidate().
These methods will be used in subsequent patches to implement recompilation of
SP instructions on failure.
Currently, the following instructions are derived from the class sp_lex_instr:
sp_instr_stmt,
sp_instr_set,
sp_instr_set_trigger_field,
sp_instr_jump_if_not,
sp_instr_freturn,
sp_instr_cpush,
sp_instr_cursor_copy_struct,
sp_instr_set_case_expr
Additionally, this patch converts the class sp_instr_opt_meta
to a base abstract class (that is, not inherited from the class
sp_instr). Since this class originally was designed to provide a way
for opimizer to update a destination address for jump SP-instructions,
the only useful method at the interface of this class is set_destination
and therefore inheritance from the class sp_instr is meaningless.
Every jump SP instruction now must be inherited directly from
the class sp_instr_opt_meta and additionally from either the class
sp_lex_instr or sp_instr depending on whether this SP instruction
need to get access to a LEX object or not.
Moreover, the class sp_cursor doesn't own a data member of
the class sp_lex_keeper any more. Instead, the virtual method
get_lex_keeper() has been added to the class sp_cursor() that
returns nullptr and this method is overridden in the derived class
sp_instr_cpush to provide a pointer to a real instance of
the class sp_lex_keeper. Doing this way we exclude duplication
of a data member of the type sp_lex_keeper at the class sp_instr_cpush
since it is derived both from sp_lex_instr and sp_cursor, and sp_lex_instr
already encapsulates a data member of the class sp_lex_keeper.
2023-07-19 12:50:47 +02:00
|
|
|
uint get_cont_dest() const override
|
|
|
|
{
|
|
|
|
return m_cont_dest;
|
|
|
|
}
|
|
|
|
|
2023-07-19 12:43:31 +02:00
|
|
|
void set_destination(uint old_dest, uint new_dest) override
|
|
|
|
{
|
MDEV-5816: Stored programs: validation of stored program statements
This is the prerequisite patch introducing the class sp_lex_instr
that encapsulates access to an instance of the class sp_lex_keeper.
Every SP instruction that need to get access to a LEX object on its
processing should inherit this class and implement two abstract methods:
is_invalid(),
invalidate().
These methods will be used in subsequent patches to implement recompilation of
SP instructions on failure.
Currently, the following instructions are derived from the class sp_lex_instr:
sp_instr_stmt,
sp_instr_set,
sp_instr_set_trigger_field,
sp_instr_jump_if_not,
sp_instr_freturn,
sp_instr_cpush,
sp_instr_cursor_copy_struct,
sp_instr_set_case_expr
Additionally, this patch converts the class sp_instr_opt_meta
to a base abstract class (that is, not inherited from the class
sp_instr). Since this class originally was designed to provide a way
for opimizer to update a destination address for jump SP-instructions,
the only useful method at the interface of this class is set_destination
and therefore inheritance from the class sp_instr is meaningless.
Every jump SP instruction now must be inherited directly from
the class sp_instr_opt_meta and additionally from either the class
sp_lex_instr or sp_instr depending on whether this SP instruction
need to get access to a LEX object or not.
Moreover, the class sp_cursor doesn't own a data member of
the class sp_lex_keeper any more. Instead, the virtual method
get_lex_keeper() has been added to the class sp_cursor() that
returns nullptr and this method is overridden in the derived class
sp_instr_cpush to provide a pointer to a real instance of
the class sp_lex_keeper. Doing this way we exclude duplication
of a data member of the type sp_lex_keeper at the class sp_instr_cpush
since it is derived both from sp_lex_instr and sp_cursor, and sp_lex_instr
already encapsulates a data member of the class sp_lex_keeper.
2023-07-19 12:50:47 +02:00
|
|
|
if (m_dest == old_dest)
|
|
|
|
m_dest= new_dest;
|
2023-07-19 12:43:31 +02:00
|
|
|
if (m_cont_dest == old_dest)
|
|
|
|
m_cont_dest= new_dest;
|
|
|
|
}
|
|
|
|
|
MDEV-5816: Stored programs: validation of stored program statements
This is the prerequisite patch introducing the class sp_lex_instr
that encapsulates access to an instance of the class sp_lex_keeper.
Every SP instruction that need to get access to a LEX object on its
processing should inherit this class and implement two abstract methods:
is_invalid(),
invalidate().
These methods will be used in subsequent patches to implement recompilation of
SP instructions on failure.
Currently, the following instructions are derived from the class sp_lex_instr:
sp_instr_stmt,
sp_instr_set,
sp_instr_set_trigger_field,
sp_instr_jump_if_not,
sp_instr_freturn,
sp_instr_cpush,
sp_instr_cursor_copy_struct,
sp_instr_set_case_expr
Additionally, this patch converts the class sp_instr_opt_meta
to a base abstract class (that is, not inherited from the class
sp_instr). Since this class originally was designed to provide a way
for opimizer to update a destination address for jump SP-instructions,
the only useful method at the interface of this class is set_destination
and therefore inheritance from the class sp_instr is meaningless.
Every jump SP instruction now must be inherited directly from
the class sp_instr_opt_meta and additionally from either the class
sp_lex_instr or sp_instr depending on whether this SP instruction
need to get access to a LEX object or not.
Moreover, the class sp_cursor doesn't own a data member of
the class sp_lex_keeper any more. Instead, the virtual method
get_lex_keeper() has been added to the class sp_cursor() that
returns nullptr and this method is overridden in the derived class
sp_instr_cpush to provide a pointer to a real instance of
the class sp_lex_keeper. Doing this way we exclude duplication
of a data member of the type sp_lex_keeper at the class sp_instr_cpush
since it is derived both from sp_lex_instr and sp_cursor, and sp_lex_instr
already encapsulates a data member of the class sp_lex_keeper.
2023-07-19 12:50:47 +02:00
|
|
|
void backpatch(uint dest, sp_pcontext *dst_ctx) override
|
|
|
|
{
|
|
|
|
/* Calling backpatch twice is a logic flaw in jump resolution. */
|
|
|
|
DBUG_ASSERT(m_dest == 0);
|
|
|
|
m_dest= dest;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool is_invalid() const override
|
|
|
|
{
|
|
|
|
return m_expr == nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void invalidate() override
|
|
|
|
{
|
|
|
|
m_expr= nullptr;
|
|
|
|
}
|
|
|
|
|
2023-07-19 12:53:55 +02:00
|
|
|
protected:
|
|
|
|
LEX_CSTRING get_expr_query() const override
|
|
|
|
{
|
|
|
|
return m_expr_str;
|
|
|
|
}
|
|
|
|
|
2023-07-19 12:57:13 +02:00
|
|
|
void adjust_sql_command(LEX *lex) override
|
|
|
|
{
|
|
|
|
assert(lex->sql_command == SQLCOM_SELECT);
|
|
|
|
lex->sql_command= SQLCOM_END;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool on_after_expr_parsing(THD *thd) override
|
|
|
|
{
|
|
|
|
DBUG_ASSERT(thd->lex->current_select->item_list.elements == 1);
|
|
|
|
|
|
|
|
m_expr= thd->lex->current_select->item_list.head();
|
|
|
|
DBUG_ASSERT(m_expr != nullptr);
|
|
|
|
|
|
|
|
// Return error in release version if m_expr == nullptr
|
|
|
|
return m_expr == nullptr;
|
|
|
|
}
|
|
|
|
|
2023-07-19 12:43:31 +02:00
|
|
|
private:
|
|
|
|
Item *m_expr; ///< The condition
|
2023-07-19 12:53:55 +02:00
|
|
|
LEX_CSTRING m_expr_str;
|
2023-07-19 12:43:31 +02:00
|
|
|
|
|
|
|
public:
|
|
|
|
PSI_statement_info* get_psi_info() override { return & psi_info; }
|
|
|
|
static PSI_statement_info psi_info;
|
MDEV-5816: Stored programs: validation of stored program statements
This is the prerequisite patch introducing the class sp_lex_instr
that encapsulates access to an instance of the class sp_lex_keeper.
Every SP instruction that need to get access to a LEX object on its
processing should inherit this class and implement two abstract methods:
is_invalid(),
invalidate().
These methods will be used in subsequent patches to implement recompilation of
SP instructions on failure.
Currently, the following instructions are derived from the class sp_lex_instr:
sp_instr_stmt,
sp_instr_set,
sp_instr_set_trigger_field,
sp_instr_jump_if_not,
sp_instr_freturn,
sp_instr_cpush,
sp_instr_cursor_copy_struct,
sp_instr_set_case_expr
Additionally, this patch converts the class sp_instr_opt_meta
to a base abstract class (that is, not inherited from the class
sp_instr). Since this class originally was designed to provide a way
for opimizer to update a destination address for jump SP-instructions,
the only useful method at the interface of this class is set_destination
and therefore inheritance from the class sp_instr is meaningless.
Every jump SP instruction now must be inherited directly from
the class sp_instr_opt_meta and additionally from either the class
sp_lex_instr or sp_instr depending on whether this SP instruction
need to get access to a LEX object or not.
Moreover, the class sp_cursor doesn't own a data member of
the class sp_lex_keeper any more. Instead, the virtual method
get_lex_keeper() has been added to the class sp_cursor() that
returns nullptr and this method is overridden in the derived class
sp_instr_cpush to provide a pointer to a real instance of
the class sp_lex_keeper. Doing this way we exclude duplication
of a data member of the type sp_lex_keeper at the class sp_instr_cpush
since it is derived both from sp_lex_instr and sp_cursor, and sp_lex_instr
already encapsulates a data member of the class sp_lex_keeper.
2023-07-19 12:50:47 +02:00
|
|
|
}; // class sp_instr_jump_if_not
|
2023-07-19 12:43:31 +02:00
|
|
|
|
|
|
|
|
|
|
|
class sp_instr_preturn : public sp_instr
|
|
|
|
{
|
|
|
|
sp_instr_preturn(const sp_instr_preturn &); /**< Prevent use of these */
|
|
|
|
void operator=(sp_instr_preturn &);
|
|
|
|
|
|
|
|
public:
|
|
|
|
sp_instr_preturn(uint ip, sp_pcontext *ctx)
|
|
|
|
: sp_instr(ip, ctx)
|
|
|
|
{}
|
|
|
|
|
|
|
|
virtual ~sp_instr_preturn() = default;
|
|
|
|
|
|
|
|
int execute(THD *thd, uint *nextp) override;
|
|
|
|
|
|
|
|
void print(String *str) override;
|
|
|
|
|
|
|
|
uint opt_mark(sp_head *sp, List<sp_instr> *leads) override
|
|
|
|
{
|
|
|
|
marked= 1;
|
|
|
|
return UINT_MAX;
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
PSI_statement_info* get_psi_info() override { return & psi_info; }
|
|
|
|
static PSI_statement_info psi_info;
|
|
|
|
}; // class sp_instr_preturn : public sp_instr
|
|
|
|
|
|
|
|
|
MDEV-5816: Stored programs: validation of stored program statements
This is the prerequisite patch introducing the class sp_lex_instr
that encapsulates access to an instance of the class sp_lex_keeper.
Every SP instruction that need to get access to a LEX object on its
processing should inherit this class and implement two abstract methods:
is_invalid(),
invalidate().
These methods will be used in subsequent patches to implement recompilation of
SP instructions on failure.
Currently, the following instructions are derived from the class sp_lex_instr:
sp_instr_stmt,
sp_instr_set,
sp_instr_set_trigger_field,
sp_instr_jump_if_not,
sp_instr_freturn,
sp_instr_cpush,
sp_instr_cursor_copy_struct,
sp_instr_set_case_expr
Additionally, this patch converts the class sp_instr_opt_meta
to a base abstract class (that is, not inherited from the class
sp_instr). Since this class originally was designed to provide a way
for opimizer to update a destination address for jump SP-instructions,
the only useful method at the interface of this class is set_destination
and therefore inheritance from the class sp_instr is meaningless.
Every jump SP instruction now must be inherited directly from
the class sp_instr_opt_meta and additionally from either the class
sp_lex_instr or sp_instr depending on whether this SP instruction
need to get access to a LEX object or not.
Moreover, the class sp_cursor doesn't own a data member of
the class sp_lex_keeper any more. Instead, the virtual method
get_lex_keeper() has been added to the class sp_cursor() that
returns nullptr and this method is overridden in the derived class
sp_instr_cpush to provide a pointer to a real instance of
the class sp_lex_keeper. Doing this way we exclude duplication
of a data member of the type sp_lex_keeper at the class sp_instr_cpush
since it is derived both from sp_lex_instr and sp_cursor, and sp_lex_instr
already encapsulates a data member of the class sp_lex_keeper.
2023-07-19 12:50:47 +02:00
|
|
|
class sp_instr_freturn : public sp_lex_instr
|
2023-07-19 12:43:31 +02:00
|
|
|
{
|
|
|
|
sp_instr_freturn(const sp_instr_freturn &); /**< Prevent use of these */
|
|
|
|
void operator=(sp_instr_freturn &);
|
|
|
|
|
|
|
|
public:
|
|
|
|
sp_instr_freturn(uint ip, sp_pcontext *ctx,
|
2023-07-19 12:53:55 +02:00
|
|
|
Item *val, const Type_handler *handler, sp_expr_lex *lex)
|
MDEV-5816: Stored programs: validation of stored program statements
This is the prerequisite patch introducing the class sp_lex_instr
that encapsulates access to an instance of the class sp_lex_keeper.
Every SP instruction that need to get access to a LEX object on its
processing should inherit this class and implement two abstract methods:
is_invalid(),
invalidate().
These methods will be used in subsequent patches to implement recompilation of
SP instructions on failure.
Currently, the following instructions are derived from the class sp_lex_instr:
sp_instr_stmt,
sp_instr_set,
sp_instr_set_trigger_field,
sp_instr_jump_if_not,
sp_instr_freturn,
sp_instr_cpush,
sp_instr_cursor_copy_struct,
sp_instr_set_case_expr
Additionally, this patch converts the class sp_instr_opt_meta
to a base abstract class (that is, not inherited from the class
sp_instr). Since this class originally was designed to provide a way
for opimizer to update a destination address for jump SP-instructions,
the only useful method at the interface of this class is set_destination
and therefore inheritance from the class sp_instr is meaningless.
Every jump SP instruction now must be inherited directly from
the class sp_instr_opt_meta and additionally from either the class
sp_lex_instr or sp_instr depending on whether this SP instruction
need to get access to a LEX object or not.
Moreover, the class sp_cursor doesn't own a data member of
the class sp_lex_keeper any more. Instead, the virtual method
get_lex_keeper() has been added to the class sp_cursor() that
returns nullptr and this method is overridden in the derived class
sp_instr_cpush to provide a pointer to a real instance of
the class sp_lex_keeper. Doing this way we exclude duplication
of a data member of the type sp_lex_keeper at the class sp_instr_cpush
since it is derived both from sp_lex_instr and sp_cursor, and sp_lex_instr
already encapsulates a data member of the class sp_lex_keeper.
2023-07-19 12:50:47 +02:00
|
|
|
: sp_lex_instr(ip, ctx, lex, true),
|
2023-07-19 12:43:31 +02:00
|
|
|
m_value(val),
|
2023-07-19 12:53:55 +02:00
|
|
|
m_type_handler(handler),
|
|
|
|
m_expr_str(lex->get_expr_str())
|
2023-07-19 12:43:31 +02:00
|
|
|
{}
|
|
|
|
|
|
|
|
virtual ~sp_instr_freturn() = default;
|
|
|
|
|
|
|
|
int execute(THD *thd, uint *nextp) override;
|
|
|
|
|
|
|
|
int exec_core(THD *thd, uint *nextp) override;
|
|
|
|
|
|
|
|
void print(String *str) override;
|
|
|
|
|
|
|
|
uint opt_mark(sp_head *sp, List<sp_instr> *leads) override
|
|
|
|
{
|
|
|
|
marked= 1;
|
|
|
|
return UINT_MAX;
|
|
|
|
}
|
|
|
|
|
MDEV-5816: Stored programs: validation of stored program statements
This is the prerequisite patch introducing the class sp_lex_instr
that encapsulates access to an instance of the class sp_lex_keeper.
Every SP instruction that need to get access to a LEX object on its
processing should inherit this class and implement two abstract methods:
is_invalid(),
invalidate().
These methods will be used in subsequent patches to implement recompilation of
SP instructions on failure.
Currently, the following instructions are derived from the class sp_lex_instr:
sp_instr_stmt,
sp_instr_set,
sp_instr_set_trigger_field,
sp_instr_jump_if_not,
sp_instr_freturn,
sp_instr_cpush,
sp_instr_cursor_copy_struct,
sp_instr_set_case_expr
Additionally, this patch converts the class sp_instr_opt_meta
to a base abstract class (that is, not inherited from the class
sp_instr). Since this class originally was designed to provide a way
for opimizer to update a destination address for jump SP-instructions,
the only useful method at the interface of this class is set_destination
and therefore inheritance from the class sp_instr is meaningless.
Every jump SP instruction now must be inherited directly from
the class sp_instr_opt_meta and additionally from either the class
sp_lex_instr or sp_instr depending on whether this SP instruction
need to get access to a LEX object or not.
Moreover, the class sp_cursor doesn't own a data member of
the class sp_lex_keeper any more. Instead, the virtual method
get_lex_keeper() has been added to the class sp_cursor() that
returns nullptr and this method is overridden in the derived class
sp_instr_cpush to provide a pointer to a real instance of
the class sp_lex_keeper. Doing this way we exclude duplication
of a data member of the type sp_lex_keeper at the class sp_instr_cpush
since it is derived both from sp_lex_instr and sp_cursor, and sp_lex_instr
already encapsulates a data member of the class sp_lex_keeper.
2023-07-19 12:50:47 +02:00
|
|
|
bool is_invalid() const override
|
|
|
|
{
|
|
|
|
return m_value == nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void invalidate() override
|
|
|
|
{
|
|
|
|
m_value= nullptr;
|
|
|
|
}
|
|
|
|
|
2023-07-19 12:43:31 +02:00
|
|
|
protected:
|
2023-07-19 12:53:55 +02:00
|
|
|
LEX_CSTRING get_expr_query() const override
|
|
|
|
{
|
|
|
|
return m_expr_str;
|
|
|
|
}
|
|
|
|
|
2023-07-19 12:57:13 +02:00
|
|
|
bool on_after_expr_parsing(THD *thd) override
|
|
|
|
{
|
|
|
|
DBUG_ASSERT(thd->lex->current_select->item_list.elements == 1);
|
|
|
|
m_value= thd->lex->current_select->item_list.head();
|
|
|
|
DBUG_ASSERT(m_value != nullptr);
|
|
|
|
|
|
|
|
// Return error in release version if m_value == nullptr
|
|
|
|
return m_value == nullptr;
|
|
|
|
}
|
|
|
|
|
2023-07-19 12:43:31 +02:00
|
|
|
Item *m_value;
|
|
|
|
const Type_handler *m_type_handler;
|
|
|
|
|
2023-07-19 12:53:55 +02:00
|
|
|
private:
|
|
|
|
/**
|
|
|
|
SQL-query corresponding to the RETURN-expression.
|
|
|
|
*/
|
|
|
|
LEX_CSTRING m_expr_str;
|
|
|
|
|
2023-07-19 12:43:31 +02:00
|
|
|
public:
|
|
|
|
PSI_statement_info* get_psi_info() override { return & psi_info; }
|
|
|
|
static PSI_statement_info psi_info;
|
MDEV-5816: Stored programs: validation of stored program statements
This is the prerequisite patch introducing the class sp_lex_instr
that encapsulates access to an instance of the class sp_lex_keeper.
Every SP instruction that need to get access to a LEX object on its
processing should inherit this class and implement two abstract methods:
is_invalid(),
invalidate().
These methods will be used in subsequent patches to implement recompilation of
SP instructions on failure.
Currently, the following instructions are derived from the class sp_lex_instr:
sp_instr_stmt,
sp_instr_set,
sp_instr_set_trigger_field,
sp_instr_jump_if_not,
sp_instr_freturn,
sp_instr_cpush,
sp_instr_cursor_copy_struct,
sp_instr_set_case_expr
Additionally, this patch converts the class sp_instr_opt_meta
to a base abstract class (that is, not inherited from the class
sp_instr). Since this class originally was designed to provide a way
for opimizer to update a destination address for jump SP-instructions,
the only useful method at the interface of this class is set_destination
and therefore inheritance from the class sp_instr is meaningless.
Every jump SP instruction now must be inherited directly from
the class sp_instr_opt_meta and additionally from either the class
sp_lex_instr or sp_instr depending on whether this SP instruction
need to get access to a LEX object or not.
Moreover, the class sp_cursor doesn't own a data member of
the class sp_lex_keeper any more. Instead, the virtual method
get_lex_keeper() has been added to the class sp_cursor() that
returns nullptr and this method is overridden in the derived class
sp_instr_cpush to provide a pointer to a real instance of
the class sp_lex_keeper. Doing this way we exclude duplication
of a data member of the type sp_lex_keeper at the class sp_instr_cpush
since it is derived both from sp_lex_instr and sp_cursor, and sp_lex_instr
already encapsulates a data member of the class sp_lex_keeper.
2023-07-19 12:50:47 +02:00
|
|
|
}; // class sp_instr_freturn : public sp_lex_instr
|
2023-07-19 12:43:31 +02:00
|
|
|
|
|
|
|
|
|
|
|
class sp_instr_hpush_jump : public sp_instr_jump
|
|
|
|
{
|
|
|
|
sp_instr_hpush_jump(const sp_instr_hpush_jump &); /**< Prevent use of these */
|
|
|
|
void operator=(sp_instr_hpush_jump &);
|
|
|
|
|
|
|
|
public:
|
|
|
|
sp_instr_hpush_jump(uint ip,
|
|
|
|
sp_pcontext *ctx,
|
|
|
|
sp_handler *handler)
|
|
|
|
: sp_instr_jump(ip, ctx),
|
|
|
|
m_handler(handler),
|
|
|
|
m_opt_hpop(0),
|
|
|
|
m_frame(ctx->current_var_count())
|
|
|
|
{
|
|
|
|
DBUG_ASSERT(m_handler->condition_values.elements == 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
~sp_instr_hpush_jump() override
|
|
|
|
{
|
|
|
|
m_handler->condition_values.empty();
|
|
|
|
m_handler= nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
int execute(THD *thd, uint *nextp) override;
|
|
|
|
|
|
|
|
void print(String *str) override;
|
|
|
|
|
|
|
|
uint opt_mark(sp_head *sp, List<sp_instr> *leads) override;
|
|
|
|
|
|
|
|
/** Override sp_instr_jump's shortcut; we stop here. */
|
|
|
|
uint opt_shortcut_jump(sp_head *sp, sp_instr *start) override
|
|
|
|
{
|
|
|
|
return m_ip;
|
|
|
|
}
|
|
|
|
|
|
|
|
void backpatch(uint dest, sp_pcontext *dst_ctx) override
|
|
|
|
{
|
|
|
|
DBUG_ASSERT(!m_dest || !m_opt_hpop);
|
|
|
|
if (!m_dest)
|
|
|
|
m_dest= dest;
|
|
|
|
else
|
|
|
|
m_opt_hpop= dest;
|
|
|
|
}
|
|
|
|
|
|
|
|
void add_condition(sp_condition_value *condition_value)
|
|
|
|
{
|
|
|
|
m_handler->condition_values.push_back(condition_value);
|
|
|
|
}
|
|
|
|
|
|
|
|
sp_handler *get_handler()
|
|
|
|
{
|
|
|
|
return m_handler;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
/// Handler.
|
|
|
|
sp_handler *m_handler;
|
|
|
|
|
|
|
|
/// hpop marking end of handler scope.
|
|
|
|
uint m_opt_hpop;
|
|
|
|
|
|
|
|
// This attribute is needed for SHOW PROCEDURE CODE only (i.e. it's needed in
|
|
|
|
// debug version only). It's used in print().
|
|
|
|
uint m_frame;
|
|
|
|
|
|
|
|
public:
|
|
|
|
PSI_statement_info* get_psi_info() override { return & psi_info; }
|
|
|
|
static PSI_statement_info psi_info;
|
|
|
|
}; // class sp_instr_hpush_jump : public sp_instr_jump
|
|
|
|
|
|
|
|
|
|
|
|
class sp_instr_hpop : public sp_instr
|
|
|
|
{
|
|
|
|
sp_instr_hpop(const sp_instr_hpop &); /**< Prevent use of these */
|
|
|
|
void operator=(sp_instr_hpop &);
|
|
|
|
|
|
|
|
public:
|
|
|
|
sp_instr_hpop(uint ip, sp_pcontext *ctx, uint count)
|
|
|
|
: sp_instr(ip, ctx),
|
|
|
|
m_count(count)
|
|
|
|
{}
|
|
|
|
|
|
|
|
virtual ~sp_instr_hpop() = default;
|
|
|
|
|
|
|
|
void update_count(uint count)
|
|
|
|
{
|
|
|
|
m_count= count;
|
|
|
|
}
|
|
|
|
|
|
|
|
int execute(THD *thd, uint *nextp) override;
|
|
|
|
|
|
|
|
void print(String *str) override;
|
|
|
|
|
|
|
|
private:
|
|
|
|
uint m_count;
|
|
|
|
|
|
|
|
public:
|
|
|
|
PSI_statement_info* get_psi_info() override { return & psi_info; }
|
|
|
|
static PSI_statement_info psi_info;
|
|
|
|
}; // class sp_instr_hpop : public sp_instr
|
|
|
|
|
|
|
|
|
|
|
|
class sp_instr_hreturn : public sp_instr_jump
|
|
|
|
{
|
|
|
|
sp_instr_hreturn(const sp_instr_hreturn &); /**< Prevent use of these */
|
|
|
|
void operator=(sp_instr_hreturn &);
|
|
|
|
|
|
|
|
public:
|
|
|
|
sp_instr_hreturn(uint ip, sp_pcontext *ctx)
|
|
|
|
: sp_instr_jump(ip, ctx),
|
|
|
|
m_frame(ctx->current_var_count())
|
|
|
|
{}
|
|
|
|
|
|
|
|
virtual ~sp_instr_hreturn() = default;
|
|
|
|
|
|
|
|
int execute(THD *thd, uint *nextp) override;
|
|
|
|
|
|
|
|
void print(String *str) override;
|
|
|
|
|
|
|
|
/* This instruction will not be short cut optimized. */
|
|
|
|
uint opt_shortcut_jump(sp_head *sp, sp_instr *start) override
|
|
|
|
{
|
|
|
|
return m_ip;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint opt_mark(sp_head *sp, List<sp_instr> *leads) override;
|
|
|
|
|
|
|
|
private:
|
|
|
|
uint m_frame;
|
|
|
|
|
|
|
|
public:
|
|
|
|
PSI_statement_info* get_psi_info() override { return & psi_info; }
|
|
|
|
static PSI_statement_info psi_info;
|
|
|
|
}; // class sp_instr_hreturn : public sp_instr_jump
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
This is DECLARE CURSOR
|
|
|
|
*/
|
|
|
|
|
MDEV-5816: Stored programs: validation of stored program statements
This is the prerequisite patch introducing the class sp_lex_instr
that encapsulates access to an instance of the class sp_lex_keeper.
Every SP instruction that need to get access to a LEX object on its
processing should inherit this class and implement two abstract methods:
is_invalid(),
invalidate().
These methods will be used in subsequent patches to implement recompilation of
SP instructions on failure.
Currently, the following instructions are derived from the class sp_lex_instr:
sp_instr_stmt,
sp_instr_set,
sp_instr_set_trigger_field,
sp_instr_jump_if_not,
sp_instr_freturn,
sp_instr_cpush,
sp_instr_cursor_copy_struct,
sp_instr_set_case_expr
Additionally, this patch converts the class sp_instr_opt_meta
to a base abstract class (that is, not inherited from the class
sp_instr). Since this class originally was designed to provide a way
for opimizer to update a destination address for jump SP-instructions,
the only useful method at the interface of this class is set_destination
and therefore inheritance from the class sp_instr is meaningless.
Every jump SP instruction now must be inherited directly from
the class sp_instr_opt_meta and additionally from either the class
sp_lex_instr or sp_instr depending on whether this SP instruction
need to get access to a LEX object or not.
Moreover, the class sp_cursor doesn't own a data member of
the class sp_lex_keeper any more. Instead, the virtual method
get_lex_keeper() has been added to the class sp_cursor() that
returns nullptr and this method is overridden in the derived class
sp_instr_cpush to provide a pointer to a real instance of
the class sp_lex_keeper. Doing this way we exclude duplication
of a data member of the type sp_lex_keeper at the class sp_instr_cpush
since it is derived both from sp_lex_instr and sp_cursor, and sp_lex_instr
already encapsulates a data member of the class sp_lex_keeper.
2023-07-19 12:50:47 +02:00
|
|
|
class sp_instr_cpush : public sp_lex_instr, public sp_cursor
|
2023-07-19 12:43:31 +02:00
|
|
|
{
|
|
|
|
sp_instr_cpush(const sp_instr_cpush &); /**< Prevent use of these */
|
|
|
|
void operator=(sp_instr_cpush &);
|
|
|
|
|
|
|
|
public:
|
2023-07-19 12:53:55 +02:00
|
|
|
sp_instr_cpush(uint ip, sp_pcontext *ctx, sp_lex_cursor *lex, uint offset)
|
MDEV-5816: Stored programs: validation of stored program statements
This is the prerequisite patch introducing the class sp_lex_instr
that encapsulates access to an instance of the class sp_lex_keeper.
Every SP instruction that need to get access to a LEX object on its
processing should inherit this class and implement two abstract methods:
is_invalid(),
invalidate().
These methods will be used in subsequent patches to implement recompilation of
SP instructions on failure.
Currently, the following instructions are derived from the class sp_lex_instr:
sp_instr_stmt,
sp_instr_set,
sp_instr_set_trigger_field,
sp_instr_jump_if_not,
sp_instr_freturn,
sp_instr_cpush,
sp_instr_cursor_copy_struct,
sp_instr_set_case_expr
Additionally, this patch converts the class sp_instr_opt_meta
to a base abstract class (that is, not inherited from the class
sp_instr). Since this class originally was designed to provide a way
for opimizer to update a destination address for jump SP-instructions,
the only useful method at the interface of this class is set_destination
and therefore inheritance from the class sp_instr is meaningless.
Every jump SP instruction now must be inherited directly from
the class sp_instr_opt_meta and additionally from either the class
sp_lex_instr or sp_instr depending on whether this SP instruction
need to get access to a LEX object or not.
Moreover, the class sp_cursor doesn't own a data member of
the class sp_lex_keeper any more. Instead, the virtual method
get_lex_keeper() has been added to the class sp_cursor() that
returns nullptr and this method is overridden in the derived class
sp_instr_cpush to provide a pointer to a real instance of
the class sp_lex_keeper. Doing this way we exclude duplication
of a data member of the type sp_lex_keeper at the class sp_instr_cpush
since it is derived both from sp_lex_instr and sp_cursor, and sp_lex_instr
already encapsulates a data member of the class sp_lex_keeper.
2023-07-19 12:50:47 +02:00
|
|
|
: sp_lex_instr(ip, ctx, lex, true),
|
|
|
|
m_cursor(offset),
|
2023-07-19 12:53:55 +02:00
|
|
|
m_metadata_changed(false),
|
|
|
|
m_cursor_stmt(lex->get_expr_str())
|
2023-07-19 12:43:31 +02:00
|
|
|
{}
|
|
|
|
|
|
|
|
virtual ~sp_instr_cpush() = default;
|
|
|
|
|
|
|
|
int execute(THD *thd, uint *nextp) override;
|
|
|
|
|
MDEV-5816: Stored programs: validation of stored program statements
Added re-parsing of a failing cursor body. Re-parsing of a failing
SP statement is implemented by the method validate_lex_and_exec_core(),
therefore invocation of the method reset_lex_and_exec_core() inside
sp_lex_keeper::cursor_reset_lex_and_exec_core
was replaced by the method validate_lex_and_exec_core().
Re-parsing of a failed SP statement is relied upon interface provided
by the class sp_lex_instr (the methods used for this goal are
is_invalid(), parse_expr(), invalidate(), get_query(), get_expr_query()).
To provide access to these methods on opening a cursor, the signature of
the method
sp_lex_keeper::cursor_reset_lex_and_exec_core
was changed to accept a pointer to the class sp_lex_instr instead of
the class sp_instr, and the new method get_push_instr() was added
into the class sp_cursor. This method is to get access to an instance
of the class sp_instr_cpush on opening a cursor (on handling the statement
OPEN cursors_name).
Default implementation of this method just returns NULL pointer of
the type sp_instr_cpush. This method is overridden in the class
sp_instr_cpush with trivial implementation
{ return this; }
On handling the statement DECLARE CURSOR FOR the new instruction of
the type sp_instr_cpush is added into sp_head. The class sp_instr_cpush
holds a text of SELECT query referencing by a cursor declaration.
When a cursor is being opened (on handling the statement 'OPEN cur_name')
a pointer to sp_instr_cpush is returned by the method
sp_cursor::get_push_instr()
and this pointer is passed to the method
sp_lex_keeper::cursor_reset_lex_and_exec_core
in order to open a cursor and provide access to an interface required
for SP statement re-parsing in case metadata changes took place.
Since real access to a lex object is required on handling instruction
sp_instr_cpush (an instance of this class is created during parsing of
cursor declaration statement), calling of the method sp_cursor::open
is moved from the method
sp_instr_copen::exec_core
into the method
sp_instr_cpush::exec_core.
Additionally, updated the methods get_query/get_expr_query in the classes
sp_instr_cpush, sp_instr_cursor_copy_struct in order to return correct text of
cursor's body taking into account that lexer treated the clause CURSOR FOR/
CURSOR IS as two different tokens following one after another. So, to return
a correct text of SELECT statement specified in CURSOR declaration statement,
the token FOR/IS should be skipped and text following it should be returned as
a text of cursors's query.
2023-07-19 13:14:00 +02:00
|
|
|
int exec_core(THD *thd, uint *nextp) override;
|
|
|
|
|
2023-07-19 12:43:31 +02:00
|
|
|
void print(String *str) override;
|
|
|
|
|
|
|
|
/**
|
|
|
|
This call is used to cleanup the instruction when a sensitive
|
|
|
|
cursor is closed. For now stored procedures always use materialized
|
|
|
|
cursors and the call is not used.
|
|
|
|
*/
|
|
|
|
bool cleanup_stmt(bool /*restore_set_statement_vars*/) override
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
MDEV-5816: Stored programs: validation of stored program statements
This is the prerequisite patch introducing the class sp_lex_instr
that encapsulates access to an instance of the class sp_lex_keeper.
Every SP instruction that need to get access to a LEX object on its
processing should inherit this class and implement two abstract methods:
is_invalid(),
invalidate().
These methods will be used in subsequent patches to implement recompilation of
SP instructions on failure.
Currently, the following instructions are derived from the class sp_lex_instr:
sp_instr_stmt,
sp_instr_set,
sp_instr_set_trigger_field,
sp_instr_jump_if_not,
sp_instr_freturn,
sp_instr_cpush,
sp_instr_cursor_copy_struct,
sp_instr_set_case_expr
Additionally, this patch converts the class sp_instr_opt_meta
to a base abstract class (that is, not inherited from the class
sp_instr). Since this class originally was designed to provide a way
for opimizer to update a destination address for jump SP-instructions,
the only useful method at the interface of this class is set_destination
and therefore inheritance from the class sp_instr is meaningless.
Every jump SP instruction now must be inherited directly from
the class sp_instr_opt_meta and additionally from either the class
sp_lex_instr or sp_instr depending on whether this SP instruction
need to get access to a LEX object or not.
Moreover, the class sp_cursor doesn't own a data member of
the class sp_lex_keeper any more. Instead, the virtual method
get_lex_keeper() has been added to the class sp_cursor() that
returns nullptr and this method is overridden in the derived class
sp_instr_cpush to provide a pointer to a real instance of
the class sp_lex_keeper. Doing this way we exclude duplication
of a data member of the type sp_lex_keeper at the class sp_instr_cpush
since it is derived both from sp_lex_instr and sp_cursor, and sp_lex_instr
already encapsulates a data member of the class sp_lex_keeper.
2023-07-19 12:50:47 +02:00
|
|
|
bool is_invalid() const override
|
|
|
|
{
|
|
|
|
return m_metadata_changed;
|
|
|
|
}
|
|
|
|
|
|
|
|
void invalidate() override
|
|
|
|
{
|
|
|
|
m_metadata_changed= true;
|
|
|
|
}
|
|
|
|
|
|
|
|
sp_lex_keeper *get_lex_keeper() override
|
|
|
|
{
|
|
|
|
return &m_lex_keeper;
|
|
|
|
}
|
|
|
|
|
2023-07-19 12:53:55 +02:00
|
|
|
void get_query(String *sql_query) const override
|
|
|
|
{
|
|
|
|
sql_query->append(get_expr_query());
|
|
|
|
}
|
|
|
|
|
MDEV-5816: Stored programs: validation of stored program statements
Added re-parsing of a failing cursor body. Re-parsing of a failing
SP statement is implemented by the method validate_lex_and_exec_core(),
therefore invocation of the method reset_lex_and_exec_core() inside
sp_lex_keeper::cursor_reset_lex_and_exec_core
was replaced by the method validate_lex_and_exec_core().
Re-parsing of a failed SP statement is relied upon interface provided
by the class sp_lex_instr (the methods used for this goal are
is_invalid(), parse_expr(), invalidate(), get_query(), get_expr_query()).
To provide access to these methods on opening a cursor, the signature of
the method
sp_lex_keeper::cursor_reset_lex_and_exec_core
was changed to accept a pointer to the class sp_lex_instr instead of
the class sp_instr, and the new method get_push_instr() was added
into the class sp_cursor. This method is to get access to an instance
of the class sp_instr_cpush on opening a cursor (on handling the statement
OPEN cursors_name).
Default implementation of this method just returns NULL pointer of
the type sp_instr_cpush. This method is overridden in the class
sp_instr_cpush with trivial implementation
{ return this; }
On handling the statement DECLARE CURSOR FOR the new instruction of
the type sp_instr_cpush is added into sp_head. The class sp_instr_cpush
holds a text of SELECT query referencing by a cursor declaration.
When a cursor is being opened (on handling the statement 'OPEN cur_name')
a pointer to sp_instr_cpush is returned by the method
sp_cursor::get_push_instr()
and this pointer is passed to the method
sp_lex_keeper::cursor_reset_lex_and_exec_core
in order to open a cursor and provide access to an interface required
for SP statement re-parsing in case metadata changes took place.
Since real access to a lex object is required on handling instruction
sp_instr_cpush (an instance of this class is created during parsing of
cursor declaration statement), calling of the method sp_cursor::open
is moved from the method
sp_instr_copen::exec_core
into the method
sp_instr_cpush::exec_core.
Additionally, updated the methods get_query/get_expr_query in the classes
sp_instr_cpush, sp_instr_cursor_copy_struct in order to return correct text of
cursor's body taking into account that lexer treated the clause CURSOR FOR/
CURSOR IS as two different tokens following one after another. So, to return
a correct text of SELECT statement specified in CURSOR declaration statement,
the token FOR/IS should be skipped and text following it should be returned as
a text of cursors's query.
2023-07-19 13:14:00 +02:00
|
|
|
sp_instr_cpush *get_push_instr() override { return this; }
|
|
|
|
|
2023-07-19 12:53:55 +02:00
|
|
|
protected:
|
|
|
|
LEX_CSTRING get_expr_query() const override
|
|
|
|
{
|
MDEV-5816: Stored programs: validation of stored program statements
Added re-parsing of a failing cursor body. Re-parsing of a failing
SP statement is implemented by the method validate_lex_and_exec_core(),
therefore invocation of the method reset_lex_and_exec_core() inside
sp_lex_keeper::cursor_reset_lex_and_exec_core
was replaced by the method validate_lex_and_exec_core().
Re-parsing of a failed SP statement is relied upon interface provided
by the class sp_lex_instr (the methods used for this goal are
is_invalid(), parse_expr(), invalidate(), get_query(), get_expr_query()).
To provide access to these methods on opening a cursor, the signature of
the method
sp_lex_keeper::cursor_reset_lex_and_exec_core
was changed to accept a pointer to the class sp_lex_instr instead of
the class sp_instr, and the new method get_push_instr() was added
into the class sp_cursor. This method is to get access to an instance
of the class sp_instr_cpush on opening a cursor (on handling the statement
OPEN cursors_name).
Default implementation of this method just returns NULL pointer of
the type sp_instr_cpush. This method is overridden in the class
sp_instr_cpush with trivial implementation
{ return this; }
On handling the statement DECLARE CURSOR FOR the new instruction of
the type sp_instr_cpush is added into sp_head. The class sp_instr_cpush
holds a text of SELECT query referencing by a cursor declaration.
When a cursor is being opened (on handling the statement 'OPEN cur_name')
a pointer to sp_instr_cpush is returned by the method
sp_cursor::get_push_instr()
and this pointer is passed to the method
sp_lex_keeper::cursor_reset_lex_and_exec_core
in order to open a cursor and provide access to an interface required
for SP statement re-parsing in case metadata changes took place.
Since real access to a lex object is required on handling instruction
sp_instr_cpush (an instance of this class is created during parsing of
cursor declaration statement), calling of the method sp_cursor::open
is moved from the method
sp_instr_copen::exec_core
into the method
sp_instr_cpush::exec_core.
Additionally, updated the methods get_query/get_expr_query in the classes
sp_instr_cpush, sp_instr_cursor_copy_struct in order to return correct text of
cursor's body taking into account that lexer treated the clause CURSOR FOR/
CURSOR IS as two different tokens following one after another. So, to return
a correct text of SELECT statement specified in CURSOR declaration statement,
the token FOR/IS should be skipped and text following it should be returned as
a text of cursors's query.
2023-07-19 13:14:00 +02:00
|
|
|
/*
|
|
|
|
Lexer on processing the clause CURSOR FOR / CURSOR IS doesn't
|
|
|
|
move a pointer on cpp_buf after the token FOR/IS so skip it explicitly
|
|
|
|
in order to get correct value of cursor's query string.
|
|
|
|
*/
|
|
|
|
if (strncasecmp(m_cursor_stmt.str, "FOR ", 4) == 0)
|
|
|
|
return LEX_CSTRING{m_cursor_stmt.str + 4, m_cursor_stmt.length - 4};
|
|
|
|
if (strncasecmp(m_cursor_stmt.str, "IS ", 3) == 0)
|
|
|
|
return LEX_CSTRING{m_cursor_stmt.str + 3, m_cursor_stmt.length - 3};
|
2023-07-19 12:53:55 +02:00
|
|
|
return m_cursor_stmt;
|
|
|
|
}
|
|
|
|
|
2023-07-19 12:43:31 +02:00
|
|
|
private:
|
|
|
|
uint m_cursor; /**< Frame offset (for debugging) */
|
MDEV-5816: Stored programs: validation of stored program statements
This is the prerequisite patch introducing the class sp_lex_instr
that encapsulates access to an instance of the class sp_lex_keeper.
Every SP instruction that need to get access to a LEX object on its
processing should inherit this class and implement two abstract methods:
is_invalid(),
invalidate().
These methods will be used in subsequent patches to implement recompilation of
SP instructions on failure.
Currently, the following instructions are derived from the class sp_lex_instr:
sp_instr_stmt,
sp_instr_set,
sp_instr_set_trigger_field,
sp_instr_jump_if_not,
sp_instr_freturn,
sp_instr_cpush,
sp_instr_cursor_copy_struct,
sp_instr_set_case_expr
Additionally, this patch converts the class sp_instr_opt_meta
to a base abstract class (that is, not inherited from the class
sp_instr). Since this class originally was designed to provide a way
for opimizer to update a destination address for jump SP-instructions,
the only useful method at the interface of this class is set_destination
and therefore inheritance from the class sp_instr is meaningless.
Every jump SP instruction now must be inherited directly from
the class sp_instr_opt_meta and additionally from either the class
sp_lex_instr or sp_instr depending on whether this SP instruction
need to get access to a LEX object or not.
Moreover, the class sp_cursor doesn't own a data member of
the class sp_lex_keeper any more. Instead, the virtual method
get_lex_keeper() has been added to the class sp_cursor() that
returns nullptr and this method is overridden in the derived class
sp_instr_cpush to provide a pointer to a real instance of
the class sp_lex_keeper. Doing this way we exclude duplication
of a data member of the type sp_lex_keeper at the class sp_instr_cpush
since it is derived both from sp_lex_instr and sp_cursor, and sp_lex_instr
already encapsulates a data member of the class sp_lex_keeper.
2023-07-19 12:50:47 +02:00
|
|
|
/**
|
|
|
|
Flag if a statement's metadata has been changed in result of running DDL
|
|
|
|
on depending database objects used in the statement.
|
|
|
|
*/
|
|
|
|
bool m_metadata_changed;
|
2023-07-19 12:43:31 +02:00
|
|
|
|
2023-07-19 12:53:55 +02:00
|
|
|
LEX_CSTRING m_cursor_stmt;
|
|
|
|
|
2023-07-19 12:43:31 +02:00
|
|
|
public:
|
|
|
|
PSI_statement_info* get_psi_info() override { return & psi_info; }
|
|
|
|
static PSI_statement_info psi_info;
|
|
|
|
}; // class sp_instr_cpush : public sp_instr
|
|
|
|
|
|
|
|
|
|
|
|
class sp_instr_cpop : public sp_instr
|
|
|
|
{
|
|
|
|
sp_instr_cpop(const sp_instr_cpop &); /**< Prevent use of these */
|
|
|
|
void operator=(sp_instr_cpop &);
|
|
|
|
|
|
|
|
public:
|
|
|
|
sp_instr_cpop(uint ip, sp_pcontext *ctx, uint count)
|
|
|
|
: sp_instr(ip, ctx),
|
|
|
|
m_count(count)
|
|
|
|
{}
|
|
|
|
|
|
|
|
virtual ~sp_instr_cpop() = default;
|
|
|
|
|
|
|
|
void update_count(uint count)
|
|
|
|
{
|
|
|
|
m_count= count;
|
|
|
|
}
|
|
|
|
|
|
|
|
int execute(THD *thd, uint *nextp) override;
|
|
|
|
|
|
|
|
void print(String *str) override;
|
|
|
|
|
|
|
|
private:
|
|
|
|
uint m_count;
|
|
|
|
|
|
|
|
public:
|
|
|
|
PSI_statement_info* get_psi_info() override { return & psi_info; }
|
|
|
|
static PSI_statement_info psi_info;
|
|
|
|
}; // class sp_instr_cpop : public sp_instr
|
|
|
|
|
|
|
|
|
|
|
|
class sp_instr_copen : public sp_instr
|
|
|
|
{
|
|
|
|
sp_instr_copen(const sp_instr_copen &); /**< Prevent use of these */
|
|
|
|
void operator=(sp_instr_copen &);
|
|
|
|
|
|
|
|
public:
|
|
|
|
sp_instr_copen(uint ip, sp_pcontext *ctx, uint c)
|
|
|
|
: sp_instr(ip, ctx),
|
|
|
|
m_cursor(c)
|
|
|
|
{}
|
|
|
|
|
|
|
|
virtual ~sp_instr_copen() = default;
|
|
|
|
|
|
|
|
int execute(THD *thd, uint *nextp) override;
|
|
|
|
|
|
|
|
void print(String *str) override;
|
|
|
|
|
|
|
|
private:
|
|
|
|
uint m_cursor; ///< Stack index
|
|
|
|
|
|
|
|
public:
|
|
|
|
PSI_statement_info* get_psi_info() override { return & psi_info; }
|
|
|
|
static PSI_statement_info psi_info;
|
|
|
|
}; // class sp_instr_copen : public sp_instr_stmt
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
Initialize the structure of a cursor%ROWTYPE variable
|
|
|
|
from the LEX containing the cursor SELECT statement.
|
|
|
|
*/
|
|
|
|
|
MDEV-5816: Stored programs: validation of stored program statements
This is the prerequisite patch introducing the class sp_lex_instr
that encapsulates access to an instance of the class sp_lex_keeper.
Every SP instruction that need to get access to a LEX object on its
processing should inherit this class and implement two abstract methods:
is_invalid(),
invalidate().
These methods will be used in subsequent patches to implement recompilation of
SP instructions on failure.
Currently, the following instructions are derived from the class sp_lex_instr:
sp_instr_stmt,
sp_instr_set,
sp_instr_set_trigger_field,
sp_instr_jump_if_not,
sp_instr_freturn,
sp_instr_cpush,
sp_instr_cursor_copy_struct,
sp_instr_set_case_expr
Additionally, this patch converts the class sp_instr_opt_meta
to a base abstract class (that is, not inherited from the class
sp_instr). Since this class originally was designed to provide a way
for opimizer to update a destination address for jump SP-instructions,
the only useful method at the interface of this class is set_destination
and therefore inheritance from the class sp_instr is meaningless.
Every jump SP instruction now must be inherited directly from
the class sp_instr_opt_meta and additionally from either the class
sp_lex_instr or sp_instr depending on whether this SP instruction
need to get access to a LEX object or not.
Moreover, the class sp_cursor doesn't own a data member of
the class sp_lex_keeper any more. Instead, the virtual method
get_lex_keeper() has been added to the class sp_cursor() that
returns nullptr and this method is overridden in the derived class
sp_instr_cpush to provide a pointer to a real instance of
the class sp_lex_keeper. Doing this way we exclude duplication
of a data member of the type sp_lex_keeper at the class sp_instr_cpush
since it is derived both from sp_lex_instr and sp_cursor, and sp_lex_instr
already encapsulates a data member of the class sp_lex_keeper.
2023-07-19 12:50:47 +02:00
|
|
|
class sp_instr_cursor_copy_struct: public sp_lex_instr
|
2023-07-19 12:43:31 +02:00
|
|
|
{
|
|
|
|
/**< Prevent use of these */
|
|
|
|
sp_instr_cursor_copy_struct(const sp_instr_cursor_copy_struct &);
|
|
|
|
void operator=(sp_instr_cursor_copy_struct &);
|
|
|
|
uint m_cursor;
|
|
|
|
uint m_var;
|
MDEV-5816: Stored programs: validation of stored program statements
This is the prerequisite patch introducing the class sp_lex_instr
that encapsulates access to an instance of the class sp_lex_keeper.
Every SP instruction that need to get access to a LEX object on its
processing should inherit this class and implement two abstract methods:
is_invalid(),
invalidate().
These methods will be used in subsequent patches to implement recompilation of
SP instructions on failure.
Currently, the following instructions are derived from the class sp_lex_instr:
sp_instr_stmt,
sp_instr_set,
sp_instr_set_trigger_field,
sp_instr_jump_if_not,
sp_instr_freturn,
sp_instr_cpush,
sp_instr_cursor_copy_struct,
sp_instr_set_case_expr
Additionally, this patch converts the class sp_instr_opt_meta
to a base abstract class (that is, not inherited from the class
sp_instr). Since this class originally was designed to provide a way
for opimizer to update a destination address for jump SP-instructions,
the only useful method at the interface of this class is set_destination
and therefore inheritance from the class sp_instr is meaningless.
Every jump SP instruction now must be inherited directly from
the class sp_instr_opt_meta and additionally from either the class
sp_lex_instr or sp_instr depending on whether this SP instruction
need to get access to a LEX object or not.
Moreover, the class sp_cursor doesn't own a data member of
the class sp_lex_keeper any more. Instead, the virtual method
get_lex_keeper() has been added to the class sp_cursor() that
returns nullptr and this method is overridden in the derived class
sp_instr_cpush to provide a pointer to a real instance of
the class sp_lex_keeper. Doing this way we exclude duplication
of a data member of the type sp_lex_keeper at the class sp_instr_cpush
since it is derived both from sp_lex_instr and sp_cursor, and sp_lex_instr
already encapsulates a data member of the class sp_lex_keeper.
2023-07-19 12:50:47 +02:00
|
|
|
/**
|
|
|
|
Flag to tell whether metadata has been changed and the LEX object should
|
|
|
|
be reinitialized.
|
|
|
|
*/
|
|
|
|
bool m_valid;
|
2023-07-19 12:53:55 +02:00
|
|
|
LEX_CSTRING m_cursor_stmt;
|
2023-07-19 12:43:31 +02:00
|
|
|
|
|
|
|
public:
|
|
|
|
sp_instr_cursor_copy_struct(uint ip, sp_pcontext *ctx, uint coffs,
|
|
|
|
sp_lex_cursor *lex, uint voffs)
|
MDEV-5816: Stored programs: validation of stored program statements
This is the prerequisite patch introducing the class sp_lex_instr
that encapsulates access to an instance of the class sp_lex_keeper.
Every SP instruction that need to get access to a LEX object on its
processing should inherit this class and implement two abstract methods:
is_invalid(),
invalidate().
These methods will be used in subsequent patches to implement recompilation of
SP instructions on failure.
Currently, the following instructions are derived from the class sp_lex_instr:
sp_instr_stmt,
sp_instr_set,
sp_instr_set_trigger_field,
sp_instr_jump_if_not,
sp_instr_freturn,
sp_instr_cpush,
sp_instr_cursor_copy_struct,
sp_instr_set_case_expr
Additionally, this patch converts the class sp_instr_opt_meta
to a base abstract class (that is, not inherited from the class
sp_instr). Since this class originally was designed to provide a way
for opimizer to update a destination address for jump SP-instructions,
the only useful method at the interface of this class is set_destination
and therefore inheritance from the class sp_instr is meaningless.
Every jump SP instruction now must be inherited directly from
the class sp_instr_opt_meta and additionally from either the class
sp_lex_instr or sp_instr depending on whether this SP instruction
need to get access to a LEX object or not.
Moreover, the class sp_cursor doesn't own a data member of
the class sp_lex_keeper any more. Instead, the virtual method
get_lex_keeper() has been added to the class sp_cursor() that
returns nullptr and this method is overridden in the derived class
sp_instr_cpush to provide a pointer to a real instance of
the class sp_lex_keeper. Doing this way we exclude duplication
of a data member of the type sp_lex_keeper at the class sp_instr_cpush
since it is derived both from sp_lex_instr and sp_cursor, and sp_lex_instr
already encapsulates a data member of the class sp_lex_keeper.
2023-07-19 12:50:47 +02:00
|
|
|
: sp_lex_instr(ip, ctx, lex, false),
|
2023-07-19 12:43:31 +02:00
|
|
|
m_cursor(coffs),
|
MDEV-5816: Stored programs: validation of stored program statements
This is the prerequisite patch introducing the class sp_lex_instr
that encapsulates access to an instance of the class sp_lex_keeper.
Every SP instruction that need to get access to a LEX object on its
processing should inherit this class and implement two abstract methods:
is_invalid(),
invalidate().
These methods will be used in subsequent patches to implement recompilation of
SP instructions on failure.
Currently, the following instructions are derived from the class sp_lex_instr:
sp_instr_stmt,
sp_instr_set,
sp_instr_set_trigger_field,
sp_instr_jump_if_not,
sp_instr_freturn,
sp_instr_cpush,
sp_instr_cursor_copy_struct,
sp_instr_set_case_expr
Additionally, this patch converts the class sp_instr_opt_meta
to a base abstract class (that is, not inherited from the class
sp_instr). Since this class originally was designed to provide a way
for opimizer to update a destination address for jump SP-instructions,
the only useful method at the interface of this class is set_destination
and therefore inheritance from the class sp_instr is meaningless.
Every jump SP instruction now must be inherited directly from
the class sp_instr_opt_meta and additionally from either the class
sp_lex_instr or sp_instr depending on whether this SP instruction
need to get access to a LEX object or not.
Moreover, the class sp_cursor doesn't own a data member of
the class sp_lex_keeper any more. Instead, the virtual method
get_lex_keeper() has been added to the class sp_cursor() that
returns nullptr and this method is overridden in the derived class
sp_instr_cpush to provide a pointer to a real instance of
the class sp_lex_keeper. Doing this way we exclude duplication
of a data member of the type sp_lex_keeper at the class sp_instr_cpush
since it is derived both from sp_lex_instr and sp_cursor, and sp_lex_instr
already encapsulates a data member of the class sp_lex_keeper.
2023-07-19 12:50:47 +02:00
|
|
|
m_var(voffs),
|
2023-07-19 12:53:55 +02:00
|
|
|
m_valid(true),
|
|
|
|
m_cursor_stmt(lex->get_expr_str())
|
2023-07-19 12:43:31 +02:00
|
|
|
{}
|
|
|
|
virtual ~sp_instr_cursor_copy_struct() = default;
|
|
|
|
int execute(THD *thd, uint *nextp) override;
|
|
|
|
int exec_core(THD *thd, uint *nextp) override;
|
|
|
|
void print(String *str) override;
|
MDEV-5816: Stored programs: validation of stored program statements
This is the prerequisite patch introducing the class sp_lex_instr
that encapsulates access to an instance of the class sp_lex_keeper.
Every SP instruction that need to get access to a LEX object on its
processing should inherit this class and implement two abstract methods:
is_invalid(),
invalidate().
These methods will be used in subsequent patches to implement recompilation of
SP instructions on failure.
Currently, the following instructions are derived from the class sp_lex_instr:
sp_instr_stmt,
sp_instr_set,
sp_instr_set_trigger_field,
sp_instr_jump_if_not,
sp_instr_freturn,
sp_instr_cpush,
sp_instr_cursor_copy_struct,
sp_instr_set_case_expr
Additionally, this patch converts the class sp_instr_opt_meta
to a base abstract class (that is, not inherited from the class
sp_instr). Since this class originally was designed to provide a way
for opimizer to update a destination address for jump SP-instructions,
the only useful method at the interface of this class is set_destination
and therefore inheritance from the class sp_instr is meaningless.
Every jump SP instruction now must be inherited directly from
the class sp_instr_opt_meta and additionally from either the class
sp_lex_instr or sp_instr depending on whether this SP instruction
need to get access to a LEX object or not.
Moreover, the class sp_cursor doesn't own a data member of
the class sp_lex_keeper any more. Instead, the virtual method
get_lex_keeper() has been added to the class sp_cursor() that
returns nullptr and this method is overridden in the derived class
sp_instr_cpush to provide a pointer to a real instance of
the class sp_lex_keeper. Doing this way we exclude duplication
of a data member of the type sp_lex_keeper at the class sp_instr_cpush
since it is derived both from sp_lex_instr and sp_cursor, and sp_lex_instr
already encapsulates a data member of the class sp_lex_keeper.
2023-07-19 12:50:47 +02:00
|
|
|
bool is_invalid() const override
|
|
|
|
{
|
|
|
|
return !m_valid;
|
|
|
|
}
|
|
|
|
|
|
|
|
void invalidate() override
|
|
|
|
{
|
|
|
|
m_valid= false;
|
|
|
|
}
|
2023-07-19 12:43:31 +02:00
|
|
|
|
2023-07-19 12:53:55 +02:00
|
|
|
void get_query(String *sql_query) const override
|
|
|
|
{
|
|
|
|
sql_query->append(get_expr_query());
|
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
LEX_CSTRING get_expr_query() const override
|
|
|
|
{
|
MDEV-5816: Stored programs: validation of stored program statements
Added re-parsing of a failing cursor body. Re-parsing of a failing
SP statement is implemented by the method validate_lex_and_exec_core(),
therefore invocation of the method reset_lex_and_exec_core() inside
sp_lex_keeper::cursor_reset_lex_and_exec_core
was replaced by the method validate_lex_and_exec_core().
Re-parsing of a failed SP statement is relied upon interface provided
by the class sp_lex_instr (the methods used for this goal are
is_invalid(), parse_expr(), invalidate(), get_query(), get_expr_query()).
To provide access to these methods on opening a cursor, the signature of
the method
sp_lex_keeper::cursor_reset_lex_and_exec_core
was changed to accept a pointer to the class sp_lex_instr instead of
the class sp_instr, and the new method get_push_instr() was added
into the class sp_cursor. This method is to get access to an instance
of the class sp_instr_cpush on opening a cursor (on handling the statement
OPEN cursors_name).
Default implementation of this method just returns NULL pointer of
the type sp_instr_cpush. This method is overridden in the class
sp_instr_cpush with trivial implementation
{ return this; }
On handling the statement DECLARE CURSOR FOR the new instruction of
the type sp_instr_cpush is added into sp_head. The class sp_instr_cpush
holds a text of SELECT query referencing by a cursor declaration.
When a cursor is being opened (on handling the statement 'OPEN cur_name')
a pointer to sp_instr_cpush is returned by the method
sp_cursor::get_push_instr()
and this pointer is passed to the method
sp_lex_keeper::cursor_reset_lex_and_exec_core
in order to open a cursor and provide access to an interface required
for SP statement re-parsing in case metadata changes took place.
Since real access to a lex object is required on handling instruction
sp_instr_cpush (an instance of this class is created during parsing of
cursor declaration statement), calling of the method sp_cursor::open
is moved from the method
sp_instr_copen::exec_core
into the method
sp_instr_cpush::exec_core.
Additionally, updated the methods get_query/get_expr_query in the classes
sp_instr_cpush, sp_instr_cursor_copy_struct in order to return correct text of
cursor's body taking into account that lexer treated the clause CURSOR FOR/
CURSOR IS as two different tokens following one after another. So, to return
a correct text of SELECT statement specified in CURSOR declaration statement,
the token FOR/IS should be skipped and text following it should be returned as
a text of cursors's query.
2023-07-19 13:14:00 +02:00
|
|
|
/*
|
|
|
|
Lexer on processing the clause CURSOR FOR / CURSOR IS doesn't
|
|
|
|
move a pointer on cpp_buf after the token FOR/IS so skip it explicitly
|
|
|
|
in order to get correct value of cursor's query string.
|
|
|
|
*/
|
|
|
|
if (strncasecmp(m_cursor_stmt.str, "FOR ", 4) == 0)
|
|
|
|
return LEX_CSTRING{m_cursor_stmt.str + 4, m_cursor_stmt.length - 4};
|
|
|
|
if (strncasecmp(m_cursor_stmt.str, "IS ", 3) == 0)
|
|
|
|
return LEX_CSTRING{m_cursor_stmt.str + 3, m_cursor_stmt.length - 3};
|
2023-07-19 12:53:55 +02:00
|
|
|
return m_cursor_stmt;
|
|
|
|
}
|
|
|
|
|
2023-07-19 12:57:13 +02:00
|
|
|
bool on_after_expr_parsing(THD *) override
|
|
|
|
{
|
|
|
|
m_valid= true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-07-19 12:43:31 +02:00
|
|
|
public:
|
|
|
|
PSI_statement_info* get_psi_info() override { return & psi_info; }
|
|
|
|
static PSI_statement_info psi_info;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class sp_instr_cclose : public sp_instr
|
|
|
|
{
|
|
|
|
sp_instr_cclose(const sp_instr_cclose &); /**< Prevent use of these */
|
|
|
|
void operator=(sp_instr_cclose &);
|
|
|
|
|
|
|
|
public:
|
|
|
|
sp_instr_cclose(uint ip, sp_pcontext *ctx, uint c)
|
|
|
|
: sp_instr(ip, ctx),
|
|
|
|
m_cursor(c)
|
|
|
|
{}
|
|
|
|
|
|
|
|
virtual ~sp_instr_cclose() = default;
|
|
|
|
|
|
|
|
int execute(THD *thd, uint *nextp) override;
|
|
|
|
|
|
|
|
void print(String *str) override;
|
|
|
|
|
|
|
|
private:
|
|
|
|
uint m_cursor;
|
|
|
|
|
|
|
|
public:
|
|
|
|
PSI_statement_info* get_psi_info() override { return & psi_info; }
|
|
|
|
static PSI_statement_info psi_info;
|
|
|
|
}; // class sp_instr_cclose : public sp_instr
|
|
|
|
|
|
|
|
|
|
|
|
class sp_instr_cfetch : public sp_instr
|
|
|
|
{
|
|
|
|
sp_instr_cfetch(const sp_instr_cfetch &); /**< Prevent use of these */
|
|
|
|
void operator=(sp_instr_cfetch &);
|
|
|
|
|
|
|
|
public:
|
|
|
|
sp_instr_cfetch(uint ip, sp_pcontext *ctx, uint c, bool error_on_no_data)
|
|
|
|
: sp_instr(ip, ctx),
|
|
|
|
m_cursor(c),
|
|
|
|
m_error_on_no_data(error_on_no_data)
|
|
|
|
{
|
|
|
|
m_varlist.empty();
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual ~sp_instr_cfetch() = default;
|
|
|
|
|
|
|
|
int execute(THD *thd, uint *nextp) override;
|
|
|
|
|
|
|
|
void print(String *str) override;
|
|
|
|
|
|
|
|
void add_to_varlist(sp_variable *var)
|
|
|
|
{
|
|
|
|
m_varlist.push_back(var);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
uint m_cursor;
|
|
|
|
List<sp_variable> m_varlist;
|
|
|
|
bool m_error_on_no_data;
|
|
|
|
|
|
|
|
public:
|
|
|
|
PSI_statement_info* get_psi_info() override { return & psi_info; }
|
|
|
|
static PSI_statement_info psi_info;
|
|
|
|
}; // class sp_instr_cfetch : public sp_instr
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
This class is created for the special fetch instruction
|
|
|
|
FETCH GROUP NEXT ROW, used in the user-defined aggregate
|
|
|
|
functions
|
|
|
|
*/
|
|
|
|
|
|
|
|
class sp_instr_agg_cfetch : public sp_instr
|
|
|
|
{
|
|
|
|
sp_instr_agg_cfetch(const sp_instr_cfetch &); /**< Prevent use of these */
|
|
|
|
void operator=(sp_instr_cfetch &);
|
|
|
|
|
|
|
|
public:
|
|
|
|
sp_instr_agg_cfetch(uint ip, sp_pcontext *ctx)
|
|
|
|
: sp_instr(ip, ctx)
|
|
|
|
{}
|
|
|
|
|
|
|
|
virtual ~sp_instr_agg_cfetch() = default;
|
|
|
|
|
|
|
|
int execute(THD *thd, uint *nextp) override;
|
|
|
|
|
|
|
|
void print(String *str) override;
|
|
|
|
|
|
|
|
public:
|
|
|
|
PSI_statement_info* get_psi_info() override { return & psi_info; }
|
|
|
|
static PSI_statement_info psi_info;
|
|
|
|
}; // class sp_instr_agg_cfetch : public sp_instr
|
|
|
|
|
|
|
|
|
|
|
|
class sp_instr_error : public sp_instr
|
|
|
|
{
|
|
|
|
sp_instr_error(const sp_instr_error &); /**< Prevent use of these */
|
|
|
|
void operator=(sp_instr_error &);
|
|
|
|
|
|
|
|
public:
|
|
|
|
sp_instr_error(uint ip, sp_pcontext *ctx, int errcode)
|
|
|
|
: sp_instr(ip, ctx),
|
|
|
|
m_errcode(errcode)
|
|
|
|
{}
|
|
|
|
|
|
|
|
virtual ~sp_instr_error() = default;
|
|
|
|
|
|
|
|
int execute(THD *thd, uint *nextp) override;
|
|
|
|
|
|
|
|
void print(String *str) override;
|
|
|
|
|
|
|
|
uint opt_mark(sp_head *sp, List<sp_instr> *leads) override
|
|
|
|
{
|
|
|
|
marked= 1;
|
|
|
|
return UINT_MAX;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
int m_errcode;
|
|
|
|
|
|
|
|
public:
|
|
|
|
PSI_statement_info* get_psi_info() override { return & psi_info; }
|
|
|
|
static PSI_statement_info psi_info;
|
|
|
|
}; // class sp_instr_error : public sp_instr
|
|
|
|
|
|
|
|
|
MDEV-5816: Stored programs: validation of stored program statements
This is the prerequisite patch introducing the class sp_lex_instr
that encapsulates access to an instance of the class sp_lex_keeper.
Every SP instruction that need to get access to a LEX object on its
processing should inherit this class and implement two abstract methods:
is_invalid(),
invalidate().
These methods will be used in subsequent patches to implement recompilation of
SP instructions on failure.
Currently, the following instructions are derived from the class sp_lex_instr:
sp_instr_stmt,
sp_instr_set,
sp_instr_set_trigger_field,
sp_instr_jump_if_not,
sp_instr_freturn,
sp_instr_cpush,
sp_instr_cursor_copy_struct,
sp_instr_set_case_expr
Additionally, this patch converts the class sp_instr_opt_meta
to a base abstract class (that is, not inherited from the class
sp_instr). Since this class originally was designed to provide a way
for opimizer to update a destination address for jump SP-instructions,
the only useful method at the interface of this class is set_destination
and therefore inheritance from the class sp_instr is meaningless.
Every jump SP instruction now must be inherited directly from
the class sp_instr_opt_meta and additionally from either the class
sp_lex_instr or sp_instr depending on whether this SP instruction
need to get access to a LEX object or not.
Moreover, the class sp_cursor doesn't own a data member of
the class sp_lex_keeper any more. Instead, the virtual method
get_lex_keeper() has been added to the class sp_cursor() that
returns nullptr and this method is overridden in the derived class
sp_instr_cpush to provide a pointer to a real instance of
the class sp_lex_keeper. Doing this way we exclude duplication
of a data member of the type sp_lex_keeper at the class sp_instr_cpush
since it is derived both from sp_lex_instr and sp_cursor, and sp_lex_instr
already encapsulates a data member of the class sp_lex_keeper.
2023-07-19 12:50:47 +02:00
|
|
|
class sp_instr_set_case_expr : public sp_lex_instr, public sp_instr_opt_meta
|
2023-07-19 12:43:31 +02:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
sp_instr_set_case_expr(uint ip, sp_pcontext *ctx, uint case_expr_id,
|
2023-07-19 12:53:55 +02:00
|
|
|
Item *case_expr, LEX *lex,
|
|
|
|
const LEX_CSTRING &case_expr_query)
|
MDEV-5816: Stored programs: validation of stored program statements
This is the prerequisite patch introducing the class sp_lex_instr
that encapsulates access to an instance of the class sp_lex_keeper.
Every SP instruction that need to get access to a LEX object on its
processing should inherit this class and implement two abstract methods:
is_invalid(),
invalidate().
These methods will be used in subsequent patches to implement recompilation of
SP instructions on failure.
Currently, the following instructions are derived from the class sp_lex_instr:
sp_instr_stmt,
sp_instr_set,
sp_instr_set_trigger_field,
sp_instr_jump_if_not,
sp_instr_freturn,
sp_instr_cpush,
sp_instr_cursor_copy_struct,
sp_instr_set_case_expr
Additionally, this patch converts the class sp_instr_opt_meta
to a base abstract class (that is, not inherited from the class
sp_instr). Since this class originally was designed to provide a way
for opimizer to update a destination address for jump SP-instructions,
the only useful method at the interface of this class is set_destination
and therefore inheritance from the class sp_instr is meaningless.
Every jump SP instruction now must be inherited directly from
the class sp_instr_opt_meta and additionally from either the class
sp_lex_instr or sp_instr depending on whether this SP instruction
need to get access to a LEX object or not.
Moreover, the class sp_cursor doesn't own a data member of
the class sp_lex_keeper any more. Instead, the virtual method
get_lex_keeper() has been added to the class sp_cursor() that
returns nullptr and this method is overridden in the derived class
sp_instr_cpush to provide a pointer to a real instance of
the class sp_lex_keeper. Doing this way we exclude duplication
of a data member of the type sp_lex_keeper at the class sp_instr_cpush
since it is derived both from sp_lex_instr and sp_cursor, and sp_lex_instr
already encapsulates a data member of the class sp_lex_keeper.
2023-07-19 12:50:47 +02:00
|
|
|
: sp_lex_instr(ip, ctx, lex, true),
|
|
|
|
sp_instr_opt_meta(0),
|
2023-07-19 12:43:31 +02:00
|
|
|
m_case_expr_id(case_expr_id),
|
2023-07-19 12:53:55 +02:00
|
|
|
m_case_expr(case_expr),
|
|
|
|
m_expr_str(case_expr_query)
|
2023-07-19 12:43:31 +02:00
|
|
|
{}
|
|
|
|
|
|
|
|
virtual ~sp_instr_set_case_expr() = default;
|
|
|
|
|
|
|
|
int execute(THD *thd, uint *nextp) override;
|
|
|
|
|
|
|
|
int exec_core(THD *thd, uint *nextp) override;
|
|
|
|
|
|
|
|
void print(String *str) override;
|
|
|
|
|
|
|
|
uint opt_mark(sp_head *sp, List<sp_instr> *leads) override;
|
|
|
|
|
2023-07-19 12:48:31 +02:00
|
|
|
void opt_move(uint dst, List<sp_instr_opt_meta> *ibp) override;
|
2023-07-19 12:43:31 +02:00
|
|
|
|
MDEV-5816: Stored programs: validation of stored program statements
This is the prerequisite patch introducing the class sp_lex_instr
that encapsulates access to an instance of the class sp_lex_keeper.
Every SP instruction that need to get access to a LEX object on its
processing should inherit this class and implement two abstract methods:
is_invalid(),
invalidate().
These methods will be used in subsequent patches to implement recompilation of
SP instructions on failure.
Currently, the following instructions are derived from the class sp_lex_instr:
sp_instr_stmt,
sp_instr_set,
sp_instr_set_trigger_field,
sp_instr_jump_if_not,
sp_instr_freturn,
sp_instr_cpush,
sp_instr_cursor_copy_struct,
sp_instr_set_case_expr
Additionally, this patch converts the class sp_instr_opt_meta
to a base abstract class (that is, not inherited from the class
sp_instr). Since this class originally was designed to provide a way
for opimizer to update a destination address for jump SP-instructions,
the only useful method at the interface of this class is set_destination
and therefore inheritance from the class sp_instr is meaningless.
Every jump SP instruction now must be inherited directly from
the class sp_instr_opt_meta and additionally from either the class
sp_lex_instr or sp_instr depending on whether this SP instruction
need to get access to a LEX object or not.
Moreover, the class sp_cursor doesn't own a data member of
the class sp_lex_keeper any more. Instead, the virtual method
get_lex_keeper() has been added to the class sp_cursor() that
returns nullptr and this method is overridden in the derived class
sp_instr_cpush to provide a pointer to a real instance of
the class sp_lex_keeper. Doing this way we exclude duplication
of a data member of the type sp_lex_keeper at the class sp_instr_cpush
since it is derived both from sp_lex_instr and sp_cursor, and sp_lex_instr
already encapsulates a data member of the class sp_lex_keeper.
2023-07-19 12:50:47 +02:00
|
|
|
uint get_cont_dest() const override
|
|
|
|
{
|
|
|
|
return m_cont_dest;
|
|
|
|
}
|
|
|
|
|
2023-07-19 12:43:31 +02:00
|
|
|
void set_destination(uint old_dest, uint new_dest) override
|
|
|
|
{
|
|
|
|
if (m_cont_dest == old_dest)
|
|
|
|
m_cont_dest= new_dest;
|
|
|
|
}
|
|
|
|
|
MDEV-5816: Stored programs: validation of stored program statements
This is the prerequisite patch introducing the class sp_lex_instr
that encapsulates access to an instance of the class sp_lex_keeper.
Every SP instruction that need to get access to a LEX object on its
processing should inherit this class and implement two abstract methods:
is_invalid(),
invalidate().
These methods will be used in subsequent patches to implement recompilation of
SP instructions on failure.
Currently, the following instructions are derived from the class sp_lex_instr:
sp_instr_stmt,
sp_instr_set,
sp_instr_set_trigger_field,
sp_instr_jump_if_not,
sp_instr_freturn,
sp_instr_cpush,
sp_instr_cursor_copy_struct,
sp_instr_set_case_expr
Additionally, this patch converts the class sp_instr_opt_meta
to a base abstract class (that is, not inherited from the class
sp_instr). Since this class originally was designed to provide a way
for opimizer to update a destination address for jump SP-instructions,
the only useful method at the interface of this class is set_destination
and therefore inheritance from the class sp_instr is meaningless.
Every jump SP instruction now must be inherited directly from
the class sp_instr_opt_meta and additionally from either the class
sp_lex_instr or sp_instr depending on whether this SP instruction
need to get access to a LEX object or not.
Moreover, the class sp_cursor doesn't own a data member of
the class sp_lex_keeper any more. Instead, the virtual method
get_lex_keeper() has been added to the class sp_cursor() that
returns nullptr and this method is overridden in the derived class
sp_instr_cpush to provide a pointer to a real instance of
the class sp_lex_keeper. Doing this way we exclude duplication
of a data member of the type sp_lex_keeper at the class sp_instr_cpush
since it is derived both from sp_lex_instr and sp_cursor, and sp_lex_instr
already encapsulates a data member of the class sp_lex_keeper.
2023-07-19 12:50:47 +02:00
|
|
|
bool is_invalid() const override
|
|
|
|
{
|
|
|
|
return m_case_expr == nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void invalidate() override
|
|
|
|
{
|
|
|
|
m_case_expr= nullptr;
|
|
|
|
}
|
|
|
|
|
2023-07-19 12:53:55 +02:00
|
|
|
protected:
|
|
|
|
LEX_CSTRING get_expr_query() const override
|
|
|
|
{
|
|
|
|
return m_expr_str;
|
|
|
|
}
|
|
|
|
|
2023-07-19 12:57:13 +02:00
|
|
|
void adjust_sql_command(LEX *lex) override
|
|
|
|
{
|
|
|
|
assert(lex->sql_command == SQLCOM_SELECT);
|
|
|
|
lex->sql_command= SQLCOM_END;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool on_after_expr_parsing(THD *thd) override
|
|
|
|
{
|
|
|
|
DBUG_ASSERT(thd->lex->current_select->item_list.elements == 1);
|
|
|
|
|
|
|
|
m_case_expr= thd->lex->current_select->item_list.head();
|
|
|
|
DBUG_ASSERT(m_case_expr != nullptr);
|
|
|
|
|
|
|
|
// Return error in release version if m_case_expr == nullptr
|
|
|
|
return m_case_expr == nullptr;
|
|
|
|
}
|
|
|
|
|
2023-07-19 12:43:31 +02:00
|
|
|
private:
|
|
|
|
uint m_case_expr_id;
|
|
|
|
Item *m_case_expr;
|
2023-07-19 12:53:55 +02:00
|
|
|
LEX_CSTRING m_expr_str;
|
2023-07-19 12:43:31 +02:00
|
|
|
|
|
|
|
public:
|
|
|
|
PSI_statement_info* get_psi_info() override { return & psi_info; }
|
|
|
|
static PSI_statement_info psi_info;
|
MDEV-5816: Stored programs: validation of stored program statements
This is the prerequisite patch introducing the class sp_lex_instr
that encapsulates access to an instance of the class sp_lex_keeper.
Every SP instruction that need to get access to a LEX object on its
processing should inherit this class and implement two abstract methods:
is_invalid(),
invalidate().
These methods will be used in subsequent patches to implement recompilation of
SP instructions on failure.
Currently, the following instructions are derived from the class sp_lex_instr:
sp_instr_stmt,
sp_instr_set,
sp_instr_set_trigger_field,
sp_instr_jump_if_not,
sp_instr_freturn,
sp_instr_cpush,
sp_instr_cursor_copy_struct,
sp_instr_set_case_expr
Additionally, this patch converts the class sp_instr_opt_meta
to a base abstract class (that is, not inherited from the class
sp_instr). Since this class originally was designed to provide a way
for opimizer to update a destination address for jump SP-instructions,
the only useful method at the interface of this class is set_destination
and therefore inheritance from the class sp_instr is meaningless.
Every jump SP instruction now must be inherited directly from
the class sp_instr_opt_meta and additionally from either the class
sp_lex_instr or sp_instr depending on whether this SP instruction
need to get access to a LEX object or not.
Moreover, the class sp_cursor doesn't own a data member of
the class sp_lex_keeper any more. Instead, the virtual method
get_lex_keeper() has been added to the class sp_cursor() that
returns nullptr and this method is overridden in the derived class
sp_instr_cpush to provide a pointer to a real instance of
the class sp_lex_keeper. Doing this way we exclude duplication
of a data member of the type sp_lex_keeper at the class sp_instr_cpush
since it is derived both from sp_lex_instr and sp_cursor, and sp_lex_instr
already encapsulates a data member of the class sp_lex_keeper.
2023-07-19 12:50:47 +02:00
|
|
|
}; // class sp_instr_set_case_expr : public sp_lex_instr,
|
2023-07-19 12:43:31 +02:00
|
|
|
|
|
|
|
#endif
|