summaryrefslogtreecommitdiff
path: root/sql/sp_instr.h
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sp_instr.h')
-rw-r--r--sql/sp_instr.h251
1 files changed, 193 insertions, 58 deletions
diff --git a/sql/sp_instr.h b/sql/sp_instr.h
index e53f521b785..086f52ae5dd 100644
--- a/sql/sp_instr.h
+++ b/sql/sp_instr.h
@@ -254,19 +254,47 @@ private:
/**
+ The base class for any stored program instruction that does need to
+ get access to the LEX object on execution.
+*/
+
+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;
+
+protected:
+ sp_lex_keeper m_lex_keeper;
+};
+
+
+/**
Call out to some prepared SQL statement.
*/
-class sp_instr_stmt : public sp_instr
+class sp_instr_stmt : public sp_lex_instr
{
sp_instr_stmt(const sp_instr_stmt &); /**< Prevent use of these */
void operator=(sp_instr_stmt &);
+ /**
+ Flag to tell whether a metadata this instruction depends on
+ has been changed and a LEX object should be reinitialized.
+ */
+ bool m_valid;
+
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)
+ : sp_lex_instr(ip, ctx, lex, true),
+ m_valid(true)
{
m_query.str= 0;
m_query.length= 0;
@@ -278,18 +306,24 @@ public:
void print(String *str) override;
-private:
+ bool is_invalid() const override
+ {
+ return !m_valid;
+ }
- sp_lex_keeper m_lex_keeper;
+ void invalidate() override
+ {
+ m_valid= false;
+ }
public:
PSI_statement_info* get_psi_info() override { return & psi_info; }
static PSI_statement_info psi_info;
-}; // class sp_instr_stmt : public sp_instr
+}; // class sp_instr_stmt : public sp_lex_instr
-class sp_instr_set : public sp_instr
+class sp_instr_set : public sp_lex_instr
{
sp_instr_set(const sp_instr_set &); /**< Prevent use of these */
void operator=(sp_instr_set &);
@@ -300,9 +334,8 @@ public:
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)
+ : sp_lex_instr(ip, ctx, lex, lex_resp),
+ m_rcontext_handler(rh), m_offset(offset), m_value(val)
{}
int execute(THD *thd, uint *nextp) override;
@@ -311,17 +344,26 @@ public:
void print(String *str) override;
+ bool is_invalid() const override
+ {
+ return m_value == nullptr;
+ }
+
+ void invalidate() override
+ {
+ m_value= nullptr;
+ }
+
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:
PSI_statement_info* get_psi_info() override { return & psi_info; }
static PSI_statement_info psi_info;
-}; // class sp_instr_set : public sp_instr
+}; // class sp_instr_set : public sp_lex_instr
/*
@@ -396,7 +438,7 @@ public:
/**
Set NEW/OLD row field value instruction. Used in triggers.
*/
-class sp_instr_set_trigger_field : public sp_instr
+class sp_instr_set_trigger_field : public sp_lex_instr
{
sp_instr_set_trigger_field(const sp_instr_set_trigger_field &);
void operator=(sp_instr_set_trigger_field &);
@@ -406,9 +448,9 @@ public:
sp_instr_set_trigger_field(uint ip, sp_pcontext *ctx,
Item_trigger_field *trg_fld,
Item *val, LEX *lex)
- : sp_instr(ip, ctx),
+ : sp_lex_instr(ip, ctx, lex, true),
trigger_field(trg_fld),
- value(val), m_lex_keeper(lex, true)
+ value(val)
{}
int execute(THD *thd, uint *nextp) override;
@@ -417,15 +459,24 @@ public:
void print(String *str) override;
+ bool is_invalid() const override
+ {
+ return value == nullptr;
+ }
+
+ void invalidate() override
+ {
+ value= nullptr;
+ }
+
private:
Item_trigger_field *trigger_field;
Item *value;
- sp_lex_keeper m_lex_keeper;
public:
PSI_statement_info* get_psi_info() override { return & psi_info; }
static PSI_statement_info psi_info;
-}; // class sp_instr_trigger_field : public sp_instr
+}; // class sp_instr_trigger_field : public sp_lex_instr
/**
@@ -435,36 +486,32 @@ public:
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
+class sp_instr_opt_meta
{
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)
+ explicit sp_instr_opt_meta(uint dest)
+ : m_dest(dest), 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()
{}
virtual void set_destination(uint old_dest, uint new_dest)
= 0;
- uint get_cont_dest() const override;
-
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_opt_meta
-class sp_instr_jump : public sp_instr_opt_meta
+
+class sp_instr_jump : public sp_instr, public sp_instr_opt_meta
{
sp_instr_jump(const sp_instr_jump &); /**< Prevent use of these */
void operator=(sp_instr_jump &);
@@ -472,11 +519,11 @@ class sp_instr_jump : public sp_instr_opt_meta
public:
sp_instr_jump(uint ip, sp_pcontext *ctx)
- : sp_instr_opt_meta(ip, ctx)
+ : sp_instr(ip, ctx), sp_instr_opt_meta(0)
{}
sp_instr_jump(uint ip, sp_pcontext *ctx, uint dest)
- : sp_instr_opt_meta(ip, ctx, dest)
+ : sp_instr(ip, ctx), sp_instr_opt_meta(dest)
{}
int execute(THD *thd, uint *nextp) override;
@@ -496,6 +543,11 @@ public:
m_dest= dest;
}
+ uint get_cont_dest() const override
+ {
+ return m_cont_dest;
+ }
+
/**
Update the destination; used by the optimizer.
*/
@@ -508,10 +560,10 @@ public:
public:
PSI_statement_info* get_psi_info() override { return & psi_info; }
static PSI_statement_info psi_info;
-}; // class sp_instr_jump : public sp_instr_opt_meta
+}; // class sp_instr_jump : public sp_instr, public sp_instr_opt_meta
-class sp_instr_jump_if_not : public sp_instr_jump
+class sp_instr_jump_if_not : public sp_lex_instr, public sp_instr_opt_meta
{
sp_instr_jump_if_not(const sp_instr_jump_if_not &); /**< Prevent use of these */
void operator=(sp_instr_jump_if_not &);
@@ -519,13 +571,15 @@ class sp_instr_jump_if_not : public sp_instr_jump
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_lex_instr(ip, ctx, lex, true),
+ sp_instr_opt_meta(0),
+ m_expr(i)
{}
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)
+ : sp_lex_instr(ip, ctx, lex, true),
+ sp_instr_opt_meta(dest),
+ m_expr(i)
{}
int execute(THD *thd, uint *nextp) override;
@@ -544,22 +598,44 @@ public:
void opt_move(uint dst, List<sp_instr_opt_meta> *ibp) override;
+ uint get_cont_dest() const override
+ {
+ return m_cont_dest;
+ }
+
void set_destination(uint old_dest, uint new_dest) override
{
- sp_instr_jump::set_destination(old_dest, new_dest);
+ if (m_dest == old_dest)
+ m_dest= new_dest;
if (m_cont_dest == old_dest)
m_cont_dest= new_dest;
}
+ 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;
+ }
+
private:
Item *m_expr; ///< The condition
- sp_lex_keeper m_lex_keeper;
public:
PSI_statement_info* get_psi_info() override { return & psi_info; }
static PSI_statement_info psi_info;
-}; // class sp_instr_jump_if_not : public sp_instr_jump
+}; // class sp_instr_jump_if_not : public sp_lex_instr, public sp_instr_opt_meta
class sp_instr_preturn : public sp_instr
@@ -589,7 +665,7 @@ public:
}; // class sp_instr_preturn : public sp_instr
-class sp_instr_freturn : public sp_instr
+class sp_instr_freturn : public sp_lex_instr
{
sp_instr_freturn(const sp_instr_freturn &); /**< Prevent use of these */
void operator=(sp_instr_freturn &);
@@ -598,8 +674,8 @@ 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)
+ : sp_lex_instr(ip, ctx, lex, true),
+ m_value(val), m_type_handler(handler)
{}
int execute(THD *thd, uint *nextp) override;
@@ -618,12 +694,22 @@ protected:
Item *m_value;
const Type_handler *m_type_handler;
- sp_lex_keeper m_lex_keeper;
+ bool is_invalid() const override
+ {
+ return m_value == nullptr;
+ }
+
+ void invalidate() override
+ {
+ /* TODO: be careful and check that the object referenced by m_value
+ is not leaked */
+ m_value= nullptr;
+ }
public:
PSI_statement_info* get_psi_info() override { return & psi_info; }
static PSI_statement_info psi_info;
-}; // class sp_instr_freturn : public sp_instr
+}; // class sp_instr_freturn : public sp_lex_instr
class sp_instr_hpush_jump : public sp_instr_jump
@@ -759,7 +845,7 @@ public:
/** This is DECLARE CURSOR */
-class sp_instr_cpush : public sp_instr, public sp_cursor
+class sp_instr_cpush : public sp_lex_instr, public sp_cursor
{
sp_instr_cpush(const sp_instr_cpush &); /**< Prevent use of these */
void operator=(sp_instr_cpush &);
@@ -767,7 +853,8 @@ class sp_instr_cpush : public sp_instr, public sp_cursor
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)
+ : sp_lex_instr(ip, ctx, lex, true), m_cursor(offset),
+ m_metadata_changed(false)
{}
int execute(THD *thd, uint *nextp) override;
@@ -781,15 +868,35 @@ public:
*/
bool cleanup_stmt(bool /*restore_set_statement_vars*/) override
{ return false; }
+
+ 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;
+ }
private:
- sp_lex_keeper m_lex_keeper;
uint m_cursor; /**< Frame offset (for debugging) */
+ /**
+ 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;
+
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_cpush : public sp_lex_instr, public sp_cursor
class sp_instr_cpop : public sp_instr
@@ -846,32 +953,47 @@ private:
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
+}; // class sp_instr_copen : public sp_instr
/**
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
+class sp_instr_cursor_copy_struct: public sp_lex_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;
+ /**
+ Flag to tell whether metadata has been changed and the LEX object should
+ be reinitialized.
+ */
+ bool m_valid;
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),
+ : sp_lex_instr(ip, ctx, lex, false),
m_cursor(coffs),
- m_var(voffs)
+ m_var(voffs),
+ m_valid(true)
{}
int execute(THD *thd, uint *nextp) override;
int exec_core(THD *thd, uint *nextp) override;
void print(String *str) override;
+ bool is_invalid() const override
+ {
+ return !m_valid;
+ }
+
+ void invalidate() override
+ {
+ m_valid= true;
+ }
+
public:
PSI_statement_info* get_psi_info() override { return & psi_info; }
static PSI_statement_info psi_info;
@@ -993,15 +1115,14 @@ public:
}; // class sp_instr_error : public sp_instr
-class sp_instr_set_case_expr : public sp_instr_opt_meta
+class sp_instr_set_case_expr : public sp_lex_instr, 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)
+ : sp_lex_instr(ip, ctx, lex, true), sp_instr_opt_meta(0),
+ m_case_expr_id(case_expr_id), m_case_expr(case_expr)
{}
int execute(THD *thd, uint *nextp) override;
@@ -1014,21 +1135,35 @@ public:
void opt_move(uint dst, List<sp_instr_opt_meta> *ibp) override;
+ uint get_cont_dest() const override
+ {
+ return m_cont_dest;
+ }
+
void set_destination(uint old_dest, uint new_dest) override
{
if (m_cont_dest == old_dest)
m_cont_dest= new_dest;
}
+ bool is_invalid() const override
+ {
+ return m_case_expr == nullptr;
+ }
+
+ void invalidate() override
+ {
+ m_case_expr= nullptr;
+ }
+
private:
uint m_case_expr_id;
Item *m_case_expr;
- sp_lex_keeper m_lex_keeper;
public:
PSI_statement_info* get_psi_info() override { return & psi_info; }
static PSI_statement_info psi_info;
-}; // class sp_instr_set_case_expr : public sp_instr_opt_meta
+}; // public sp_lex_instr, public sp_instr_opt_meta
#endif