Commit 6840af6e authored by Dmitry Shulga's avatar Dmitry Shulga

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.
parent 40d730fb
...@@ -747,15 +747,6 @@ sp_instr_set_trigger_field::print(String *str) ...@@ -747,15 +747,6 @@ sp_instr_set_trigger_field::print(String *str)
QT_ITEM_ORIGINAL_FUNC_NULLIF)); QT_ITEM_ORIGINAL_FUNC_NULLIF));
} }
/*
sp_instr_opt_meta
*/
uint sp_instr_opt_meta::get_cont_dest() const
{
return m_cont_dest;
}
/* /*
sp_instr_jump class functions sp_instr_jump class functions
...@@ -918,8 +909,15 @@ sp_instr_jump_if_not::opt_move(uint dst, List<sp_instr_opt_meta> *bp) ...@@ -918,8 +909,15 @@ sp_instr_jump_if_not::opt_move(uint dst, List<sp_instr_opt_meta> *bp)
} }
else if (m_cont_optdest) else if (m_cont_optdest)
m_cont_dest= m_cont_optdest->m_ip; // Backward m_cont_dest= m_cont_optdest->m_ip; // Backward
/* This will take care of m_dest and m_ip */
sp_instr_jump::opt_move(dst, bp); /*
Take care about m_dest and m_ip
*/
if (m_dest > m_ip)
bp->push_back(this); // Forward
else if (m_optdest)
m_dest= m_optdest->m_ip; // Backward
m_ip= dst;
} }
...@@ -1195,7 +1193,7 @@ sp_instr_cpush::execute(THD *thd, uint *nextp) ...@@ -1195,7 +1193,7 @@ sp_instr_cpush::execute(THD *thd, uint *nextp)
{ {
DBUG_ENTER("sp_instr_cpush::execute"); DBUG_ENTER("sp_instr_cpush::execute");
sp_cursor::reset(thd, &m_lex_keeper); sp_cursor::reset(thd);
m_lex_keeper.disable_query_cache(); m_lex_keeper.disable_query_cache();
thd->spcont->push_cursor(this); thd->spcont->push_cursor(this);
...@@ -1492,14 +1490,14 @@ sp_instr_cursor_copy_struct::exec_core(THD *thd, uint *nextp) ...@@ -1492,14 +1490,14 @@ sp_instr_cursor_copy_struct::exec_core(THD *thd, uint *nextp)
/* /*
Copy structure only once. If the cursor%ROWTYPE variable is declared Copy structure only once. If the cursor%ROWTYPE variable is declared
inside a LOOP block, it gets its structure on the first loop interation inside a LOOP block, it gets its structure on the first loop iteration
and remembers the structure for all consequent loop iterations. and remembers the structure for all consequent loop iterations.
It we recreated the structure on every iteration, we would get It we recreated the structure on every iteration, we would get
potential memory leaks, and it would be less efficient. potential memory leaks, and it would be less efficient.
*/ */
if (!row->arguments()) if (!row->arguments())
{ {
sp_cursor tmp(thd, &m_lex_keeper, true); sp_cursor tmp(thd, true);
// Open the cursor without copying data // Open the cursor without copying data
if (!(ret= tmp.open(thd))) if (!(ret= tmp.open(thd)))
{ {
......
...@@ -280,20 +280,48 @@ class sp_lex_keeper final ...@@ -280,20 +280,48 @@ class sp_lex_keeper final
/** /**
Call out to some prepared SQL statement. The base class for any stored program instruction that need to get access
to a LEX object on execution.
*/ */
class sp_instr_stmt : public sp_instr 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;
};
/**
The class sp_instr_stmt represents almost all conventional SQL-statements.
*/
class sp_instr_stmt : public sp_lex_instr
{ {
sp_instr_stmt(const sp_instr_stmt &); /**< Prevent use of these */ sp_instr_stmt(const sp_instr_stmt &); /**< Prevent use of these */
void operator=(sp_instr_stmt &); 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: public:
LEX_STRING m_query; ///< For thd->query LEX_STRING m_query; ///< For thd->query
sp_instr_stmt(uint ip, sp_pcontext *ctx, LEX *lex) sp_instr_stmt(uint ip, sp_pcontext *ctx, LEX *lex)
: sp_instr(ip, ctx), : sp_lex_instr(ip, ctx, lex, true),
m_lex_keeper(lex, true) m_valid(true)
{ {
m_query.str= 0; m_query.str= 0;
m_query.length= 0; m_query.length= 0;
...@@ -307,16 +335,23 @@ class sp_instr_stmt : public sp_instr ...@@ -307,16 +335,23 @@ class sp_instr_stmt : public sp_instr
void print(String *str) override; void print(String *str) override;
private: bool is_invalid() const override
sp_lex_keeper m_lex_keeper; {
return !m_valid;
}
void invalidate() override
{
m_valid= false;
}
public: public:
PSI_statement_info* get_psi_info() override { return & psi_info; } PSI_statement_info* get_psi_info() override { return & psi_info; }
static PSI_statement_info 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 */ sp_instr_set(const sp_instr_set &); /**< Prevent use of these */
void operator=(sp_instr_set &); void operator=(sp_instr_set &);
...@@ -326,11 +361,10 @@ class sp_instr_set : public sp_instr ...@@ -326,11 +361,10 @@ class sp_instr_set : public sp_instr
const Sp_rcontext_handler *rh, const Sp_rcontext_handler *rh,
uint offset, Item *val, uint offset, Item *val,
LEX *lex, bool lex_resp) LEX *lex, bool lex_resp)
: sp_instr(ip, ctx), : sp_lex_instr(ip, ctx, lex, lex_resp),
m_rcontext_handler(rh), m_rcontext_handler(rh),
m_offset(offset), m_offset(offset),
m_value(val), m_value(val)
m_lex_keeper(lex, lex_resp)
{} {}
virtual ~sp_instr_set() = default; virtual ~sp_instr_set() = default;
...@@ -341,17 +375,26 @@ class sp_instr_set : public sp_instr ...@@ -341,17 +375,26 @@ class sp_instr_set : public sp_instr
void print(String *str) override; void print(String *str) override;
bool is_invalid() const override
{
return m_value == nullptr;
}
void invalidate() override
{
m_value= nullptr;
}
protected: protected:
sp_rcontext *get_rcontext(THD *thd) const; sp_rcontext *get_rcontext(THD *thd) const;
const Sp_rcontext_handler *m_rcontext_handler; const Sp_rcontext_handler *m_rcontext_handler;
uint m_offset; ///< Frame offset uint m_offset; ///< Frame offset
Item *m_value; Item *m_value;
sp_lex_keeper m_lex_keeper;
public: public:
PSI_statement_info* get_psi_info() override { return & psi_info; } PSI_statement_info* get_psi_info() override { return & psi_info; }
static PSI_statement_info psi_info; static PSI_statement_info psi_info;
}; // class sp_instr_set : public sp_instr }; // class sp_instr_set : public sp_lex_instr
/* /*
...@@ -431,7 +474,7 @@ class sp_instr_set_row_field_by_name : public sp_instr_set ...@@ -431,7 +474,7 @@ class sp_instr_set_row_field_by_name : public sp_instr_set
Set NEW/OLD row field value instruction. Used in triggers. 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 &); sp_instr_set_trigger_field(const sp_instr_set_trigger_field &);
void operator=(sp_instr_set_trigger_field &); void operator=(sp_instr_set_trigger_field &);
...@@ -440,10 +483,9 @@ class sp_instr_set_trigger_field : public sp_instr ...@@ -440,10 +483,9 @@ class sp_instr_set_trigger_field : public sp_instr
sp_instr_set_trigger_field(uint ip, sp_pcontext *ctx, sp_instr_set_trigger_field(uint ip, sp_pcontext *ctx,
Item_trigger_field *trg_fld, Item_trigger_field *trg_fld,
Item *val, LEX *lex) Item *val, LEX *lex)
: sp_instr(ip, ctx), : sp_lex_instr(ip, ctx, lex, true),
trigger_field(trg_fld), trigger_field(trg_fld),
value(val), value(val)
m_lex_keeper(lex, true)
{} {}
virtual ~sp_instr_set_trigger_field() = default; virtual ~sp_instr_set_trigger_field() = default;
...@@ -454,15 +496,24 @@ class sp_instr_set_trigger_field : public sp_instr ...@@ -454,15 +496,24 @@ class sp_instr_set_trigger_field : public sp_instr
void print(String *str) override; void print(String *str) override;
bool is_invalid() const override
{
return value == nullptr;
}
void invalidate() override
{
value= nullptr;
}
private: private:
Item_trigger_field *trigger_field; Item_trigger_field *trigger_field;
Item *value; Item *value;
sp_lex_keeper m_lex_keeper;
public: public:
PSI_statement_info* get_psi_info() override { return & psi_info; } PSI_statement_info* get_psi_info() override { return & psi_info; }
static PSI_statement_info 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
/** /**
...@@ -473,23 +524,14 @@ class sp_instr_set_trigger_field : public sp_instr ...@@ -473,23 +524,14 @@ class sp_instr_set_trigger_field : public sp_instr
the continuation destination, we put them both here for simplicity. the continuation destination, we put them both here for simplicity.
*/ */
class sp_instr_opt_meta : public sp_instr class sp_instr_opt_meta
{ {
public: public:
uint m_dest; ///< Where we will go uint m_dest; ///< Where we will go
uint m_cont_dest; ///< Where continue handlers will go uint m_cont_dest; ///< Where continue handlers will go
sp_instr_opt_meta(uint ip, sp_pcontext *ctx) explicit sp_instr_opt_meta(uint dest)
: sp_instr(ip, ctx), : m_dest(dest),
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_cont_dest(0),
m_optdest(0), m_optdest(0),
m_cont_optdest(0) m_cont_optdest(0)
...@@ -499,26 +541,26 @@ class sp_instr_opt_meta : public sp_instr ...@@ -499,26 +541,26 @@ class sp_instr_opt_meta : public sp_instr
virtual void set_destination(uint old_dest, uint new_dest) = 0; virtual void set_destination(uint old_dest, uint new_dest) = 0;
uint get_cont_dest() const override;
protected: protected:
sp_instr *m_optdest; ///< Used during optimization sp_instr *m_optdest; ///< Used during optimization
sp_instr *m_cont_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 */ sp_instr_jump(const sp_instr_jump &); /**< Prevent use of these */
void operator=(sp_instr_jump &); void operator=(sp_instr_jump &);
public: public:
sp_instr_jump(uint ip, sp_pcontext *ctx) 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_jump(uint ip, sp_pcontext *ctx, uint dest)
: sp_instr_opt_meta(ip, ctx, dest) : sp_instr(ip, ctx),
sp_instr_opt_meta(dest)
{} {}
virtual ~sp_instr_jump() = default; virtual ~sp_instr_jump() = default;
...@@ -540,6 +582,11 @@ class sp_instr_jump : public sp_instr_opt_meta ...@@ -540,6 +582,11 @@ class sp_instr_jump : public sp_instr_opt_meta
m_dest= dest; m_dest= dest;
} }
uint get_cont_dest() const override
{
return m_cont_dest;
}
/** /**
Update the destination; used by the optimizer. Update the destination; used by the optimizer.
*/ */
...@@ -552,10 +599,10 @@ class sp_instr_jump : public sp_instr_opt_meta ...@@ -552,10 +599,10 @@ class sp_instr_jump : public sp_instr_opt_meta
public: public:
PSI_statement_info* get_psi_info() override { return & psi_info; } PSI_statement_info* get_psi_info() override { return & psi_info; }
static PSI_statement_info 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
{ {
/**< Prevent use of these */ /**< Prevent use of these */
sp_instr_jump_if_not(const sp_instr_jump_if_not &); sp_instr_jump_if_not(const sp_instr_jump_if_not &);
...@@ -563,15 +610,15 @@ class sp_instr_jump_if_not : public sp_instr_jump ...@@ -563,15 +610,15 @@ class sp_instr_jump_if_not : public sp_instr_jump
public: public:
sp_instr_jump_if_not(uint ip, sp_pcontext *ctx, Item *i, LEX *lex) sp_instr_jump_if_not(uint ip, sp_pcontext *ctx, Item *i, LEX *lex)
: sp_instr_jump(ip, ctx), : sp_lex_instr(ip, ctx, lex, true),
m_expr(i), sp_instr_opt_meta(0),
m_lex_keeper(lex, true) m_expr(i)
{} {}
sp_instr_jump_if_not(uint ip, sp_pcontext *ctx, Item *i, uint dest, LEX *lex) sp_instr_jump_if_not(uint ip, sp_pcontext *ctx, Item *i, uint dest, LEX *lex)
: sp_instr_jump(ip, ctx, dest), : sp_lex_instr(ip, ctx, lex, true),
m_expr(i), sp_instr_opt_meta(dest),
m_lex_keeper(lex, true) m_expr(i)
{} {}
virtual ~sp_instr_jump_if_not() = default; virtual ~sp_instr_jump_if_not() = default;
...@@ -592,21 +639,43 @@ class sp_instr_jump_if_not : public sp_instr_jump ...@@ -592,21 +639,43 @@ class sp_instr_jump_if_not : public sp_instr_jump
void opt_move(uint dst, List<sp_instr_opt_meta> *ibp) override; 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 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) if (m_cont_dest == old_dest)
m_cont_dest= new_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: private:
Item *m_expr; ///< The condition Item *m_expr; ///< The condition
sp_lex_keeper m_lex_keeper;
public: public:
PSI_statement_info* get_psi_info() override { return & psi_info; } PSI_statement_info* get_psi_info() override { return & psi_info; }
static PSI_statement_info psi_info; static PSI_statement_info psi_info;
}; // class sp_instr_jump_if_not : public sp_instr_jump }; // class sp_instr_jump_if_not
class sp_instr_preturn : public sp_instr class sp_instr_preturn : public sp_instr
...@@ -637,7 +706,7 @@ class sp_instr_preturn : public sp_instr ...@@ -637,7 +706,7 @@ class sp_instr_preturn : public sp_instr
}; // class sp_instr_preturn : public sp_instr }; // 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 */ sp_instr_freturn(const sp_instr_freturn &); /**< Prevent use of these */
void operator=(sp_instr_freturn &); void operator=(sp_instr_freturn &);
...@@ -645,10 +714,9 @@ class sp_instr_freturn : public sp_instr ...@@ -645,10 +714,9 @@ class sp_instr_freturn : public sp_instr
public: public:
sp_instr_freturn(uint ip, sp_pcontext *ctx, sp_instr_freturn(uint ip, sp_pcontext *ctx,
Item *val, const Type_handler *handler, LEX *lex) Item *val, const Type_handler *handler, LEX *lex)
: sp_instr(ip, ctx), : sp_lex_instr(ip, ctx, lex, true),
m_value(val), m_value(val),
m_type_handler(handler), m_type_handler(handler)
m_lex_keeper(lex, true)
{} {}
virtual ~sp_instr_freturn() = default; virtual ~sp_instr_freturn() = default;
...@@ -665,15 +733,24 @@ class sp_instr_freturn : public sp_instr ...@@ -665,15 +733,24 @@ class sp_instr_freturn : public sp_instr
return UINT_MAX; return UINT_MAX;
} }
bool is_invalid() const override
{
return m_value == nullptr;
}
void invalidate() override
{
m_value= nullptr;
}
protected: protected:
Item *m_value; Item *m_value;
const Type_handler *m_type_handler; const Type_handler *m_type_handler;
sp_lex_keeper m_lex_keeper;
public: public:
PSI_statement_info* get_psi_info() override { return & psi_info; } PSI_statement_info* get_psi_info() override { return & psi_info; }
static PSI_statement_info 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 class sp_instr_hpush_jump : public sp_instr_jump
...@@ -816,16 +893,16 @@ class sp_instr_hreturn : public sp_instr_jump ...@@ -816,16 +893,16 @@ class sp_instr_hreturn : public sp_instr_jump
This is DECLARE CURSOR 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 */ sp_instr_cpush(const sp_instr_cpush &); /**< Prevent use of these */
void operator=(sp_instr_cpush &); void operator=(sp_instr_cpush &);
public: public:
sp_instr_cpush(uint ip, sp_pcontext *ctx, LEX *lex, uint offset) sp_instr_cpush(uint ip, sp_pcontext *ctx, LEX *lex, uint offset)
: sp_instr(ip, ctx), : sp_lex_instr(ip, ctx, lex, true),
m_lex_keeper(lex, true), m_cursor(offset),
m_cursor(offset) m_metadata_changed(false)
{} {}
virtual ~sp_instr_cpush() = default; virtual ~sp_instr_cpush() = default;
...@@ -844,9 +921,28 @@ class sp_instr_cpush : public sp_instr, public sp_cursor ...@@ -844,9 +921,28 @@ class sp_instr_cpush : public sp_instr, public sp_cursor
return false; 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: private:
sp_lex_keeper m_lex_keeper;
uint m_cursor; /**< Frame offset (for debugging) */ 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: public:
PSI_statement_info* get_psi_info() override { return & psi_info; } PSI_statement_info* get_psi_info() override { return & psi_info; }
...@@ -918,27 +1014,40 @@ class sp_instr_copen : public sp_instr ...@@ -918,27 +1014,40 @@ class sp_instr_copen : public sp_instr
from the LEX containing the cursor SELECT statement. 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 */ /**< Prevent use of these */
sp_instr_cursor_copy_struct(const sp_instr_cursor_copy_struct &); sp_instr_cursor_copy_struct(const sp_instr_cursor_copy_struct &);
void operator=(sp_instr_cursor_copy_struct &); void operator=(sp_instr_cursor_copy_struct &);
sp_lex_keeper m_lex_keeper;
uint m_cursor; uint m_cursor;
uint m_var; uint m_var;
/**
Flag to tell whether metadata has been changed and the LEX object should
be reinitialized.
*/
bool m_valid;
public: public:
sp_instr_cursor_copy_struct(uint ip, sp_pcontext *ctx, uint coffs, sp_instr_cursor_copy_struct(uint ip, sp_pcontext *ctx, uint coffs,
sp_lex_cursor *lex, uint voffs) sp_lex_cursor *lex, uint voffs)
: sp_instr(ip, ctx), : sp_lex_instr(ip, ctx, lex, false),
m_lex_keeper(lex, false),
m_cursor(coffs), m_cursor(coffs),
m_var(voffs) m_var(voffs),
m_valid(true)
{} {}
virtual ~sp_instr_cursor_copy_struct() = default; virtual ~sp_instr_cursor_copy_struct() = default;
int execute(THD *thd, uint *nextp) override; int execute(THD *thd, uint *nextp) override;
int exec_core(THD *thd, uint *nextp) override; int exec_core(THD *thd, uint *nextp) override;
void print(String *str) override; void print(String *str) override;
bool is_invalid() const override
{
return !m_valid;
}
void invalidate() override
{
m_valid= false;
}
public: public:
PSI_statement_info* get_psi_info() override { return & psi_info; } PSI_statement_info* get_psi_info() override { return & psi_info; }
...@@ -1068,15 +1177,15 @@ class sp_instr_error : public sp_instr ...@@ -1068,15 +1177,15 @@ class sp_instr_error : public sp_instr
}; // class sp_instr_error : public sp_instr }; // 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: public:
sp_instr_set_case_expr(uint ip, sp_pcontext *ctx, uint case_expr_id, sp_instr_set_case_expr(uint ip, sp_pcontext *ctx, uint case_expr_id,
Item *case_expr, LEX *lex) Item *case_expr, LEX *lex)
: sp_instr_opt_meta(ip, ctx), : sp_lex_instr(ip, ctx, lex, true),
sp_instr_opt_meta(0),
m_case_expr_id(case_expr_id), m_case_expr_id(case_expr_id),
m_case_expr(case_expr), m_case_expr(case_expr)
m_lex_keeper(lex, true)
{} {}
virtual ~sp_instr_set_case_expr() = default; virtual ~sp_instr_set_case_expr() = default;
...@@ -1091,20 +1200,34 @@ class sp_instr_set_case_expr : public sp_instr_opt_meta ...@@ -1091,20 +1200,34 @@ class sp_instr_set_case_expr : public sp_instr_opt_meta
void opt_move(uint dst, List<sp_instr_opt_meta> *ibp) override; 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 void set_destination(uint old_dest, uint new_dest) override
{ {
if (m_cont_dest == old_dest) if (m_cont_dest == old_dest)
m_cont_dest= new_dest; m_cont_dest= new_dest;
} }
bool is_invalid() const override
{
return m_case_expr == nullptr;
}
void invalidate() override
{
m_case_expr= nullptr;
}
private: private:
uint m_case_expr_id; uint m_case_expr_id;
Item *m_case_expr; Item *m_case_expr;
sp_lex_keeper m_lex_keeper;
public: public:
PSI_statement_info* get_psi_info() override { return & psi_info; } PSI_statement_info* get_psi_info() override { return & psi_info; }
static PSI_statement_info psi_info; static PSI_statement_info psi_info;
}; // class sp_instr_set_case_expr : public sp_instr_opt_meta }; // class sp_instr_set_case_expr : public sp_lex_instr,
#endif #endif
...@@ -6016,19 +6016,17 @@ class sp_cursor: public sp_cursor_statistics ...@@ -6016,19 +6016,17 @@ class sp_cursor: public sp_cursor_statistics
public: public:
sp_cursor() sp_cursor()
:result(NULL, false), :result(NULL, false),
m_lex_keeper(NULL),
server_side_cursor(NULL) server_side_cursor(NULL)
{ } { }
sp_cursor(THD *thd_arg, sp_lex_keeper *lex_keeper, bool view_structure_only) sp_cursor(THD *thd_arg, bool view_structure_only)
:result(thd_arg, view_structure_only), :result(thd_arg, view_structure_only),
m_lex_keeper(lex_keeper),
server_side_cursor(NULL) server_side_cursor(NULL)
{} {}
virtual ~sp_cursor() virtual ~sp_cursor()
{ destroy(); } { destroy(); }
sp_lex_keeper *get_lex_keeper() { return m_lex_keeper; } virtual sp_lex_keeper *get_lex_keeper() { return nullptr; }
int open(THD *thd); int open(THD *thd);
...@@ -6041,17 +6039,15 @@ class sp_cursor: public sp_cursor_statistics ...@@ -6041,17 +6039,15 @@ class sp_cursor: public sp_cursor_statistics
bool export_structure(THD *thd, Row_definition_list *list); bool export_structure(THD *thd, Row_definition_list *list);
void reset(THD *thd_arg, sp_lex_keeper *lex_keeper) void reset(THD *thd_arg)
{ {
sp_cursor_statistics::reset(); sp_cursor_statistics::reset();
result.reset(thd_arg); result.reset(thd_arg);
m_lex_keeper= lex_keeper;
server_side_cursor= NULL; server_side_cursor= NULL;
} }
private: private:
Select_fetch_into_spvars result; Select_fetch_into_spvars result;
sp_lex_keeper *m_lex_keeper;
Server_side_cursor *server_side_cursor; Server_side_cursor *server_side_cursor;
void destroy(); void destroy();
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment