Below is the list of changes that have just been committed into a local
5.0 repository of alik. When alik does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet@stripped, 2006-07-28 02:49:18+04:00, anozdrin@booka. +12 -0
Fix for BUG#20438: CREATE statements for views, stored routines and triggers
can be not replicable.
Now CREATE statements for writing in the binlog are created as follows:
- the beginning of the statement is re-created;
- the rest of the statement is copied from the original query.
The problem appears when there is a version-specific comment (produced by
mysqldump), started in the re-created part of the statement and closed in the
copied part -- there is closing comment-parenthesis, but there is no opening
one.
The proper fix could be to re-create original statement, but we can not
implement it in 5.0. So, for 5.0 the fix is just to cut closing
comment-parenthesis. This technique is also used for SHOW CREATE PROCEDURE
statement (so we are able to reuse existing code).
mysql-test/r/rpl_sp.result@stripped, 2006-07-28 02:49:11+04:00, anozdrin@booka. +44 -0
Updated result file.
mysql-test/r/rpl_trigger.result@stripped, 2006-07-28 02:49:11+04:00, anozdrin@booka. +47 -0
Updated result file.
mysql-test/r/rpl_view.result@stripped, 2006-07-28 02:49:11+04:00, anozdrin@booka. +37 -0
Updated result file.
mysql-test/t/rpl_sp.test@stripped, 2006-07-28 02:49:11+04:00, anozdrin@booka. +80 -0
Added test case for BUG#20438.
mysql-test/t/rpl_trigger.test@stripped, 2006-07-28 02:49:11+04:00, anozdrin@booka. +92 -0
Added test case for BUG#20438.
mysql-test/t/rpl_view.test@stripped, 2006-07-28 02:49:11+04:00, anozdrin@booka. +84 -0
Added test case for BUG#20438.
sql/sp.cc@stripped, 2006-07-28 02:49:11+04:00, anozdrin@booka. +4 -1
Trim comments at the end.
sql/sp_head.cc@stripped, 2006-07-28 02:49:11+04:00, anozdrin@booka. +1 -4
Moved this code to the separate function to be re-used.
sql/sql_lex.cc@stripped, 2006-07-28 02:49:12+04:00, anozdrin@booka. +24 -0
Added a new function.
sql/sql_lex.h@stripped, 2006-07-28 02:49:12+04:00, anozdrin@booka. +1 -1
Added a new function.
sql/sql_trigger.cc@stripped, 2006-07-28 02:49:12+04:00, anozdrin@booka. +4 -1
Trim comments at the end.
sql/sql_view.cc@stripped, 2006-07-28 02:49:12+04:00, anozdrin@booka. +4 -2
Trim comments at the end.
# This is a BitKeeper patch. What follows are the unified diffs for the
# set of deltas contained in the patch. The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: anozdrin
# Host: booka.
# Root: /home/alik/MySQL/devel/5.0-rt-bug20438
--- 1.192/sql/sql_lex.cc 2006-07-28 02:49:30 +04:00
+++ 1.193/sql/sql_lex.cc 2006-07-28 02:49:30 +04:00
@@ -1054,6 +1054,30 @@ int MYSQLlex(void *arg, void *yythd)
}
}
+
+/*
+ Skip comment in the end of statement.
+
+ SYNOPSIS
+ skip_rear_comments()
+ begin pointer to the beginning of statement
+ end pointer to the end of statement
+
+ DESCRIPTION
+ The function is intended to trim comments at the end of the statement.
+
+ RETURN
+ Pointer to the last non-comment symbol of the statement.
+*/
+
+uchar *skip_rear_comments(uchar *begin, uchar *end)
+{
+ while (begin < end && (end[-1] <= ' ' || end[-1] == '*' ||
+ end[-1] == '/' || end[-1] == ';'))
+ end-= 1;
+ return end;
+}
+
/*
st_select_lex structures initialisations
*/
--- 1.222/sql/sql_lex.h 2006-07-28 02:49:30 +04:00
+++ 1.223/sql/sql_lex.h 2006-07-28 02:49:31 +04:00
@@ -1115,4 +1115,4 @@ extern void lex_free(void);
extern void lex_start(THD *thd, uchar *buf,uint length);
extern void lex_end(LEX *lex);
extern int MYSQLlex(void *arg, void *yythd);
-
+extern uchar *skip_rear_comments(uchar *begin, uchar *end);
--- 1.4/mysql-test/r/rpl_view.result 2006-07-28 02:49:31 +04:00
+++ 1.5/mysql-test/r/rpl_view.result 2006-07-28 02:49:31 +04:00
@@ -54,3 +54,40 @@ slave-bin.000001 # Query 1 # use `test`;
slave-bin.000001 # Query 1 # use `test`; ALTER ALGORITHM=UNDEFINED DEFINER=root@localhost SQL SECURITY DEFINER VIEW v1 AS select a as b from t1
slave-bin.000001 # Query 1 # use `test`; drop view v1
slave-bin.000001 # Query 1 # use `test`; drop table t1
+
+---> Test for BUG#20438
+
+---> Preparing environment...
+---> connection: master
+DROP TABLE IF EXISTS t1;
+DROP VIEW IF EXISTS v1;
+
+---> Synchronizing slave with master...
+
+---> connection: master
+
+---> Creating objects...
+CREATE TABLE t1(c INT);
+/*!50003 CREATE VIEW v1 AS SELECT * FROM t1 */;
+
+---> Inserting value...
+INSERT INTO t1 VALUES(1);
+
+---> Checking on master...
+SELECT * FROM t1;
+c
+1
+
+---> Synchronizing slave with master...
+---> connection: master
+
+---> Checking on slave...
+SELECT * FROM t1;
+c
+1
+
+---> connection: master
+
+---> Cleaning up...
+DROP VIEW v1;
+DROP TABLE t1;
--- 1.3/mysql-test/t/rpl_view.test 2006-07-28 02:49:31 +04:00
+++ 1.4/mysql-test/t/rpl_view.test 2006-07-28 02:49:31 +04:00
@@ -45,3 +45,87 @@ drop table t1;
sync_slave_with_master;
--replace_column 2 # 5 #
show binlog events limit 1,100;
+
+
+
+#
+# BUG#20438: CREATE statements for views, stored routines and triggers can be
+# not replicable.
+#
+
+--echo
+--echo ---> Test for BUG#20438
+
+# Prepare environment.
+
+--echo
+--echo ---> Preparing environment...
+--echo ---> connection: master
+--connection master
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+DROP VIEW IF EXISTS v1;
+--enable_warnings
+
+--echo
+--echo ---> Synchronizing slave with master...
+
+--save_master_pos
+--connection slave
+--sync_with_master
+
+--echo
+--echo ---> connection: master
+--connection master
+
+# Test.
+
+--echo
+--echo ---> Creating objects...
+
+CREATE TABLE t1(c INT);
+
+/*!50003 CREATE VIEW v1 AS SELECT * FROM t1 */;
+
+--echo
+--echo ---> Inserting value...
+
+INSERT INTO t1 VALUES(1);
+
+--echo
+--echo ---> Checking on master...
+
+SELECT * FROM t1;
+
+--echo
+--echo ---> Synchronizing slave with master...
+
+--save_master_pos
+--connection slave
+--sync_with_master
+
+--echo ---> connection: master
+
+--echo
+--echo ---> Checking on slave...
+
+SELECT * FROM t1;
+
+# Cleanup.
+
+--echo
+--echo ---> connection: master
+--connection master
+
+--echo
+--echo ---> Cleaning up...
+
+DROP VIEW v1;
+DROP TABLE t1;
+
+--save_master_pos
+--connection slave
+--sync_with_master
+--connection master
+
--- 1.89/sql/sql_view.cc 2006-07-28 02:49:31 +04:00
+++ 1.90/sql/sql_view.cc 2006-07-28 02:49:31 +04:00
@@ -671,8 +671,10 @@ static int mysql_register_view(THD *thd,
view->query.str= (char*)str.ptr();
view->query.length= str.length()-1; // we do not need last \0
view->source.str= thd->query + thd->lex->create_view_select_start;
- view->source.length= (thd->query_length -
- thd->lex->create_view_select_start);
+ view->source.length= (char *)skip_rear_comments((uchar *)view->source.str,
+ (uchar *)thd->query +
+ thd->query_length) -
+ view->source.str;
view->file_version= 1;
view->calc_md5(md5);
view->md5.str= md5;
--- 1.53/sql/sql_trigger.cc 2006-07-28 02:49:31 +04:00
+++ 1.54/sql/sql_trigger.cc 2006-07-28 02:49:31 +04:00
@@ -295,7 +295,10 @@ end:
append_definer(thd, &log_query, &definer_user, &definer_host);
}
- log_query.append(thd->lex->stmt_definition_begin);
+ log_query.append(thd->lex->stmt_definition_begin,
+ (char *)thd->lex->sphead->m_body_begin -
+ thd->lex->stmt_definition_begin +
+ thd->lex->sphead->m_body.length);
}
/* Such a statement can always go directly to binlog, no trans cache. */
--- 1.17/mysql-test/r/rpl_sp.result 2006-07-28 02:49:31 +04:00
+++ 1.18/mysql-test/r/rpl_sp.result 2006-07-28 02:49:31 +04:00
@@ -420,4 +420,48 @@ SELECT * FROM t1;
col
test
DROP PROCEDURE p1;
+
+---> Test for BUG#20438
+
+---> Preparing environment...
+---> connection: master
+DROP PROCEDURE IF EXISTS p1;
+DROP FUNCTION IF EXISTS f1;
+
+---> Synchronizing slave with master...
+
+---> connection: master
+
+---> Creating procedure...
+/*!50003 CREATE PROCEDURE p1() SET @a = 1 */;
+/*!50003 CREATE FUNCTION f1() RETURNS INT RETURN 0 */;
+
+---> Checking on master...
+SHOW CREATE PROCEDURE p1;
+Procedure sql_mode Create Procedure
+p1 CREATE DEFINER=`root`@`localhost` PROCEDURE `p1`()
+SET @a = 1
+SHOW CREATE FUNCTION f1;
+Function sql_mode Create Function
+f1 CREATE DEFINER=`root`@`localhost` FUNCTION `f1`() RETURNS int(11)
+RETURN 0
+
+---> Synchronizing slave with master...
+---> connection: master
+
+---> Checking on slave...
+SHOW CREATE PROCEDURE p1;
+Procedure sql_mode Create Procedure
+p1 CREATE DEFINER=`root`@`localhost` PROCEDURE `p1`()
+SET @a = 1
+SHOW CREATE FUNCTION f1;
+Function sql_mode Create Function
+f1 CREATE DEFINER=`root`@`localhost` FUNCTION `f1`() RETURNS int(11)
+RETURN 0
+
+---> connection: master
+
+---> Cleaning up...
+DROP PROCEDURE p1;
+DROP FUNCTION f1;
drop table t1;
--- 1.12/mysql-test/t/rpl_sp.test 2006-07-28 02:49:31 +04:00
+++ 1.13/mysql-test/t/rpl_sp.test 2006-07-28 02:49:31 +04:00
@@ -435,6 +435,86 @@ connection master;
DROP PROCEDURE p1;
+
+#
+# BUG#20438: CREATE statements for views, stored routines and triggers can be
+# not replicable.
+#
+
+--echo
+--echo ---> Test for BUG#20438
+
+# Prepare environment.
+
+--echo
+--echo ---> Preparing environment...
+--echo ---> connection: master
+--connection master
+
+--disable_warnings
+DROP PROCEDURE IF EXISTS p1;
+DROP FUNCTION IF EXISTS f1;
+--enable_warnings
+
+--echo
+--echo ---> Synchronizing slave with master...
+
+--save_master_pos
+--connection slave
+--sync_with_master
+
+--echo
+--echo ---> connection: master
+--connection master
+
+# Test.
+
+--echo
+--echo ---> Creating procedure...
+
+/*!50003 CREATE PROCEDURE p1() SET @a = 1 */;
+
+/*!50003 CREATE FUNCTION f1() RETURNS INT RETURN 0 */;
+
+--echo
+--echo ---> Checking on master...
+
+SHOW CREATE PROCEDURE p1;
+SHOW CREATE FUNCTION f1;
+
+--echo
+--echo ---> Synchronizing slave with master...
+
+--save_master_pos
+--connection slave
+--sync_with_master
+
+--echo ---> connection: master
+
+--echo
+--echo ---> Checking on slave...
+
+SHOW CREATE PROCEDURE p1;
+SHOW CREATE FUNCTION f1;
+
+# Cleanup.
+
+--echo
+--echo ---> connection: master
+--connection master
+
+--echo
+--echo ---> Cleaning up...
+
+DROP PROCEDURE p1;
+DROP FUNCTION f1;
+
+--save_master_pos
+--connection slave
+--sync_with_master
+--connection master
+
+
# cleanup
connection master;
drop table t1;
--- 1.8/mysql-test/r/rpl_trigger.result 2006-07-28 02:49:31 +04:00
+++ 1.9/mysql-test/r/rpl_trigger.result 2006-07-28 02:49:31 +04:00
@@ -896,3 +896,50 @@ Tables_in_test (t_)
SHOW TRIGGERS;
Trigger Event Table Statement Timing Created sql_mode Definer
RESET MASTER;
+START SLAVE;
+
+---> Test for BUG#20438
+
+---> Preparing environment...
+---> connection: master
+DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t2;
+
+---> Synchronizing slave with master...
+
+---> connection: master
+
+---> Creating objects...
+CREATE TABLE t1(c INT);
+CREATE TABLE t2(c INT);
+/*!50003 CREATE TRIGGER t1_bi BEFORE INSERT ON t1
+FOR EACH ROW
+INSERT INTO t2 VALUES(NEW.c * 10) */;
+
+---> Inserting value...
+INSERT INTO t1 VALUES(1);
+
+---> Checking on master...
+SELECT * FROM t1;
+c
+1
+SELECT * FROM t2;
+c
+10
+
+---> Synchronizing slave with master...
+---> connection: master
+
+---> Checking on slave...
+SELECT * FROM t1;
+c
+1
+SELECT * FROM t2;
+c
+10
+
+---> connection: master
+
+---> Cleaning up...
+DROP TABLE t1;
+DROP TABLE t2;
--- 1.7/mysql-test/t/rpl_trigger.test 2006-07-28 02:49:31 +04:00
+++ 1.8/mysql-test/t/rpl_trigger.test 2006-07-28 02:49:31 +04:00
@@ -331,6 +331,98 @@ SHOW TRIGGERS;
RESET MASTER;
+# Restart slave.
+
+connection slave;
+START SLAVE;
+
+
+#
+# BUG#20438: CREATE statements for views, stored routines and triggers can be
+# not replicable.
+#
+
+--echo
+--echo ---> Test for BUG#20438
+
+# Prepare environment.
+
+--echo
+--echo ---> Preparing environment...
+--echo ---> connection: master
+--connection master
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t2;
+--enable_warnings
+
+--echo
+--echo ---> Synchronizing slave with master...
+
+--save_master_pos
+--connection slave
+--sync_with_master
+
+--echo
+--echo ---> connection: master
+--connection master
+
+# Test.
+
+--echo
+--echo ---> Creating objects...
+
+CREATE TABLE t1(c INT);
+CREATE TABLE t2(c INT);
+
+/*!50003 CREATE TRIGGER t1_bi BEFORE INSERT ON t1
+ FOR EACH ROW
+ INSERT INTO t2 VALUES(NEW.c * 10) */;
+
+--echo
+--echo ---> Inserting value...
+
+INSERT INTO t1 VALUES(1);
+
+--echo
+--echo ---> Checking on master...
+
+SELECT * FROM t1;
+SELECT * FROM t2;
+
+--echo
+--echo ---> Synchronizing slave with master...
+
+--save_master_pos
+--connection slave
+--sync_with_master
+
+--echo ---> connection: master
+
+--echo
+--echo ---> Checking on slave...
+
+SELECT * FROM t1;
+SELECT * FROM t2;
+
+# Cleanup.
+
+--echo
+--echo ---> connection: master
+--connection master
+
+--echo
+--echo ---> Cleaning up...
+
+DROP TABLE t1;
+DROP TABLE t2;
+
+--save_master_pos
+--connection slave
+--sync_with_master
+--connection master
+
#
# End of tests
--- 1.114/sql/sp.cc 2006-07-28 02:49:31 +04:00
+++ 1.115/sql/sp.cc 2006-07-28 02:49:31 +04:00
@@ -633,7 +633,10 @@ db_create_routine(THD *thd, int type, sp
log_query.append(STRING_WITH_LEN("CREATE "));
append_definer(thd, &log_query, &thd->lex->definer->user,
&thd->lex->definer->host);
- log_query.append(thd->lex->stmt_definition_begin);
+ log_query.append(thd->lex->stmt_definition_begin,
+ (char *)sp->m_body_begin -
+ thd->lex->stmt_definition_begin +
+ sp->m_body.length);
/* Such a statement can always go directly to binlog, no trans cache */
Query_log_event qinfo(thd, log_query.c_ptr(), log_query.length(), 0,
--- 1.220/sql/sp_head.cc 2006-07-28 02:49:31 +04:00
+++ 1.221/sql/sp_head.cc 2006-07-28 02:49:31 +04:00
@@ -527,10 +527,7 @@ sp_head::init_strings(THD *thd, LEX *lex
Trim "garbage" at the end. This is sometimes needed with the
"/ * ! VERSION... * /" wrapper in dump files.
*/
- while (m_body_begin < endp &&
- (endp[-1] <= ' ' || endp[-1] == '*' ||
- endp[-1] == '/' || endp[-1] == ';'))
- endp-= 1;
+ endp= skip_rear_comments(m_body_begin, endp);
m_body.length= endp - m_body_begin;
m_body.str= strmake_root(root, (char *)m_body_begin, m_body.length);
| Thread |
|---|
| • bk commit into 5.0 tree (anozdrin:1.2243) BUG#20438 | Alexander Nozdrin | 28 Jul |