summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Shulga <dmitry.shulga@mariadb.com>2022-12-22 13:25:22 +0700
committerDmitry Shulga <dmitry.shulga@mariadb.com>2022-12-22 13:25:22 +0700
commit5ebff75946ef6d43d154f8f0b1644f6a537ec17d (patch)
tree7d8c8d1194b9189fa529ade48245f1270f8019bf
parent4669fe5fa4634edd29ac9a9f308f3c71f018e4a2 (diff)
downloadmariadb-git-5ebff75946ef6d43d154f8f0b1644f6a537ec17d.tar.gz
MDEV-5816: Stored programs: validation of stored program statements
For those SP instructions that need to get access to LEX object on execution, added storing of their original sql expressions inside 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 derived classes. Since an expression constituting a SP instruction could be non valid SQL statement in general case (not parseable statement), the virtual method sp_lex_instr::get_query() has been introduced to return a valid string for a statement that corresponds to the given instruction. Additionally, introduced the rule remember_start_opt in the grammar. The new rule intended to get correct position of a current token taking into attention the fact whether lookahead was done or not.
-rw-r--r--sql/sp.cc4
-rw-r--r--sql/sp.h5
-rw-r--r--sql/sp_head.cc25
-rw-r--r--sql/sp_head.h15
-rw-r--r--sql/sp_instr.cc21
-rw-r--r--sql/sp_instr.h164
-rw-r--r--sql/sql_class.cc8
-rw-r--r--sql/sql_class.h16
-rw-r--r--sql/sql_lex.cc177
-rw-r--r--sql/sql_lex.h98
-rw-r--r--sql/sql_yacc.yy253
11 files changed, 594 insertions, 192 deletions
diff --git a/sql/sp.cc b/sql/sp.cc
index 6cfe1045b0c..eff9a78b80b 100644
--- a/sql/sp.cc
+++ b/sql/sp.cc
@@ -65,7 +65,7 @@ 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, sp_expr_lex *lex) const
{
my_error(ER_SP_BADRETURN, MYF(0));
return true;
@@ -82,7 +82,7 @@ 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, sp_expr_lex *lex) const
{
return sp->add_instr_freturn(thd, spcont, item, lex);
}
diff --git a/sql/sp.h b/sql/sp.h
index 0b79877a3e1..30b59d1d33c 100644
--- a/sql/sp.h
+++ b/sql/sp.h
@@ -35,6 +35,7 @@ class sp_head;
class sp_package;
class sp_pcontext;
class sp_name;
+class sp_expr_lex;
class Database_qualified_name;
struct st_sp_chistics;
class Stored_program_creation_ctx;
@@ -185,7 +186,7 @@ public:
}
virtual bool add_instr_freturn(THD *thd, sp_head *sp,
sp_pcontext *spcont,
- Item *item, LEX *lex) const;
+ Item *item, sp_expr_lex *lex) 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, sp_expr_lex *lex) const;
};
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index ffcedaea315..9c847845c05 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -3077,11 +3077,11 @@ 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, sp_expr_lex *lex)
{
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);
if (i == NULL || add_instr(i))
return true;
m_flags|= sp_head::HAS_RETURN;
@@ -3594,7 +3594,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,
+ const LEX_CSTRING &value_query)
{
if (!(val= adjust_assignment_source(thd, val, spv->default_value)))
return true;
@@ -3605,7 +3606,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);
}
@@ -3619,7 +3621,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,
+ const LEX_CSTRING &value_query)
{
if (!(val= adjust_assignment_source(thd, val, NULL)))
return true;
@@ -3629,7 +3632,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);
}
@@ -3639,7 +3643,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,
+ const LEX_CSTRING &value_query)
{
if (!(val= adjust_assignment_source(thd, val, NULL)))
return true;
@@ -3650,7 +3655,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);
}
@@ -3729,7 +3735,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 2be7312fe7a..42966389018 100644
--- a/sql/sp_head.h
+++ b/sql/sp_head.h
@@ -392,7 +392,8 @@ public:
}
bool
- add_instr_freturn(THD *thd, sp_pcontext *spcont, Item *item, LEX *lex);
+ add_instr_freturn(THD *thd, sp_pcontext *spcont, Item *item,
+ sp_expr_lex *lex);
bool
add_instr_preturn(THD *thd, sp_pcontext *spcont);
@@ -412,16 +413,19 @@ public:
bool set_local_variable(THD *thd, sp_pcontext *spcont,
const Sp_rcontext_handler *rh,
sp_variable *spv, Item *val, LEX *lex,
- bool responsible_to_free_lex);
+ bool responsible_to_free_lex,
+ const LEX_CSTRING &value_query);
bool set_local_variable_row_field(THD *thd, sp_pcontext *spcont,
const Sp_rcontext_handler *rh,
sp_variable *spv, uint field_idx,
- Item *val, LEX *lex);
+ Item *val, LEX *lex,
+ const LEX_CSTRING &value_query);
bool set_local_variable_row_field_by_name(THD *thd, sp_pcontext *spcont,
const Sp_rcontext_handler *rh,
sp_variable *spv,
const LEX_CSTRING *field_name,
- Item *val, LEX *lex);
+ Item *val, LEX *lex,
+ const LEX_CSTRING &value_query);
bool check_package_routine_end_name(const LEX_CSTRING &end_name) const;
bool check_standalone_routine_end_name(const sp_name *end_name) const;
bool check_group_aggregate_instructions_function() const;
@@ -451,7 +455,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:
diff --git a/sql/sp_instr.cc b/sql/sp_instr.cc
index 684322e3552..489350f4436 100644
--- a/sql/sp_instr.cc
+++ b/sql/sp_instr.cc
@@ -419,6 +419,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
*/
diff --git a/sql/sp_instr.h b/sql/sp_instr.h
index b307d1a014d..0c5a966f18f 100644
--- a/sql/sp_instr.h
+++ b/sql/sp_instr.h
@@ -18,12 +18,14 @@ class sp_lex_cursor: public sp_lex_local, public Query_arena
public:
sp_lex_cursor(THD *thd, const LEX *oldlex, MEM_ROOT *mem_root_arg)
:sp_lex_local(thd, oldlex),
- Query_arena(mem_root_arg, STMT_INITIALIZED_FOR_SP)
+ Query_arena(mem_root_arg, STMT_INITIALIZED_FOR_SP),
+ m_expr_str(empty_clex_str)
{ }
//sp_lex_cursor(THD *thd, const LEX *oldlex);
sp_lex_cursor(THD *thd, const LEX *oldlex)
- :sp_lex_local(thd, oldlex),
- Query_arena(thd->lex->sphead->get_main_mem_root(), STMT_INITIALIZED_FOR_SP)
+ :sp_lex_local(thd, oldlex),
+ Query_arena(thd->lex->sphead->get_main_mem_root(), STMT_INITIALIZED_FOR_SP),
+ m_expr_str(empty_clex_str)
{}
~sp_lex_cursor()
{
@@ -51,6 +53,19 @@ public:
thd->free_list= nullptr;
return false;
}
+
+ void set_expr_str(const LEX_CSTRING &expr_str)
+ {
+ m_expr_str= expr_str;
+ }
+
+ const LEX_CSTRING &get_expr_str() const
+ {
+ return m_expr_str;
+ }
+
+private:
+ LEX_CSTRING m_expr_str;
};
@@ -287,7 +302,21 @@ public:
virtual void invalidate() = 0;
+ /**
+ Return the query string, which can be passed to the parser,
+ that is a valid SQL-statement.
+
+ @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't be passed directly
+ to the parser as it is most likely not a valid SQL-statement.
+ */
+ virtual LEX_CSTRING get_expr_query() const = 0;
+
sp_lex_keeper m_lex_keeper;
};
@@ -307,17 +336,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, const 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;
@@ -335,6 +360,17 @@ public:
m_valid= false;
}
+ void get_query(String *sql_query) const override
+ {
+ sql_query->append(get_expr_query());
+ }
+
+protected:
+ LEX_CSTRING get_expr_query() const override
+ {
+ return LEX_CSTRING{m_query.str, m_query.length};
+ }
+
public:
PSI_statement_info* get_psi_info() override { return & psi_info; }
static PSI_statement_info psi_info;
@@ -352,9 +388,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, const 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;
@@ -374,11 +411,19 @@ public:
}
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;
+private:
+ LEX_CSTRING m_expr_str;
+
public:
PSI_statement_info* get_psi_info() override { return & psi_info; }
static PSI_statement_info psi_info;
@@ -403,8 +448,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,
+ const LEX_CSTRING &value_query)
+ : sp_instr_set(ip, ctx, rh, offset, val, lex, lex_resp, value_query),
m_field_offset(field_offset)
{}
@@ -444,8 +490,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,
+ const LEX_CSTRING &value_query)
+ : sp_instr_set(ip, ctx, rh, offset, val, lex, lex_resp, value_query),
m_field_name(field_name)
{}
@@ -468,10 +515,12 @@ public:
sp_instr_set_trigger_field(uint ip, sp_pcontext *ctx,
Item_trigger_field *trg_fld,
- Item *val, LEX *lex)
+ Item *val, LEX *lex,
+ const 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;
@@ -490,9 +539,19 @@ public:
value= nullptr;
}
+protected:
+ LEX_CSTRING get_expr_query() const override
+ {
+ return m_expr_str;
+ }
+
private:
Item_trigger_field *trigger_field;
Item *value;
+ /**
+ SQL clause corresponding to the expression value.
+ */
+ LEX_CSTRING m_expr_str;
public:
PSI_statement_info* get_psi_info() override { return & psi_info; }
@@ -593,16 +652,18 @@ class sp_instr_jump_if_not : public sp_lex_instr, public sp_instr_opt_meta
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,
+ const LEX_CSTRING &expr_query)
: sp_lex_instr(ip, ctx, lex, true),
sp_instr_opt_meta(0),
- 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,
+ const LEX_CSTRING &expr_query)
: sp_lex_instr(ip, ctx, lex, true),
sp_instr_opt_meta(dest),
- m_expr(i)
+ m_expr(i), m_expr_str(expr_query)
{}
int execute(THD *thd, uint *nextp) override;
@@ -651,10 +712,20 @@ public:
m_expr= nullptr;
}
+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;
public:
PSI_statement_info* get_psi_info() override { return & psi_info; }
static PSI_statement_info psi_info;
@@ -696,9 +767,10 @@ 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, sp_expr_lex *lex)
: sp_lex_instr(ip, ctx, lex, true),
- m_value(val), m_type_handler(handler)
+ m_value(val), m_type_handler(handler),
+ m_expr_str(lex->get_expr_str())
{}
int execute(THD *thd, uint *nextp) override;
@@ -715,6 +787,11 @@ public:
protected:
+ LEX_CSTRING get_expr_query() const override
+ {
+ return m_expr_str;
+ }
+
Item *m_value;
const Type_handler *m_type_handler;
@@ -727,6 +804,13 @@ protected:
{
m_value= nullptr;
}
+
+private:
+ /**
+ SQL-query corresponding to the RETURN-expression.
+ */
+ LEX_CSTRING m_expr_str;
+
public:
PSI_statement_info* get_psi_info() override { return & psi_info; }
static PSI_statement_info psi_info;
@@ -914,6 +998,16 @@ public:
return &m_lex_keeper;
}
+ void get_query(String *sql_query) const override
+ {
+ sql_query->append(get_expr_query());
+ }
+
+protected:
+ LEX_CSTRING get_expr_query() const override
+ {
+ return empty_clex_str;
+ }
private:
uint m_cursor; /**< Frame offset (for debugging) */
@@ -922,6 +1016,7 @@ private:
on depending database objects used in the statement.
*/
bool m_metadata_changed;
+
public:
PSI_statement_info* get_psi_info() override { return & psi_info; }
static PSI_statement_info psi_info;
@@ -1024,6 +1119,12 @@ public:
m_valid= true;
}
+protected:
+ LEX_CSTRING get_expr_query() const override
+ {
+ return empty_clex_str;
+ }
+
public:
PSI_statement_info* get_psi_info() override { return & psi_info; }
static PSI_statement_info psi_info;
@@ -1152,9 +1253,11 @@ class sp_instr_set_case_expr : public sp_lex_instr, public sp_instr_opt_meta
public:
sp_instr_set_case_expr(uint ip, sp_pcontext *ctx, uint case_expr_id,
- Item *case_expr, LEX *lex)
+ Item *case_expr, LEX *lex,
+ const LEX_CSTRING &case_expr_query)
: sp_lex_instr(ip, ctx, lex, true), sp_instr_opt_meta(0),
- 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;
@@ -1188,10 +1291,17 @@ public:
m_case_expr= nullptr;
}
+protected:
+ LEX_CSTRING get_expr_query() const override
+ {
+ return m_expr_str;
+ }
+
private:
uint m_case_expr_id;
Item *m_case_expr;
+ LEX_CSTRING m_expr_str;
public:
PSI_statement_info* get_psi_info() override { return & psi_info; }
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index d85de205836..71e88e2e8b0 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -8382,3 +8382,11 @@ void Charset_loader_server::raise_not_applicable_error(const char *cs,
{
my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0), cl, cs);
}
+
+
+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 b5bdb874e44..22866399da3 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -7952,5 +7952,21 @@ public:
}
};
+
+/**
+ 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 295151373e1..f59defd05a4 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -77,7 +77,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);
@@ -111,10 +111,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
@@ -207,7 +209,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,
+ const LEX_CSTRING &expr_str)
{
Item_trigger_field *trg_fld;
sp_instr_set_trigger_field *sp_fld;
@@ -230,7 +233,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;
@@ -420,6 +423,7 @@ bool sp_create_assignment_lex(THD *thd, const char *pos)
@param thd - Thread context
@param no_lookahead - True if the parser has no lookahead
+ @param rhs_value_str - a string value for right hand side of assignment
@param need_set_keyword - if a SET statement "SET a=10",
or a direct assignment overwise "a:=10"
@return false if success, true otherwise.
@@ -6483,7 +6487,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,
+ const LEX_CSTRING &expr_str)
{
bool has_default_clause= dflt_value_item != NULL;
if (!has_default_clause &&
@@ -6519,7 +6524,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;
}
@@ -6531,7 +6536,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,
+ const LEX_CSTRING &expr_str)
{
for (uint i= 0 ; i < (uint) nvars; i++)
{
@@ -6545,7 +6551,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);
@@ -6554,20 +6560,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,
+ const 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,
+ const LEX_CSTRING &expr_str)
{
DBUG_ASSERT(row);
/*
@@ -6593,7 +6601,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);
@@ -6612,7 +6621,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,
+ const LEX_CSTRING &expr_str)
{
uint coffp;
const sp_pcursor *pcursor= ref->table.str && ref->db.str ? NULL :
@@ -6620,7 +6630,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),
@@ -6635,7 +6646,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);
}
@@ -6643,7 +6654,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,
+ const LEX_CSTRING &expr_str)
{
Table_ident *table_ref;
if (unlikely(!(table_ref=
@@ -6656,7 +6668,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;
@@ -6668,7 +6680,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,
+ const LEX_CSTRING &expr_str)
{
const sp_pcursor *pcursor= spcont->find_cursor(offset);
@@ -6688,7 +6701,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;
@@ -6706,18 +6720,22 @@ 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,
+ const 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,
+ const LEX_CSTRING &expr_str)
{
for (uint i= 0 ; i < (uint) nvars; i++)
{
@@ -6726,7 +6744,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);
@@ -6736,7 +6754,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,
+ const LEX_CSTRING &expr_str)
{
sp_variable *t;
if (!spcont || !(t= spcont->find_variable(&ref, false)))
@@ -6750,14 +6769,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())
@@ -6766,7 +6787,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
@@ -6774,7 +6796,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);
}
@@ -6803,7 +6826,8 @@ 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,
+ const LEX_CSTRING &expr_str)
{
sp_variable *spvar= spcont->add_variable(thd, name);
spcont->declare_var_boundary(1);
@@ -6819,7 +6843,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);
@@ -6918,7 +6942,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));
}
@@ -6950,7 +6975,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);
}
@@ -6975,13 +7000,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;
@@ -7074,7 +7104,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;
}
@@ -7133,6 +7164,7 @@ 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)
+
{
uint offp;
sp_instr_cpush *i;
@@ -7582,7 +7614,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)
@@ -7650,7 +7682,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,
+ const LEX_CSTRING &expr_str)
{
if (!when)
return sp_exit_block(thd, lab);
@@ -7660,7 +7693,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)))
@@ -7670,7 +7703,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, const LEX_CSTRING &expr_str)
{
sp_label *lab= spcont->find_label_current_loop_start();
if (unlikely(!lab))
@@ -7679,11 +7712,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, const LEX_CSTRING &expr_str)
{
sp_label *lab= spcont->find_label(label_name);
if (unlikely(!lab || lab->type != sp_label::ITERATION))
@@ -7691,7 +7725,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);
}
@@ -7748,7 +7782,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,
+ const LEX_CSTRING &expr_str)
{
DBUG_ASSERT(when);
DBUG_ASSERT(sphead == thd->lex->sphead);
@@ -7756,7 +7791,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)))
@@ -7775,7 +7810,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);
}
@@ -7788,7 +7823,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);
}
@@ -7853,10 +7888,11 @@ 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,
+ const 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())) ||
@@ -8481,12 +8517,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,
+ const 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);
}
@@ -8497,7 +8535,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, const LEX_CSTRING &expr_str)
{
const Sp_rcontext_handler *rh;
sp_pcontext *ctx;
@@ -8509,17 +8547,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);
}
@@ -8576,7 +8615,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, const LEX_CSTRING &expr_str)
{
DBUG_ASSERT(is_trigger_new_or_old_reference(name1));
if (unlikely(name1->str[0]=='O' || name1->str[0]=='o'))
@@ -8594,7 +8633,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);
}
@@ -10544,7 +10583,14 @@ bool SELECT_LEX::make_unique_derived_name(THD *thd, LEX_CSTRING *alias)
/*
Make a new sp_instr_stmt and set its m_query to a concatenation
of two strings.
+
+ @param thd Thread context
+ @param prefix the first part of a concatenated string value
+ @param suffix the second part of a concatenated string value
+
+ @return false on success, else return true
*/
+
bool LEX::new_sp_instr_stmt(THD *thd,
const LEX_CSTRING &prefix,
const LEX_CSTRING &suffix)
@@ -10552,17 +10598,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);
}
@@ -11632,7 +11678,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;
@@ -11646,7 +11692,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 9d4dd02759c..ad2d7644424 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,
+ const 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,
+ const LEX_CSTRING &expr_str);
public:
void parse_error(uint err_number= ER_SYNTAX_ERROR);
@@ -3829,9 +3831,10 @@ public:
bool set_names(const char *pos,
const Lex_exact_charset_opt_extended_collate &cs,
bool no_lookahead);
- bool set_trigger_new_row(const LEX_CSTRING *name, Item *val);
+ bool set_trigger_new_row(const LEX_CSTRING *name, Item *val,
+ const LEX_CSTRING &expr_str);
bool set_trigger_field(const LEX_CSTRING *name1, const LEX_CSTRING *name2,
- Item *val);
+ Item *val, const 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,
@@ -3887,40 +3890,52 @@ 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,
+ const 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,
+ const 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,
+ const LEX_CSTRING &expr_str);
+ bool sp_variable_declarations_set_default(THD *thd, int nvars, Item *def,
+ const LEX_CSTRING &expr_str);
bool sp_variable_declarations_row_finalize(THD *thd, int nvars,
Row_definition_list *row,
- Item *def);
+ Item *def,
+ const LEX_CSTRING &expr_str);
bool sp_variable_declarations_with_ref_finalize(THD *thd, int nvars,
Qualified_column_ident *col,
- Item *def);
+ Item *def,
+ const LEX_CSTRING &expr_str);
bool sp_variable_declarations_rowtype_finalize(THD *thd, int nvars,
Qualified_column_ident *,
- Item *def);
+ Item *def,
+ const LEX_CSTRING &expr_str);
bool sp_variable_declarations_cursor_rowtype_finalize(THD *thd, int nvars,
uint offset,
- Item *def);
+ Item *def,
+ const 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,
+ const LEX_CSTRING &expr_str);
bool sp_variable_declarations_column_type_finalize(THD *thd, int nvars,
Qualified_column_ident *ref,
- Item *def);
+ Item *def,
+ const LEX_CSTRING &expr_str);
bool sp_variable_declarations_vartype_finalize(THD *thd, int nvars,
const LEX_CSTRING &name,
- Item *def);
+ Item *def,
+ const 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,
+ const LEX_CSTRING &expr_str);
LEX_USER *current_user_for_set_password(THD *thd);
bool sp_create_set_password_instr(THD *thd,
@@ -4211,8 +4226,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, const LEX_CSTRING &expr_str);
+ bool sp_exit_statement(THD *thd, const LEX_CSTRING *label_name, Item *item,
+ const 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);
@@ -4225,7 +4241,8 @@ 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,
+ const 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);
@@ -4235,11 +4252,13 @@ 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,
+ const LEX_CSTRING &expr_str);
+ sp_variable *sp_add_for_loop_target_bound(THD *thd, Item *value,
+ const 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,
@@ -4834,6 +4853,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;
+ }
};
@@ -5060,10 +5088,12 @@ 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(nullptr),
+ m_expr_str(empty_clex_str)
{ }
void set_item(Item *item)
{
@@ -5079,10 +5109,18 @@ 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);
+ void set_expr_str(const LEX_CSTRING &expr_str)
+ {
+ m_expr_str= expr_str;
+ }
+ const LEX_CSTRING &get_expr_str() const
+ {
+ return m_expr_str;
+ }
};
@@ -5113,11 +5151,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(nullptr),
+ m_expr_str(empty_clex_str)
{ }
void set_item_and_free_list(Item *item, Item *free_list)
{
@@ -5132,6 +5172,14 @@ public:
{
return m_free_list;
}
+ void set_expr_str(const LEX_CSTRING &expr_str)
+ {
+ m_expr_str= expr_str;
+ }
+ const LEX_CSTRING &get_expr_str() const
+ {
+ return m_expr_str;
+ }
};
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index a6363f321ad..88fb22f252d 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -330,6 +330,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;
+ } expr_and_query_str;
}
%{
@@ -1359,7 +1364,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%type <simple_string>
remember_name remember_end
remember_tok_start
+ remember_cpp_ptr
wild_and_where
+ remember_start_opt
%type <const_simple_string>
field_length_str
@@ -1483,9 +1490,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
table_wild simple_expr column_default_non_parenthesized_expr udf_expr
primary_expr string_factor_expr mysql_concatenation_expr
select_sublist_qualified_asterisk
- expr_or_ignore expr_or_ignore_or_default set_expr_or_default
+ expr_or_ignore expr_or_ignore_or_default
signed_literal expr_or_literal
- sp_opt_default
simple_ident_nospvar
field_or_var limit_option
part_func_expr
@@ -1505,6 +1511,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
simple_target_specification
condition_number
opt_versioning_interval_start
+ set_expr_misc
%type <num> opt_vers_auto_part
@@ -1529,6 +1536,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%type <expr_lex>
expr_lex
+%type <expr_and_query_str> sp_opt_default set_expr_or_default
+
%type <assignment_lex>
assignment_source_lex
assignment_source_expr
@@ -3200,7 +3209,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);
}
@@ -3208,7 +3218,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);
}
@@ -3253,13 +3265,23 @@ sp_cursor_stmt:
if (Lex->main_select_push(true))
MYSQL_YYABORT;
}
- select
+ remember_name select remember_end
{
DBUG_ASSERT(Lex == $1);
Lex->pop_select(); //main select
- if (unlikely($1->stmt_finalize(thd)) ||
- unlikely($1->sphead->restore_lex(thd)))
+ if (unlikely($1->stmt_finalize(thd)))
+ MYSQL_YYABORT;
+ if (Lex->is_metadata_used())
+ {
+ LEX_CSTRING expr_str= make_string(thd, $3, $5);
+
+ if (expr_str.str == nullptr)
+ MYSQL_YYABORT;
+ $1->set_expr_str(expr_str);
+ }
+ if (unlikely($1->sphead->restore_lex(thd)))
MYSQL_YYABORT;
+
$$= $1;
}
;
@@ -3753,22 +3775,25 @@ 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, nullptr, 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, nullptr,
+ 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(),
+ $3->get_expr_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(),
+ $4->get_expr_str())))
MYSQL_YYABORT;
}
;
@@ -3832,11 +3857,21 @@ expr_lex:
if (Lex->main_select_push(true))
MYSQL_YYABORT;
}
- expr
+ remember_start_opt expr remember_end
{
$$= $<expr_lex>1;
$$->sp_lex_in_use= true;
- $$->set_item($2);
+ $$->set_item($3);
+
+ if (Lex->is_metadata_used())
+ {
+ LEX_CSTRING expr_str= make_string(thd, $2, $4);
+
+ if (expr_str.str == nullptr)
+ MYSQL_YYABORT;
+ $$->set_expr_str(expr_str);
+ }
+
Lex->pop_select(); //min select
if (Lex->check_cte_dependencies_and_resolve_references())
MYSQL_YYABORT;
@@ -3863,12 +3898,22 @@ assignment_source_expr:
if (Lex->main_select_push(true))
MYSQL_YYABORT;
}
- expr
+ remember_cpp_ptr 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))
@@ -3884,12 +3929,22 @@ for_loop_bound_expr:
MYSQL_YYABORT;
Lex->current_select->parsing_place= FOR_LOOP_BOUND;
}
- expr
+ remember_cpp_ptr 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;
@@ -9010,6 +9065,21 @@ remember_end:
}
;
+remember_cpp_ptr:
+ {
+ $$= (char*) YYLIP->get_cpp_ptr();
+ }
+ ;
+
+remember_start_opt:
+ {
+ if (yychar == YYEMPTY)
+ $$= (char*) YYLIP->get_cpp_ptr();
+ else
+ $$= (char*) YYLIP->get_cpp_tok_start();
+ }
+ ;
+
select_alias:
/* empty */ { $$=null_clex_str;}
| AS ident { $$=$2; }
@@ -16446,7 +16516,8 @@ set_stmt_option:
{
Lex_ident_sys tmp(thd, &$1);
if (unlikely(!tmp.str) ||
- unlikely(Lex->set_system_variable(Lex->option_type, &tmp, $4)))
+ unlikely(Lex->set_system_variable(Lex->option_type, &tmp,
+ $4.expr)))
MYSQL_YYABORT;
Lex->pop_select(); //min select
}
@@ -16460,7 +16531,7 @@ set_stmt_option:
Lex_ident_sys tmp(thd, &$1);
if (unlikely(!tmp.str) ||
unlikely(Lex->set_system_variable(thd, Lex->option_type,
- &tmp, &$3, $6)))
+ &tmp, &$3, $6.expr)))
MYSQL_YYABORT;
Lex->pop_select(); //min select
}
@@ -16472,7 +16543,7 @@ set_stmt_option:
set_expr_or_default
{
if (unlikely(Lex->set_default_system_variable(Lex->option_type,
- &$3, $6)))
+ &$3, $6.expr)))
MYSQL_YYABORT;
Lex->pop_select(); //min select
}
@@ -16490,7 +16561,8 @@ option_value_following_option_type:
{
Lex_ident_sys tmp(thd, &$1);
if (unlikely(!tmp.str) ||
- unlikely(Lex->set_system_variable(Lex->option_type, &tmp, $4)) ||
+ unlikely(Lex->set_system_variable(Lex->option_type, &tmp,
+ $4.expr)) ||
unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
@@ -16503,7 +16575,8 @@ option_value_following_option_type:
{
Lex_ident_sys tmp(thd, &$1);
if (unlikely(!tmp.str) ||
- unlikely(Lex->set_system_variable(thd, Lex->option_type, &tmp, &$3, $6)) ||
+ unlikely(Lex->set_system_variable(thd, Lex->option_type, &tmp,
+ &$3, $6.expr)) ||
unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
@@ -16514,7 +16587,8 @@ option_value_following_option_type:
}
set_expr_or_default
{
- if (unlikely(Lex->set_default_system_variable(Lex->option_type, &$3, $6)) ||
+ if (unlikely(Lex->set_default_system_variable(Lex->option_type,
+ &$3, $6.expr)) ||
unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
@@ -16530,8 +16604,9 @@ option_value_no_option_type:
set_expr_or_default
{
Lex_ident_sys tmp(thd, &$1);
+
if (unlikely(!tmp.str) ||
- unlikely(Lex->set_variable(&tmp, $4)) ||
+ unlikely(Lex->set_variable(&tmp, $4.expr, $4.expr_str)) ||
unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
@@ -16543,8 +16618,9 @@ option_value_no_option_type:
set_expr_or_default
{
Lex_ident_sys tmp(thd, &$1);
+
if (unlikely(!tmp.str) ||
- unlikely(Lex->set_variable(&tmp, &$3, $6)) ||
+ unlikely(Lex->set_variable(&tmp, &$3, $6.expr, $6.expr_str)) ||
unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
@@ -16555,7 +16631,8 @@ option_value_no_option_type:
}
set_expr_or_default
{
- if (unlikely(Lex->set_default_system_variable(Lex->option_type, &$3, $6)))
+ if (unlikely(Lex->set_default_system_variable(Lex->option_type,
+ &$3, $6.expr)))
MYSQL_YYABORT;
if (unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
@@ -16571,9 +16648,17 @@ option_value_no_option_type:
if (sp_create_assignment_lex(thd, $1.str))
MYSQL_YYABORT;
}
- expr
+ remember_cpp_ptr expr remember_end
{
- if (unlikely(Lex->set_user_variable(thd, &$2, $5)) ||
+ LEX_CSTRING expr_str= empty_clex_str;
+
+ if (Lex->is_metadata_used())
+ {
+ expr_str= make_string(thd, $5, $7);
+ if (expr_str.str == nullptr)
+ MYSQL_YYABORT;
+ }
+ if (unlikely(Lex->set_user_variable(thd, &$2, $6)) ||
unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
@@ -16584,7 +16669,7 @@ option_value_no_option_type:
}
set_expr_or_default
{
- if (unlikely(Lex->set_system_variable($3, &$4, $7)) ||
+ if (unlikely(Lex->set_system_variable($3, &$4, $7.expr)) ||
unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
@@ -16595,7 +16680,8 @@ option_value_no_option_type:
}
set_expr_or_default
{
- if (unlikely(Lex->set_system_variable(thd, $3, &$4, &$6, $9)) ||
+ if (unlikely(Lex->set_system_variable(thd, $3, &$4, &$6,
+ $9.expr)) ||
unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
@@ -16606,7 +16692,7 @@ option_value_no_option_type:
}
set_expr_or_default
{
- if (unlikely(Lex->set_default_system_variable($3, &$6, $9)) ||
+ if (unlikely(Lex->set_default_system_variable($3, &$6, $9.expr)) ||
unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
@@ -16712,8 +16798,9 @@ option_value_no_option_type:
set_expr_or_default
{
Lex_ident_sys tmp(thd, &$1);
+
if (unlikely(!tmp.str) ||
- unlikely(Lex->set_variable(&tmp, $4)) ||
+ unlikely(Lex->set_variable(&tmp, $4.expr, $4.expr_str)) ||
unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
MYSQL_YYABORT;
}
@@ -16820,28 +16907,37 @@ text_or_password:
;
set_expr_or_default:
- expr { $$=$1; }
- | DEFAULT { $$=0; }
- | ON
+ remember_cpp_ptr expr remember_end
{
- $$=new (thd->mem_root) Item_string_sys(thd, "ON", 2);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
+ 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;
+ }
+
+ $$= { $2, expr_str };
}
- | ALL
+ | remember_cpp_ptr set_expr_misc remember_end
{
- $$=new (thd->mem_root) Item_string_sys(thd, "ALL", 3);
- if (unlikely($$ == NULL))
+ if (unlikely($2 == nullptr))
MYSQL_YYABORT;
+ $$= {$2, empty_clex_str};
}
- | BINARY
+ | remember_cpp_ptr DEFAULT remember_end
{
- $$=new (thd->mem_root) Item_string_sys(thd, "binary", 6);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
+ $$= { nullptr, empty_clex_str };
}
;
+set_expr_misc:
+ ON { $$= new (thd->mem_root) Item_string_sys(thd, "ON", 2); }
+ | ALL { $$= new (thd->mem_root) Item_string_sys(thd, "ALL", 3); }
+ | BINARY { $$= new (thd->mem_root) Item_string_sys(thd, "binary", 6); }
+ ;
+
/* Lock function */
lock:
@@ -18131,8 +18227,20 @@ sp_block_label:
;
sp_opt_default:
- _empty { $$ = NULL; }
- | DEFAULT expr { $$ = $2; }
+ _empty { $$= { nullptr, empty_clex_str}; }
+ | DEFAULT remember_cpp_ptr 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_decl_variable_list_anchored:
@@ -18140,7 +18248,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);
}
@@ -18148,7 +18257,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);
}
@@ -18588,9 +18698,33 @@ remember_end_opt:
;
sp_opt_default:
- _empty { $$ = NULL; }
- | DEFAULT expr { $$ = $2; }
- | SET_VAR expr { $$ = $2; }
+ _empty { $$= { nullptr, empty_clex_str}; }
+ | DEFAULT remember_cpp_ptr 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_cpp_ptr 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:
@@ -18654,8 +18788,9 @@ set_assign:
set_expr_or_default
{
Lex_ident_sys tmp(thd, &$1);
+
if (unlikely(!tmp.str) ||
- unlikely(Lex->set_variable(&tmp, $4)) ||
+ unlikely(Lex->set_variable(&tmp, $4.expr, $4.expr_str)) ||
unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY,
false)))
MYSQL_YYABORT;
@@ -18672,8 +18807,9 @@ set_assign:
LEX *lex= Lex;
DBUG_ASSERT(lex->var_list.is_empty());
Lex_ident_sys tmp(thd, &$1);
+
if (unlikely(!tmp.str) ||
- unlikely(lex->set_variable(&tmp, &$3, $6)) ||
+ unlikely(lex->set_variable(&tmp, &$3, $6.expr, $6.expr_str)) ||
unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY,
false)))
MYSQL_YYABORT;
@@ -18693,7 +18829,8 @@ set_assign:
set_expr_or_default
{
LEX_CSTRING tmp= { $2.str, $2.length };
- if (unlikely(Lex->set_trigger_field(&tmp, &$4, $7)) ||
+ if (unlikely(Lex->set_trigger_field(&tmp, &$4, $7.expr,
+ $7.expr_str)) ||
unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY,
false)))
MYSQL_YYABORT;
@@ -19018,7 +19155,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);
}
@@ -19026,7 +19164,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);
}