mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03: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.
This commit is contained in:
@ -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)
|
|||||||
}
|
}
|
||||||
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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
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)))
|
||||||
{
|
{
|
||||||
|
263
sql/sp_instr.h
263
sql/sp_instr.h
@ -280,20 +280,48 @@ private:
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
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 @@ public:
|
|||||||
|
|
||||||
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 @@ public:
|
|||||||
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 @@ public:
|
|||||||
|
|
||||||
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 @@ public:
|
|||||||
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 @@ public:
|
|||||||
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 @@ public:
|
|||||||
|
|
||||||
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 @@ public:
|
|||||||
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 @@ public:
|
|||||||
|
|
||||||
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 @@ public:
|
|||||||
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 @@ public:
|
|||||||
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
|
|||||||
|
|
||||||
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 @@ public:
|
|||||||
|
|
||||||
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 @@ public:
|
|||||||
}; // 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
|
|||||||
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 @@ public:
|
|||||||
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 @@ public:
|
|||||||
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 @@ public:
|
|||||||
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 @@ public:
|
|||||||
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 @@ public:
|
|||||||
}; // 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 @@ public:
|
|||||||
|
|
||||||
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 @@ private:
|
|||||||
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 @@ public:
|
|||||||
|
|
||||||
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();
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user