diff options
author | Gleb Shchepa <gshchepa@mysql.com> | 2008-09-18 13:38:44 +0500 |
---|---|---|
committer | Gleb Shchepa <gshchepa@mysql.com> | 2008-09-18 13:38:44 +0500 |
commit | 25d96ed45b3054e9313210b5ab0ca2a4757d3cb5 (patch) | |
tree | 2645104a2a73aa7f9368263d59ff44c7052e9599 /sql/item_func.h | |
parent | a45d12f37807a24cf6a0c1f47752b9aaaed8bc3a (diff) | |
download | mariadb-git-25d96ed45b3054e9313210b5ab0ca2a4757d3cb5.tar.gz |
Bug#26020: User-Defined Variables are not consistent with
columns data types
The "SELECT @lastId, @lastId := Id FROM t" query returns
different result sets depending on the type of the Id column
(INT or BIGINT).
Note: this fix doesn't cover the case when a select query
references an user variable and stored function that
updates a value of that variable, in this case a result
is indeterminate.
The server uses incorrect assumption about a constantness of
an user variable value as a select list item:
The server caches a last query number where that variable
was changed and compares this number with a current query
number. If these numbers are different, the server guesses,
that the variable is not updating in the current query, so
a respective select list item is a constant. However, in some
common cases the server updates cached query number too late.
The server has been modified to memorize user variable
assignments during the parse phase to take them into account
on the next (query preparation) phase independently of the
order of user variable references/assignments in a select
item list.
mysql-test/r/user_var.result:
Added test case for bug #26020.
mysql-test/t/user_var.test:
Added test case for bug #26020.
sql/item_func.cc:
An update of entry and update_query_id variables has been
moved from Item_func_set_user_var::fix_fields() to a separate
method, Item_func_set_user_var::set_entry().
sql/item_func.h:
1. The Item_func_set_user_var::set_entry() method has been
added to update Item_func_set_user_var::entry.
2. The Item_func_set_user_var::entry_thd field has beend
added to update Item_func_set_user_var::entry only when
needed.
sql/sql_base.cc:
Fix: setup_fiedls() calls Item_func_set_user_var::set_entry()
for all items from the thd->lex->set_var_list before the first
call of ::fix_fields().
sql/sql_lex.cc:
The lex_start function has been modified to reset
the st_lex::set_var_list list.
sql/sql_lex.h:
New st_lex::set_var_list field has been added to
memorize all user variable assignments in the current
select query.
sql/sql_yacc.yy:
The variable_aux rule has been modified to memorize
in-query user variable assignments in the
st_lex::set_var_list list.
Diffstat (limited to 'sql/item_func.h')
-rw-r--r-- | sql/item_func.h | 15 |
1 files changed, 14 insertions, 1 deletions
diff --git a/sql/item_func.h b/sql/item_func.h index 02631d7643d..d84abdb6e56 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -1294,6 +1294,17 @@ class Item_func_set_user_var :public Item_func { enum Item_result cached_result_type; user_var_entry *entry; + /* + The entry_thd variable is used: + 1) to skip unnecessary updates of the entry field (see above); + 2) to reset the entry field that was initialized in the other thread + (for example, an item tree of a trigger that updates user variables + may be shared between several connections, and the entry_thd field + prevents updates of one connection user variables from a concurrent + connection calling the same trigger that initially updated some + user variable it the first connection context). + */ + THD *entry_thd; char buffer[MAX_FIELD_WIDTH]; String value; my_decimal decimal_buff; @@ -1309,7 +1320,8 @@ class Item_func_set_user_var :public Item_func public: LEX_STRING name; // keep it public Item_func_set_user_var(LEX_STRING a,Item *b) - :Item_func(b), cached_result_type(INT_RESULT), name(a) + :Item_func(b), cached_result_type(INT_RESULT), + entry(NULL), entry_thd(NULL), name(a) {} enum Functype functype() const { return SUSERVAR_FUNC; } double val_real(); @@ -1340,6 +1352,7 @@ public: } void save_org_in_field(Field *field) { (void)save_in_field(field, 1, 0); } bool register_field_in_read_map(uchar *arg); + bool set_entry(THD *thd, bool create_if_not_exists); }; |