List:Commits« Previous MessageNext Message »
From:Nuno Carvalho Date:March 27 2012 8:45am
Subject:bzr push into mysql-trunk branch (nuno.carvalho:3866 to 3867) Bug#13810456
View as plain text  
 3867 Nuno Carvalho	2012-03-27 [merge]
      BUG#13810456: GTID: UNTIL_SQL_BEFORE_GTID DOES NOT WORK
      Problem:
       The logic for START SLAVE UNTIL SQL_BEFORE_GTIDS was wrong, it stopped
       SQL thread before the last GTID and not any GTID present on the
       parameter.
      
      Solution:
       1. Fixed START SLAVE UNTIL SQL_BEFORE_GTIDS logic to stop SQL thread
          before any GTID present on the parameter is applied.
       2. Added START SLAVE UNTIL SQL_AFTER_GTIDS implementation, that stops
          after all GTIDs present on the parameter are applied.
       3. Call sql_print_information from this function in order to remove
          duplicated code from the places where it is called.

    added:
      mysql-test/suite/rpl/r/rpl_gtid_sql_until_before_after.result
      mysql-test/suite/rpl/t/rpl_gtid_sql_until_before_after.test
    modified:
      sql/rpl_gtid.h
      sql/rpl_gtid_set.cc
      sql/rpl_rli.cc
      sql/rpl_rli.h
      sql/rpl_slave.cc
      sql/sql_lex.h
      sql/sql_yacc.yy
 3866 Tor Didriksen	2012-03-27
      Bug#13880759 BUILD IS BROKEN WHEN -DWITH_SSL=SYSTEM
      
      Previous patch broke it for WITH_SSL=NO
      Fixed #including my_global.h when it is actually needed.

    modified:
      include/my_md5.h
=== added file 'mysql-test/suite/rpl/r/rpl_gtid_sql_until_before_after.result'
--- a/mysql-test/suite/rpl/r/rpl_gtid_sql_until_before_after.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl/r/rpl_gtid_sql_until_before_after.result	2012-03-27 08:43:25 +0000
@@ -0,0 +1,112 @@
+include/master-slave.inc
+Warnings:
+Note	1756	Sending passwords in plain text without SSL/TLS is extremely insecure.
+Note	1757	Storing MySQL user name or password information in the master.info repository is not secure and is therefore not recommended. Please see the MySQL Manual for more about this issue and possible alternatives.
+[connection master]
+include/rpl_set_gtid_mode.inc
+CREATE TABLE t1(c1 INTEGER) ENGINE= Innodb;
+[connection slave]
+include/stop_slave.inc
+[connection master]
+INSERT INTO t1 VALUES(2);
+INSERT INTO t1 VALUES(3);
+INSERT INTO t1 VALUES(4);
+INSERT INTO t1 VALUES(5);
+INSERT INTO t1 VALUES(6);
+INSERT INTO t1 VALUES(7);
+INSERT INTO t1 VALUES(8);
+INSERT INTO t1 VALUES(9);
+INSERT INTO t1 VALUES(10);
+[connection slave]
+SQL thread must stop *before* INSERT 4
+START SLAVE UNTIL SQL_BEFORE_GTIDS= "MASTER_UUID:4-5";
+include/wait_for_slave_sql_to_stop.inc
+SELECT * FROM t1;
+c1
+2
+3
+SQL thread must stop *after* INSERT 5
+START SLAVE UNTIL SQL_AFTER_GTIDS= "MASTER_UUID:4-5";
+include/wait_for_slave_sql_to_stop.inc
+SELECT * FROM t1;
+c1
+2
+3
+4
+5
+SQL thread must stop *before* INSERT 6
+START SLAVE UNTIL SQL_BEFORE_GTIDS= "MASTER_UUID:2-7";
+include/wait_for_slave_sql_to_stop.inc
+SELECT * FROM t1;
+c1
+2
+3
+4
+5
+SQL thread must stop *after* INSERT 5
+1-5 are already applied so it will stop immediately
+START SLAVE UNTIL SQL_AFTER_GTIDS= "MASTER_UUID:1-5";
+include/wait_for_slave_sql_to_stop.inc
+SELECT * FROM t1;
+c1
+2
+3
+4
+5
+SQL thread must stop *before* INSERT 10
+START SLAVE UNTIL SQL_BEFORE_GTIDS= "MASTER_UUID:10";
+include/wait_for_slave_sql_to_stop.inc
+SELECT * FROM t1;
+c1
+2
+3
+4
+5
+6
+7
+8
+9
+SQL thread must stop *before* INSERT 3-6
+3-6 is already applied so it will stop immediately
+START SLAVE UNTIL SQL_BEFORE_GTIDS= "MASTER_UUID:3-6";
+include/wait_for_slave_sql_to_stop.inc
+SELECT * FROM t1;
+c1
+2
+3
+4
+5
+6
+7
+8
+9
+SQL thread must stop *before* INSERT 9
+9 is already applied so it will stop immediately
+START SLAVE UNTIL SQL_BEFORE_GTIDS= "MASTER_UUID:9";
+include/wait_for_slave_sql_to_stop.inc
+SELECT * FROM t1;
+c1
+2
+3
+4
+5
+6
+7
+8
+9
+Sync slave with master
+include/start_slave_sql.inc
+SELECT SQL_THREAD_WAIT_AFTER_GTIDS('MASTER_UUID:10', 300);
+SELECT * FROM t1;
+c1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+DROP TABLE t1;
+include/rpl_end.inc

=== added file 'mysql-test/suite/rpl/t/rpl_gtid_sql_until_before_after.test'
--- a/mysql-test/suite/rpl/t/rpl_gtid_sql_until_before_after.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl/t/rpl_gtid_sql_until_before_after.test	2012-03-27 08:43:25 +0000
@@ -0,0 +1,107 @@
+# BUG#13810456: GTID: UNTIL_SQL_BEFORE_GTID DOES NOT WORK
+#
+# This test performs multiple invocations of
+# START SLAVE UNTIL SQL_BEFORE_GTIDS and START SLAVE UNTIL SQL_AFTER_GTIDS
+# to demonstrate its correct operation.
+#
+# Create a set of transactions on the master and applied them individually
+# by using START SLAVE UNTIL SQL_BEFORE_GTIDS and
+# START SLAVE UNTIL SQL_AFTER_GTIDS with different sets of missing and/or
+# already applied GTIDs.
+#
+--source include/master-slave.inc
+--source include/rpl_set_gtid_mode.inc
+
+--connection master
+--let $master_uuid= query_get_value(SELECT @@SERVER_UUID, @@SERVER_UUID, 1)
+CREATE TABLE t1(c1 INTEGER) ENGINE= Innodb;
+--sync_slave_with_master
+--echo [connection slave]
+--source include/stop_slave.inc
+
+# Generate a set of transactions on the master.
+# INSERT value is the equal to sequence number.
+--echo [connection master]
+--connection master
+--let $i=2
+while ($i != 11)
+{
+  --eval INSERT INTO t1 VALUES($i)
+  --inc $i
+}
+
+--connection slave
+--echo [connection slave]
+--echo SQL thread must stop *before* INSERT 4
+--disable_query_log
+--replace_result $master_uuid MASTER_UUID
+--enable_query_log
+--eval START SLAVE UNTIL SQL_BEFORE_GTIDS= "$master_uuid:4-5"
+--source include/wait_for_slave_sql_to_stop.inc
+SELECT * FROM t1;
+
+--echo SQL thread must stop *after* INSERT 5
+--disable_query_log
+--replace_result $master_uuid MASTER_UUID
+--enable_query_log
+--eval START SLAVE UNTIL SQL_AFTER_GTIDS= "$master_uuid:4-5"
+--source include/wait_for_slave_sql_to_stop.inc
+SELECT * FROM t1;
+
+--echo SQL thread must stop *before* INSERT 6
+--disable_query_log
+--replace_result $master_uuid MASTER_UUID
+--enable_query_log
+--eval START SLAVE UNTIL SQL_BEFORE_GTIDS= "$master_uuid:2-7"
+--source include/wait_for_slave_sql_to_stop.inc
+SELECT * FROM t1;
+
+--echo SQL thread must stop *after* INSERT 5
+--echo 1-5 are already applied so it will stop immediately
+--disable_query_log
+--replace_result $master_uuid MASTER_UUID
+--enable_query_log
+--eval START SLAVE UNTIL SQL_AFTER_GTIDS= "$master_uuid:1-5"
+--source include/wait_for_slave_sql_to_stop.inc
+SELECT * FROM t1;
+
+--echo SQL thread must stop *before* INSERT 10
+--disable_query_log
+--replace_result $master_uuid MASTER_UUID
+--enable_query_log
+--eval START SLAVE UNTIL SQL_BEFORE_GTIDS= "$master_uuid:10"
+--source include/wait_for_slave_sql_to_stop.inc
+SELECT * FROM t1;
+
+--echo SQL thread must stop *before* INSERT 3-6
+--echo 3-6 is already applied so it will stop immediately
+--disable_query_log
+--replace_result $master_uuid MASTER_UUID
+--enable_query_log
+--eval START SLAVE UNTIL SQL_BEFORE_GTIDS= "$master_uuid:3-6"
+--source include/wait_for_slave_sql_to_stop.inc
+SELECT * FROM t1;
+
+--echo SQL thread must stop *before* INSERT 9
+--echo 9 is already applied so it will stop immediately
+--disable_query_log
+--replace_result $master_uuid MASTER_UUID
+--enable_query_log
+--eval START SLAVE UNTIL SQL_BEFORE_GTIDS= "$master_uuid:9"
+--source include/wait_for_slave_sql_to_stop.inc
+SELECT * FROM t1;
+
+--echo Sync slave with master
+--source include/start_slave_sql.inc
+--disable_query_log
+--replace_result $master_uuid MASTER_UUID
+--enable_query_log
+--disable_result_log
+--eval SELECT SQL_THREAD_WAIT_AFTER_GTIDS('$master_uuid:10', 300)
+--enable_result_log
+SELECT * FROM t1;
+
+# Cleanup
+--connection master
+DROP TABLE t1;
+--source include/rpl_end.inc

=== modified file 'sql/rpl_gtid.h'
--- a/sql/rpl_gtid.h	2012-02-28 12:04:45 +0000
+++ b/sql/rpl_gtid.h	2012-03-27 08:43:25 +0000
@@ -1003,6 +1003,11 @@ public:
   enum_return_status ensure_sidno(rpl_sidno sidno);
   /// Returns true if this Gtid_set is a subset of the other Gtid_set.
   bool is_subset(const Gtid_set *super) const;
+  /// Returns true if there is a least one element of this Gtid_set in
+  /// the other Gtid_set.
+  bool is_intersection(const Gtid_set *other) const;
+  /// Result is the intersection of this Gtid_set and the other Gtid_set.
+  enum_return_status intersection(const Gtid_set *other, Gtid_set *result);
   /// Returns true if this Gtid_set is empty.
   bool is_empty() const
   {

=== modified file 'sql/rpl_gtid_set.cc'
--- a/sql/rpl_gtid_set.cc	2012-02-24 11:29:46 +0000
+++ b/sql/rpl_gtid_set.cc	2012-03-27 08:43:25 +0000
@@ -1087,6 +1087,49 @@ bool Gtid_set::is_subset(const Gtid_set
 }
 
 
+bool Gtid_set::is_intersection(const Gtid_set *other) const
+{
+  DBUG_ENTER("Gtid_set::is_intersection(Gtid_set *)");
+  if (sid_lock != NULL)
+    sid_lock->assert_some_wrlock();
+  Gtid_iterator git(this);
+  Gtid g= git.get();
+  while (g.sidno != 0)
+  {
+    if (other->contains_gtid(g.sidno, g.gno))
+      DBUG_RETURN(true);
+    git.next();
+    g= git.get();
+  }
+  DBUG_RETURN(false);
+}
+
+
+enum_return_status
+Gtid_set::intersection(const Gtid_set *other, Gtid_set *result)
+{
+  DBUG_ENTER("Gtid_set::intersection(Gtid_set *, Gtid_set *)");
+  if (sid_lock != NULL)
+    sid_lock->assert_some_wrlock();
+  DBUG_ASSERT(result != NULL);
+  result->clear();
+  Gtid_iterator git(this);
+  Gtid g= git.get();
+  while (g.sidno != 0)
+  {
+    if (other->contains_gtid(g.sidno, g.gno))
+    {
+      if (result->ensure_sidno(g.sidno) ||
+          result->_add_gtid(g.sidno, g.gno))
+        RETURN_REPORTED_ERROR;
+    }
+    git.next();
+    g= git.get();
+  }
+  RETURN_OK;
+}
+
+
 void Gtid_set::encode(uchar *buf) const
 {
   DBUG_ENTER("Gtid_set::encode(uchar *)");

=== modified file 'sql/rpl_rli.cc'
--- a/sql/rpl_rli.cc	2012-03-14 09:52:49 +0000
+++ b/sql/rpl_rli.cc	2012-03-27 08:43:25 +0000
@@ -80,8 +80,9 @@ Relay_log_info::Relay_log_info(bool is_s
    last_master_timestamp(0), slave_skip_counter(0),
    abort_pos_wait(0), until_condition(UNTIL_NONE),
    until_log_pos(0),
-   until_gtids_obj(&global_sid_map),
-   request_gtids_obj(&global_sid_map),
+   until_sql_gtids(&global_sid_map),
+   until_sql_gtids_seen(&global_sid_map),
+   until_sql_gtids_first_event(true),
    retried_trans(0),
    tables_to_lock(0), tables_to_lock_count(0),
    rows_query_ev(NULL), last_event_start_time(0),
@@ -297,8 +298,9 @@ void Relay_log_info::clear_until_conditi
   until_condition= Relay_log_info::UNTIL_NONE;
   until_log_name[0]= 0;
   until_log_pos= 0;
-  request_gtids_obj.clear();
-  until_gtids_obj.clear();
+  until_sql_gtids.clear();
+  until_sql_gtids_seen.clear();
+  until_sql_gtids_first_event= true;
   DBUG_VOID_RETURN;
 }
 
@@ -1087,9 +1089,10 @@ bool Relay_log_info::is_until_satisfied(
                     "condition is bad.";
   DBUG_ENTER("Relay_log_info::is_until_satisfied");
 
-  DBUG_ASSERT(until_condition != UNTIL_NONE);
-
-  if (until_condition == UNTIL_MASTER_POS || until_condition == UNTIL_RELAY_POS)
+  switch (until_condition)
+  {
+  case UNTIL_MASTER_POS:
+  case UNTIL_RELAY_POS:
   {
     const char *log_name= NULL;
     ulonglong log_pos= 0;
@@ -1097,7 +1100,7 @@ bool Relay_log_info::is_until_satisfied(
     if (until_condition == UNTIL_MASTER_POS)
     {
       if (ev && ev->server_id == (uint32) ::server_id && !replicate_same_server_id)
-        DBUG_RETURN(FALSE);
+        DBUG_RETURN(false);
       log_name= group_master_log_name;
       log_pos= (!ev)? group_master_log_pos :
         ((thd->variables.option_bits & OPTION_BEGIN || !ev->log_pos) ?
@@ -1154,48 +1157,99 @@ bool Relay_log_info::is_until_satisfied(
         }
         else
         {
-          /* Probably error so we aborting */
+          /* Base names do not match, so we abort */
           sql_print_error("%s", error_msg);
-          DBUG_RETURN(TRUE);
+          DBUG_RETURN(true);
         }
       }
       else
         DBUG_RETURN(until_log_pos == 0);
     }
 
-    DBUG_RETURN(((until_log_names_cmp_result == UNTIL_LOG_NAMES_CMP_EQUAL &&
-             log_pos >= until_log_pos) ||
-            until_log_names_cmp_result == UNTIL_LOG_NAMES_CMP_GREATER));
-  }
-  else if (ev != NULL && ev->get_type_code() == GTID_LOG_EVENT)
-  {
-    global_sid_lock.wrlock();
-    if (until_gtids_obj._remove_gtid(((Gtid_log_event *)(ev))->get_sidno(false),
-                                     ((Gtid_log_event *)(ev))->get_gno())
-        != RETURN_STATUS_OK || until_gtids_obj.is_empty())
+    if (((until_log_names_cmp_result == UNTIL_LOG_NAMES_CMP_EQUAL &&
+          log_pos >= until_log_pos) ||
+         until_log_names_cmp_result == UNTIL_LOG_NAMES_CMP_GREATER))
     {
-      global_sid_lock.unlock();
+      char buf[22];
+      sql_print_information("Slave SQL thread stopped because it reached its"
+                            " UNTIL position %s", llstr(until_pos(), buf));
       DBUG_RETURN(true);
     }
+    DBUG_RETURN(false);
+  }
 
-#ifndef DBUG_OFF
-    char* buffer= NULL;
-    if (!(buffer= (char *) my_malloc(until_gtids_obj.get_string_length() + 1,
-                                     MYF(MY_WME))))
+  case UNTIL_SQL_BEFORE_GTIDS:
+    if (ev != NULL && ev->get_type_code() == GTID_LOG_EVENT)
     {
+      Gtid_log_event *gev= (Gtid_log_event *)ev;
+      global_sid_lock.rdlock();
+      if (until_sql_gtids.contains_gtid(gev->get_sidno(false), gev->get_gno()))
+      {
+        char *buffer= until_sql_gtids.to_string();
+        global_sid_lock.unlock();
+        sql_print_information("Slave SQL thread stopped because it reached "
+                              "UNTIL SQL_BEFORE_GTIDS %s", buffer);
+        my_free(buffer);
+        DBUG_RETURN(true);
+      }
       global_sid_lock.unlock();
-      DBUG_RETURN(true);
+      // We only need to check once if logged_gtids set contains any of the until_sql_gtids.
+      if (until_sql_gtids_first_event)
+      {
+        until_sql_gtids_first_event= false;
+        global_sid_lock.wrlock();
+        /* Check if until GTIDs were already applied. */
+        const Gtid_set* logged_gtids= gtid_state.get_logged_gtids();
+        if (until_sql_gtids.is_intersection(logged_gtids))
+        {
+          char *buffer= until_sql_gtids.to_string();
+          global_sid_lock.unlock();
+          sql_print_information("Slave SQL thread stopped because "
+                                "UNTIL SQL_BEFORE_GTIDS %s is already "
+                                "applied", buffer);
+          my_free(buffer);
+          DBUG_RETURN(true);
+        }
+        global_sid_lock.unlock();
+      }
     }
-    else
+    DBUG_RETURN(false);
+    break;
+
+  case UNTIL_SQL_AFTER_GTIDS:
+    if (ev != NULL && ev->get_type_code() == GTID_LOG_EVENT)
     {
-      until_gtids_obj.to_string(buffer);
-      DBUG_PRINT("info", ("Waiting for %s to be processed.", buffer));
-      my_free(buffer);
+      global_sid_lock.wrlock();
+      // We only need to compute until_sql_gtids_seen once.
+      if (until_sql_gtids_first_event)
+      {
+        until_sql_gtids_first_event= false;
+        const Gtid_set* logged_gtids= gtid_state.get_logged_gtids();
+        until_sql_gtids.intersection(logged_gtids, &until_sql_gtids_seen);
+      }
+      if (until_sql_gtids.is_subset(const_cast<Gtid_set *>(&until_sql_gtids_seen)))
+      {
+        char *buffer= until_sql_gtids.to_string();
+        global_sid_lock.unlock();
+        sql_print_information("Slave SQL thread stopped because it reached "
+                              "UNTIL SQL_AFTER_GTIDS %s", buffer);
+        my_free(buffer);
+        DBUG_RETURN(true);
+      }
+      Gtid_log_event *gev= (Gtid_log_event *)ev;
+      until_sql_gtids_seen.ensure_sidno(gev->get_sidno(false));
+      until_sql_gtids_seen._add_gtid(gev->get_sidno(false), gev->get_gno());
+      global_sid_lock.unlock();
     }
-#endif
-    global_sid_lock.unlock();
+    DBUG_RETURN(false);
+    break;
+
+  case UNTIL_NONE:
+    DBUG_ASSERT(0);
+    break;
   }
 
+  DBUG_ASSERT(0);
   DBUG_RETURN(false);
 }
 

=== modified file 'sql/rpl_rli.h'
--- a/sql/rpl_rli.h	2012-03-12 22:08:24 +0000
+++ b/sql/rpl_rli.h	2012-03-27 08:43:25 +0000
@@ -309,29 +309,29 @@ public:
      thread is running).
    */
   enum {UNTIL_NONE= 0, UNTIL_MASTER_POS, UNTIL_RELAY_POS,
-        UNTIL_SQL_BEFORE_GTIDS} until_condition;
+        UNTIL_SQL_BEFORE_GTIDS, UNTIL_SQL_AFTER_GTIDS} until_condition;
   char until_log_name[FN_REFLEN];
   ulonglong until_log_pos;
   /* extension extracted from log_name and converted to int */
   ulong until_log_name_extension;
   /**
-    The START SLAVE UNTIL SQL_BEFORE_GTIDS initializes both
-    the until_gtids_obj and request_gtids_obj. Each time a
-    gtid is about to be processed, it is removed from the
-    until_gtids_obj and when until_gtids_obj becomes empty,
-    the SQL Thread is stopped and a message saying that 
-    the condition was reached, i.e. request_gtids_obj, is
-    printed out.
-
-    This is used by the START SLAVE UNTIL SQL_BEFORE_GTIDS.
-    is issued.
+    The START SLAVE UNTIL SQL_*_GTIDS initializes until_sql_gtids.
+    Each time a gtid is about to be processed, we check if it is in the
+    set. Depending on until_condition, SQL thread is stopped before or
+    after applying the gtid.
   */
-  Gtid_set until_gtids_obj;
-  /**
-    This is used when the START SLAVE UNTIL SQL_BEFORE_GTIDS
-    is issued.
+  Gtid_set until_sql_gtids;
+  /*
+    On START SLAVE UNTIL SQL_AFTER_GTIDS this set contains the
+    intersection between logged gtids set and gtids scheduled on MTS
+    worker queues.
+  */
+  Gtid_set until_sql_gtids_seen;
+  /*
+    True if the current event is the first gtid event to be processed
+    after executing START SLAVE UNTIL SQL_*_GTIDS.
   */
-  Gtid_set request_gtids_obj;
+  bool until_sql_gtids_first_event;
   /* 
      Cached result of comparison of until_log_name and current log name
      -2 means unitialised, -1,0,1 are comarison results 

=== modified file 'sql/rpl_slave.cc'
--- a/sql/rpl_slave.cc	2012-03-26 19:30:00 +0000
+++ b/sql/rpl_slave.cc	2012-03-27 08:43:25 +0000
@@ -3519,23 +3519,6 @@ static int exec_relay_log_event(THD* thd
     if (rli->until_condition != Relay_log_info::UNTIL_NONE &&
         rli->is_until_satisfied(thd, ev))
     {
-      char buf[22];
-      if (rli->until_condition == Relay_log_info::UNTIL_MASTER_POS ||
-          rli->until_condition == Relay_log_info::UNTIL_RELAY_POS)
-        sql_print_information("Slave SQL thread stopped because it reached its"
-                              " UNTIL position %s", llstr(rli->until_pos(), buf));
-      else
-      {
-        char *buffer;
-        global_sid_lock.wrlock();
-        if ((buffer= (char *) my_malloc(rli->request_gtids_obj.get_string_length() + 1,
-                                        MYF(MY_WME))))
-          rli->request_gtids_obj.to_string(buffer);
-        global_sid_lock.unlock();
-        sql_print_information("Slave SQL thread stopped because it reached its"
-                              " UNTIL SQL_BEFORE_GTIDS %s", buffer);
-        my_free(buffer);
-      }
       /*
         Setting abort_slave flag because we do not want additional message about
         error in query execution to be printed.
@@ -5257,23 +5240,6 @@ log '%s' at position %s, relay log '%s'
   if (rli->until_condition != Relay_log_info::UNTIL_NONE &&
       rli->is_until_satisfied(thd, NULL))
   {
-    char buf[22];
-    if (rli->until_condition == Relay_log_info::UNTIL_MASTER_POS ||
-        rli->until_condition == Relay_log_info::UNTIL_RELAY_POS)
-      sql_print_information("Slave SQL thread stopped because it reached its"
-                            " UNTIL position %s", llstr(rli->until_pos(), buf));
-    else
-    {
-      char* buffer= NULL;
-      global_sid_lock.rdlock();
-      if ((buffer= (char *) my_malloc(rli->request_gtids_obj.get_string_length() + 1,
-                                      MYF(MY_WME))))
-        rli->request_gtids_obj.to_string(buffer);
-      global_sid_lock.unlock();
-      sql_print_information("Slave SQL thread stopped because it reached its"
-                            " UNTIL SQL_BEFORE_GTIDS %s", buffer);
-      my_free(buffer);
-    }
     mysql_mutex_unlock(&rli->data_lock);
     goto err;
   }
@@ -7475,15 +7441,15 @@ int start_slave(THD* thd , Master_info*
         {
           global_sid_lock.wrlock();
           mi->rli->clear_until_condition();
-          if (mi->rli->until_gtids_obj.add_gtid_text(thd->lex->mi.gtid)
-              != RETURN_STATUS_OK ||
-              mi->rli->request_gtids_obj.add_gtid_text(thd->lex->mi.gtid)
+          if (mi->rli->until_sql_gtids.add_gtid_text(thd->lex->mi.gtid)
               != RETURN_STATUS_OK)
             slave_errno= ER_BAD_SLAVE_UNTIL_COND;
-          if (mi->rli->until_gtids_obj.remove_gtid_set(gtid_state.get_logged_gtids()) 
-              != RETURN_STATUS_OK)
-            slave_errno= ER_BAD_SLAVE_UNTIL_COND;
-          mi->rli->until_condition= Relay_log_info::UNTIL_SQL_BEFORE_GTIDS;
+          else {
+            mi->rli->until_condition=
+              LEX_MASTER_INFO::UNTIL_SQL_BEFORE_GTIDS == thd->lex->mi.gtid_until_condition
+              ? Relay_log_info::UNTIL_SQL_BEFORE_GTIDS
+              : Relay_log_info::UNTIL_SQL_AFTER_GTIDS;
+          }
           global_sid_lock.unlock();
         }
         else

=== modified file 'sql/sql_lex.h'
--- a/sql/sql_lex.h	2012-03-14 13:12:36 +0000
+++ b/sql/sql_lex.h	2012-03-27 08:43:25 +0000
@@ -213,6 +213,7 @@ typedef struct st_lex_master_info
   ulonglong pos;
   ulong server_id, retry_count;
   char *gtid;
+  enum {UNTIL_SQL_BEFORE_GTIDS= 0, UNTIL_SQL_AFTER_GTIDS} gtid_until_condition;
 
   /*
     Enum is used for making it possible to detect if the user

=== modified file 'sql/sql_yacc.yy'
--- a/sql/sql_yacc.yy	2012-03-21 14:27:34 +0000
+++ b/sql/sql_yacc.yy	2012-03-27 08:43:25 +0000
@@ -1510,7 +1510,7 @@ bool my_yyoverflow(short **a, YYSTYPE **
 %token  SQLEXCEPTION_SYM              /* SQL-2003-R */
 %token  SQLSTATE_SYM                  /* SQL-2003-R */
 %token  SQLWARNING_SYM                /* SQL-2003-R */
-%token  SQL_AFTER_GTIDS               /* MYSQL, FUTURE-USE */
+%token  SQL_AFTER_GTIDS               /* MYSQL */
 %token  SQL_BEFORE_GTIDS              /* MYSQL */
 %token  SQL_BIG_RESULT
 %token  SQL_BUFFER_RESULT
@@ -7700,6 +7700,12 @@ slave_until_opts:
         | SQL_BEFORE_GTIDS EQ TEXT_STRING_sys
           {
             Lex->mi.gtid= $3.str;
+            Lex->mi.gtid_until_condition= LEX_MASTER_INFO::UNTIL_SQL_BEFORE_GTIDS;
+          }
+        | SQL_AFTER_GTIDS EQ TEXT_STRING_sys
+          {
+            Lex->mi.gtid= $3.str;
+            Lex->mi.gtid_until_condition= LEX_MASTER_INFO::UNTIL_SQL_AFTER_GTIDS;
           }
         ;
 

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-trunk branch (nuno.carvalho:3866 to 3867) Bug#13810456Nuno Carvalho27 Mar