summaryrefslogtreecommitdiffstats
path: root/sql/sp_head.h
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-07-01 18:15:00 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-07-01 18:15:00 +0000
commita2a2e32c02643a0cec111511220227703fda1cd5 (patch)
tree69cc2b631234c2a8e026b9cd4d72676c61c594df /sql/sp_head.h
parentReleasing progress-linux version 1:10.11.8-1~progress7.99u1. (diff)
downloadmariadb-a2a2e32c02643a0cec111511220227703fda1cd5.tar.xz
mariadb-a2a2e32c02643a0cec111511220227703fda1cd5.zip
Merging upstream version 1:11.4.2.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sql/sp_head.h')
-rw-r--r--sql/sp_head.h1169
1 files changed, 63 insertions, 1106 deletions
diff --git a/sql/sp_head.h b/sql/sp_head.h
index b418ef25..d115ae60 100644
--- a/sql/sp_head.h
+++ b/sql/sp_head.h
@@ -272,6 +272,7 @@ private:
*/
uint32 unsafe_flags;
+ bool new_query_arena_is_set;
public:
inline Stored_program_creation_ctx *get_creation_ctx()
{
@@ -339,15 +340,6 @@ public:
*/
Security_context m_security_ctx;
- /**
- List of all items (Item_trigger_field objects) representing fields in
- old/new version of row in trigger. We use this list for checking whenever
- all such fields are valid at trigger creation time and for binding these
- fields to TABLE object at table open (although for latter pointer to table
- being opened is probably enough).
- */
- SQL_I_List<Item_trigger_field> m_trg_table_fields;
-
protected:
sp_head(MEM_ROOT *mem_root, sp_package *parent, const Sp_handler *handler,
enum_sp_aggregate_type agg_type);
@@ -355,14 +347,15 @@ protected:
public:
static void destroy(sp_head *sp);
static sp_head *create(sp_package *parent, const Sp_handler *handler,
- enum_sp_aggregate_type agg_type);
+ enum_sp_aggregate_type agg_type,
+ MEM_ROOT *sp_mem_root);
/// Initialize after we have reset mem_root
void
init(LEX *lex);
/** Copy sp name from parser. */
- void
+ bool
init_sp_name(const sp_name *spname);
/** Set the body-definition start position. */
@@ -415,7 +408,8 @@ public:
}
bool
- add_instr_freturn(THD *thd, sp_pcontext *spcont, Item *item, LEX *lex);
+ add_instr_freturn(THD *thd, sp_pcontext *spcont, Item *item,
+ sp_expr_lex *lex);
bool
add_instr_preturn(THD *thd, sp_pcontext *spcont);
@@ -435,16 +429,19 @@ public:
bool set_local_variable(THD *thd, sp_pcontext *spcont,
const Sp_rcontext_handler *rh,
sp_variable *spv, Item *val, LEX *lex,
- bool responsible_to_free_lex);
+ bool responsible_to_free_lex,
+ const LEX_CSTRING &value_query);
bool set_local_variable_row_field(THD *thd, sp_pcontext *spcont,
const Sp_rcontext_handler *rh,
sp_variable *spv, uint field_idx,
- Item *val, LEX *lex);
+ Item *val, LEX *lex,
+ const LEX_CSTRING &value_query);
bool set_local_variable_row_field_by_name(THD *thd, sp_pcontext *spcont,
const Sp_rcontext_handler *rh,
sp_variable *spv,
const LEX_CSTRING *field_name,
- Item *val, LEX *lex);
+ Item *val, LEX *lex,
+ const LEX_CSTRING &value_query);
bool check_package_routine_end_name(const LEX_CSTRING &end_name) const;
bool check_standalone_routine_end_name(const sp_name *end_name) const;
bool check_group_aggregate_instructions_function() const;
@@ -474,7 +471,8 @@ private:
m_thd->free_list= prm->get_free_list();
if (set_local_variable(thd, param_spcont,
&sp_rcontext_handler_local,
- spvar, prm->get_item(), prm, true))
+ spvar, prm->get_item(), prm, true,
+ prm->get_expr_str()))
return true;
/*
Safety:
@@ -655,6 +653,16 @@ public:
DBUG_RETURN(thd->restore_from_local_lex_to_old_lex(oldlex));
}
+
+ /**
+ Delete all auxiliary LEX objects created on parsing a statement and
+ restore a value of the data member THD::lex to point on the LEX object
+ that was actual before parsing started.
+ */
+
+ void unwind_aux_lexes_and_restore_original_lex();
+
+
/**
Iterate through the LEX stack from the top (the newest) to the bottom
(the oldest) and find the one that contains a non-zero spname.
@@ -815,6 +823,10 @@ public:
m_definer.copy(mem_root, user_name, host_name);
}
+ void set_definition_string(LEX_STRING &defstr)
+ {
+ m_definition_string= defstr;
+ }
void reset_thd_mem_root(THD *thd);
void restore_thd_mem_root(THD *thd);
@@ -965,6 +977,12 @@ protected:
*/
HASH m_sptabs;
+ /**
+ Text of the query CREATE PROCEDURE/FUNCTION/TRIGGER/EVENT ...
+ used for DDL parsing.
+ */
+ LEX_STRING m_definition_string;
+
bool
execute(THD *thd, bool merge_da_on_success);
@@ -985,6 +1003,30 @@ protected:
push_backpatch(THD *thd, sp_instr *, sp_label *, List<bp_t> *list,
backpatch_instr_type itype);
+public:
+ /*
+ List of lists of Item_trigger_field objects representing all fields in
+ old/new version of row in trigger. We use this list of lists for checking
+ whenever all such fields are valid at trigger creation time and for binding
+ these fields to TABLE object at table open (although for latter pointer
+ to table being opened is probably enough).
+ */
+ SQL_I_List<SQL_I_List<Item_trigger_field> > m_trg_table_fields;
+
+ /**
+ The object of the Trigger class corresponding to this sp_head object.
+ This data member is set on table's triggers loading at the function
+ check_n_load and is used at the method sp_lex_instr::parse_expr
+ for accessing to the trigger's table after re-parsing of failed
+ trigger's instruction.
+ */
+ Trigger *m_trg= nullptr;
+
+ /*
+ List of Item_trigger_field objects created on parsing
+ a current instruction of trigger's body
+ */
+ SQL_I_List<Item_trigger_field> m_cur_instr_trig_field_items;
}; // class sp_head : public Sql_alloc
@@ -1044,7 +1086,7 @@ private:
~sp_package();
public:
static sp_package *create(LEX *top_level_lex, const sp_name *name,
- const Sp_handler *sph);
+ const Sp_handler *sph, MEM_ROOT *sp_mem_root);
bool add_routine_declaration(LEX *lex)
{
@@ -1081,1096 +1123,11 @@ public:
};
-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),
- Query_arena(mem_root_arg, STMT_INITIALIZED_FOR_SP)
- { }
- sp_lex_cursor(THD *thd, const LEX *oldlex)
- :sp_lex_local(thd, oldlex),
- Query_arena(thd->lex->sphead->get_main_mem_root(), STMT_INITIALIZED_FOR_SP)
- { }
- ~sp_lex_cursor() { free_items(); }
- virtual 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= NULL;
- return false;
- }
-};
-
-
-//
-// "Instructions"...
-//
-
-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)
-#ifdef PROTECT_STATEMENT_MEMROOT
- , m_has_been_run(NON_RUN)
-#endif
- {}
-
- 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'.
- */
- virtual void opt_move(uint dst, List<sp_instr> *ibp)
- {
- m_ip= dst;
- }
- virtual PSI_statement_info* get_psi_info() = 0;
-
-#ifdef PROTECT_STATEMENT_MEMROOT
- bool has_been_run() const
- {
- return m_has_been_run == RUN;
- }
-
- void mark_as_qc_used()
- {
- m_has_been_run= QC;
- }
-
- void mark_as_run()
- {
- if (m_has_been_run == QC)
- m_has_been_run= NON_RUN; // answer was from WC => not really executed
- else
- m_has_been_run= RUN;
- }
-
- void mark_as_not_run()
- {
- m_has_been_run= NON_RUN;
- }
-
-private:
- enum {NON_RUN, QC, RUN} m_has_been_run;
-#endif
-}; // class sp_instr : public Sql_alloc
-
-
-/**
- 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
-{
- /** 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),
- lex_query_tables_own_last(NULL)
- {
- lex->sp_lex_in_use= TRUE;
- }
- virtual ~sp_lex_keeper()
- {
- if (m_lex_resp)
- {
- /* Prevent endless recursion. */
- m_lex->sphead= NULL;
- 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);
-
- int cursor_reset_lex_and_exec_core(THD *thd, uint *nextp, bool open_tables,
- sp_instr *instr);
-
- inline uint sql_command() const
- {
- return (uint)m_lex->sql_command;
- }
-
- void disable_query_cache()
- {
- m_lex->safe_to_cache_query= 0;
- }
-
-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;
-};
-
-
-/**
- Call out to some prepared SQL statement.
-*/
-class sp_instr_stmt : public sp_instr
-{
- sp_instr_stmt(const sp_instr_stmt &); /**< Prevent use of these */
- void operator=(sp_instr_stmt &);
-
-public:
-
- LEX_STRING m_query; ///< For thd->query
-
- sp_instr_stmt(uint ip, sp_pcontext *ctx, LEX *lex)
- : sp_instr(ip, ctx), m_lex_keeper(lex, TRUE)
- {
- m_query.str= 0;
- m_query.length= 0;
- }
-
- virtual ~sp_instr_stmt() = default;
-
- virtual int execute(THD *thd, uint *nextp);
-
- virtual int exec_core(THD *thd, uint *nextp);
-
- virtual void print(String *str);
-
-private:
-
- sp_lex_keeper m_lex_keeper;
-
-public:
- virtual PSI_statement_info* get_psi_info() { return & psi_info; }
- static PSI_statement_info psi_info;
-
-}; // class sp_instr_stmt : public sp_instr
-
-
-class sp_instr_set : public sp_instr
-{
- 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,
- LEX *lex, bool lex_resp)
- : sp_instr(ip, ctx),
- m_rcontext_handler(rh), m_offset(offset), m_value(val),
- m_lex_keeper(lex, lex_resp)
- {}
-
- virtual ~sp_instr_set() = default;
-
- virtual int execute(THD *thd, uint *nextp);
-
- virtual int exec_core(THD *thd, uint *nextp);
-
- virtual void print(String *str);
-
-protected:
- sp_rcontext *get_rcontext(THD *thd) const;
- const Sp_rcontext_handler *m_rcontext_handler;
- uint m_offset; ///< Frame offset
- Item *m_value;
- sp_lex_keeper m_lex_keeper;
-
-public:
- virtual PSI_statement_info* get_psi_info() { return & psi_info; }
- static PSI_statement_info psi_info;
-}; // class sp_instr_set : public sp_instr
-
-
-/*
- 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,
- LEX *lex, bool lex_resp)
- : sp_instr_set(ip, ctx, rh, offset, val, lex, lex_resp),
- m_field_offset(field_offset)
- {}
-
- virtual ~sp_instr_set_row_field() = default;
-
- virtual int exec_core(THD *thd, uint *nextp);
-
- virtual void print(String *str);
-}; // 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,
- LEX *lex, bool lex_resp)
- : sp_instr_set(ip, ctx, rh, offset, val, lex, lex_resp),
- m_field_name(field_name)
- {}
-
- virtual ~sp_instr_set_row_field_by_name() = default;
-
- virtual int exec_core(THD *thd, uint *nextp);
-
- virtual void print(String *str);
-}; // class sp_instr_set_field_by_name : public sp_instr_set
-
-
-/**
- Set NEW/OLD row field value instruction. Used in triggers.
-*/
-class sp_instr_set_trigger_field : public sp_instr
-{
- 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,
- Item *val, LEX *lex)
- : sp_instr(ip, ctx),
- trigger_field(trg_fld),
- value(val), m_lex_keeper(lex, TRUE)
- {}
-
- virtual ~sp_instr_set_trigger_field() = default;
-
- virtual int execute(THD *thd, uint *nextp);
-
- virtual int exec_core(THD *thd, uint *nextp);
-
- virtual void print(String *str);
-
-private:
- Item_trigger_field *trigger_field;
- Item *value;
- sp_lex_keeper m_lex_keeper;
-
-public:
- virtual PSI_statement_info* get_psi_info() { return & psi_info; }
- static PSI_statement_info psi_info;
-}; // class sp_instr_trigger_field : public sp_instr
-
-
-/**
- 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.
-*/
-class sp_instr_opt_meta : public sp_instr
-{
-public:
-
- uint m_dest; ///< Where we will go
- uint m_cont_dest; ///< Where continue handlers will go
-
- sp_instr_opt_meta(uint ip, sp_pcontext *ctx)
- : sp_instr(ip, ctx),
- m_dest(0), m_cont_dest(0), m_optdest(0), m_cont_optdest(0)
- {}
-
- sp_instr_opt_meta(uint ip, sp_pcontext *ctx, uint dest)
- : sp_instr(ip, ctx),
- m_dest(dest), 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;
-
- virtual uint get_cont_dest() const;
-
-protected:
-
- sp_instr *m_optdest; ///< Used during optimization
- sp_instr *m_cont_optdest; ///< Used during optimization
-
-}; // class sp_instr_opt_meta : public sp_instr
-
-class sp_instr_jump : public sp_instr_opt_meta
-{
- 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)
- : sp_instr_opt_meta(ip, ctx)
- {}
-
- sp_instr_jump(uint ip, sp_pcontext *ctx, uint dest)
- : sp_instr_opt_meta(ip, ctx, dest)
- {}
-
- virtual ~sp_instr_jump() = default;
-
- virtual int execute(THD *thd, uint *nextp);
-
- virtual void print(String *str);
-
- virtual uint opt_mark(sp_head *sp, List<sp_instr> *leads);
-
- virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start);
-
- virtual void opt_move(uint dst, List<sp_instr> *ibp);
-
- virtual void backpatch(uint dest, sp_pcontext *dst_ctx)
- {
- /* Calling backpatch twice is a logic flaw in jump resolution. */
- DBUG_ASSERT(m_dest == 0);
- m_dest= dest;
- }
-
- /**
- Update the destination; used by the optimizer.
- */
- virtual void set_destination(uint old_dest, uint new_dest)
- {
- if (m_dest == old_dest)
- m_dest= new_dest;
- }
-
-public:
- virtual PSI_statement_info* get_psi_info() { return & psi_info; }
- static PSI_statement_info psi_info;
-}; // class sp_instr_jump : public sp_instr_opt_meta
-
-
-class sp_instr_jump_if_not : public sp_instr_jump
-{
- sp_instr_jump_if_not(const sp_instr_jump_if_not &); /**< Prevent use of these */
- void operator=(sp_instr_jump_if_not &);
-
-public:
-
- sp_instr_jump_if_not(uint ip, sp_pcontext *ctx, Item *i, LEX *lex)
- : sp_instr_jump(ip, ctx), m_expr(i),
- m_lex_keeper(lex, TRUE)
- {}
-
- sp_instr_jump_if_not(uint ip, sp_pcontext *ctx, Item *i, uint dest, LEX *lex)
- : sp_instr_jump(ip, ctx, dest), m_expr(i),
- m_lex_keeper(lex, TRUE)
- {}
-
- virtual ~sp_instr_jump_if_not() = default;
-
- virtual int execute(THD *thd, uint *nextp);
-
- virtual int exec_core(THD *thd, uint *nextp);
-
- virtual void print(String *str);
-
- virtual uint opt_mark(sp_head *sp, List<sp_instr> *leads);
-
- /** Override sp_instr_jump's shortcut; we stop here */
- virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start)
- {
- return m_ip;
- }
-
- virtual void opt_move(uint dst, List<sp_instr> *ibp);
-
- virtual void set_destination(uint old_dest, uint new_dest)
- {
- sp_instr_jump::set_destination(old_dest, new_dest);
- if (m_cont_dest == old_dest)
- m_cont_dest= new_dest;
- }
-
-private:
-
- Item *m_expr; ///< The condition
- sp_lex_keeper m_lex_keeper;
-
-public:
- virtual PSI_statement_info* get_psi_info() { return & psi_info; }
- static PSI_statement_info psi_info;
-}; // class sp_instr_jump_if_not : public sp_instr_jump
-
-
-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;
-
- virtual int execute(THD *thd, uint *nextp);
-
- virtual void print(String *str);
-
- virtual uint opt_mark(sp_head *sp, List<sp_instr> *leads)
- {
- marked= 1;
- return UINT_MAX;
- }
-
-public:
- virtual PSI_statement_info* get_psi_info() { return & psi_info; }
- static PSI_statement_info psi_info;
-}; // class sp_instr_preturn : public sp_instr
-
-
-class sp_instr_freturn : public sp_instr
-{
- 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,
- Item *val, const Type_handler *handler, LEX *lex)
- : sp_instr(ip, ctx), m_value(val), m_type_handler(handler),
- m_lex_keeper(lex, TRUE)
- {}
-
- virtual ~sp_instr_freturn() = default;
-
- virtual int execute(THD *thd, uint *nextp);
-
- virtual int exec_core(THD *thd, uint *nextp);
-
- virtual void print(String *str);
-
- virtual uint opt_mark(sp_head *sp, List<sp_instr> *leads)
- {
- marked= 1;
- return UINT_MAX;
- }
-
-protected:
-
- Item *m_value;
- const Type_handler *m_type_handler;
- sp_lex_keeper m_lex_keeper;
-
-public:
- virtual PSI_statement_info* get_psi_info() { return & psi_info; }
- static PSI_statement_info psi_info;
-}; // class sp_instr_freturn : public sp_instr
-
-
-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);
- }
-
- virtual ~sp_instr_hpush_jump()
- {
- m_handler->condition_values.empty();
- m_handler= NULL;
- }
-
- virtual int execute(THD *thd, uint *nextp);
-
- virtual void print(String *str);
-
- virtual uint opt_mark(sp_head *sp, List<sp_instr> *leads);
-
- /** Override sp_instr_jump's shortcut; we stop here. */
- virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start)
- {
- return m_ip;
- }
-
- virtual void backpatch(uint dest, sp_pcontext *dst_ctx)
- {
- 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:
- virtual PSI_statement_info* get_psi_info() { 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;
- }
-
- virtual int execute(THD *thd, uint *nextp);
-
- virtual void print(String *str);
-
-private:
-
- uint m_count;
-
-public:
- virtual PSI_statement_info* get_psi_info() { 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;
-
- virtual int execute(THD *thd, uint *nextp);
-
- virtual void print(String *str);
-
- /* This instruction will not be short cut optimized. */
- virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start)
- {
- return m_ip;
- }
-
- virtual uint opt_mark(sp_head *sp, List<sp_instr> *leads);
-
-private:
-
- uint m_frame;
-
-public:
- virtual PSI_statement_info* get_psi_info() { return & psi_info; }
- static PSI_statement_info psi_info;
-}; // class sp_instr_hreturn : public sp_instr_jump
-
-
-/** This is DECLARE CURSOR */
-class sp_instr_cpush : public sp_instr, public sp_cursor
-{
- sp_instr_cpush(const sp_instr_cpush &); /**< Prevent use of these */
- void operator=(sp_instr_cpush &);
-
-public:
-
- sp_instr_cpush(uint ip, sp_pcontext *ctx, LEX *lex, uint offset)
- : sp_instr(ip, ctx), m_lex_keeper(lex, TRUE), m_cursor(offset)
- {}
-
- virtual ~sp_instr_cpush() = default;
-
- int execute(THD *thd, uint *nextp) override;
-
- 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.
- */
- virtual bool cleanup_stmt(bool /*restore_set_statement_vars*/) override
- { return false; }
-private:
-
- sp_lex_keeper m_lex_keeper;
- uint m_cursor; /**< Frame offset (for debugging) */
-
-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;
- }
-
- virtual int execute(THD *thd, uint *nextp);
-
- virtual void print(String *str);
-
-private:
-
- uint m_count;
-
-public:
- virtual PSI_statement_info* get_psi_info() { 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;
-
- virtual int execute(THD *thd, uint *nextp);
-
- virtual int exec_core(THD *thd, uint *nextp);
-
- virtual void print(String *str);
-
-private:
-
- uint m_cursor; ///< Stack index
-
-public:
- virtual PSI_statement_info* get_psi_info() { 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.
-*/
-class sp_instr_cursor_copy_struct: public sp_instr
-{
- /**< Prevent use of these */
- sp_instr_cursor_copy_struct(const sp_instr_cursor_copy_struct &);
- void operator=(sp_instr_cursor_copy_struct &);
- sp_lex_keeper m_lex_keeper;
- uint m_cursor;
- uint m_var;
-public:
- sp_instr_cursor_copy_struct(uint ip, sp_pcontext *ctx, uint coffs,
- sp_lex_cursor *lex, uint voffs)
- : sp_instr(ip, ctx), m_lex_keeper(lex, FALSE),
- m_cursor(coffs),
- m_var(voffs)
- {}
- virtual ~sp_instr_cursor_copy_struct() = default;
- virtual int execute(THD *thd, uint *nextp);
- virtual int exec_core(THD *thd, uint *nextp);
- virtual void print(String *str);
-
-public:
- virtual PSI_statement_info* get_psi_info() { 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;
-
- virtual int execute(THD *thd, uint *nextp);
-
- virtual void print(String *str);
-
-private:
-
- uint m_cursor;
-
-public:
- virtual PSI_statement_info* get_psi_info() { 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;
-
- virtual int execute(THD *thd, uint *nextp);
-
- virtual void print(String *str);
-
- 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:
- virtual PSI_statement_info* get_psi_info() { 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;
-
- virtual int execute(THD *thd, uint *nextp);
-
- virtual void print(String *str);
-
-public:
- virtual PSI_statement_info* get_psi_info() { 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;
-
- virtual int execute(THD *thd, uint *nextp);
-
- virtual void print(String *str);
-
- virtual uint opt_mark(sp_head *sp, List<sp_instr> *leads)
- {
- marked= 1;
- return UINT_MAX;
- }
-
-private:
-
- int m_errcode;
-
-public:
- virtual PSI_statement_info* get_psi_info() { return & psi_info; }
- static PSI_statement_info psi_info;
-}; // class sp_instr_error : public sp_instr
-
-
-class sp_instr_set_case_expr : public sp_instr_opt_meta
-{
-public:
-
- sp_instr_set_case_expr(uint ip, sp_pcontext *ctx, uint case_expr_id,
- Item *case_expr, LEX *lex)
- : sp_instr_opt_meta(ip, ctx),
- m_case_expr_id(case_expr_id), m_case_expr(case_expr),
- m_lex_keeper(lex, TRUE)
- {}
-
- virtual ~sp_instr_set_case_expr() = default;
-
- virtual int execute(THD *thd, uint *nextp);
-
- virtual int exec_core(THD *thd, uint *nextp);
-
- virtual void print(String *str);
-
- virtual uint opt_mark(sp_head *sp, List<sp_instr> *leads);
-
- virtual void opt_move(uint dst, List<sp_instr> *ibp);
-
- virtual void set_destination(uint old_dest, uint new_dest)
- {
- if (m_cont_dest == old_dest)
- m_cont_dest= new_dest;
- }
-
-private:
-
- uint m_case_expr_id;
- Item *m_case_expr;
- sp_lex_keeper m_lex_keeper;
-
-public:
- virtual PSI_statement_info* get_psi_info() { return & psi_info; }
- static PSI_statement_info psi_info;
-}; // class sp_instr_set_case_expr : public sp_instr_opt_meta
-
bool check_show_routine_access(THD *thd, sp_head *sp, bool *full_access);
+bool check_db_routine_access(THD *thd, privilege_t privilege,
+ const char *db, const char *name,
+ const Sp_handler *sph,
+ bool no_errors);
#ifndef NO_EMBEDDED_ACCESS_CHECKS
bool