Commit dbb0513f authored by unknown's avatar unknown

Bug#15728: LAST_INSERT_ID function inside a stored function returns 0

Do not reset value of LAST_INSERT_ID() in sub-statement.


mysql-test/r/rpl_insert_id.result:
  Add result for bug#15728.
mysql-test/r/sp.result:
  Add result for bug#15728.
mysql-test/t/rpl_insert_id.test:
  Add test case for bug#15728.
mysql-test/t/sp.test:
  Add test case for bug#15728.
sql/sql_class.cc:
  Do not reset value of LAST_INSERT_ID() in sub-statement.
parent 71da6569
...@@ -74,3 +74,61 @@ SET FOREIGN_KEY_CHECKS=0; ...@@ -74,3 +74,61 @@ SET FOREIGN_KEY_CHECKS=0;
INSERT INTO t1 VALUES (1),(1); INSERT INTO t1 VALUES (1),(1);
ERROR 23000: Duplicate entry '1' for key 1 ERROR 23000: Duplicate entry '1' for key 1
drop table t1; drop table t1;
drop function if exists bug15728;
drop function if exists bug15728_insert;
drop table if exists t1, t2;
create table t1 (
id int not null auto_increment,
last_id int,
primary key (id)
);
create function bug15728() returns int(11)
return last_insert_id();
insert into t1 (last_id) values (0);
insert into t1 (last_id) values (last_insert_id());
insert into t1 (last_id) values (bug15728());
create table t2 (
id int not null auto_increment,
last_id int,
primary key (id)
);
create function bug15728_insert() returns int(11) modifies sql data
begin
insert into t2 (last_id) values (bug15728());
return bug15728();
end|
create trigger t1_bi before insert on t1 for each row
begin
declare res int;
select bug15728_insert() into res;
set NEW.last_id = res;
end|
insert into t1 (last_id) values (0);
drop trigger t1_bi;
select last_insert_id();
last_insert_id()
4
select bug15728_insert();
bug15728_insert()
2
select last_insert_id();
last_insert_id()
4
insert into t1 (last_id) values (bug15728());
select last_insert_id();
last_insert_id()
5
select * from t1;
id last_id
1 0
2 1
3 2
4 1
5 4
select * from t2;
id last_id
1 3
2 4
drop function bug15728;
drop function bug15728_insert;
drop table t1, t2;
...@@ -4848,6 +4848,23 @@ c 2 ...@@ -4848,6 +4848,23 @@ c 2
b 3 b 3
a 1 a 1
delete from t1| delete from t1|
drop function if exists bug15728|
drop table if exists t3|
create table t3 (
id int not null auto_increment,
primary key (id)
)|
create function bug15728() returns int(11)
return last_insert_id()|
insert into t3 values (0)|
select last_insert_id()|
last_insert_id()
1
select bug15728()|
bug15728()
1
drop function bug15728|
drop table t3|
drop procedure if exists bug18787| drop procedure if exists bug18787|
create procedure bug18787() create procedure bug18787()
begin begin
......
...@@ -78,3 +78,73 @@ connection master; ...@@ -78,3 +78,73 @@ connection master;
drop table t1; drop table t1;
sync_slave_with_master; sync_slave_with_master;
# End of 4.1 tests # End of 4.1 tests
#
# BUG#15728: LAST_INSERT_ID function inside a stored function returns 0
#
# The solution is not to reset last_insert_id on enter to sub-statement.
#
connection master;
--disable_warnings
drop function if exists bug15728;
drop function if exists bug15728_insert;
drop table if exists t1, t2;
--enable_warnings
create table t1 (
id int not null auto_increment,
last_id int,
primary key (id)
);
create function bug15728() returns int(11)
return last_insert_id();
insert into t1 (last_id) values (0);
insert into t1 (last_id) values (last_insert_id());
insert into t1 (last_id) values (bug15728());
# Check that nested call replicates too.
create table t2 (
id int not null auto_increment,
last_id int,
primary key (id)
);
delimiter |;
create function bug15728_insert() returns int(11) modifies sql data
begin
insert into t2 (last_id) values (bug15728());
return bug15728();
end|
create trigger t1_bi before insert on t1 for each row
begin
declare res int;
select bug15728_insert() into res;
set NEW.last_id = res;
end|
delimiter ;|
insert into t1 (last_id) values (0);
drop trigger t1_bi;
# Check that nested call doesn't affect outer context.
select last_insert_id();
select bug15728_insert();
select last_insert_id();
insert into t1 (last_id) values (bug15728());
# This should be exactly one greater than in the previous call.
select last_insert_id();
save_master_pos;
connection slave;
sync_with_master;
select * from t1;
select * from t2;
connection master;
drop function bug15728;
drop function bug15728_insert;
drop table t1, t2;
# End of 5.0 tests
...@@ -5698,6 +5698,31 @@ select * from t1 order by @x| ...@@ -5698,6 +5698,31 @@ select * from t1 order by @x|
delete from t1| delete from t1|
#
# BUG#15728: LAST_INSERT_ID function inside a stored function returns 0
#
# The solution is not to reset last_insert_id on enter to sub-statement.
#
--disable_warnings
drop function if exists bug15728|
drop table if exists t3|
--enable_warnings
create table t3 (
id int not null auto_increment,
primary key (id)
)|
create function bug15728() returns int(11)
return last_insert_id()|
insert into t3 values (0)|
select last_insert_id()|
select bug15728()|
drop function bug15728|
drop table t3|
# #
# BUG#18787: Server crashed when calling a stored procedure containing # BUG#18787: Server crashed when calling a stored procedure containing
# a misnamed function # a misnamed function
......
...@@ -2025,7 +2025,7 @@ void THD::restore_backup_open_tables_state(Open_tables_state *backup) ...@@ -2025,7 +2025,7 @@ void THD::restore_backup_open_tables_state(Open_tables_state *backup)
The following things is done The following things is done
- Disable binary logging for the duration of the statement - Disable binary logging for the duration of the statement
- Disable multi-result-sets for the duration of the statement - Disable multi-result-sets for the duration of the statement
- Value of last_insert_id() is reset and restored - Value of last_insert_id() is saved and restored
- Value set by 'SET INSERT_ID=#' is reset and restored - Value set by 'SET INSERT_ID=#' is reset and restored
- Value for found_rows() is reset and restored - Value for found_rows() is reset and restored
- examined_row_count is added to the total - examined_row_count is added to the total
...@@ -2037,6 +2037,8 @@ void THD::restore_backup_open_tables_state(Open_tables_state *backup) ...@@ -2037,6 +2037,8 @@ void THD::restore_backup_open_tables_state(Open_tables_state *backup)
We reset examined_row_count and cuted_fields and add these to the We reset examined_row_count and cuted_fields and add these to the
result to ensure that if we have a bug that would reset these within result to ensure that if we have a bug that would reset these within
a function, we are not loosing any rows from the main statement. a function, we are not loosing any rows from the main statement.
We do not reset value of last_insert_id().
****************************************************************************/ ****************************************************************************/
void THD::reset_sub_statement_state(Sub_statement_state *backup, void THD::reset_sub_statement_state(Sub_statement_state *backup,
...@@ -2062,7 +2064,6 @@ void THD::reset_sub_statement_state(Sub_statement_state *backup, ...@@ -2062,7 +2064,6 @@ void THD::reset_sub_statement_state(Sub_statement_state *backup,
/* Disable result sets */ /* Disable result sets */
client_capabilities &= ~CLIENT_MULTI_RESULTS; client_capabilities &= ~CLIENT_MULTI_RESULTS;
in_sub_stmt|= new_state; in_sub_stmt|= new_state;
last_insert_id= 0;
next_insert_id= 0; next_insert_id= 0;
insert_id_used= 0; insert_id_used= 0;
examined_row_count= 0; examined_row_count= 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment