mirror of
https://github.com/MariaDB/server.git
synced 2026-01-06 05:22:24 +03:00
BUG#21726: Incorrect result with multiple invocations of LAST_INSERT_ID.
Note: bug#21726 does not directly apply to 4.1, as it doesn't have stored
procedures. However, 4.1 had some bugs that were fixed in 5.0 by the
patch for bug#21726, and this patch is a backport of those fixes.
Namely, in 4.1 it fixes:
- LAST_INSERT_ID(expr) didn't return value of expr (4.1 specific).
- LAST_INSERT_ID() could return the value generated by current
statement if the call happens after the generation, like in
CREATE TABLE t1 (i INT AUTO_INCREMENT PRIMARY KEY, j INT);
INSERT INTO t1 VALUES (NULL, 0), (NULL, LAST_INSERT_ID());
- Redundant binary log LAST_INSERT_ID_EVENTs could be generated.
mysql-test/r/rpl_insert_id.result:
Add result for bug#21726: Incorrect result with multiple invocations
of LAST_INSERT_ID.
mysql-test/t/rpl_insert_id.test:
Add test case for bug#21726: Incorrect result with multiple invocations
of LAST_INSERT_ID.
sql/item_func.cc:
Add implementation of Item_func_last_insert_id::fix_fields(), where we
set THD::last_insert_id_used when statement calls LAST_INSERT_ID().
In Item_func_last_insert_id::val_int(), return THD::current_insert_id
if called like LAST_INSERT_ID(), otherwise return value of argument if
called like LAST_INSERT_ID(expr).
sql/item_func.h:
Add declaration of Item_func_last_insert_id::fix_fields().
sql/log_event.cc:
Do not set THD::last_insert_id_used on LAST_INSERT_ID_EVENT. Though we
know the statement will call LAST_INSERT_ID(), it wasn't called yet.
sql/set_var.cc:
In sys_var_last_insert_id::value_ptr(), set THD::last_insert_id_used,
and return THD::current_insert_id for @@LAST_INSERT_ID.
sql/sql_class.h:
Update comments.
Remove THD::insert_id(), as it has lost its purpose now.
sql/sql_insert.cc:
Now it is OK to read THD::last_insert_id directly.
sql/sql_load.cc:
Now it is OK to read THD::last_insert_id directly.
sql/sql_parse.cc:
In mysql_execute_command(), remember THD::last_insert_id (first
generated value of the previous statement) in THD::current_insert_id,
which then will be returned for LAST_INSERT_ID() and @@LAST_INSERT_ID.
sql/sql_select.cc:
If "IS NULL" is replaced with "= <LAST_INSERT_ID>", use right value,
which is THD::current_insert_id, and also set THD::last_insert_id_used
to issue binary log LAST_INSERT_ID_EVENT.
sql/sql_update.cc:
Now it is OK to read THD::last_insert_id directly.
tests/mysql_client_test.c:
Add test case for bug#21726: Incorrect result with multiple invocations
of LAST_INSERT_ID.
This commit is contained in:
@@ -4820,7 +4820,7 @@ remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value)
|
||||
Field *field=((Item_field*) args[0])->field;
|
||||
if (field->flags & AUTO_INCREMENT_FLAG && !field->table->maybe_null &&
|
||||
(thd->options & OPTION_AUTO_IS_NULL) &&
|
||||
thd->insert_id() && thd->substitute_null_with_insert_id)
|
||||
thd->current_insert_id && thd->substitute_null_with_insert_id)
|
||||
{
|
||||
#ifdef HAVE_QUERY_CACHE
|
||||
query_cache_abort(&thd->net);
|
||||
@@ -4828,9 +4828,16 @@ remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value)
|
||||
COND *new_cond;
|
||||
if ((new_cond= new Item_func_eq(args[0],
|
||||
new Item_int("last_insert_id()",
|
||||
thd->insert_id(),
|
||||
thd->current_insert_id,
|
||||
21))))
|
||||
{
|
||||
/*
|
||||
Set THD::last_insert_id_used manually, as this statement
|
||||
uses LAST_INSERT_ID() in a sense, and should issue
|
||||
LAST_INSERT_ID_EVENT.
|
||||
*/
|
||||
thd->last_insert_id_used= TRUE;
|
||||
|
||||
cond=new_cond;
|
||||
cond->fix_fields(thd, 0, &cond);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user