summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/rpl_insert_id.result18
-rw-r--r--mysql-test/t/rpl_insert_id.test17
-rw-r--r--sql/filesort.cc1
-rw-r--r--sql/item_func.cc1
-rw-r--r--sql/log.cc4
-rw-r--r--sql/set_var.cc1
-rw-r--r--sql/sql_class.cc10
-rw-r--r--sql/sql_class.h13
-rw-r--r--sql/sql_parse.cc1
-rw-r--r--sql/sql_select.cc8
10 files changed, 62 insertions, 12 deletions
diff --git a/mysql-test/r/rpl_insert_id.result b/mysql-test/r/rpl_insert_id.result
index d0360c8b9a3..d133a2ae8ed 100644
--- a/mysql-test/r/rpl_insert_id.result
+++ b/mysql-test/r/rpl_insert_id.result
@@ -272,6 +272,7 @@ DROP TABLE t1, t2;
DROP PROCEDURE IF EXISTS p1;
DROP FUNCTION IF EXISTS f1;
DROP FUNCTION IF EXISTS f2;
+DROP FUNCTION IF EXISTS f3;
DROP TABLE IF EXISTS t1, t2;
CREATE TABLE t1 (
i INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
@@ -295,6 +296,11 @@ RETURN 0;
END |
CREATE FUNCTION f2() RETURNS INT NOT DETERMINISTIC
RETURN LAST_INSERT_ID() |
+CREATE FUNCTION f3() RETURNS INT MODIFIES SQL DATA
+BEGIN
+INSERT INTO t2 (i) VALUES (LAST_INSERT_ID());
+RETURN 0;
+END |
INSERT INTO t1 VALUES (NULL, -1);
CALL p1();
SELECT f1();
@@ -307,6 +313,11 @@ 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;
+INSERT INTO t1 (i) VALUES (NULL);
+INSERT INTO t1 (i) VALUES (NULL);
+SELECT f3();
+f3()
+0
SELECT * FROM t1;
i j
1 -1
@@ -327,12 +338,15 @@ i j
16 13
17 -1
18 14
+19 0
+20 0
SELECT * FROM t2;
i
2
3
5
6
+19
SELECT * FROM t1;
i j
1 -1
@@ -353,15 +367,19 @@ i j
16 13
17 -1
18 14
+19 0
+20 0
SELECT * FROM t2;
i
2
3
5
6
+19
DROP PROCEDURE p1;
DROP FUNCTION f1;
DROP FUNCTION f2;
+DROP FUNCTION f3;
DROP TABLE t1, t2;
# End of 5.0 tests
diff --git a/mysql-test/t/rpl_insert_id.test b/mysql-test/t/rpl_insert_id.test
index 126aad68df4..331a913256c 100644
--- a/mysql-test/t/rpl_insert_id.test
+++ b/mysql-test/t/rpl_insert_id.test
@@ -299,6 +299,7 @@ DROP TABLE t1, t2;
DROP PROCEDURE IF EXISTS p1;
DROP FUNCTION IF EXISTS f1;
DROP FUNCTION IF EXISTS f2;
+DROP FUNCTION IF EXISTS f3;
DROP TABLE IF EXISTS t1, t2;
--enable_warnings
@@ -328,6 +329,12 @@ END |
CREATE FUNCTION f2() RETURNS INT NOT DETERMINISTIC
RETURN LAST_INSERT_ID() |
+
+CREATE FUNCTION f3() RETURNS INT MODIFIES SQL DATA
+BEGIN
+ INSERT INTO t2 (i) VALUES (LAST_INSERT_ID());
+ RETURN 0;
+END |
delimiter ;|
INSERT INTO t1 VALUES (NULL, -1);
@@ -342,6 +349,15 @@ INSERT INTO t1 VALUES (NULL, LAST_INSERT_ID()), (NULL, LAST_INSERT_ID(5)),
INSERT INTO t1 VALUES (NULL, 0), (NULL, LAST_INSERT_ID());
UPDATE t1 SET j= -1 WHERE i IS NULL;
+# Test statement-based replication of function calls.
+INSERT INTO t1 (i) VALUES (NULL);
+
+connection master1;
+INSERT INTO t1 (i) VALUES (NULL);
+
+connection master;
+SELECT f3();
+
SELECT * FROM t1;
SELECT * FROM t2;
@@ -353,6 +369,7 @@ connection master;
DROP PROCEDURE p1;
DROP FUNCTION f1;
DROP FUNCTION f2;
+DROP FUNCTION f3;
DROP TABLE t1, t2;
diff --git a/sql/filesort.cc b/sql/filesort.cc
index f13354d5c72..b063b416191 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -601,6 +601,7 @@ static inline void store_length(uchar *to, uint length, uint pack_length)
break;
case 3:
mi_int3store(to, length);
+ break;
default:
mi_int4store(to, length);
break;
diff --git a/sql/item_func.cc b/sql/item_func.cc
index e395a7a3af5..a294bbd7a71 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -3362,6 +3362,7 @@ bool Item_func_last_insert_id::fix_fields(THD *thd, Item **ref)
id of the previous statement in THD::current_insert_id.
*/
thd->last_insert_id_used= TRUE;
+ thd->last_insert_id_used_bin_log= TRUE;
thd->current_insert_id= thd->last_insert_id;
}
null_value= FALSE;
diff --git a/sql/log.cc b/sql/log.cc
index 212c6403666..960fc4f60c2 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -1705,7 +1705,7 @@ bool MYSQL_LOG::write(Log_event *event_info)
if (thd)
{
- if (thd->last_insert_id_used)
+ if (thd->last_insert_id_used_bin_log)
{
Intvar_log_event e(thd,(uchar) LAST_INSERT_ID_EVENT,
thd->current_insert_id);
@@ -1997,7 +1997,7 @@ bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length,
tmp_errno=errno;
strmov(db,thd->db);
}
- if (thd->last_insert_id_used)
+ if (thd->last_insert_id_used_bin_log)
{
end=strmov(end,",last_insert_id=");
end=longlong10_to_str((longlong) thd->current_insert_id,end,-10);
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 3dadc632911..d0268d7017b 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -2579,6 +2579,7 @@ byte *sys_var_last_insert_id::value_ptr(THD *thd, enum_var_type type,
of the previous statement in THD::current_insert_id.
*/
thd->last_insert_id_used= TRUE;
+ thd->last_insert_id_used_bin_log= TRUE;
thd->current_insert_id= thd->last_insert_id;
}
return (byte*) &thd->current_insert_id;
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 4d47ec338c0..645ac6e28f3 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -179,9 +179,9 @@ THD::THD()
lock_id(&main_lock_id),
user_time(0), in_sub_stmt(0), global_read_lock(0), is_fatal_error(0),
rand_used(0), time_zone_used(0),
- last_insert_id_used(0), insert_id_used(0), clear_next_insert_id(0),
- in_lock_tables(0), bootstrap(0), derived_tables_processing(FALSE),
- spcont(NULL)
+ last_insert_id_used(0), last_insert_id_used_bin_log(0), insert_id_used(0),
+ clear_next_insert_id(0), in_lock_tables(0), bootstrap(0),
+ derived_tables_processing(FALSE), spcont(NULL)
{
stmt_arena= this;
thread_stack= 0;
@@ -560,7 +560,7 @@ bool THD::store_globals()
THD::cleanup_after_query()
DESCRIPTION
- This function is used to reset thread data to it's default state.
+ This function is used to reset thread data to its default state.
NOTE
This function is not suitable for setting thread data to some
@@ -568,6 +568,7 @@ bool THD::store_globals()
different master threads may overwrite data of each other on
slave.
*/
+
void THD::cleanup_after_query()
{
last_insert_id_used= FALSE;
@@ -582,6 +583,7 @@ void THD::cleanup_after_query()
where= THD::DEFAULT_WHERE;
}
+
/*
Convert a string to another character set
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 6e1a061f279..62cfb0119aa 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -1340,12 +1340,21 @@ public:
/*
last_insert_id_used is set when current statement calls
- LAST_INSERT_ID() or reads @@LAST_INSERT_ID, so that binary log
- LAST_INSERT_ID_EVENT be generated.
+ LAST_INSERT_ID() or reads @@LAST_INSERT_ID.
*/
bool last_insert_id_used;
/*
+ last_insert_id_used is set when current statement or any stored
+ function called from this statement calls LAST_INSERT_ID() or
+ reads @@LAST_INSERT_ID, so that binary log LAST_INSERT_ID_EVENT be
+ generated. Required for statement-based binary log for issuing
+ "SET LAST_INSERT_ID= #" before "SELECT func()", if func() reads
+ LAST_INSERT_ID.
+ */
+ bool last_insert_id_used_bin_log;
+
+ /*
insert_id_used is set when current statement updates
THD::last_insert_id, so that binary log INSERT_ID_EVENT be
generated.
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 1b69e266442..c62c286cfdb 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -5651,6 +5651,7 @@ void mysql_reset_thd_for_next_command(THD *thd)
thd->free_list= 0;
thd->select_number= 1;
thd->query_start_used= thd->insert_id_used=0;
+ thd->last_insert_id_used_bin_log= FALSE;
thd->is_fatal_error= thd->time_zone_used= 0;
thd->server_status&= ~ (SERVER_MORE_RESULTS_EXISTS |
SERVER_QUERY_NO_INDEX_USED |
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 274251f2df3..6d17faf8509 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -8165,11 +8165,11 @@ remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value)
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.
+ Set THD::last_insert_id_used_bin_log manually, as this
+ statement uses LAST_INSERT_ID() in a sense, and should
+ issue LAST_INSERT_ID_EVENT.
*/
- thd->last_insert_id_used= TRUE;
+ thd->last_insert_id_used_bin_log= TRUE;
cond=new_cond;
/*