Loading mysql-test/r/rpl_insert_id.result +129 −0 Original line number Diff line number Diff line Loading @@ -234,6 +234,135 @@ n b 2 100 3 350 drop table t1; DROP PROCEDURE IF EXISTS p1; DROP TABLE IF EXISTS t1, t2; SELECT LAST_INSERT_ID(0); LAST_INSERT_ID(0) 0 CREATE TABLE t1 ( id INT NOT NULL DEFAULT 0, last_id INT, PRIMARY KEY (id) ); CREATE TABLE t2 ( id INT NOT NULL AUTO_INCREMENT, last_id INT, PRIMARY KEY (id) ); CREATE PROCEDURE p1() BEGIN INSERT INTO t2 (last_id) VALUES (LAST_INSERT_ID()); INSERT INTO t1 (last_id) VALUES (LAST_INSERT_ID()); END| CALL p1(); SELECT * FROM t1; id last_id 0 1 SELECT * FROM t2; id last_id 1 0 SELECT * FROM t1; id last_id 0 1 SELECT * FROM t2; id last_id 1 0 DROP PROCEDURE p1; DROP TABLE t1, t2; DROP PROCEDURE IF EXISTS p1; DROP FUNCTION IF EXISTS f1; DROP FUNCTION IF EXISTS f2; DROP TABLE IF EXISTS t1, t2; CREATE TABLE t1 ( i INT NOT NULL AUTO_INCREMENT PRIMARY KEY, j INT DEFAULT 0 ); CREATE TABLE t2 (i INT); CREATE PROCEDURE p1() BEGIN INSERT INTO t1 (i) VALUES (NULL); INSERT INTO t2 (i) VALUES (LAST_INSERT_ID()); INSERT INTO t1 (i) VALUES (NULL), (NULL); INSERT INTO t2 (i) VALUES (LAST_INSERT_ID()); END | CREATE FUNCTION f1() RETURNS INT MODIFIES SQL DATA BEGIN INSERT INTO t1 (i) VALUES (NULL); INSERT INTO t2 (i) VALUES (LAST_INSERT_ID()); INSERT INTO t1 (i) VALUES (NULL), (NULL); INSERT INTO t2 (i) VALUES (LAST_INSERT_ID()); RETURN 0; END | CREATE FUNCTION f2() RETURNS INT NOT DETERMINISTIC RETURN LAST_INSERT_ID() | INSERT INTO t1 VALUES (NULL, -1); CALL p1(); SELECT f1(); f1() 0 INSERT INTO t1 VALUES (NULL, f2()), (NULL, LAST_INSERT_ID()), (NULL, LAST_INSERT_ID()), (NULL, f2()), (NULL, f2()); INSERT INTO t1 VALUES (NULL, f2()); INSERT INTO t1 VALUES (NULL, LAST_INSERT_ID()), (NULL, LAST_INSERT_ID(5)), (NULL, @@LAST_INSERT_ID); INSERT INTO t1 VALUES (NULL, 0), (NULL, LAST_INSERT_ID()); UPDATE t1 SET j= -1 WHERE i IS NULL; SELECT * FROM t1; i j 1 -1 2 0 3 0 4 0 5 0 6 0 7 0 8 3 9 3 10 3 11 3 12 3 13 8 14 13 15 5 16 13 17 -1 18 14 SELECT * FROM t2; i 2 3 5 6 SELECT * FROM t1; i j 1 -1 2 0 3 0 4 0 5 0 6 0 7 0 8 3 9 3 10 3 11 3 12 3 13 8 14 13 15 5 16 13 17 -1 18 14 SELECT * FROM t2; i 2 3 5 6 DROP PROCEDURE p1; DROP FUNCTION f1; DROP FUNCTION f2; DROP TABLE t1, t2; # End of 5.0 tests mysql-test/t/rpl_insert_id.test +112 −0 Original line number Diff line number Diff line Loading @@ -244,6 +244,118 @@ select * from t1 order by n; connection master; drop table t1; # # BUG#20339: stored procedure using LAST_INSERT_ID() does not # replicate statement-based # --disable_warnings DROP PROCEDURE IF EXISTS p1; DROP TABLE IF EXISTS t1, t2; --enable_warnings # Reset result of LAST_INSERT_ID(). SELECT LAST_INSERT_ID(0); CREATE TABLE t1 ( id INT NOT NULL DEFAULT 0, last_id INT, PRIMARY KEY (id) ); CREATE TABLE t2 ( id INT NOT NULL AUTO_INCREMENT, last_id INT, PRIMARY KEY (id) ); delimiter |; CREATE PROCEDURE p1() BEGIN INSERT INTO t2 (last_id) VALUES (LAST_INSERT_ID()); INSERT INTO t1 (last_id) VALUES (LAST_INSERT_ID()); END| delimiter ;| CALL p1(); SELECT * FROM t1; SELECT * FROM t2; sync_slave_with_master; SELECT * FROM t1; SELECT * FROM t2; connection master; DROP PROCEDURE p1; DROP TABLE t1, t2; # # BUG#21726: Incorrect result with multiple invocations of # LAST_INSERT_ID # --disable_warnings DROP PROCEDURE IF EXISTS p1; DROP FUNCTION IF EXISTS f1; DROP FUNCTION IF EXISTS f2; DROP TABLE IF EXISTS t1, t2; --enable_warnings CREATE TABLE t1 ( i INT NOT NULL AUTO_INCREMENT PRIMARY KEY, j INT DEFAULT 0 ); CREATE TABLE t2 (i INT); delimiter |; CREATE PROCEDURE p1() BEGIN INSERT INTO t1 (i) VALUES (NULL); INSERT INTO t2 (i) VALUES (LAST_INSERT_ID()); INSERT INTO t1 (i) VALUES (NULL), (NULL); INSERT INTO t2 (i) VALUES (LAST_INSERT_ID()); END | CREATE FUNCTION f1() RETURNS INT MODIFIES SQL DATA BEGIN INSERT INTO t1 (i) VALUES (NULL); INSERT INTO t2 (i) VALUES (LAST_INSERT_ID()); INSERT INTO t1 (i) VALUES (NULL), (NULL); INSERT INTO t2 (i) VALUES (LAST_INSERT_ID()); RETURN 0; END | CREATE FUNCTION f2() RETURNS INT NOT DETERMINISTIC RETURN LAST_INSERT_ID() | delimiter ;| INSERT INTO t1 VALUES (NULL, -1); CALL p1(); SELECT f1(); INSERT INTO t1 VALUES (NULL, f2()), (NULL, LAST_INSERT_ID()), (NULL, LAST_INSERT_ID()), (NULL, f2()), (NULL, f2()); INSERT INTO t1 VALUES (NULL, f2()); INSERT INTO t1 VALUES (NULL, LAST_INSERT_ID()), (NULL, LAST_INSERT_ID(5)), (NULL, @@LAST_INSERT_ID); # Test replication of substitution "IS NULL" -> "= LAST_INSERT_ID". INSERT INTO t1 VALUES (NULL, 0), (NULL, LAST_INSERT_ID()); UPDATE t1 SET j= -1 WHERE i IS NULL; SELECT * FROM t1; SELECT * FROM t2; sync_slave_with_master; SELECT * FROM t1; SELECT * FROM t2; connection master; DROP PROCEDURE p1; DROP FUNCTION f1; DROP FUNCTION f2; DROP TABLE t1, t2; sync_slave_with_master; --echo Loading sql/item_func.cc +32 −3 Original line number Diff line number Diff line Loading @@ -3345,6 +3345,34 @@ longlong Item_func_release_lock::val_int() } bool Item_func_last_insert_id::fix_fields(THD *thd, Item **ref) { DBUG_ASSERT(fixed == 0); if (Item_int_func::fix_fields(thd, ref)) return TRUE; if (arg_count == 0) { if (!thd->last_insert_id_used) { /* As this statement calls LAST_INSERT_ID(), set THD::last_insert_id_used and remember first generated insert id of the previous statement in THD::current_insert_id. */ thd->last_insert_id_used= TRUE; thd->current_insert_id= thd->last_insert_id; } null_value= FALSE; } thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT); return FALSE; } longlong Item_func_last_insert_id::val_int() { THD *thd= current_thd; Loading @@ -3354,12 +3382,13 @@ longlong Item_func_last_insert_id::val_int() longlong value= args[0]->val_int(); thd->insert_id(value); null_value= args[0]->null_value; return value; // Avoid side effect of insert_id() return value; } thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT); return thd->last_insert_id_used ? thd->current_insert_id : thd->insert_id(); return thd->current_insert_id; } /* This function is just used to test speed of different functions */ longlong Item_func_benchmark::val_int() Loading sql/item_func.h +1 −0 Original line number Diff line number Diff line Loading @@ -891,6 +891,7 @@ class Item_func_last_insert_id :public Item_int_func if (arg_count) max_length= args[0]->max_length; } bool fix_fields(THD *thd, Item **ref); }; Loading sql/log_event.cc +0 −1 Original line number Diff line number Diff line Loading @@ -3365,7 +3365,6 @@ int Intvar_log_event::exec_event(struct st_relay_log_info* rli) { switch (type) { case LAST_INSERT_ID_EVENT: thd->last_insert_id_used = 1; thd->last_insert_id = val; break; case INSERT_ID_EVENT: Loading Loading
mysql-test/r/rpl_insert_id.result +129 −0 Original line number Diff line number Diff line Loading @@ -234,6 +234,135 @@ n b 2 100 3 350 drop table t1; DROP PROCEDURE IF EXISTS p1; DROP TABLE IF EXISTS t1, t2; SELECT LAST_INSERT_ID(0); LAST_INSERT_ID(0) 0 CREATE TABLE t1 ( id INT NOT NULL DEFAULT 0, last_id INT, PRIMARY KEY (id) ); CREATE TABLE t2 ( id INT NOT NULL AUTO_INCREMENT, last_id INT, PRIMARY KEY (id) ); CREATE PROCEDURE p1() BEGIN INSERT INTO t2 (last_id) VALUES (LAST_INSERT_ID()); INSERT INTO t1 (last_id) VALUES (LAST_INSERT_ID()); END| CALL p1(); SELECT * FROM t1; id last_id 0 1 SELECT * FROM t2; id last_id 1 0 SELECT * FROM t1; id last_id 0 1 SELECT * FROM t2; id last_id 1 0 DROP PROCEDURE p1; DROP TABLE t1, t2; DROP PROCEDURE IF EXISTS p1; DROP FUNCTION IF EXISTS f1; DROP FUNCTION IF EXISTS f2; DROP TABLE IF EXISTS t1, t2; CREATE TABLE t1 ( i INT NOT NULL AUTO_INCREMENT PRIMARY KEY, j INT DEFAULT 0 ); CREATE TABLE t2 (i INT); CREATE PROCEDURE p1() BEGIN INSERT INTO t1 (i) VALUES (NULL); INSERT INTO t2 (i) VALUES (LAST_INSERT_ID()); INSERT INTO t1 (i) VALUES (NULL), (NULL); INSERT INTO t2 (i) VALUES (LAST_INSERT_ID()); END | CREATE FUNCTION f1() RETURNS INT MODIFIES SQL DATA BEGIN INSERT INTO t1 (i) VALUES (NULL); INSERT INTO t2 (i) VALUES (LAST_INSERT_ID()); INSERT INTO t1 (i) VALUES (NULL), (NULL); INSERT INTO t2 (i) VALUES (LAST_INSERT_ID()); RETURN 0; END | CREATE FUNCTION f2() RETURNS INT NOT DETERMINISTIC RETURN LAST_INSERT_ID() | INSERT INTO t1 VALUES (NULL, -1); CALL p1(); SELECT f1(); f1() 0 INSERT INTO t1 VALUES (NULL, f2()), (NULL, LAST_INSERT_ID()), (NULL, LAST_INSERT_ID()), (NULL, f2()), (NULL, f2()); INSERT INTO t1 VALUES (NULL, f2()); INSERT INTO t1 VALUES (NULL, LAST_INSERT_ID()), (NULL, LAST_INSERT_ID(5)), (NULL, @@LAST_INSERT_ID); INSERT INTO t1 VALUES (NULL, 0), (NULL, LAST_INSERT_ID()); UPDATE t1 SET j= -1 WHERE i IS NULL; SELECT * FROM t1; i j 1 -1 2 0 3 0 4 0 5 0 6 0 7 0 8 3 9 3 10 3 11 3 12 3 13 8 14 13 15 5 16 13 17 -1 18 14 SELECT * FROM t2; i 2 3 5 6 SELECT * FROM t1; i j 1 -1 2 0 3 0 4 0 5 0 6 0 7 0 8 3 9 3 10 3 11 3 12 3 13 8 14 13 15 5 16 13 17 -1 18 14 SELECT * FROM t2; i 2 3 5 6 DROP PROCEDURE p1; DROP FUNCTION f1; DROP FUNCTION f2; DROP TABLE t1, t2; # End of 5.0 tests
mysql-test/t/rpl_insert_id.test +112 −0 Original line number Diff line number Diff line Loading @@ -244,6 +244,118 @@ select * from t1 order by n; connection master; drop table t1; # # BUG#20339: stored procedure using LAST_INSERT_ID() does not # replicate statement-based # --disable_warnings DROP PROCEDURE IF EXISTS p1; DROP TABLE IF EXISTS t1, t2; --enable_warnings # Reset result of LAST_INSERT_ID(). SELECT LAST_INSERT_ID(0); CREATE TABLE t1 ( id INT NOT NULL DEFAULT 0, last_id INT, PRIMARY KEY (id) ); CREATE TABLE t2 ( id INT NOT NULL AUTO_INCREMENT, last_id INT, PRIMARY KEY (id) ); delimiter |; CREATE PROCEDURE p1() BEGIN INSERT INTO t2 (last_id) VALUES (LAST_INSERT_ID()); INSERT INTO t1 (last_id) VALUES (LAST_INSERT_ID()); END| delimiter ;| CALL p1(); SELECT * FROM t1; SELECT * FROM t2; sync_slave_with_master; SELECT * FROM t1; SELECT * FROM t2; connection master; DROP PROCEDURE p1; DROP TABLE t1, t2; # # BUG#21726: Incorrect result with multiple invocations of # LAST_INSERT_ID # --disable_warnings DROP PROCEDURE IF EXISTS p1; DROP FUNCTION IF EXISTS f1; DROP FUNCTION IF EXISTS f2; DROP TABLE IF EXISTS t1, t2; --enable_warnings CREATE TABLE t1 ( i INT NOT NULL AUTO_INCREMENT PRIMARY KEY, j INT DEFAULT 0 ); CREATE TABLE t2 (i INT); delimiter |; CREATE PROCEDURE p1() BEGIN INSERT INTO t1 (i) VALUES (NULL); INSERT INTO t2 (i) VALUES (LAST_INSERT_ID()); INSERT INTO t1 (i) VALUES (NULL), (NULL); INSERT INTO t2 (i) VALUES (LAST_INSERT_ID()); END | CREATE FUNCTION f1() RETURNS INT MODIFIES SQL DATA BEGIN INSERT INTO t1 (i) VALUES (NULL); INSERT INTO t2 (i) VALUES (LAST_INSERT_ID()); INSERT INTO t1 (i) VALUES (NULL), (NULL); INSERT INTO t2 (i) VALUES (LAST_INSERT_ID()); RETURN 0; END | CREATE FUNCTION f2() RETURNS INT NOT DETERMINISTIC RETURN LAST_INSERT_ID() | delimiter ;| INSERT INTO t1 VALUES (NULL, -1); CALL p1(); SELECT f1(); INSERT INTO t1 VALUES (NULL, f2()), (NULL, LAST_INSERT_ID()), (NULL, LAST_INSERT_ID()), (NULL, f2()), (NULL, f2()); INSERT INTO t1 VALUES (NULL, f2()); INSERT INTO t1 VALUES (NULL, LAST_INSERT_ID()), (NULL, LAST_INSERT_ID(5)), (NULL, @@LAST_INSERT_ID); # Test replication of substitution "IS NULL" -> "= LAST_INSERT_ID". INSERT INTO t1 VALUES (NULL, 0), (NULL, LAST_INSERT_ID()); UPDATE t1 SET j= -1 WHERE i IS NULL; SELECT * FROM t1; SELECT * FROM t2; sync_slave_with_master; SELECT * FROM t1; SELECT * FROM t2; connection master; DROP PROCEDURE p1; DROP FUNCTION f1; DROP FUNCTION f2; DROP TABLE t1, t2; sync_slave_with_master; --echo Loading
sql/item_func.cc +32 −3 Original line number Diff line number Diff line Loading @@ -3345,6 +3345,34 @@ longlong Item_func_release_lock::val_int() } bool Item_func_last_insert_id::fix_fields(THD *thd, Item **ref) { DBUG_ASSERT(fixed == 0); if (Item_int_func::fix_fields(thd, ref)) return TRUE; if (arg_count == 0) { if (!thd->last_insert_id_used) { /* As this statement calls LAST_INSERT_ID(), set THD::last_insert_id_used and remember first generated insert id of the previous statement in THD::current_insert_id. */ thd->last_insert_id_used= TRUE; thd->current_insert_id= thd->last_insert_id; } null_value= FALSE; } thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT); return FALSE; } longlong Item_func_last_insert_id::val_int() { THD *thd= current_thd; Loading @@ -3354,12 +3382,13 @@ longlong Item_func_last_insert_id::val_int() longlong value= args[0]->val_int(); thd->insert_id(value); null_value= args[0]->null_value; return value; // Avoid side effect of insert_id() return value; } thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT); return thd->last_insert_id_used ? thd->current_insert_id : thd->insert_id(); return thd->current_insert_id; } /* This function is just used to test speed of different functions */ longlong Item_func_benchmark::val_int() Loading
sql/item_func.h +1 −0 Original line number Diff line number Diff line Loading @@ -891,6 +891,7 @@ class Item_func_last_insert_id :public Item_int_func if (arg_count) max_length= args[0]->max_length; } bool fix_fields(THD *thd, Item **ref); }; Loading
sql/log_event.cc +0 −1 Original line number Diff line number Diff line Loading @@ -3365,7 +3365,6 @@ int Intvar_log_event::exec_event(struct st_relay_log_info* rli) { switch (type) { case LAST_INSERT_ID_EVENT: thd->last_insert_id_used = 1; thd->last_insert_id = val; break; case INSERT_ID_EVENT: Loading