diff options
-rw-r--r-- | sql/sp.cc | 4 | ||||
-rw-r--r-- | sql/sp.h | 5 | ||||
-rw-r--r-- | sql/sp_head.cc | 25 | ||||
-rw-r--r-- | sql/sp_head.h | 15 | ||||
-rw-r--r-- | sql/sp_instr.cc | 21 | ||||
-rw-r--r-- | sql/sp_instr.h | 164 | ||||
-rw-r--r-- | sql/sql_class.cc | 8 | ||||
-rw-r--r-- | sql/sql_class.h | 16 | ||||
-rw-r--r-- | sql/sql_lex.cc | 177 | ||||
-rw-r--r-- | sql/sql_lex.h | 98 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 253 |
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); } @@ -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, ¬_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); } |