MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:Alexander Nozdrin Date:July 27 2006 10:49pm
Subject:bk commit into 5.0 tree (anozdrin:1.2243) BUG#20438
View as plain text  
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#20438Alexander Nozdrin28 Jul