summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Shulga <dmitry.shulga@mariadb.com>2022-02-15 12:20:43 +0700
committerDmitry Shulga <dmitry.shulga@mariadb.com>2022-02-16 21:53:12 +0700
commite5693d31e2bbb5be23f0f57e309e280a6de2ac4b (patch)
tree536d0833b4735d46a777d4ac25e9285cd1716a27
parente12d841ea7c5f4851e3bb8189668ff9de9135e3b (diff)
downloadmariadb-git-e5693d31e2bbb5be23f0f57e309e280a6de2ac4b.tar.gz
MDEV-5816: Stored programs: validation of stored program statementsbb-10.8-MDEV-5816
Added storing of sql expression for instruction being parsed inside the classes derived from the class sp_lex_instr. Stored sql expression is returned by the abstract method sp_lex_instr::get_expr_query redefined in the derived classes. The virtual method sp_lex_instr::get_query() has beens added to return a parseable string for a statement that corresponds to the given instruction.
-rw-r--r--sql/sp.cc8
-rw-r--r--sql/sp.h5
-rw-r--r--sql/sp_head.cc32
-rw-r--r--sql/sp_head.h18
-rw-r--r--sql/sp_instr.cc27
-rw-r--r--sql/sp_instr.h192
-rw-r--r--sql/sql_class.cc8
-rw-r--r--sql/sql_class.h26
-rw-r--r--sql/sql_lex.cc176
-rw-r--r--sql/sql_lex.h98
-rw-r--r--sql/sql_yacc.yy287
11 files changed, 654 insertions, 223 deletions
diff --git a/sql/sp.cc b/sql/sp.cc
index 4ef23983f78..8071ebcfc54 100644
--- a/sql/sp.cc
+++ b/sql/sp.cc
@@ -65,7 +65,8 @@ ulong Sp_handler_procedure::recursion_depth(THD *thd) const
bool Sp_handler::add_instr_freturn(THD *thd, sp_head *sp,
sp_pcontext *spcont,
- Item *item, LEX *lex) const
+ Item *item, LEX *lex,
+ LEX_CSTRING expr_query) const
{
my_error(ER_SP_BADRETURN, MYF(0));
return true;
@@ -82,9 +83,10 @@ bool Sp_handler::add_instr_preturn(THD *thd, sp_head *sp,
bool Sp_handler_function::add_instr_freturn(THD *thd, sp_head *sp,
sp_pcontext *spcont,
- Item *item, LEX *lex) const
+ Item *item, LEX *lex,
+ LEX_CSTRING expr_query) const
{
- return sp->add_instr_freturn(thd, spcont, item, lex);
+ return sp->add_instr_freturn(thd, spcont, item, lex, expr_query);
}
diff --git a/sql/sp.h b/sql/sp.h
index 0b79877a3e1..33143edd9f9 100644
--- a/sql/sp.h
+++ b/sql/sp.h
@@ -185,7 +185,8 @@ public:
}
virtual bool add_instr_freturn(THD *thd, sp_head *sp,
sp_pcontext *spcont,
- Item *item, LEX *lex) const;
+ Item *item, LEX *lex,
+ LEX_CSTRING expr_query) const;
virtual bool add_instr_preturn(THD *thd, sp_head *sp,
sp_pcontext *spcont) const;
@@ -324,7 +325,7 @@ public:
HASH *get_priv_hash() const;
#endif
bool add_instr_freturn(THD *thd, sp_head *sp, sp_pcontext *spcont,
- Item *item, LEX *lex) const;
+ Item *item, LEX *lex, LEX_CSTRING expr_query) const;
};
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 4eda7fe0e09..58ffb8a76b9 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -2641,14 +2641,16 @@ sp_head::do_cont_backpatch()
bool
-sp_head::sp_add_instr_cpush_for_cursors(THD *thd, sp_pcontext *pcontext)
+sp_head::sp_add_instr_cpush_for_cursors(THD *thd, sp_pcontext *pcontext,
+ LEX_CSTRING cursor_query)
{
for (uint i= 0; i < pcontext->frame_cursor_count(); i++)
{
const sp_pcursor *c= pcontext->get_cursor_by_local_frame_offset(i);
sp_instr_cpush *instr= new (thd->mem_root)
sp_instr_cpush(instructions(), pcontext, c->lex(),
- pcontext->cursor_offset() + i);
+ pcontext->cursor_offset() + i,
+ cursor_query);
if (instr == NULL || add_instr(instr))
return true;
}
@@ -2999,11 +3001,12 @@ bool sp_head::add_instr_jump_forward_with_backpatch(THD *thd,
bool sp_head::add_instr_freturn(THD *thd, sp_pcontext *spcont,
- Item *item, LEX *lex)
+ Item *item, LEX *lex, LEX_CSTRING expr_query)
{
sp_instr_freturn *i= new (thd->mem_root)
sp_instr_freturn(instructions(), spcont, item,
- m_return_field_def.type_handler(), lex);
+ m_return_field_def.type_handler(), lex,
+ expr_query);
if (i == NULL || add_instr(i))
return true;
m_flags|= sp_head::HAS_RETURN;
@@ -3516,7 +3519,8 @@ bool
sp_head::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,
+ LEX_CSTRING value_query)
{
if (!(val= adjust_assignment_source(thd, val, spv->default_value)))
return true;
@@ -3527,7 +3531,8 @@ sp_head::set_local_variable(THD *thd, sp_pcontext *spcont,
sp_instr_set *sp_set= new (thd->mem_root)
sp_instr_set(instructions(), spcont, rh,
spv->offset, val, lex,
- responsible_to_free_lex);
+ responsible_to_free_lex,
+ value_query);
return sp_set == NULL || add_instr(sp_set);
}
@@ -3541,7 +3546,8 @@ bool
sp_head::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,
+ LEX_CSTRING value_query)
{
if (!(val= adjust_assignment_source(thd, val, NULL)))
return true;
@@ -3551,7 +3557,8 @@ sp_head::set_local_variable_row_field(THD *thd, sp_pcontext *spcont,
spcont, rh,
spv->offset,
field_idx, val,
- lex, true);
+ lex, true,
+ value_query);
return sp_set == NULL || add_instr(sp_set);
}
@@ -3561,7 +3568,8 @@ sp_head::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,
+ LEX_CSTRING value_query)
{
if (!(val= adjust_assignment_source(thd, val, NULL)))
return true;
@@ -3572,7 +3580,8 @@ sp_head::set_local_variable_row_field_by_name(THD *thd, sp_pcontext *spcont,
spv->offset,
*field_name,
val,
- lex, true);
+ lex, true,
+ value_query);
return sp_set == NULL || add_instr(sp_set);
}
@@ -3651,7 +3660,8 @@ sp_head::add_set_for_loop_cursor_param_variables(THD *thd,
if (set_local_variable(thd, param_spcont,
&sp_rcontext_handler_local,
spvar, parameters->arguments()[idx],
- param_lex, last))
+ param_lex, last,
+ param_lex->get_expr_str()))
return true;
}
return false;
diff --git a/sql/sp_head.h b/sql/sp_head.h
index 1b4cc0369b6..cdcc0ef97d4 100644
--- a/sql/sp_head.h
+++ b/sql/sp_head.h
@@ -391,7 +391,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, LEX *lex,
+ LEX_CSTRING expr_query);
bool
add_instr_preturn(THD *thd, sp_pcontext *spcont);
@@ -411,16 +412,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,
+ 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,
+ 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,
+ 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;
@@ -450,7 +454,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:
@@ -645,7 +650,8 @@ public:
do_cont_backpatch();
/// Add cpush instructions for all cursors declared in the current frame
- bool sp_add_instr_cpush_for_cursors(THD *thd, sp_pcontext *pcontext);
+ bool sp_add_instr_cpush_for_cursors(THD *thd, sp_pcontext *pcontext,
+ LEX_CSTRING cursor_query);
const LEX_CSTRING *name() const
{ return &m_name; }
diff --git a/sql/sp_instr.cc b/sql/sp_instr.cc
index 8d5542e8673..f2901af3e56 100644
--- a/sql/sp_instr.cc
+++ b/sql/sp_instr.cc
@@ -418,6 +418,27 @@ int sp_instr::exec_core(THD *thd, uint *nextp)
return 0;
}
+
+void sp_lex_instr::get_query(String *sql_query) const
+{
+ LEX_CSTRING expr_query = get_expr_query();
+
+ /*
+ the expression string must me initialized in constructor of a derived class
+ */
+ DBUG_ASSERT(expr_query.str != null_clex_str.str &&
+ expr_query.length != null_clex_str.length);
+
+ /*
+ Leave the method in case of empty query string.
+ */
+ if (!expr_query.length)
+ return;
+
+ sql_query->append(C_STRING_WITH_LEN("SELECT "));
+ sql_query->append(expr_query.str, expr_query.length);
+}
+
/*
sp_instr_stmt class functions
*/
@@ -1192,7 +1213,7 @@ sp_instr_cpush::execute(THD *thd, uint *nextp)
{
DBUG_ENTER("sp_instr_cpush::execute");
- sp_cursor::reset(thd, &m_lex_keeper);
+ sp_cursor::reset(thd);
m_lex_keeper.disable_query_cache();
thd->spcont->push_cursor(this);
@@ -1495,14 +1516,14 @@ sp_instr_cursor_copy_struct::exec_core(THD *thd, uint *nextp)
/*
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.
It we recreated the structure on every iteration, we would get
potential memory leaks, and it would be less efficient.
*/
if (!row->arguments())
{
- sp_cursor tmp(thd, &m_lex_keeper, true);
+ sp_cursor tmp(thd, true);
// Open the cursor without copying data
if (!(ret= tmp.open(thd)))
{
diff --git a/sql/sp_instr.h b/sql/sp_instr.h
index 2eb9d340e67..79d78d7acfd 100644
--- a/sql/sp_instr.h
+++ b/sql/sp_instr.h
@@ -233,7 +233,24 @@ public:
virtual void invalidate() = 0;
+ /**
+ Return the query string, which can be passed to the parser. I.e. the
+ operation should return a valid SQL-statement query string.
+
+ @param[out] sql_query SQL-statement query string.
+ */
+ virtual void get_query(String *sql_query) const;
+
protected:
+ /**
+ @return the expression query string. This string can not be passed directly
+ to the parser as it is most likely not a valid SQL-statement.
+ */
+ virtual LEX_CSTRING get_expr_query() const
+ {
+ return null_clex_str;
+ }
+
sp_lex_keeper m_lex_keeper;
};
@@ -252,17 +269,13 @@ class sp_instr_stmt : public sp_lex_instr
*/
bool m_valid;
-public:
-
LEX_STRING m_query; ///< For thd->query
- sp_instr_stmt(uint ip, sp_pcontext *ctx, LEX *lex)
+public:
+ sp_instr_stmt(uint ip, sp_pcontext *ctx, LEX *lex, LEX_STRING query)
: sp_lex_instr(ip, ctx, lex, true),
- m_valid{true}
- {
- m_query.str= 0;
- m_query.length= 0;
- }
+ m_valid(true), m_query(query)
+ {}
int execute(THD *thd, uint *nextp) override;
@@ -280,6 +293,11 @@ public:
m_valid= false;
}
+ void get_query(String *sql_query) const override
+ {
+ sql_query->append(m_query.str, m_query.length);
+ }
+
PSI_statement_info* get_psi_info() override { return & psi_info; }
static PSI_statement_info psi_info;
};
@@ -295,9 +313,10 @@ public:
sp_instr_set(uint ip, sp_pcontext *ctx,
const Sp_rcontext_handler *rh,
uint offset, Item *val,
- LEX *lex, bool lex_resp)
+ LEX *lex, bool lex_resp, LEX_CSTRING expr_str)
: sp_lex_instr(ip, ctx, lex, lex_resp),
- m_rcontext_handler(rh), m_offset(offset), m_value(val)
+ m_rcontext_handler(rh), m_offset(offset), m_value(val),
+ m_expr_str(expr_str)
{}
int execute(THD *thd, uint *nextp) override;
@@ -310,15 +329,22 @@ public:
void invalidate() override { m_value= nullptr; }
+ PSI_statement_info* get_psi_info() override { return & psi_info; }
+ static PSI_statement_info psi_info;
+
protected:
+ LEX_CSTRING get_expr_query() const override
+ {
+ return m_expr_str;
+ }
+
sp_rcontext *get_rcontext(THD *thd) const;
const Sp_rcontext_handler *m_rcontext_handler;
uint m_offset; ///< Frame offset
Item *m_value;
-public:
- PSI_statement_info* get_psi_info() override { return & psi_info; }
- static PSI_statement_info psi_info;
+private:
+ LEX_CSTRING m_expr_str;
};
@@ -340,8 +366,9 @@ public:
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),
+ LEX *lex, bool lex_resp,
+ LEX_CSTRING value_query)
+ : sp_instr_set(ip, ctx, rh, offset, val, lex, lex_resp, value_query),
m_field_offset(field_offset)
{}
@@ -381,8 +408,9 @@ public:
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),
+ LEX *lex, bool lex_resp,
+ LEX_CSTRING value_query)
+ : sp_instr_set(ip, ctx, rh, offset, val, lex, lex_resp, value_query),
m_field_name(field_name)
{}
@@ -405,10 +433,11 @@ public:
sp_instr_set_trigger_field(uint ip, sp_pcontext *ctx,
Item_trigger_field *trg_fld,
- Item *val, LEX *lex)
+ Item *val, LEX *lex, LEX_CSTRING value_query)
: sp_lex_instr(ip, ctx, lex, true),
trigger_field(trg_fld),
- value(val)
+ value(val),
+ m_expr_str(value_query)
{}
int execute(THD *thd, uint *nextp) override;
@@ -427,13 +456,22 @@ public:
value= nullptr;
}
+ PSI_statement_info* get_psi_info() override { return & psi_info; }
+ static PSI_statement_info psi_info;
+
+protected:
+ LEX_CSTRING get_expr_query() const override
+ {
+ return m_expr_str;
+ }
+
private:
Item_trigger_field *trigger_field;
Item *value;
-
-public:
- PSI_statement_info* get_psi_info() override { return & psi_info; }
- static PSI_statement_info psi_info;
+ /**
+ SQL clause corresponding to the expression value.
+ */
+ LEX_CSTRING m_expr_str;
}; // class sp_instr_trigger_field : public sp_instr
@@ -528,16 +566,18 @@ class sp_instr_jump_if_not : public sp_instr_opt_meta, public sp_lex_instr
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,
+ LEX_CSTRING expr_query)
: sp_instr_opt_meta(0),
sp_lex_instr(ip, ctx, lex, true),
- m_expr(i)
+ m_expr(i), m_expr_str(expr_query)
{}
- 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,
+ LEX_CSTRING expr_query)
: sp_instr_opt_meta(dest),
sp_lex_instr(ip, ctx, lex, true),
- m_expr(i)
+ m_expr(i), m_expr_str(expr_query)
{}
int execute(THD *thd, uint *nextp) override;
@@ -586,13 +626,21 @@ public:
m_expr= nullptr;
}
-private:
-
- Item *m_expr; ///< The condition
-
-public:
PSI_statement_info* get_psi_info() override { return & psi_info; }
static PSI_statement_info psi_info;
+
+protected:
+ LEX_CSTRING get_expr_query() const override
+ {
+ return m_expr_str;
+ }
+
+private:
+ Item *m_expr; ///< The condition
+ /**
+ SQL clause corresponding to the expression value.
+ */
+ LEX_CSTRING m_expr_str;
};
@@ -631,7 +679,8 @@ class sp_instr_freturn : public sp_lex_instr
public:
sp_instr_freturn(uint ip, sp_pcontext *ctx,
- Item *val, const Type_handler *handler, LEX *lex)
+ Item *val, const Type_handler *handler, LEX *lex,
+ LEX_CSTRING expr_query)
: sp_lex_instr(ip, ctx, lex, true),
m_value(val), m_type_handler(handler)
{}
@@ -656,14 +705,23 @@ public:
m_value= nullptr;
}
+ PSI_statement_info* get_psi_info() override { return & psi_info; }
+ static PSI_statement_info psi_info;
+
protected:
+ LEX_CSTRING get_expr_query() const override
+ {
+ return m_expr_str;
+ }
Item *m_value;
const Type_handler *m_type_handler;
-public:
- PSI_statement_info* get_psi_info() override { return & psi_info; }
- static PSI_statement_info psi_info;
+private:
+ /**
+ SQL-query corresponding to the RETURN-expression.
+ */
+ LEX_CSTRING m_expr_str;
};
@@ -800,15 +858,17 @@ 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 &);
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_instr_cpush(uint ip, sp_pcontext *ctx, LEX *lex, uint offset,
+ LEX_CSTRING cursor_query)
+ : sp_lex_instr(ip, ctx, lex, true), m_cursor(offset),
+ m_cursor_query(cursor_query), m_metadata_changed(false)
{}
int execute(THD *thd, uint *nextp) override;
@@ -822,10 +882,39 @@ public:
*/
void cleanup_stmt(bool /*restore_set_statement_vars*/) override
{ /* no op */ }
+
+ void get_query(String *sql_query) const override
+ {
+ sql_query->append(m_cursor_query.str, m_cursor_query.length);
+ }
+
+ 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) */
+ /**
+ This attribute keeps the cursor SELECT statement.
+ */
+ LEX_CSTRING m_cursor_query;
+
+ /**
+ Flag if the 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; }
@@ -1091,9 +1180,10 @@ class sp_instr_set_case_expr : public sp_instr_opt_meta, public sp_lex_instr
public:
sp_instr_set_case_expr(uint ip, sp_pcontext *ctx, uint case_expr_id,
- Item *case_expr, LEX *lex)
+ Item *case_expr, LEX *lex, LEX_CSTRING case_expr_query)
: sp_instr_opt_meta(0), sp_lex_instr(ip, ctx, lex, true),
- m_case_expr_id(case_expr_id), m_case_expr(case_expr)
+ m_case_expr_id(case_expr_id), m_case_expr(case_expr),
+ m_expr_str(case_expr_query)
{}
int execute(THD *thd, uint *nextp) override;
@@ -1127,14 +1217,22 @@ public:
m_case_expr= nullptr;
}
-private:
+ PSI_statement_info* get_psi_info() override { return & psi_info; }
+ static PSI_statement_info psi_info;
+
+protected:
+ LEX_CSTRING get_expr_query() const override
+ {
+ return m_expr_str;
+ }
+private:
uint m_case_expr_id;
Item *m_case_expr;
-
-public:
- PSI_statement_info* get_psi_info() override { return & psi_info; }
- static PSI_statement_info psi_info;
+ /**
+ SQL clause corresponding to the expression value.
+ */
+ LEX_CSTRING m_expr_str;
};
#endif // _SP_HEAD_H_
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index ac050eb2fd4..ab15a08874f 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -8153,3 +8153,11 @@ THD_list_iterator *THD_list_iterator::iterator()
{
return &server_threads;
}
+
+
+LEX_CSTRING make_string(THD *thd, const char *start_ptr,
+ const char *end_ptr)
+{
+ size_t length = end_ptr - start_ptr;
+ return {strmake_root(thd->mem_root, start_ptr, length), length};
+}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 0d02f74686f..3a5cf5c12a4 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -5868,19 +5868,17 @@ private:
public:
sp_cursor()
:result(NULL, false),
- m_lex_keeper(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),
- m_lex_keeper(lex_keeper),
server_side_cursor(NULL)
{}
virtual ~sp_cursor()
{ destroy(); }
- sp_lex_keeper *get_lex_keeper() { return m_lex_keeper; }
+ virtual sp_lex_keeper *get_lex_keeper() { return nullptr; }
int open(THD *thd);
@@ -5893,17 +5891,15 @@ public:
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();
result.reset(thd_arg);
- m_lex_keeper= lex_keeper;
server_side_cursor= NULL;
}
private:
Select_fetch_into_spvars result;
- sp_lex_keeper *m_lex_keeper;
Server_side_cursor *server_side_cursor;
void destroy();
};
@@ -7776,5 +7772,21 @@ extern THD_list server_threads;
void setup_tmp_table_column_bitmaps(TABLE *table, uchar *bitmaps,
uint field_count);
+
+/**
+ Make a new string allocated on THD's mem-root.
+
+ @param thd thread handler.
+ @param start_ptr start of the new string.
+ @param end_ptr end of the new string.
+
+ @return LEX_CSTRING object, containing a pointer to a newly
+ constructed/allocated string, and its length. The data member
+ LEX_CSTRING::str has the value nullptr in case of out-of-memory error.
+*/
+
+LEX_CSTRING make_string(THD *thd, const char *start_ptr,
+ const char *end_ptr);
+
#endif /* MYSQL_SERVER */
#endif /* SQL_CLASS_INCLUDED */
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 2311c7fd30f..e040b6641ba 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -74,7 +74,7 @@ int sp_expr_lex::case_stmt_action_expr()
i= new (thd->mem_root)
sp_instr_set_case_expr(sphead->instructions(), spcont, case_expr_id,
- get_item(), this);
+ get_item(), this, m_expr_str);
sphead->add_cont_backpatch(i);
return sphead->add_instr(i);
@@ -108,10 +108,12 @@ int sp_expr_lex::case_stmt_action_when(bool simple)
#endif
expr= new (thd->mem_root) Item_func_eq(thd, var, get_item());
- i= new (thd->mem_root) sp_instr_jump_if_not(ip, spcont, expr, this);
+ i= new (thd->mem_root) sp_instr_jump_if_not(ip, spcont, expr, this,
+ m_expr_str);
}
else
- i= new (thd->mem_root) sp_instr_jump_if_not(ip, spcont, get_item(), this);
+ i= new (thd->mem_root) sp_instr_jump_if_not(ip, spcont, get_item(), this,
+ m_expr_str);
/*
BACKPATCH: Registering forward jump from
@@ -204,7 +206,8 @@ LEX::set_system_variable(enum enum_var_type var_type,
@return TRUE if error, FALSE otherwise.
*/
-bool LEX::set_trigger_new_row(const LEX_CSTRING *name, Item *val)
+bool LEX::set_trigger_new_row(const LEX_CSTRING *name, Item *val,
+ LEX_CSTRING expr_str)
{
Item_trigger_field *trg_fld;
sp_instr_set_trigger_field *sp_fld;
@@ -227,7 +230,7 @@ bool LEX::set_trigger_new_row(const LEX_CSTRING *name, Item *val)
sp_fld= new (thd->mem_root)
sp_instr_set_trigger_field(sphead->instructions(),
- spcont, trg_fld, val, this);
+ spcont, trg_fld, val, this, expr_str);
if (unlikely(sp_fld == NULL))
return TRUE;
@@ -6480,7 +6483,8 @@ void LEX::sp_variable_declarations_init(THD *thd, int nvars)
bool LEX::sp_variable_declarations_set_default(THD *thd, int nvars,
- Item *dflt_value_item)
+ Item *dflt_value_item,
+ LEX_CSTRING expr_str)
{
bool has_default_clause= dflt_value_item != NULL;
if (!has_default_clause &&
@@ -6516,7 +6520,7 @@ bool LEX::sp_variable_declarations_set_default(THD *thd, int nvars,
sp_instr_set(sphead->instructions(),
spcont, &sp_rcontext_handler_local,
spvar->offset, dflt_value_item,
- this, last);
+ this, last, expr_str);
if (unlikely(is == NULL || sphead->add_instr(is)))
return true;
}
@@ -6528,7 +6532,8 @@ bool
LEX::sp_variable_declarations_copy_type_finalize(THD *thd, int nvars,
const Column_definition &ref,
Row_definition_list *fields,
- Item *default_value)
+ Item *default_value,
+ LEX_CSTRING expr_str)
{
for (uint i= 0 ; i < (uint) nvars; i++)
{
@@ -6542,7 +6547,7 @@ LEX::sp_variable_declarations_copy_type_finalize(THD *thd, int nvars,
spvar->field_def.field_name= spvar->name;
}
if (unlikely(sp_variable_declarations_set_default(thd, nvars,
- default_value)))
+ default_value, expr_str)))
return true;
spcont->declare_var_boundary(0);
return sphead->restore_lex(thd);
@@ -6551,20 +6556,22 @@ LEX::sp_variable_declarations_copy_type_finalize(THD *thd, int nvars,
bool LEX::sp_variable_declarations_finalize(THD *thd, int nvars,
const Column_definition *cdef,
- Item *dflt_value_item)
+ Item *dflt_value_item,
+ LEX_CSTRING expr_str)
{
DBUG_ASSERT(cdef);
Column_definition tmp(*cdef);
if (sphead->fill_spvar_definition(thd, &tmp))
return true;
return sp_variable_declarations_copy_type_finalize(thd, nvars, tmp, NULL,
- dflt_value_item);
+ dflt_value_item, expr_str);
}
bool LEX::sp_variable_declarations_row_finalize(THD *thd, int nvars,
Row_definition_list *row,
- Item *dflt_value_item)
+ Item *dflt_value_item,
+ LEX_CSTRING expr_str)
{
DBUG_ASSERT(row);
/*
@@ -6590,7 +6597,8 @@ bool LEX::sp_variable_declarations_row_finalize(THD *thd, int nvars,
return true;
}
- if (sp_variable_declarations_set_default(thd, nvars, dflt_value_item))
+ if (sp_variable_declarations_set_default(thd, nvars, dflt_value_item,
+ expr_str))
return true;
spcont->declare_var_boundary(0);
return sphead->restore_lex(thd);
@@ -6609,7 +6617,8 @@ bool LEX::sp_variable_declarations_row_finalize(THD *thd, int nvars,
bool
LEX::sp_variable_declarations_rowtype_finalize(THD *thd, int nvars,
Qualified_column_ident *ref,
- Item *def)
+ Item *def,
+ LEX_CSTRING expr_str)
{
uint coffp;
const sp_pcursor *pcursor= ref->table.str && ref->db.str ? NULL :
@@ -6617,7 +6626,8 @@ LEX::sp_variable_declarations_rowtype_finalize(THD *thd, int nvars,
false);
if (pcursor)
return sp_variable_declarations_cursor_rowtype_finalize(thd, nvars,
- coffp, def);
+ coffp, def,
+ expr_str);
/*
When parsing a qualified identifier chain, the parser does not know yet
if it's going to be a qualified column name (for %TYPE),
@@ -6632,7 +6642,7 @@ LEX::sp_variable_declarations_rowtype_finalize(THD *thd, int nvars,
return sp_variable_declarations_table_rowtype_finalize(thd, nvars,
ref->table,
ref->m_column,
- def);
+ def, expr_str);
}
@@ -6640,7 +6650,8 @@ bool
LEX::sp_variable_declarations_table_rowtype_finalize(THD *thd, int nvars,
const LEX_CSTRING &db,
const LEX_CSTRING &table,
- Item *def)
+ Item *def,
+ LEX_CSTRING expr_str)
{
Table_ident *table_ref;
if (unlikely(!(table_ref=
@@ -6653,7 +6664,7 @@ LEX::sp_variable_declarations_table_rowtype_finalize(THD *thd, int nvars,
spvar->field_def.set_table_rowtype_ref(table_ref);
sphead->fill_spvar_definition(thd, &spvar->field_def, &spvar->name);
}
- if (sp_variable_declarations_set_default(thd, nvars, def))
+ if (sp_variable_declarations_set_default(thd, nvars, def, expr_str))
return true;
// Make sure sp_rcontext is created using the invoker security context:
sphead->m_flags|= sp_head::HAS_COLUMN_TYPE_REFS;
@@ -6665,7 +6676,8 @@ LEX::sp_variable_declarations_table_rowtype_finalize(THD *thd, int nvars,
bool
LEX::sp_variable_declarations_cursor_rowtype_finalize(THD *thd, int nvars,
uint offset,
- Item *def)
+ Item *def,
+ LEX_CSTRING expr_str)
{
const sp_pcursor *pcursor= spcont->find_cursor(offset);
@@ -6685,7 +6697,8 @@ LEX::sp_variable_declarations_cursor_rowtype_finalize(THD *thd, int nvars,
sphead->fill_spvar_definition(thd, &spvar->field_def, &spvar->name);
}
- if (unlikely(sp_variable_declarations_set_default(thd, nvars, def)))
+ if (unlikely(sp_variable_declarations_set_default(thd, nvars, def,
+ expr_str)))
return true;
// Make sure sp_rcontext is created using the invoker security context:
sphead->m_flags|= sp_head::HAS_COLUMN_TYPE_REFS;
@@ -6703,18 +6716,21 @@ LEX::sp_variable_declarations_cursor_rowtype_finalize(THD *thd, int nvars,
bool
LEX::sp_variable_declarations_with_ref_finalize(THD *thd, int nvars,
Qualified_column_ident *ref,
- Item *def)
+ Item *def, LEX_CSTRING expr_str)
{
return ref->db.length == 0 && ref->table.length == 0 ?
- sp_variable_declarations_vartype_finalize(thd, nvars, ref->m_column, def) :
- sp_variable_declarations_column_type_finalize(thd, nvars, ref, def);
+ sp_variable_declarations_vartype_finalize(thd, nvars, ref->m_column, def,
+ expr_str) :
+ sp_variable_declarations_column_type_finalize(thd, nvars, ref, def,
+ expr_str);
}
bool
LEX::sp_variable_declarations_column_type_finalize(THD *thd, int nvars,
Qualified_column_ident *ref,
- Item *def)
+ Item *def,
+ LEX_CSTRING expr_str)
{
for (uint i= 0 ; i < (uint) nvars; i++)
{
@@ -6723,7 +6739,7 @@ LEX::sp_variable_declarations_column_type_finalize(THD *thd, int nvars,
spvar->field_def.field_name= spvar->name;
}
sphead->m_flags|= sp_head::HAS_COLUMN_TYPE_REFS;
- if (sp_variable_declarations_set_default(thd, nvars, def))
+ if (sp_variable_declarations_set_default(thd, nvars, def, expr_str))
return true;
spcont->declare_var_boundary(0);
return sphead->restore_lex(thd);
@@ -6733,7 +6749,8 @@ LEX::sp_variable_declarations_column_type_finalize(THD *thd, int nvars,
bool
LEX::sp_variable_declarations_vartype_finalize(THD *thd, int nvars,
const LEX_CSTRING &ref,
- Item *default_value)
+ Item *default_value,
+ LEX_CSTRING expr_str)
{
sp_variable *t;
if (!spcont || !(t= spcont->find_variable(&ref, false)))
@@ -6747,14 +6764,16 @@ LEX::sp_variable_declarations_vartype_finalize(THD *thd, int nvars,
uint offset= t->field_def.cursor_rowtype_offset();
return sp_variable_declarations_cursor_rowtype_finalize(thd, nvars,
offset,
- default_value);
+ default_value,
+ expr_str);
}
if (t->field_def.is_column_type_ref())
{
Qualified_column_ident *tmp= t->field_def.column_type_ref();
return sp_variable_declarations_column_type_finalize(thd, nvars, tmp,
- default_value);
+ default_value,
+ expr_str);
}
if (t->field_def.is_table_rowtype_ref())
@@ -6763,7 +6782,8 @@ LEX::sp_variable_declarations_vartype_finalize(THD *thd, int nvars,
return sp_variable_declarations_table_rowtype_finalize(thd, nvars,
tmp->db,
tmp->table,
- default_value);
+ default_value,
+ expr_str);
}
// A reference to a scalar or a row variable with an explicit data type
@@ -6771,7 +6791,8 @@ LEX::sp_variable_declarations_vartype_finalize(THD *thd, int nvars,
t->field_def,
t->field_def.
row_field_definitions(),
- default_value);
+ default_value,
+ expr_str);
}
@@ -6800,7 +6821,7 @@ LEX::sp_variable_declarations_vartype_finalize(THD *thd, int nvars,
sp_variable *LEX::sp_add_for_loop_variable(THD *thd, const LEX_CSTRING *name,
- Item *value)
+ Item *value, LEX_CSTRING expr_str)
{
sp_variable *spvar= spcont->add_variable(thd, name);
spcont->declare_var_boundary(1);
@@ -6816,7 +6837,7 @@ sp_variable *LEX::sp_add_for_loop_variable(THD *thd, const LEX_CSTRING *name,
sp_instr_set(sphead->instructions(),
spcont, &sp_rcontext_handler_local,
spvar->offset, value,
- this, true);
+ this, true, expr_str);
if (unlikely(is == NULL || sphead->add_instr(is)))
return NULL;
spcont->declare_var_boundary(0);
@@ -6826,12 +6847,13 @@ sp_variable *LEX::sp_add_for_loop_variable(THD *thd, const LEX_CSTRING *name,
bool LEX::sp_for_loop_implicit_cursor_statement(THD *thd,
Lex_for_loop_bounds_st *bounds,
- sp_lex_cursor *cur)
+ sp_lex_cursor *cur,
+ LEX_CSTRING cursor_query)
{
Item *item;
DBUG_ASSERT(sphead);
LEX_CSTRING name= {STRING_WITH_LEN("[implicit_cursor]") };
- if (sp_declare_cursor(thd, &name, cur, NULL, true))
+ if (sp_declare_cursor(thd, &name, cur, NULL, true, cursor_query))
return true;
DBUG_ASSERT(thd->lex == this);
if (unlikely(!(bounds->m_index=
@@ -6915,7 +6937,8 @@ bool LEX::sp_for_loop_condition(THD *thd, const Lex_for_loop_st &loop)
Item *expr= loop.m_direction > 0 ?
(Item *) new (thd->mem_root) Item_func_le(thd, args[0], args[1]) :
(Item *) new (thd->mem_root) Item_func_ge(thd, args[0], args[1]);
- return unlikely(!expr) || unlikely(sp_while_loop_expression(thd, expr));
+ return unlikely(!expr) || unlikely(sp_while_loop_expression(thd, expr,
+ empty_clex_str));
}
@@ -6947,7 +6970,7 @@ bool LEX::sp_for_loop_cursor_condition_test(THD *thd,
Item_func_cursor_found(thd, cursor_name,
loop.m_cursor_offset))))
return true;
- if (thd->lex->sp_while_loop_expression(thd, expr))
+ if (thd->lex->sp_while_loop_expression(thd, expr, empty_clex_str))
return true;
return thd->lex->sphead->restore_lex(thd);
}
@@ -6972,13 +6995,18 @@ bool LEX::sp_for_loop_intrange_declarations(THD *thd, Lex_for_loop_st *loop,
}
if (!(loop->m_index=
bounds.m_index->sp_add_for_loop_variable(thd, index,
- bounds.m_index->get_item())))
+ bounds.m_index->get_item(),
+ bounds.m_index->get_expr_str())
+ ))
return true;
if (unlikely(!(loop->m_target_bound=
bounds.m_target_bound->
sp_add_for_loop_target_bound(thd,
bounds.
- m_target_bound->get_item()))))
+ m_target_bound->get_item(),
+ bounds.
+ m_target_bound->get_expr_str()
+ ))))
return true;
loop->m_direction= bounds.m_direction;
loop->m_implicit_cursor= 0;
@@ -7071,7 +7099,8 @@ bool LEX::sp_for_loop_increment(THD *thd, const Lex_for_loop_st &loop)
if (unlikely(!expr) ||
unlikely(sphead->set_local_variable(thd, spcont,
&sp_rcontext_handler_local,
- loop.m_index, expr, this, true)))
+ loop.m_index, expr, this, true,
+ empty_clex_str)))
return true;
return false;
}
@@ -7129,7 +7158,9 @@ bool LEX::sp_for_loop_outer_block_finalize(THD *thd,
bool LEX::sp_declare_cursor(THD *thd, const LEX_CSTRING *name,
sp_lex_cursor *cursor_stmt,
- sp_pcontext *param_ctx, bool add_cpush_instr)
+ sp_pcontext *param_ctx, bool add_cpush_instr,
+ LEX_CSTRING cursor_query)
+
{
uint offp;
sp_instr_cpush *i;
@@ -7147,7 +7178,7 @@ bool LEX::sp_declare_cursor(THD *thd, const LEX_CSTRING *name,
{
i= new (thd->mem_root)
sp_instr_cpush(sphead->instructions(), spcont, cursor_stmt,
- spcont->current_cursor_count() - 1);
+ spcont->current_cursor_count() - 1, cursor_query);
return unlikely(i == NULL) || unlikely(sphead->add_instr(i));
}
return false;
@@ -7558,7 +7589,7 @@ bool LEX::sp_leave_statement(THD *thd, const LEX_CSTRING *label_name)
my_error(ER_SP_LILABEL_MISMATCH, MYF(0), "LEAVE", label_name->str);
return true;
}
- return sp_exit_block(thd, lab, NULL);
+ return sp_exit_block(thd, lab, NULL, empty_clex_str);
}
bool LEX::sp_goto_statement(THD *thd, const LEX_CSTRING *label_name)
@@ -7626,7 +7657,8 @@ bool LEX::sp_exit_block(THD *thd, sp_label *lab)
}
-bool LEX::sp_exit_block(THD *thd, sp_label *lab, Item *when)
+bool LEX::sp_exit_block(THD *thd, sp_label *lab, Item *when,
+ LEX_CSTRING expr_str)
{
if (!when)
return sp_exit_block(thd, lab);
@@ -7636,7 +7668,7 @@ bool LEX::sp_exit_block(THD *thd, sp_label *lab, Item *when)
sp_instr_jump_if_not *i= new (thd->mem_root)
sp_instr_jump_if_not(sphead->instructions(),
spcont,
- when, this);
+ when, this, expr_str);
if (unlikely(i == NULL) ||
unlikely(sphead->add_instr(i)) ||
unlikely(sp_exit_block(thd, lab)))
@@ -7646,7 +7678,7 @@ bool LEX::sp_exit_block(THD *thd, sp_label *lab, Item *when)
}
-bool LEX::sp_exit_statement(THD *thd, Item *item)
+bool LEX::sp_exit_statement(THD *thd, Item *item, LEX_CSTRING expr_str)
{
sp_label *lab= spcont->find_label_current_loop_start();
if (unlikely(!lab))
@@ -7655,11 +7687,12 @@ bool LEX::sp_exit_statement(THD *thd, Item *item)
return true;
}
DBUG_ASSERT(lab->type == sp_label::ITERATION);
- return sp_exit_block(thd, lab, item);
+ return sp_exit_block(thd, lab, item, expr_str);
}
-bool LEX::sp_exit_statement(THD *thd, const LEX_CSTRING *label_name, Item *item)
+bool LEX::sp_exit_statement(THD *thd, const LEX_CSTRING *label_name,
+ Item *item, LEX_CSTRING expr_str)
{
sp_label *lab= spcont->find_label(label_name);
if (unlikely(!lab || lab->type != sp_label::ITERATION))
@@ -7667,7 +7700,7 @@ bool LEX::sp_exit_statement(THD *thd, const LEX_CSTRING *label_name, Item *item)
my_error(ER_SP_LILABEL_MISMATCH, MYF(0), "EXIT", label_name->str);
return true;
}
- return sp_exit_block(thd, lab, item);
+ return sp_exit_block(thd, lab, item, expr_str);
}
@@ -7724,7 +7757,8 @@ bool LEX::sp_continue_statement(THD *thd, const LEX_CSTRING *label_name)
}
-bool LEX::sp_continue_loop(THD *thd, sp_label *lab, Item *when)
+bool LEX::sp_continue_loop(THD *thd, sp_label *lab, Item *when,
+ LEX_CSTRING expr_str)
{
DBUG_ASSERT(when);
DBUG_ASSERT(sphead == thd->lex->sphead);
@@ -7732,7 +7766,7 @@ bool LEX::sp_continue_loop(THD *thd, sp_label *lab, Item *when)
sp_instr_jump_if_not *i= new (thd->mem_root)
sp_instr_jump_if_not(sphead->instructions(),
spcont,
- when, this);
+ when, this, expr_str);
if (unlikely(i == NULL) ||
unlikely(sphead->add_instr(i)) ||
unlikely(sp_continue_loop(thd, lab)))
@@ -7751,7 +7785,7 @@ bool sp_expr_lex::sp_continue_when_statement(THD *thd)
return true;
}
DBUG_ASSERT(lab->type == sp_label::ITERATION);
- return sp_continue_loop(thd, lab, get_item());
+ return sp_continue_loop(thd, lab, get_item(), m_expr_str);
}
@@ -7764,7 +7798,7 @@ bool sp_expr_lex::sp_continue_when_statement(THD *thd,
my_error(ER_SP_LILABEL_MISMATCH, MYF(0), "CONTINUE", label_name->str);
return true;
}
- return sp_continue_loop(thd, lab, get_item());
+ return sp_continue_loop(thd, lab, get_item(), m_expr_str);
}
@@ -7829,10 +7863,10 @@ void LEX::sp_pop_loop_empty_label(THD *thd)
}
-bool LEX::sp_while_loop_expression(THD *thd, Item *item)
+bool LEX::sp_while_loop_expression(THD *thd, Item *item, LEX_CSTRING expr_str)
{
sp_instr_jump_if_not *i= new (thd->mem_root)
- sp_instr_jump_if_not(sphead->instructions(), spcont, item, this);
+ sp_instr_jump_if_not(sphead->instructions(), spcont, item, this, expr_str);
return (unlikely(i == NULL) ||
/* Jumping forward */
unlikely(sphead->push_backpatch(thd, i, spcont->last_label())) ||
@@ -8457,12 +8491,14 @@ Item *LEX::create_item_ident_sp(THD *thd, Lex_ident_sys_st *name,
-bool LEX::set_variable(const Lex_ident_sys_st *name, Item *item)
+bool LEX::set_variable(const Lex_ident_sys_st *name, Item *item,
+ LEX_CSTRING expr_str)
{
sp_pcontext *ctx;
const Sp_rcontext_handler *rh;
sp_variable *spv= find_variable(name, &ctx, &rh);
- return spv ? sphead->set_local_variable(thd, ctx, rh, spv, item, this, true) :
+ return spv ? sphead->set_local_variable(thd, ctx, rh, spv, item, this, true,
+ expr_str) :
set_system_variable(option_type, name, item);
}
@@ -8473,7 +8509,7 @@ bool LEX::set_variable(const Lex_ident_sys_st *name, Item *item)
*/
bool LEX::set_variable(const Lex_ident_sys_st *name1,
const Lex_ident_sys_st *name2,
- Item *item)
+ Item *item, LEX_CSTRING expr_str)
{
const Sp_rcontext_handler *rh;
sp_pcontext *ctx;
@@ -8485,17 +8521,18 @@ bool LEX::set_variable(const Lex_ident_sys_st *name1,
return sphead->set_local_variable_row_field_by_name(thd, ctx,
rh,
spv, name2,
- item, this);
+ item, this,
+ expr_str);
// A field of a ROW variable
uint row_field_offset;
return !spv->find_row_field(name1, name2, &row_field_offset) ||
sphead->set_local_variable_row_field(thd, ctx, rh,
spv, row_field_offset,
- item, this);
+ item, this, expr_str);
}
if (is_trigger_new_or_old_reference(name1))
- return set_trigger_field(name1, name2, item);
+ return set_trigger_field(name1, name2, item, expr_str);
return set_system_variable(thd, option_type, name1, name2, item);
}
@@ -8552,7 +8589,7 @@ bool LEX::set_system_variable(THD *thd, enum_var_type var_type,
bool LEX::set_trigger_field(const LEX_CSTRING *name1, const LEX_CSTRING *name2,
- Item *val)
+ Item *val, LEX_CSTRING expr_str)
{
DBUG_ASSERT(is_trigger_new_or_old_reference(name1));
if (unlikely(name1->str[0]=='O' || name1->str[0]=='o'))
@@ -8570,7 +8607,7 @@ bool LEX::set_trigger_field(const LEX_CSTRING *name1, const LEX_CSTRING *name2,
my_error(ER_TRG_CANT_CHANGE_ROW, MYF(0), "NEW", "after ");
return true;
}
- return set_trigger_new_row(name2, val);
+ return set_trigger_new_row(name2, val, expr_str);
}
@@ -10434,17 +10471,17 @@ bool LEX::new_sp_instr_stmt(THD *thd,
LEX_STRING qbuff;
sp_instr_stmt *i;
- if (!(i= new (thd->mem_root) sp_instr_stmt(sphead->instructions(),
- spcont, this)))
- return true;
-
qbuff.length= prefix.length + suffix.length;
if (!(qbuff.str= (char*) alloc_root(thd->mem_root, qbuff.length + 1)))
return true;
if (prefix.length)
memcpy(qbuff.str, prefix.str, prefix.length);
strmake(qbuff.str + prefix.length, suffix.str, suffix.length);
- i->m_query= qbuff;
+
+ if (!(i= new (thd->mem_root) sp_instr_stmt(sphead->instructions(),
+ spcont, this, qbuff)))
+ return true;
+
return sphead->add_instr(i);
}
@@ -11490,7 +11527,7 @@ bool sp_expr_lex::sp_repeat_loop_finalize(THD *thd)
uint ip= sphead->instructions();
sp_label *lab= spcont->last_label(); /* Jumping back */
sp_instr_jump_if_not *i= new (thd->mem_root)
- sp_instr_jump_if_not(ip, spcont, get_item(), lab->ip, this);
+ sp_instr_jump_if_not(ip, spcont, get_item(), lab->ip, this, m_expr_str);
if (unlikely(i == NULL) ||
unlikely(sphead->add_instr(i)))
return true;
@@ -11504,7 +11541,8 @@ bool sp_expr_lex::sp_if_expr(THD *thd)
{
uint ip= sphead->instructions();
sp_instr_jump_if_not *i= new (thd->mem_root)
- sp_instr_jump_if_not(ip, spcont, get_item(), this);
+ sp_instr_jump_if_not(ip, spcont, get_item(), this,
+ m_expr_str);
return
(unlikely(i == NULL) ||
unlikely(sphead->push_backpatch(thd, i,
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 1bb63833c41..58f8c5c6b04 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -3260,7 +3260,8 @@ private:
class sp_label **splabel);
bool sp_change_context(THD *thd, const sp_pcontext *ctx, bool exclusive);
bool sp_exit_block(THD *thd, sp_label *lab);
- bool sp_exit_block(THD *thd, sp_label *lab, Item *when);
+ bool sp_exit_block(THD *thd, sp_label *lab, Item *when,
+ LEX_CSTRING expr_str);
bool sp_continue_loop(THD *thd, sp_label *lab);
@@ -3275,7 +3276,8 @@ private:
bool check_expr_allows_fields_or_error(THD *thd, const char *name) const;
protected:
- bool sp_continue_loop(THD *thd, sp_label *lab, Item *when);
+ bool sp_continue_loop(THD *thd, sp_label *lab, Item *when,
+ LEX_CSTRING expr_str);
public:
void parse_error(uint err_number= ER_SYNTAX_ERROR);
@@ -3808,9 +3810,10 @@ public:
int case_stmt_action_then();
bool setup_select_in_parentheses();
- bool set_trigger_new_row(const LEX_CSTRING *name, Item *val);
+ bool set_trigger_new_row(const LEX_CSTRING *name, Item *val,
+ LEX_CSTRING expr_str);
bool set_trigger_field(const LEX_CSTRING *name1, const LEX_CSTRING *name2,
- Item *val);
+ Item *val, LEX_CSTRING expr_str);
bool set_system_variable(enum_var_type var_type, sys_var *var,
const Lex_ident_sys_st *base_name, Item *val);
bool set_system_variable(enum_var_type var_type,
@@ -3862,40 +3865,50 @@ public:
sp_pcontext *not_used_ctx;
return find_variable(name, &not_used_ctx, rh);
}
- bool set_variable(const Lex_ident_sys_st *name, Item *item);
+ bool set_variable(const Lex_ident_sys_st *name, Item *item,
+ LEX_CSTRING expr_str);
bool set_variable(const Lex_ident_sys_st *name1,
- const Lex_ident_sys_st *name2, Item *item);
+ const Lex_ident_sys_st *name2, Item *item,
+ LEX_CSTRING expr_str);
void sp_variable_declarations_init(THD *thd, int nvars);
bool sp_variable_declarations_finalize(THD *thd, int nvars,
const Column_definition *cdef,
- Item *def);
- bool sp_variable_declarations_set_default(THD *thd, int nvars, Item *def);
+ Item *def, LEX_CSTRING expr_str);
+ bool sp_variable_declarations_set_default(THD *thd, int nvars, Item *def,
+ LEX_CSTRING expr_str);
bool sp_variable_declarations_row_finalize(THD *thd, int nvars,
Row_definition_list *row,
- Item *def);
+ Item *def, LEX_CSTRING expr_str);
bool sp_variable_declarations_with_ref_finalize(THD *thd, int nvars,
Qualified_column_ident *col,
- Item *def);
+ Item *def,
+ LEX_CSTRING expr_str);
bool sp_variable_declarations_rowtype_finalize(THD *thd, int nvars,
Qualified_column_ident *,
- Item *def);
+ Item *def,
+ LEX_CSTRING expr_str);
bool sp_variable_declarations_cursor_rowtype_finalize(THD *thd, int nvars,
uint offset,
- Item *def);
+ Item *def,
+ LEX_CSTRING expr_str);
bool sp_variable_declarations_table_rowtype_finalize(THD *thd, int nvars,
const LEX_CSTRING &db,
const LEX_CSTRING &table,
- Item *def);
+ Item *def,
+ LEX_CSTRING expr_str);
bool sp_variable_declarations_column_type_finalize(THD *thd, int nvars,
Qualified_column_ident *ref,
- Item *def);
+ Item *def,
+ LEX_CSTRING expr_str);
bool sp_variable_declarations_vartype_finalize(THD *thd, int nvars,
const LEX_CSTRING &name,
- Item *def);
+ Item *def,
+ LEX_CSTRING expr_str);
bool sp_variable_declarations_copy_type_finalize(THD *thd, int nvars,
const Column_definition &ref,
Row_definition_list *fields,
- Item *def);
+ Item *def,
+ LEX_CSTRING expr_str);
LEX_USER *current_user_for_set_password(THD *thd);
bool sp_create_set_password_instr(THD *thd,
@@ -3916,7 +3929,8 @@ public:
bool sp_declare_cursor(THD *thd, const LEX_CSTRING *name,
class sp_lex_cursor *cursor_stmt,
- sp_pcontext *param_ctx, bool add_cpush_instr);
+ sp_pcontext *param_ctx, bool add_cpush_instr,
+ LEX_CSTRING cursor_query);
bool sp_open_cursor(THD *thd, const LEX_CSTRING *name,
List<sp_assignment_lex> *parameters);
@@ -4181,8 +4195,9 @@ public:
uint executable_section_ip,
uint exception_count);
bool sp_block_with_exceptions_add_empty(THD *thd);
- bool sp_exit_statement(THD *thd, Item *when);
- bool sp_exit_statement(THD *thd, const LEX_CSTRING *label_name, Item *item);
+ bool sp_exit_statement(THD *thd, Item *when, LEX_CSTRING expr_str);
+ bool sp_exit_statement(THD *thd, const LEX_CSTRING *label_name, Item *item,
+ LEX_CSTRING expr_str);
bool sp_leave_statement(THD *thd, const LEX_CSTRING *label_name);
bool sp_goto_statement(THD *thd, const LEX_CSTRING *label_name);
@@ -4195,7 +4210,7 @@ public:
bool sp_push_loop_empty_label(THD *thd);
bool sp_pop_loop_label(THD *thd, const LEX_CSTRING *label_name);
void sp_pop_loop_empty_label(THD *thd);
- bool sp_while_loop_expression(THD *thd, Item *expr);
+ bool sp_while_loop_expression(THD *thd, Item *expr, LEX_CSTRING expr_str);
bool sp_while_loop_finalize(THD *thd);
bool sp_if_after_statements(THD *thd);
bool sp_push_goto_label(THD *thd, const LEX_CSTRING *label_name);
@@ -4205,11 +4220,12 @@ public:
/* Integer range FOR LOOP methods */
sp_variable *sp_add_for_loop_variable(THD *thd, const LEX_CSTRING *name,
- Item *value);
- sp_variable *sp_add_for_loop_target_bound(THD *thd, Item *value)
+ Item *value, LEX_CSTRING expr_str);
+ sp_variable *sp_add_for_loop_target_bound(THD *thd, Item *value,
+ LEX_CSTRING expr_str)
{
LEX_CSTRING name= { STRING_WITH_LEN("[target_bound]") };
- return sp_add_for_loop_variable(thd, &name, value);
+ return sp_add_for_loop_variable(thd, &name, value, expr_str);
}
bool sp_for_loop_intrange_declarations(THD *thd, Lex_for_loop_st *loop,
const LEX_CSTRING *index,
@@ -4229,7 +4245,8 @@ public:
Item_args *parameters);
bool sp_for_loop_implicit_cursor_statement(THD *thd,
Lex_for_loop_bounds_st *bounds,
- sp_lex_cursor *cur);
+ sp_lex_cursor *cur,
+ LEX_CSTRING cursor_query);
bool sp_for_loop_cursor_condition_test(THD *thd, const Lex_for_loop_st &loop);
bool sp_for_loop_cursor_finalize(THD *thd, const Lex_for_loop_st &);
@@ -4759,6 +4776,15 @@ public:
builtin_select.options |= SELECT_DESCRIBE;
}
+
+ /**
+ Check if the current statement uses meta-data (uses a table or a stored
+ routine).
+ */
+ bool is_metadata_used() const
+ {
+ return query_tables != nullptr || sroutines.records > 0;
+ }
};
@@ -4985,14 +5011,16 @@ public:
class sp_expr_lex: public sp_lex_local
{
Item *m_item; // The expression
+ LEX_CSTRING m_expr_str;
public:
sp_expr_lex(THD *thd, LEX *oldlex)
:sp_lex_local(thd, oldlex),
- m_item(NULL)
+ m_item(NULL), m_expr_str(empty_clex_str)
{ }
- void set_item(Item *item)
+ void set_item(Item *item, LEX_CSTRING expr_str)
{
m_item= item;
+ m_expr_str= expr_str;
}
Item *get_item() const
{
@@ -5004,10 +5032,14 @@ public:
int case_stmt_action_when(bool simple);
bool sp_while_loop_expression(THD *thd)
{
- return LEX::sp_while_loop_expression(thd, get_item());
+ return LEX::sp_while_loop_expression(thd, get_item(), m_expr_str);
}
bool sp_repeat_loop_finalize(THD *thd);
bool sp_if_expr(THD *thd);
+ LEX_CSTRING get_expr_str() const
+ {
+ return m_expr_str;
+ }
};
@@ -5038,11 +5070,13 @@ class sp_assignment_lex: public sp_lex_local
{
Item *m_item; // The expression
Item *m_free_list; // The associated free_list (sub-expressions)
+ LEX_CSTRING m_expr_str;
public:
sp_assignment_lex(THD *thd, LEX *oldlex)
:sp_lex_local(thd, oldlex),
m_item(NULL),
- m_free_list(NULL)
+ m_free_list(NULL),
+ m_expr_str(empty_clex_str)
{ }
void set_item_and_free_list(Item *item, Item *free_list)
{
@@ -5057,6 +5091,14 @@ public:
{
return m_free_list;
}
+ void set_expr_str(LEX_CSTRING expr_str)
+ {
+ m_expr_str= expr_str;
+ }
+ LEX_CSTRING get_expr_str() const
+ {
+ return m_expr_str;
+ }
};
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 3c2c3f28d79..b0d6d1ef7ca 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -345,6 +345,11 @@ void _CONCAT_UNDERSCORED(turn_parser_debug_on,yyparse)()
enum Column_definition::enum_column_versioning vers_column_versioning;
enum plsql_cursor_attr_t plsql_cursor_attr;
privilege_t privilege;
+ struct
+ {
+ Item *expr;
+ LEX_CSTRING expr_str;
+ } sp_default_stmt;
}
%{
@@ -1486,7 +1491,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
select_sublist_qualified_asterisk
expr_or_ignore expr_or_ignore_or_default set_expr_or_default
signed_literal expr_or_literal
- sp_opt_default
simple_ident_nospvar
field_or_var limit_option
part_func_expr
@@ -1528,6 +1532,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%type <expr_lex>
expr_lex
+%type <sp_default_stmt> sp_opt_default
+
%type <assignment_lex>
assignment_source_lex
assignment_source_expr
@@ -3185,7 +3191,8 @@ sp_decl_variable_list:
{
if (unlikely(Lex->sp_variable_declarations_finalize(thd, $1,
&Lex->last_field[0],
- $4)))
+ $4.expr,
+ $4.expr_str)))
MYSQL_YYABORT;
$$.init_using_vars($1);
}
@@ -3193,7 +3200,9 @@ sp_decl_variable_list:
ROW_SYM row_type_body
sp_opt_default
{
- if (unlikely(Lex->sp_variable_declarations_row_finalize(thd, $1, $3, $4)))
+ if (unlikely(Lex->sp_variable_declarations_row_finalize(thd, $1, $3,
+ $4.expr,
+ $4.expr_str)))
MYSQL_YYABORT;
$$.init_using_vars($1);
}
@@ -3718,11 +3727,21 @@ RETURN_ALLMODES_SYM:
;
sp_proc_stmt_return:
- RETURN_ALLMODES_SYM expr_lex
+ RETURN_ALLMODES_SYM remember_name expr_lex remember_end
{
- sp_head *sp= $2->sphead;
- if (unlikely(sp->m_handler->add_instr_freturn(thd, sp, $2->spcont,
- $2->get_item(), $2)))
+ sp_head *sp= $3->sphead;
+ LEX_CSTRING expr_str= empty_clex_str;
+
+ if (Lex->is_metadata_used())
+ {
+ expr_str= make_string(thd, $2, $4);
+ if (expr_str.str == nullptr)
+ MYSQL_YYABORT;
+ }
+
+ if (unlikely(sp->m_handler->add_instr_freturn(thd, sp, $3->spcont,
+ $3->get_item(), $3,
+ expr_str)))
MYSQL_YYABORT;
}
| RETURN_ORACLE_SYM
@@ -3738,22 +3757,29 @@ sp_proc_stmt_return:
sp_proc_stmt_exit_oracle:
EXIT_ORACLE_SYM
{
- if (unlikely(Lex->sp_exit_statement(thd, NULL)))
+ if (unlikely(Lex->sp_exit_statement(thd, NULL, empty_clex_str)))
MYSQL_YYABORT;
}
| EXIT_ORACLE_SYM label_ident
{
- if (unlikely(Lex->sp_exit_statement(thd, &$2, NULL)))
+ if (unlikely(Lex->sp_exit_statement(thd, &$2, NULL,
+ empty_clex_str)))
MYSQL_YYABORT;
}
| EXIT_ORACLE_SYM WHEN_SYM expr_lex
{
- if (unlikely($3->sp_exit_statement(thd, $3->get_item())))
+ if (unlikely($3->sp_exit_statement(thd, $3->get_item(),
+ Lex->is_metadata_used() ?
+ $3->get_expr_str() :
+ empty_clex_str)))
MYSQL_YYABORT;
}
| EXIT_ORACLE_SYM label_ident WHEN_SYM expr_lex
{
- if (unlikely($4->sp_exit_statement(thd, &$2, $4->get_item())))
+ if (unlikely($4->sp_exit_statement(thd, &$2, $4->get_item(),
+ Lex->is_metadata_used() ?
+ $4->get_expr_str() :
+ empty_clex_str)))
MYSQL_YYABORT;
}
;
@@ -3817,11 +3843,21 @@ expr_lex:
if (Lex->main_select_push(true))
MYSQL_YYABORT;
}
- expr
+ remember_name expr remember_end
{
+ LEX_CSTRING expr_str= empty_clex_str;
+
$$= $<expr_lex>1;
$$->sp_lex_in_use= true;
- $$->set_item($2);
+
+ if (Lex->is_metadata_used())
+ {
+ expr_str= make_string(thd, $2, $4);
+ if (expr_str.str == nullptr)
+ MYSQL_YYABORT;
+ }
+
+ $$->set_item($3, expr_str);
Lex->pop_select(); //min select
if (Lex->check_cte_dependencies_and_resolve_references())
MYSQL_YYABORT;
@@ -3848,12 +3884,22 @@ assignment_source_expr:
if (Lex->main_select_push(true))
MYSQL_YYABORT;
}
- expr
+ remember_name expr remember_end
{
DBUG_ASSERT($1 == thd->lex);
$$= $1;
$$->sp_lex_in_use= true;
- $$->set_item_and_free_list($3, thd->free_list);
+ $$->set_item_and_free_list($4, thd->free_list);
+
+ if (Lex->is_metadata_used())
+ {
+ LEX_CSTRING expr_str= make_string(thd, $3, $5);
+
+ if (expr_str.str == nullptr)
+ MYSQL_YYABORT;
+ $$->set_expr_str(expr_str);
+ }
+
thd->free_list= NULL;
Lex->pop_select(); //min select
if ($$->sphead->restore_lex(thd))
@@ -3869,12 +3915,21 @@ for_loop_bound_expr:
MYSQL_YYABORT;
Lex->current_select->parsing_place= FOR_LOOP_BOUND;
}
- expr
+ remember_name expr remember_end
{
DBUG_ASSERT($1 == thd->lex);
$$= $1;
$$->sp_lex_in_use= true;
- $$->set_item_and_free_list($3, NULL);
+ $$->set_item_and_free_list($4, nullptr);
+
+ if (Lex->is_metadata_used())
+ {
+ LEX_CSTRING expr_str= make_string(thd, $3, $5);
+ if (expr_str.str == nullptr)
+ MYSQL_YYABORT;
+ $$->set_expr_str(expr_str);
+ }
+
Lex->pop_select(); //main select
if (unlikely($$->sphead->restore_lex(thd)))
MYSQL_YYABORT;
@@ -4189,10 +4244,22 @@ sp_for_loop_bounds:
$$.m_target_bound= NULL;
$$.m_implicit_cursor= false;
}
- | IN_SYM opt_sp_for_loop_direction '(' sp_cursor_stmt ')'
+ | IN_SYM opt_sp_for_loop_direction '('
+ remember_name sp_cursor_stmt remember_end ')'
{
+ LEX_CSTRING expr_str= empty_clex_str;
+
+ if (Lex->is_metadata_used())
+ {
+ expr_str= make_string(thd, $4, $6);
+ if (expr_str.str == nullptr)
+ MYSQL_YYABORT;
+ }
+
if (unlikely(Lex->sp_for_loop_implicit_cursor_statement(thd, &$$,
- $4)))
+ $5,
+ expr_str
+ )))
MYSQL_YYABORT;
}
;
@@ -16421,11 +16488,20 @@ option_value_no_option_type:
if (sp_create_assignment_lex(thd, $1.pos()))
MYSQL_YYABORT;
}
- set_expr_or_default
+ remember_name set_expr_or_default remember_end
{
Lex_ident_sys tmp(thd, &$1);
+ LEX_CSTRING expr_str= empty_clex_str;
+
+ if (Lex->is_metadata_used())
+ {
+ expr_str= make_string(thd, $4, $6);
+ if (expr_str.str == nullptr)
+ MYSQL_YYABORT;
+ }
+
if (unlikely(!tmp.str) ||
- unlikely(Lex->set_variable(&tmp, $4)) ||
+ unlikely(Lex->set_variable(&tmp, $5, expr_str)) ||
unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
@@ -16434,11 +16510,20 @@ option_value_no_option_type:
if (sp_create_assignment_lex(thd, $1.pos()))
MYSQL_YYABORT;
}
- set_expr_or_default
+ remember_name set_expr_or_default remember_end
{
Lex_ident_sys tmp(thd, &$1);
+ LEX_CSTRING expr_str= empty_clex_str;
+
+ if (Lex->is_metadata_used())
+ {
+ expr_str= make_string(thd, $6, $8);
+ if (expr_str.str == nullptr)
+ MYSQL_YYABORT;
+ }
+
if (unlikely(!tmp.str) ||
- unlikely(Lex->set_variable(&tmp, &$3, $6)) ||
+ unlikely(Lex->set_variable(&tmp, &$3, $7, expr_str)) ||
unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
@@ -16609,11 +16694,20 @@ option_value_no_option_type:
if (sp_create_assignment_lex(thd, $1.pos()))
MYSQL_YYABORT;
}
- set_expr_or_default
+ remember_name set_expr_or_default remember_end
{
Lex_ident_sys tmp(thd, &$1);
+ LEX_CSTRING expr_str= empty_clex_str;
+
+ if (Lex->is_metadata_used())
+ {
+ expr_str= make_string(thd, $4, $6);
+ if (expr_str.str == nullptr)
+ MYSQL_YYABORT;
+ }
+
if (unlikely(!tmp.str) ||
- unlikely(Lex->set_variable(&tmp, $4)) ||
+ unlikely(Lex->set_variable(&tmp, $5, expr_str)) ||
unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
@@ -18033,8 +18127,20 @@ sp_block_label:
;
sp_opt_default:
- _empty { $$ = NULL; }
- | DEFAULT expr { $$ = $2; }
+ _empty { $$= { nullptr, empty_clex_str}; }
+ | DEFAULT remember_name expr remember_end
+ {
+ LEX_CSTRING expr_str= empty_clex_str;
+
+ if (Lex->is_metadata_used())
+ {
+ expr_str= make_string(thd, $2, $4);
+ if (expr_str.str == nullptr)
+ MYSQL_YYABORT;
+ }
+
+ $$= { $3, expr_str };
+ }
;
sp_pdparam:
@@ -18047,7 +18153,8 @@ sp_decl_variable_list_anchored:
TYPE_SYM OF_SYM optionally_qualified_column_ident
sp_opt_default
{
- if (unlikely(Lex->sp_variable_declarations_with_ref_finalize(thd, $1, $4, $5)))
+ if (unlikely(Lex->sp_variable_declarations_with_ref_finalize(
+ thd, $1, $4, $5.expr, $5.expr_str)))
MYSQL_YYABORT;
$$.init_using_vars($1);
}
@@ -18055,7 +18162,8 @@ sp_decl_variable_list_anchored:
ROW_SYM TYPE_SYM OF_SYM optionally_qualified_column_ident
sp_opt_default
{
- if (unlikely(Lex->sp_variable_declarations_rowtype_finalize(thd, $1, $5, $6)))
+ if (unlikely(Lex->sp_variable_declarations_rowtype_finalize(
+ thd, $1, $5, $6.expr, $6.expr_str)))
MYSQL_YYABORT;
$$.init_using_vars($1);
}
@@ -18222,12 +18330,23 @@ sp_decl_body:
Lex->sp_block_init(thd);
}
opt_parenthesized_cursor_formal_parameters
- FOR_SYM sp_cursor_stmt
+ FOR_SYM remember_name sp_cursor_stmt remember_end
{
sp_pcontext *param_ctx= Lex->spcont;
+ LEX_CSTRING expr_str= empty_clex_str;
+
if (unlikely(Lex->sp_block_finalize(thd)))
MYSQL_YYABORT;
- if (unlikely(Lex->sp_declare_cursor(thd, &$1, $6, param_ctx, true)))
+
+ if (Lex->is_metadata_used())
+ {
+ expr_str= make_string(thd, $6, $8);
+ if (expr_str.str == nullptr)
+ MYSQL_YYABORT;
+ }
+
+ if (unlikely(Lex->sp_declare_cursor(thd, &$1, $7, param_ctx, true,
+ expr_str)))
MYSQL_YYABORT;
$$.vars= $$.conds= $$.hndlrs= 0;
$$.curs= 1;
@@ -18453,9 +18572,33 @@ remember_end_opt:
;
sp_opt_default:
- _empty { $$ = NULL; }
- | DEFAULT expr { $$ = $2; }
- | SET_VAR expr { $$ = $2; }
+ _empty { $$= { nullptr, empty_clex_str}; }
+ | DEFAULT remember_name expr remember_end
+ {
+ LEX_CSTRING expr_str= empty_clex_str;
+
+ if (Lex->is_metadata_used())
+ {
+ expr_str= make_string(thd, $2, $4);
+ if (expr_str.str == nullptr)
+ MYSQL_YYABORT;
+ }
+
+ $$= { $3, expr_str };
+ }
+ | SET_VAR remember_name expr remember_end
+ {
+ LEX_CSTRING expr_str= empty_clex_str;
+
+ if (Lex->is_metadata_used())
+ {
+ expr_str= make_string(thd, $2, $4 );
+ if (expr_str.str == nullptr)
+ MYSQL_YYABORT;
+ }
+
+ $$= { $3, expr_str };
+ }
;
sp_opt_inout:
@@ -18556,11 +18699,20 @@ set_assign:
if (sp_create_assignment_lex(thd, $1.pos()))
MYSQL_YYABORT;
}
- set_expr_or_default
+ remember_name set_expr_or_default remember_end
{
Lex_ident_sys tmp(thd, &$1);
+ LEX_CSTRING expr_str= empty_clex_str;
+
+ if (Lex->is_metadata_used())
+ {
+ expr_str= make_string(thd, $4, $6);
+ if (expr_str.str == nullptr)
+ MYSQL_YYABORT;
+ }
+
if (unlikely(!tmp.str) ||
- unlikely(Lex->set_variable(&tmp, $4)) ||
+ unlikely(Lex->set_variable(&tmp, $5, expr_str)) ||
unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY,
false)))
MYSQL_YYABORT;
@@ -18572,13 +18724,22 @@ set_assign:
if (sp_create_assignment_lex(thd, $1.pos()))
MYSQL_YYABORT;
}
- set_expr_or_default
+ remember_name set_expr_or_default remember_end
{
LEX *lex= Lex;
DBUG_ASSERT(lex->var_list.is_empty());
Lex_ident_sys tmp(thd, &$1);
+ LEX_CSTRING expr_str= empty_clex_str;
+
+ if (Lex->is_metadata_used())
+ {
+ expr_str= make_string(thd, $6, $8);
+ if (expr_str.str == nullptr)
+ MYSQL_YYABORT;
+ }
+
if (unlikely(!tmp.str) ||
- unlikely(lex->set_variable(&tmp, &$3, $6)) ||
+ unlikely(lex->set_variable(&tmp, &$3, $7, expr_str)) ||
unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY,
false)))
MYSQL_YYABORT;
@@ -18595,10 +18756,19 @@ set_assign:
if (sp_create_assignment_lex(thd, $1.pos()))
MYSQL_YYABORT;
}
- set_expr_or_default
+ remember_name set_expr_or_default remember_end
{
LEX_CSTRING tmp= { $2.str, $2.length };
- if (unlikely(Lex->set_trigger_field(&tmp, &$4, $7)) ||
+ LEX_CSTRING expr_str= empty_clex_str;
+
+ if (Lex->is_metadata_used())
+ {
+ expr_str= make_string(thd, $7, $9);
+ if (expr_str.str == nullptr)
+ MYSQL_YYABORT;
+ }
+
+ if (unlikely(Lex->set_trigger_field(&tmp, &$4, $8, expr_str)) ||
unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY,
false)))
MYSQL_YYABORT;
@@ -18921,7 +19091,8 @@ sp_decl_variable_list_anchored:
optionally_qualified_column_ident PERCENT_ORACLE_SYM TYPE_SYM
sp_opt_default
{
- if (unlikely(Lex->sp_variable_declarations_with_ref_finalize(thd, $1, $2, $5)))
+ if (unlikely(Lex->sp_variable_declarations_with_ref_finalize(thd, $1, $2,
+ $5.expr, $5.expr_str)))
MYSQL_YYABORT;
$$.init_using_vars($1);
}
@@ -18929,7 +19100,8 @@ sp_decl_variable_list_anchored:
optionally_qualified_column_ident PERCENT_ORACLE_SYM ROWTYPE_ORACLE_SYM
sp_opt_default
{
- if (unlikely(Lex->sp_variable_declarations_rowtype_finalize(thd, $1, $2, $5)))
+ if (unlikely(Lex->sp_variable_declarations_rowtype_finalize(thd, $1,
+ $2, $5.expr, $5.expr_str)))
MYSQL_YYABORT;
$$.init_using_vars($1);
}
@@ -19139,14 +19311,24 @@ opt_sp_decl_body_list:
;
sp_decl_body_list:
- sp_decl_non_handler_list
+ remember_name sp_decl_non_handler_list remember_end
{
- if (unlikely(Lex->sphead->sp_add_instr_cpush_for_cursors(thd, Lex->spcont)))
+ LEX_CSTRING expr_str= empty_clex_str;
+
+ if (Lex->is_metadata_used())
+ {
+ expr_str= make_string(thd, $1, $3);
+ if (expr_str.str == nullptr)
+ MYSQL_YYABORT;
+ }
+
+ if (unlikely(Lex->sphead->sp_add_instr_cpush_for_cursors(
+ thd, Lex->spcont, expr_str)))
MYSQL_YYABORT;
}
opt_sp_decl_handler_list
{
- $$.join($1, $3);
+ $$.join($2, $5);
}
| sp_decl_handler_list
;
@@ -19196,12 +19378,23 @@ sp_decl_non_handler:
Lex->sp_block_init(thd);
}
opt_parenthesized_cursor_formal_parameters
- IS sp_cursor_stmt
+ IS remember_name sp_cursor_stmt remember_end
{
sp_pcontext *param_ctx= Lex->spcont;
+ LEX_CSTRING expr_str= empty_clex_str;
+
if (unlikely(Lex->sp_block_finalize(thd)))
MYSQL_YYABORT;
- if (unlikely(Lex->sp_declare_cursor(thd, &$2, $6, param_ctx, false)))
+
+ if (Lex->is_metadata_used())
+ {
+ expr_str= make_string(thd, $6, $8);
+ if (expr_str.str == nullptr)
+ MYSQL_YYABORT;
+ }
+
+ if (unlikely(Lex->sp_declare_cursor(thd, &$2, $7, param_ctx, false,
+ expr_str)))
MYSQL_YYABORT;
$$.vars= $$.conds= $$.hndlrs= 0;
$$.curs= 1;