Hello Sanja, Please review a patch for MDEV-15620.
Thanks!
commit 8306aaec113a061e5e1a576ff9f932f9cac1850a Author: Alexander Barkov <b...@mariadb.com> Date: Fri Mar 23 14:23:48 2018 +0400 MDEV-15620 Crash when using "SET @@NEW.a=expr" inside a trigger The problem resided in this branch of the "option_value_no_option_type" rule: | '@' '@' opt_var_ident_type internal_variable_name equal set_expr_or_default Summary: 1. internal_variable_name initialized tmp.var to trg_new_row_fake_var (0x01). 2. The condition "if (tmp.var == NULL)" did not check the special case with trg_new_row_fake_var, so Lex->set_system_variable(&tmp, $3, $6) was called with tmp.var pointing to trg_new_row_fake_var, which created a sys_var instance pointing to 0x01 instead of a real system variable. 3. Later, at the trigger invocation time, this method was called: sys_var::do_deprecated_warning (this=0x1, thd=0x7ffe6c000a98) Notice, "this" is equal to trg_new_row_fake_var (0x01) Solution: The old implementation with separate rules internal_variable_name (in sql_yacc.yy and sql_yacc_ora.yy) and internal_variable_name_directly_assignable (in sql_yacc_ora.yy only) was too complex and hard to follow. Rewriting the code in a more straightforward way. 1. Changing LEX::set_system_variable() from: bool set_system_variable(struct sys_var_with_base *, enum_var_type, Item *); to: bool set_system_variable(enum_var_type, sys_var *, const LEX_CSTRING *, Item *); 2. Adding new methods in LEX, which operate with variable names: bool set_trigger_field(const LEX_CSTRING *, const LEX_CSTRING *, Item *); bool set_system_variable(enum_var_type var_type, const LEX_CSTRING *name, Item *val); bool set_system_variable(THD *thd, enum_var_type var_type, const LEX_CSTRING *name1, const LEX_CSTRING *name2, Item *val); bool set_default_system_variable(enum_var_type var_type, const LEX_CSTRING *name, Item *val); bool set_variable(const LEX_CSTRING *name, Item *item); 3. Changing the grammar to call the new methods directly in option_value_no_option_type, Removing rules internal_variable_name and internal_variable_name_directly_assignable. 4. Removing "struct sys_var_with_base" and trg_new_row_fake_var. Good side effect: - The code in /sql reduced from 314 to 183 lines. - MDEV-15615 Unexpected syntax error instead of "Unknown system variable" ... was also fixed automatically diff --git a/mysql-test/r/parser.result b/mysql-test/r/parser.result index f197fbe..1a65f8f 100644 --- a/mysql-test/r/parser.result +++ b/mysql-test/r/parser.result @@ -1328,3 +1328,19 @@ CREATE TABLE raw (raw int); DROP TABLE raw; CREATE TABLE varchar2 (varchar2 int); DROP TABLE varchar2; +# +# MDEV-15620 Crash when using "SET @@NEW.a=expr" inside a trigger +# +CREATE TABLE t1 (a INT); +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW SET @@NEW.a=0; +ERROR HY000: Unknown structured system variable or ROW routine variable 'NEW' +DROP TABLE t1; +# +# MDEV-15615 Unexpected syntax error instead of "Unknown system variable" inside an SP +# +BEGIN NOT ATOMIC +DECLARE a INT; +SET GLOBAL a=10; +END; +$$ +ERROR HY000: Unknown system variable 'a' diff --git a/mysql-test/r/set_statement.result b/mysql-test/r/set_statement.result index 5bcf825..c34e117 100644 --- a/mysql-test/r/set_statement.result +++ b/mysql-test/r/set_statement.result @@ -881,7 +881,7 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp SET max_error_count=100 FOR INSERT INTO t1 VALUES (1,2); ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'FOR INSERT INTO t1 VALUES (1,2)' at line 1 SET STATEMENT GLOBAL max_error_count=100 FOR INSERT INTO t1 VALUES (1,2); -ERROR HY000: Unknown system variable 'GLOBAL' +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'max_error_count=100 FOR INSERT INTO t1 VALUES (1,2)' at line 1 SET STATEMENT @@global.max_error_count=100 FOR INSERT INTO t1 VALUES (1,2); ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '@@global.max_error_count=100 FOR INSERT INTO t1 VALUES (1,2)' at line 1 '' diff --git a/mysql-test/suite/compat/oracle/r/func_misc.result b/mysql-test/suite/compat/oracle/r/func_misc.result index 0e2ba0c..f285423 100644 --- a/mysql-test/suite/compat/oracle/r/func_misc.result +++ b/mysql-test/suite/compat/oracle/r/func_misc.result @@ -35,7 +35,7 @@ CALL p1('SELECT 1'); Error1: 0 normal, successful completition CALL p1('xxx'); 'Error2: ' || SQLCODE || ' ' || SQLERRM -Error2: 1193 Unknown system variable 'xxx' +Error2: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1 CALL p1('SELECT 1'); 1 1 diff --git a/mysql-test/suite/compat/oracle/r/parser.result b/mysql-test/suite/compat/oracle/r/parser.result new file mode 100644 index 0000000..29588a6 --- /dev/null +++ b/mysql-test/suite/compat/oracle/r/parser.result @@ -0,0 +1,18 @@ +SET sql_mode=ORACLE; +# +# MDEV-15620 Crash when using "SET @@NEW.a=expr" inside a trigger +# +CREATE TABLE t1 (a INT); +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW SET @@NEW.a=0; +ERROR HY000: Unknown structured system variable or ROW routine variable 'NEW' +DROP TABLE t1; +# +# MDEV-15615 Unexpected syntax error instead of "Unknown system variable" inside an SP +# +DECLARE +a INT; +BEGIN +SET GLOBAL a=10; +END; +$$ +ERROR HY000: Unknown system variable 'a' diff --git a/mysql-test/suite/compat/oracle/r/trigger.result b/mysql-test/suite/compat/oracle/r/trigger.result index f77a565..7c24c78 100644 --- a/mysql-test/suite/compat/oracle/r/trigger.result +++ b/mysql-test/suite/compat/oracle/r/trigger.result @@ -1,10 +1,10 @@ set sql_mode=ORACLE; :NEW.a := 1; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'a := 1' at line 1 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ':NEW.a := 1' at line 1 :OLD.a := 1; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'a := 1' at line 1 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ':OLD.a := 1' at line 1 :OLa.a := 1; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'a := 1' at line 1 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ':OLa.a := 1' at line 1 SELECT :NEW.a; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'a' at line 1 SELECT :OLD.a; diff --git a/mysql-test/suite/compat/oracle/t/parser.test b/mysql-test/suite/compat/oracle/t/parser.test new file mode 100644 index 0000000..5aa37c1 --- /dev/null +++ b/mysql-test/suite/compat/oracle/t/parser.test @@ -0,0 +1,24 @@ +SET sql_mode=ORACLE; + +--echo # +--echo # MDEV-15620 Crash when using "SET @@NEW.a=expr" inside a trigger +--echo # + +CREATE TABLE t1 (a INT); +--error ER_UNKNOWN_STRUCTURED_VARIABLE +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW SET @@NEW.a=0; +DROP TABLE t1; + +--echo # +--echo # MDEV-15615 Unexpected syntax error instead of "Unknown system variable" inside an SP +--echo # + +DELIMITER $$; +--error ER_UNKNOWN_SYSTEM_VARIABLE +DECLARE + a INT; +BEGIN + SET GLOBAL a=10; +END; +$$ +DELIMITER ;$$ diff --git a/mysql-test/t/parser.test b/mysql-test/t/parser.test index 98eaa7a..08b6d34 100644 --- a/mysql-test/t/parser.test +++ b/mysql-test/t/parser.test @@ -1349,3 +1349,26 @@ DROP TABLE raw; CREATE TABLE varchar2 (varchar2 int); DROP TABLE varchar2; + + +--echo # +--echo # MDEV-15620 Crash when using "SET @@NEW.a=expr" inside a trigger +--echo # + +CREATE TABLE t1 (a INT); +--error ER_UNKNOWN_STRUCTURED_VARIABLE +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW SET @@NEW.a=0; +DROP TABLE t1; + +--echo # +--echo # MDEV-15615 Unexpected syntax error instead of "Unknown system variable" inside an SP +--echo # + +DELIMITER $$; +--error ER_UNKNOWN_SYSTEM_VARIABLE +BEGIN NOT ATOMIC + DECLARE a INT; + SET GLOBAL a=10; +END; +$$ +DELIMITER ;$$ diff --git a/mysql-test/t/set_statement.test b/mysql-test/t/set_statement.test index 32f56e4..cc36155 100644 --- a/mysql-test/t/set_statement.test +++ b/mysql-test/t/set_statement.test @@ -828,7 +828,7 @@ SET STATEMENT max_error_count=100 INSERT t1 VALUES (1,2); SET STATEMENT FOR INSERT INTO t1 VALUES (1,2); --error ER_PARSE_ERROR SET max_error_count=100 FOR INSERT INTO t1 VALUES (1,2); ---error ER_UNKNOWN_SYSTEM_VARIABLE +--error ER_PARSE_ERROR SET STATEMENT GLOBAL max_error_count=100 FOR INSERT INTO t1 VALUES (1,2); --error ER_PARSE_ERROR SET STATEMENT @@global.max_error_count=100 FOR INSERT INTO t1 VALUES (1,2); diff --git a/sql/set_var.cc b/sql/set_var.cc index 1bdbd4e..bf373dd 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -688,17 +688,6 @@ sys_var *intern_find_sys_var(const char *str, size_t length) } -bool find_sys_var_null_base(THD *thd, struct sys_var_with_base *tmp) -{ - tmp->var= find_sys_var(thd, tmp->base_name.str, tmp->base_name.length); - - if (tmp->var != NULL) - tmp->base_name= null_clex_str; - - return thd->is_error(); -} - - /** Execute update of all variables. diff --git a/sql/set_var.h b/sql/set_var.h index d0143e1..9014a9c 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -393,7 +393,6 @@ SHOW_VAR* enumerate_sys_vars(THD *thd, bool sorted, enum enum_var_type type); int fill_sysvars(THD *thd, TABLE_LIST *tables, COND *cond); sys_var *find_sys_var(THD *thd, const char *str, size_t length=0); -bool find_sys_var_null_base(THD *thd, struct sys_var_with_base *tmp); int sql_set_variables(THD *thd, List<set_var_base> *var_list, bool free); #define SYSVAR_AUTOSIZE(VAR,VAL) \ diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index b169b9e..dcf0b7a 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -41,12 +41,6 @@ void LEX::parse_error(uint err_number) static int lex_one_token(YYSTYPE *yylval, THD *thd); -/* - We are using pointer to this variable for distinguishing between assignment - to NEW row field (when parsing trigger definition) and structured variable. -*/ - -sys_var *trg_new_row_fake_var= (sys_var*) 0x01; /** LEX_STRING constant for null-string to be used in parser and other places. @@ -5253,36 +5247,7 @@ LEX::find_variable(const LEX_CSTRING *name, } -bool LEX::init_internal_variable(struct sys_var_with_base *variable, - const LEX_CSTRING *name) -{ - sp_variable *spv; - const Sp_rcontext_handler *rh; - - /* Best effort lookup for system variable. */ - if (!(spv= find_variable(name, &rh))) - { - struct sys_var_with_base tmp= {NULL, *name}; - - /* Not an SP local variable */ - if (find_sys_var_null_base(thd, &tmp)) - return true; - - *variable= tmp; - return false; - } - - /* - Possibly an SP local variable (or a shadowed sysvar). - Will depend on the context of the SET statement. - */ - variable->var= NULL; - variable->base_name= *name; - return false; -} - - -bool LEX::is_trigger_new_or_old_reference(const LEX_CSTRING *name) +bool LEX::is_trigger_new_or_old_reference(const LEX_CSTRING *name) const { return sphead && sphead->m_handler->type() == TYPE_ENUM_TRIGGER && name->length == 3 && @@ -5291,68 +5256,6 @@ bool LEX::is_trigger_new_or_old_reference(const LEX_CSTRING *name) } -bool LEX::init_internal_variable(struct sys_var_with_base *variable, - const LEX_CSTRING *dbname, - const LEX_CSTRING *name) -{ - if (check_reserved_words(dbname)) - { - my_error(ER_UNKNOWN_STRUCTURED_VARIABLE, MYF(0), - (int) dbname->length, dbname->str); - return true; - } - if (is_trigger_new_or_old_reference(dbname)) - { - if (dbname->str[0]=='O' || dbname->str[0]=='o') - { - my_error(ER_TRG_CANT_CHANGE_ROW, MYF(0), "OLD", ""); - return true; - } - if (trg_chistics.event == TRG_EVENT_DELETE) - { - my_error(ER_TRG_NO_SUCH_ROW_IN_TRG, MYF(0), "NEW", "on DELETE"); - return true; - } - if (trg_chistics.action_time == TRG_ACTION_AFTER) - { - my_error(ER_TRG_CANT_CHANGE_ROW, MYF(0), "NEW", "after "); - return true; - } - /* This special combination will denote field of NEW row */ - variable->var= trg_new_row_fake_var; - variable->base_name= *name; - return false; - } - - sys_var *tmp= find_sys_var_ex(thd, name->str, name->length, true, false); - if (!tmp) - { - my_error(ER_UNKNOWN_STRUCTURED_VARIABLE, MYF(0), - (int) dbname->length, dbname->str); - return true; - } - if (!tmp->is_struct()) - my_error(ER_VARIABLE_IS_NOT_STRUCT, MYF(0), name->str); - variable->var= tmp; - variable->base_name= *dbname; - return false; -} - - -bool LEX::init_default_internal_variable(struct sys_var_with_base *variable, - LEX_CSTRING name) -{ - sys_var *tmp= find_sys_var(thd, name.str, name.length); - if (!tmp) - return true; - if (!tmp->is_struct()) - my_error(ER_VARIABLE_IS_NOT_STRUCT, MYF(0), name.str); - variable->var= tmp; - variable->base_name.str= (char*) "default"; - variable->base_name.length= 7; - return false; -} - void LEX::sp_variable_declarations_init(THD *thd, int nvars) { sp_variable *spvar= spcont->get_last_context_variable(); @@ -6994,38 +6897,6 @@ bool LEX::set_user_variable(THD *thd, const LEX_CSTRING *name, Item *val) } -/* - Perform assignment for a trigger, a system variable, or an SP variable. - "variable" be previously set by init_internal_variable(variable, name). -*/ -bool LEX::set_variable(struct sys_var_with_base *variable, Item *item) -{ - if (variable->var == trg_new_row_fake_var) - { - /* We are in trigger and assigning value to field of new row */ - return set_trigger_new_row(&variable->base_name, item); - } - if (variable->var) - { - /* It is a system variable. */ - return set_system_variable(variable, option_type, item); - } - - /* - spcont and spv should not be NULL, as the variable - was previously checked by init_internal_variable(). - */ - DBUG_ASSERT(spcont); - const Sp_rcontext_handler *rh; - sp_pcontext *ctx; - sp_variable *spv= find_variable(&variable->base_name, &ctx, &rh); - DBUG_ASSERT(spv); - DBUG_ASSERT(ctx); - DBUG_ASSERT(rh); - return sphead->set_local_variable(thd, ctx, rh, spv, item, this, true); -} - - Item *LEX::create_item_ident_nosp(THD *thd, LEX_CSTRING *name) { if (current_select->parsing_place != IN_HAVING || @@ -7084,6 +6955,17 @@ Item *LEX::create_item_ident_sp(THD *thd, LEX_CSTRING *name, } + +bool LEX::set_variable(const LEX_CSTRING *name, Item *item) +{ + 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) : + set_system_variable(option_type, name, item); +} + + /** Generate instructions for: SET x.y= expr; @@ -7111,10 +6993,76 @@ bool LEX::set_variable(const LEX_CSTRING *name1, item, this); } - // A trigger field or a system variable - sys_var_with_base sysvar; - return init_internal_variable(&sysvar, name1, name2) || - set_variable(&sysvar, item); + if (is_trigger_new_or_old_reference(name1)) + return set_trigger_field(name1, name2, item); + + return set_system_variable(thd, option_type, name1, name2, item); +} + + +bool LEX::set_default_system_variable(enum_var_type var_type, + const LEX_CSTRING *name, + Item *val) +{ + static LEX_CSTRING default_base_name= {STRING_WITH_LEN("default")}; + sys_var *var= find_sys_var(thd, name->str, name->length); + if (!var) + return true; + if (!var->is_struct()) + my_error(ER_VARIABLE_IS_NOT_STRUCT, MYF(0), name->str); + return set_system_variable(var_type, var, &default_base_name, val); +} + + +bool LEX::set_system_variable(enum_var_type var_type, + const LEX_CSTRING *name, + Item *val) +{ + sys_var *var= find_sys_var(thd, name->str, name->length); + DBUG_ASSERT(thd->is_error() || var != NULL); + return var ? set_system_variable(var_type, var, &null_clex_str, val) : true; +} + + +bool LEX::set_system_variable(THD *thd, enum_var_type var_type, + const LEX_CSTRING *name1, + const LEX_CSTRING *name2, + Item *val) +{ + sys_var *tmp; + if (check_reserved_words(name1) || + !(tmp= find_sys_var_ex(thd, name2->str, name2->length, true, false))) + { + my_error(ER_UNKNOWN_STRUCTURED_VARIABLE, MYF(0), + (int) name1->length, name1->str); + return true; + } + if (!tmp->is_struct()) + my_error(ER_VARIABLE_IS_NOT_STRUCT, MYF(0), name2->str); + return set_system_variable(var_type, tmp, name1, val); +} + + +bool LEX::set_trigger_field(const LEX_CSTRING *name1, const LEX_CSTRING *name2, + Item *val) +{ + DBUG_ASSERT(is_trigger_new_or_old_reference(name1)); + if (name1->str[0]=='O' || name1->str[0]=='o') + { + my_error(ER_TRG_CANT_CHANGE_ROW, MYF(0), "OLD", ""); + return true; + } + if (trg_chistics.event == TRG_EVENT_DELETE) + { + my_error(ER_TRG_NO_SUCH_ROW_IN_TRG, MYF(0), "NEW", "on DELETE"); + return true; + } + if (trg_chistics.action_time == TRG_ACTION_AFTER) + { + my_error(ER_TRG_CANT_CHANGE_ROW, MYF(0), "NEW", "after "); + return true; + } + return set_trigger_new_row(name2, val); } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index f0241a3..9856ca1 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -155,15 +155,6 @@ extern uint binlog_unsafe_map[256]; void binlog_unsafe_map_init(); #endif -/** - used by the parser to store internal variable name -*/ -struct sys_var_with_base -{ - sys_var *var; - LEX_CSTRING base_name; -}; - struct LEX_TYPE { enum enum_field_types type; @@ -1338,8 +1329,6 @@ struct st_trg_chistics: public st_trg_execution_order }; -extern sys_var *trg_new_row_fake_var; - enum xa_option_words {XA_NONE, XA_JOIN, XA_RESUME, XA_ONE_PHASE, XA_SUSPEND, XA_FOR_MIGRATE}; @@ -3220,9 +3209,20 @@ struct LEX: public Query_tables_list enum sub_select_type type, bool is_top_level); bool setup_select_in_parentheses(); - bool set_trigger_new_row(LEX_CSTRING *name, Item *val); - bool set_system_variable(struct sys_var_with_base *tmp, - enum enum_var_type var_type, Item *val); + bool set_trigger_new_row(const LEX_CSTRING *name, Item *val); + bool set_trigger_field(const LEX_CSTRING *name1, const LEX_CSTRING *name2, + Item *val); + bool set_system_variable(enum_var_type var_type, sys_var *var, + const LEX_CSTRING *base_name, Item *val); + bool set_system_variable(enum_var_type var_type, const LEX_CSTRING *name, + Item *val); + bool set_system_variable(THD *thd, enum_var_type var_type, + const LEX_CSTRING *name1, + const LEX_CSTRING *name2, + Item *val); + bool set_default_system_variable(enum_var_type var_type, + const LEX_CSTRING *name, + Item *val); bool set_user_variable(THD *thd, const LEX_CSTRING *name, Item *val); void set_stmt_init(); sp_name *make_sp_name(THD *thd, const LEX_CSTRING *name); @@ -3265,14 +3265,7 @@ struct LEX: public Query_tables_list sp_pcontext *not_used_ctx; return find_variable(name, ¬_used_ctx, rh); } - bool init_internal_variable(struct sys_var_with_base *variable, - const LEX_CSTRING *name); - bool init_internal_variable(struct sys_var_with_base *variable, - const LEX_CSTRING *dbname, - const LEX_CSTRING *name); - bool init_default_internal_variable(struct sys_var_with_base *variable, - LEX_CSTRING name); - bool set_variable(struct sys_var_with_base *variable, Item *item); + bool set_variable(const LEX_CSTRING *name, Item *item); bool set_variable(const LEX_CSTRING *name1, const LEX_CSTRING *name2, Item *item); void sp_variable_declarations_init(THD *thd, int nvars); @@ -3464,7 +3457,7 @@ struct LEX: public Query_tables_list const LEX_CSTRING *var_name, const LEX_CSTRING *field_name); - bool is_trigger_new_or_old_reference(const LEX_CSTRING *name); + bool is_trigger_new_or_old_reference(const LEX_CSTRING *name) const; Item *create_and_link_Item_trigger_field(THD *thd, const LEX_CSTRING *name, bool new_row); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 35ec2d2..e3ceb3b 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -288,27 +288,28 @@ int LEX::case_stmt_action_then() */ bool -LEX::set_system_variable(struct sys_var_with_base *tmp, - enum enum_var_type var_type, Item *val) +LEX::set_system_variable(enum enum_var_type var_type, + sys_var *sysvar, const LEX_CSTRING *base_name, + Item *val) { - set_var *var; + set_var *setvar; /* No AUTOCOMMIT from a stored function or trigger. */ - if (spcont && tmp->var == Sys_autocommit_ptr) + if (spcont && sysvar == Sys_autocommit_ptr) sphead->m_flags|= sp_head::HAS_SET_AUTOCOMMIT_STMT; if (val && val->type() == Item::FIELD_ITEM && ((Item_field*)val)->table_name) { - my_error(ER_WRONG_TYPE_FOR_VAR, MYF(0), tmp->var->name.str); + my_error(ER_WRONG_TYPE_FOR_VAR, MYF(0), sysvar->name.str); return TRUE; } - if (! (var= new (thd->mem_root) - set_var(thd, var_type, tmp->var, &tmp->base_name, val))) + if (!(setvar= new (thd->mem_root) set_var(thd, var_type, sysvar, + base_name, val))) return TRUE; - return var_list.push_back(var, thd->mem_root); + return var_list.push_back(setvar, thd->mem_root); } @@ -322,7 +323,7 @@ LEX::set_system_variable(struct sys_var_with_base *tmp, @return TRUE if error, FALSE otherwise. */ -bool LEX::set_trigger_new_row(LEX_CSTRING *name, Item *val) +bool LEX::set_trigger_new_row(const LEX_CSTRING *name, Item *val) { Item_trigger_field *trg_fld; sp_instr_set_trigger_field *sp_fld; @@ -778,7 +779,6 @@ Virtual_column_info *add_virtual_expression(THD *thd, Item *expr) LEX_CSTRING lex_str; LEX_SYMBOL symbol; Lex_string_with_metadata_st lex_string_with_metadata; - struct sys_var_with_base variable; Lex_string_with_pos_st lex_string_with_pos; Lex_spblock_st spblock; Lex_spblock_handlers_st spblock_handlers; @@ -1869,8 +1869,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); opt_load_data_charset UNDERSCORE_CHARSET -%type <variable> internal_variable_name - %type <select_lex> subselect get_select_lex get_select_lex_derived simple_table @@ -15960,25 +15958,20 @@ opt_var_ident_type: /* Option values with preceding option_type. */ option_value_following_option_type: - internal_variable_name equal set_expr_or_default + ident equal set_expr_or_default { - LEX *lex= Lex; - - if ($1.var && $1.var != trg_new_row_fake_var) - { - /* It is a system variable. */ - if (lex->set_system_variable(&$1, lex->option_type, $3)) - MYSQL_YYABORT; - } - else - { - /* - Not in trigger assigning value to new row, - and option_type preceding local variable is illegal. - */ - thd->parse_error(); + if (Lex->set_system_variable(Lex->option_type, &$1, $3)) + MYSQL_YYABORT; + } + | ident '.' ident equal set_expr_or_default + { + if (Lex->set_system_variable(thd, Lex->option_type, &$1, &$3, $5)) + MYSQL_YYABORT; + } + | DEFAULT '.' ident equal set_expr_or_default + { + if (Lex->set_default_system_variable(Lex->option_type, &$3, $5)) MYSQL_YYABORT; - } } ; @@ -15986,9 +15979,7 @@ option_value_following_option_type: option_value_no_option_type: ident equal set_expr_or_default { - struct sys_var_with_base var; - if (Lex->init_internal_variable(&var, &$1) || - Lex->set_variable(&var, $3)) + if (Lex->set_variable(&$1, $3)) MYSQL_YYABORT; } | ident '.' ident equal set_expr_or_default @@ -15999,9 +15990,7 @@ option_value_no_option_type: } | DEFAULT '.' ident equal set_expr_or_default { - struct sys_var_with_base var; - if (Lex->init_default_internal_variable(&var, $3) || - Lex->set_variable(&var, $5)) + if (Lex->set_default_system_variable(Lex->option_type, &$3, $5)) MYSQL_YYABORT; } | '@' ident_or_text equal expr @@ -16009,16 +15998,19 @@ option_value_no_option_type: if (Lex->set_user_variable(thd, &$2, $4)) MYSQL_YYABORT; } - | '@' '@' opt_var_ident_type internal_variable_name equal set_expr_or_default + | '@' '@' opt_var_ident_type ident equal set_expr_or_default { - struct sys_var_with_base tmp= $4; - /* Lookup if necessary: must be a system variable. */ - if (tmp.var == NULL) - { - if (find_sys_var_null_base(thd, &tmp)) - MYSQL_YYABORT; - } - if (Lex->set_system_variable(&tmp, $3, $6)) + if (Lex->set_system_variable($3, &$4, $6)) + MYSQL_YYABORT; + } + | '@' '@' opt_var_ident_type ident '.' ident equal set_expr_or_default + { + if (Lex->set_system_variable(thd, $3, &$4, &$6, $8)) + MYSQL_YYABORT; + } + | '@' '@' opt_var_ident_type DEFAULT '.' ident equal set_expr_or_default + { + if (Lex->set_default_system_variable($3, &$6, $8)) MYSQL_YYABORT; } | charset old_or_new_charset_name_or_default @@ -16116,25 +16108,6 @@ option_value_no_option_type: } ; - -internal_variable_name: - ident - { - if (Lex->init_internal_variable(&$$, &$1)) - MYSQL_YYABORT; - } - | ident '.' ident - { - if (Lex->init_internal_variable(&$$, &$1, &$3)) - MYSQL_YYABORT; - } - | DEFAULT '.' ident - { - if (Lex->init_default_internal_variable(&$$, $3)) - MYSQL_YYABORT; - } - ; - transaction_characteristics: transaction_access_mode | isolation_level diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy index c8f93c1..bdc4694 100644 --- a/sql/sql_yacc_ora.yy +++ b/sql/sql_yacc_ora.yy @@ -171,7 +171,6 @@ void ORAerror(THD *thd, const char *s) LEX_CSTRING lex_str; LEX_SYMBOL symbol; Lex_string_with_metadata_st lex_string_with_metadata; - struct sys_var_with_base variable; Lex_string_with_pos_st lex_string_with_pos; Lex_spblock_st spblock; Lex_spblock_handlers_st spblock_handlers; @@ -1271,9 +1270,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); opt_load_data_charset UNDERSCORE_CHARSET -%type <variable> internal_variable_name - internal_variable_name_directly_assignable - %type <select_lex> subselect get_select_lex get_select_lex_derived query_specification @@ -14809,9 +14805,9 @@ simple_ident_q2: if (lex->is_trigger_new_or_old_reference(&$2)) { bool new_row= ($2.str[0]=='N' || $2.str[0]=='n'); - if (!($$= Lex->create_and_link_Item_trigger_field(thd, - &$4, - new_row))) + if (!($$= lex->create_and_link_Item_trigger_field(thd, + &$4, + new_row))) MYSQL_YYABORT; } else @@ -15659,7 +15655,7 @@ set: ; set_assign: - internal_variable_name_directly_assignable SET_VAR + ident_directly_assignable SET_VAR { LEX *lex=Lex; lex->set_stmt_init(); @@ -15687,6 +15683,25 @@ set_assign: lex->sphead->restore_lex(thd)) MYSQL_YYABORT; } + | colon_with_pos ident '.' ident SET_VAR + { + LEX *lex= Lex; + if (!lex->is_trigger_new_or_old_reference(&$2)) + { + thd->parse_error(ER_SYNTAX_ERROR, $1); + MYSQL_YYABORT; + } + lex->set_stmt_init(); + lex->var_list.empty(); + sp_create_assignment_lex(thd, yychar == YYEMPTY); + } + set_expr_or_default + { + LEX_CSTRING tmp= { $2.str, $2.length }; + if (Lex->set_trigger_field(&tmp, &$4, $7) || + sp_create_assignment_instr(thd, yychar == YYEMPTY)) + MYSQL_YYABORT; + } ; set_stmt_option_value_following_option_type_list: @@ -15798,25 +15813,20 @@ opt_var_ident_type: /* Option values with preceding option_type. */ option_value_following_option_type: - internal_variable_name equal set_expr_or_default + ident equal set_expr_or_default { - LEX *lex= Lex; - - if ($1.var && $1.var != trg_new_row_fake_var) - { - /* It is a system variable. */ - if (lex->set_system_variable(&$1, lex->option_type, $3)) - MYSQL_YYABORT; - } - else - { - /* - Not in trigger assigning value to new row, - and option_type preceding local variable is illegal. - */ - thd->parse_error(); + if (Lex->set_system_variable(Lex->option_type, &$1, $3)) + MYSQL_YYABORT; + } + | ident '.' ident equal set_expr_or_default + { + if (Lex->set_system_variable(thd, Lex->option_type, &$1, &$3, $5)) + MYSQL_YYABORT; + } + | DEFAULT '.' ident equal set_expr_or_default + { + if (Lex->set_default_system_variable(Lex->option_type, &$3, $5)) MYSQL_YYABORT; - } } ; @@ -15824,9 +15834,7 @@ option_value_following_option_type: option_value_no_option_type: ident equal set_expr_or_default { - struct sys_var_with_base var; - if (Lex->init_internal_variable(&var, &$1) || - Lex->set_variable(&var, $3)) + if (Lex->set_variable(&$1, $3)) MYSQL_YYABORT; } | ident '.' ident equal set_expr_or_default @@ -15837,9 +15845,7 @@ option_value_no_option_type: } | DEFAULT '.' ident equal set_expr_or_default { - struct sys_var_with_base var; - if (Lex->init_default_internal_variable(&var, $3) || - Lex->set_variable(&var, $5)) + if (Lex->set_default_system_variable(Lex->option_type, &$3, $5)) MYSQL_YYABORT; } | '@' ident_or_text equal expr @@ -15847,16 +15853,19 @@ option_value_no_option_type: if (Lex->set_user_variable(thd, &$2, $4)) MYSQL_YYABORT; } - | '@' '@' opt_var_ident_type internal_variable_name equal set_expr_or_default + | '@' '@' opt_var_ident_type ident equal set_expr_or_default { - struct sys_var_with_base tmp= $4; - /* Lookup if necessary: must be a system variable. */ - if (tmp.var == NULL) - { - if (find_sys_var_null_base(thd, &tmp)) - MYSQL_YYABORT; - } - if (Lex->set_system_variable(&tmp, $3, $6)) + if (Lex->set_system_variable($3, &$4, $6)) + MYSQL_YYABORT; + } + | '@' '@' opt_var_ident_type ident '.' ident equal set_expr_or_default + { + if (Lex->set_system_variable(thd, $3, &$4, &$6, $8)) + MYSQL_YYABORT; + } + | '@' '@' opt_var_ident_type DEFAULT '.' ident equal set_expr_or_default + { + if (Lex->set_default_system_variable($3, &$6, $8)) MYSQL_YYABORT; } | charset old_or_new_charset_name_or_default @@ -15955,48 +15964,6 @@ option_value_no_option_type: ; -internal_variable_name: - ident - { - if (Lex->init_internal_variable(&$$, &$1)) - MYSQL_YYABORT; - } - | ident '.' ident - { - if (Lex->init_internal_variable(&$$, &$1, &$3)) - MYSQL_YYABORT; - } - | DEFAULT '.' ident - { - if (Lex->init_default_internal_variable(&$$, $3)) - MYSQL_YYABORT; - } - ; - - -internal_variable_name_directly_assignable: - ident_directly_assignable - { - if (Lex->init_internal_variable(&$$, &$1)) - MYSQL_YYABORT; - } - | DEFAULT '.' ident - { - if (Lex->init_default_internal_variable(&$$, $3)) - MYSQL_YYABORT; - } - | colon_with_pos ident_directly_assignable '.' ident - { - if (!Lex->is_trigger_new_or_old_reference(&$2)) - { - thd->parse_error(); - MYSQL_YYABORT; - } - if (Lex->init_internal_variable(&$$, &$2, &$4)) - MYSQL_YYABORT; - } - ; - transaction_characteristics: transaction_access_mode | isolation_level
_______________________________________________ Mailing list: https://launchpad.net/~maria-developers Post to : maria-developers@lists.launchpad.net Unsubscribe : https://launchpad.net/~maria-developers More help : https://help.launchpad.net/ListHelp