]> git.pld-linux.org Git - packages/mysql.git/commitdiff
- rel 4; fix for SECURITY bug that allows any user to crash entire server (also fixes... auto/th/mysql-5.6.20-68.0.4
authorArkadiusz Miśkiewicz <arekm@maven.pl>
Fri, 26 Sep 2014 17:35:42 +0000 (19:35 +0200)
committerArkadiusz Miśkiewicz <arekm@maven.pl>
Fri, 26 Sep 2014 17:35:42 +0000 (19:35 +0200)
bug-73834.patch [new file with mode: 0644]
mysql.spec

diff --git a/bug-73834.patch b/bug-73834.patch
new file mode 100644 (file)
index 0000000..4f10824
--- /dev/null
@@ -0,0 +1,607 @@
+commit b54c850236f23c2aeb087bde53a9d975d0355486
+Author: Thirunarayanan B <thirunarayanan.balathandayuth@oracle.com>
+Date:   Wed Aug 6 15:34:47 2014 +0530
+
+    Bug #18734396      INNODB IN-PLACE ALTER FAILURES BLOCK FUTURE ALTERS
+    
+    Analysis:
+       When an InnoDB in-place ALTER fails, it leaves behind both a
+    temporary filename like "#sql-ibtid" where tid represents the table ID of
+    the table being altered) in its data dictionary. This makes future in-place
+    ALTERs of the same table impossible because the temporary table is named
+    only with the table ID.
+    
+    Solution:
+       This patch is adding more uniqueness to the temporary file name. It
+    creates a temporary tablename like
+    "#sql-ibtid-inc" where
+             tid = the table ID
+             inc = static global number that is initialized to a random
+    distributed 32-bit number using ut_time() and ut_crc32().It is then
+    incremented atomically for each temporary file name assigned.
+    
+       rb5580 Approved by Kevin, Marko
+
+diff --git a/mysql-test/suite/innodb/r/innodb-alter-tempfile.result b/mysql-test/suite/innodb/r/innodb-alter-tempfile.result
+new file mode 100644
+index 0000000..12ec408
+--- /dev/null
++++ b/mysql-test/suite/innodb/r/innodb-alter-tempfile.result
+@@ -0,0 +1,38 @@
++#
++# Bug #18734396       INNODB IN-PLACE ALTER FAILURES BLOCK FUTURE ALTERS
++#
++# Temporary tablename will be unique. This makes sure that future
++# in-place ALTERs of the same table will not be blocked due to
++# temporary tablename.
++# Crash the server in ha_innobase::commit_inplace_alter_table()
++CREATE TABLE t1 (f1 INT NOT NULL, f2 INT NOT NULL) ENGINE=innodb;
++SET debug='d,innodb_alter_commit_crash_before_commit';
++# Write file to make mysql-test-run.pl expect crash
++# Execute the statement that causes the crash
++ALTER TABLE t1 ADD PRIMARY KEY (f2, f1);
++ERROR HY000: Lost connection to MySQL server during query
++# Startup the server after the crash
++# Read and remember the temporary table name
++show create table t1;
++Table Create Table
++t1    CREATE TABLE `t1` (
++  `f1` int(11) NOT NULL,
++  `f2` int(11) NOT NULL
++) ENGINE=InnoDB DEFAULT CHARSET=latin1
++# Consecutive Alter table does not create same temporary file name
++ALTER TABLE t1 ADD PRIMARY KEY (f2, f1);
++# Shutdown the server to allow manual recovery
++# Manual recovery begin. The dictionary was not updated
++# and the files were not renamed. The rebuilt table
++# was left behind on purpose, to faciliate data recovery.
++# Manual recovery end
++# Startup the server after manual recovery
++# Drop the orphaned rebuilt table.
++show create table t1;
++Table Create Table
++t1    CREATE TABLE `t1` (
++  `f1` int(11) NOT NULL,
++  `f2` int(11) NOT NULL,
++  PRIMARY KEY (`f2`,`f1`)
++) ENGINE=InnoDB DEFAULT CHARSET=latin1
++drop table t1;
+diff --git a/mysql-test/suite/innodb/t/innodb-alter-tempfile.test b/mysql-test/suite/innodb/t/innodb-alter-tempfile.test
+new file mode 100644
+index 0000000..aff179a
+--- /dev/null
++++ b/mysql-test/suite/innodb/t/innodb-alter-tempfile.test
+@@ -0,0 +1,72 @@
++# Not supported in embedded
++--source include/not_embedded.inc
++
++# This test case needs to crash the server. Needs a debug server.
++--source include/have_debug.inc
++
++# Don't test this under valgrind, memory leaks will occur.
++--source include/not_valgrind.inc
++
++# Avoid CrashReporter popup on Mac
++--source include/not_crashrep.inc
++
++--echo #
++--echo # Bug #18734396        INNODB IN-PLACE ALTER FAILURES BLOCK FUTURE ALTERS
++--echo #
++--echo # Temporary tablename will be unique. This makes sure that future
++--echo # in-place ALTERs of the same table will not be blocked due to
++--echo # temporary tablename.
++
++let datadir= `select @@datadir`;
++
++--let $_server_id= `SELECT @@server_id`
++--let $_expect_file_name=$MYSQLTEST_VARDIR/tmp/mysqld.$_server_id.expect
++
++--echo # Crash the server in ha_innobase::commit_inplace_alter_table()
++CREATE TABLE t1 (f1 INT NOT NULL, f2 INT NOT NULL) ENGINE=innodb;
++SET debug='d,innodb_alter_commit_crash_before_commit';
++
++let $orig_table_id = `SELECT table_id
++      FROM information_schema.innodb_sys_tables
++      WHERE name = 'test/t1'`;
++
++--echo # Write file to make mysql-test-run.pl expect crash
++--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
++
++--echo # Execute the statement that causes the crash
++--error 2013
++ALTER TABLE t1 ADD PRIMARY KEY (f2, f1);
++--echo # Startup the server after the crash
++--source include/start_mysqld.inc
++
++--echo # Read and remember the temporary table name
++let $temp_table_name = `SELECT SUBSTRING(name,6)
++      FROM information_schema.innodb_sys_tables
++      WHERE name LIKE "test/#sql-ib$orig_table_id%"`;
++# This second copy is an environment variable for the perl script below.
++let temp_table_name = $temp_table_name;
++show create table t1;
++--echo # Consecutive Alter table does not create same temporary file name
++ALTER TABLE t1 ADD PRIMARY KEY (f2, f1);
++--echo # Shutdown the server to allow manual recovery
++--source include/shutdown_mysqld.inc
++
++--echo # Manual recovery begin. The dictionary was not updated
++--echo # and the files were not renamed. The rebuilt table
++--echo # was left behind on purpose, to faciliate data recovery.
++
++perl;
++my @frm_file = glob "$ENV{'datadir'}/test/#sql-*.frm";
++my $target_frm = "$ENV{'datadir'}/test/$ENV{'temp_table_name'}.frm";
++rename($frm_file[0], $target_frm);
++EOF
++--echo # Manual recovery end
++--echo # Startup the server after manual recovery
++--source include/start_mysqld.inc
++
++--echo # Drop the orphaned rebuilt table.
++--disable_query_log
++eval DROP TABLE `#mysql50#$temp_table_name`;
++--enable_query_log
++show create table t1;
++drop table t1;
+diff --git a/storage/innobase/dict/dict0mem.cc b/storage/innobase/dict/dict0mem.cc
+index 885627a..cd9eed9 100644
+--- a/storage/innobase/dict/dict0mem.cc
++++ b/storage/innobase/dict/dict0mem.cc
+@@ -35,6 +35,7 @@ Created 1/8/1996 Heikki Tuuri
+ #include "mach0data.h"
+ #include "dict0dict.h"
+ #include "fts0priv.h"
++#include "ut0crc32.h"
+ #ifndef UNIV_HOTBACKUP
+ # include "ha_prototypes.h"   /* innobase_casedn_str(),
+                               innobase_get_lower_case_table_names */
+@@ -53,6 +54,10 @@ Created 1/8/1996 Heikki Tuuri
+ UNIV_INTERN mysql_pfs_key_t   autoinc_mutex_key;
+ #endif /* UNIV_PFS_MUTEX */
++/** An interger randomly initialized at startup used to make a temporary
++table name as unique as possible. */
++static ib_uint32_t    dict_temp_file_num;
++
+ /**********************************************************************//**
+ Creates a table memory object.
+ @return       own: table object */
+@@ -614,26 +619,62 @@ dict_mem_index_free(
+       mem_heap_free(index->heap);
+ }
+-/*******************************************************************//**
+-Create a temporary tablename.
+-@return temporary tablename suitable for InnoDB use */
++/** Create a temporary tablename like "#sql-ibtid-inc where
++  tid = the Table ID
++  inc = a randomly initialized number that is incremented for each file
++The table ID is a 64 bit integer, can use up to 20 digits, and is
++initialized at bootstrap. The second number is 32 bits, can use up to 10
++digits, and is initialized at startup to a randomly distributed number.
++It is hoped that the combination of these two numbers will provide a
++reasonably unique temporary file name.
++@param[in]    heap    A memory heap
++@param[in]    dbtab   Table name in the form database/table name
++@param[in]    id      Table id
++@return A unique temporary tablename suitable for InnoDB use */
+ UNIV_INTERN
+ char*
+ dict_mem_create_temporary_tablename(
+-/*================================*/
+-      mem_heap_t*     heap,   /*!< in: memory heap */
+-      const char*     dbtab,  /*!< in: database/table name */
+-      table_id_t      id)     /*!< in: InnoDB table id */
++      mem_heap_t*     heap,
++      const char*     dbtab,
++      table_id_t      id)
+ {
+-      const char*     dbend   = strchr(dbtab, '/');
++      size_t          size;
++      char*           name;
++      const char*     dbend = strchr(dbtab, '/');
+       ut_ad(dbend);
+-      size_t          dblen   = dbend - dbtab + 1;
+-      size_t          size = tmp_file_prefix_length + 4 + 9 + 9 + dblen;
++      size_t          dblen = dbend - dbtab + 1;
++
++#ifdef HAVE_ATOMIC_BUILTINS
++      /* Increment a randomly initialized number for each temp file. */
++      os_atomic_increment_uint32(&dict_temp_file_num, 1);
++#else /* HAVE_ATOMIC_BUILTINS */
++      dict_temp_file_num++;
++#endif /* HAVE_ATOMIC_BUILTINS */
+-      char*   name = static_cast<char*>(mem_heap_alloc(heap, size));
++      size = tmp_file_prefix_length + 3 + 20 + 1 + 10 + dblen;
++      name = static_cast<char*>(mem_heap_alloc(heap, size));
+       memcpy(name, dbtab, dblen);
+       ut_snprintf(name + dblen, size - dblen,
+-                  tmp_file_prefix "-ib" UINT64PF, id);
++                  TEMP_FILE_PREFIX_INNODB UINT64PF "-" UINT32PF,
++                  id, dict_temp_file_num);
++
+       return(name);
+ }
++/** Initialize dict memory variables */
++
++void
++dict_mem_init(void)
++{
++      /* Initialize a randomly distributed temporary file number */
++      ib_uint32_t now = static_cast<ib_uint32_t>(ut_time());
++
++      const byte* buf = reinterpret_cast<const byte*>(&now);
++      ut_ad(ut_crc32 != NULL);
++
++      dict_temp_file_num = ut_crc32(buf, sizeof(now));
++
++      DBUG_PRINT("dict_mem_init",
++                 ("Starting Temporary file number is " UINT32PF,
++                 dict_temp_file_num));
++}
+diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h
+index 63bc4ff..e2977ca 100644
+--- a/storage/innobase/include/dict0mem.h
++++ b/storage/innobase/include/dict0mem.h
+@@ -384,16 +384,29 @@ dict_mem_referenced_table_name_lookup_set(
+       dict_foreign_t* foreign,        /*!< in/out: foreign struct */
+       ibool           do_alloc);      /*!< in: is an alloc needed */
+-/*******************************************************************//**
+-Create a temporary tablename.
+-@return temporary tablename suitable for InnoDB use */
+-UNIV_INTERN __attribute__((nonnull, warn_unused_result))
++/** Create a temporary tablename like "#sql-ibtid-inc where
++  tid = the Table ID
++  inc = a randomly initialized number that is incremented for each file
++The table ID is a 64 bit integer, can use up to 20 digits, and is
++initialized at bootstrap. The second number is 32 bits, can use up to 10
++digits, and is initialized at startup to a randomly distributed number.
++It is hoped that the combination of these two numbers will provide a
++reasonably unique temporary file name.
++@param[in]    heap    A memory heap
++@param[in]    dbtab   Table name in the form database/table name
++@param[in]    id      Table id
++@return A unique temporary tablename suitable for InnoDB use */
++UNIV_INTERN
+ char*
+ dict_mem_create_temporary_tablename(
+-/*================================*/
+-      mem_heap_t*     heap,   /*!< in: memory heap */
+-      const char*     dbtab,  /*!< in: database/table name */
+-      table_id_t      id);    /*!< in: InnoDB table id */
++      mem_heap_t*     heap,
++      const char*     dbtab,
++      table_id_t      id);
++
++/** Initialize dict memory variables */
++
++void
++dict_mem_init(void);
+ /** Data structure for a column in a table */
+ struct dict_col_t{
+diff --git a/storage/innobase/include/dict0types.h b/storage/innobase/include/dict0types.h
+index 1299445..d34b6f7 100644
+--- a/storage/innobase/include/dict0types.h
++++ b/storage/innobase/include/dict0types.h
+@@ -78,6 +78,7 @@ enum ib_quiesce_t {
+ /** Prefix for tmp tables, adopted from sql/table.h */
+ #define tmp_file_prefix               "#sql"
+ #define tmp_file_prefix_length        4
++#define TEMP_FILE_PREFIX_INNODB       "#sql-ib"
+ #define TEMP_TABLE_PREFIX                "#sql"
+ #define TEMP_TABLE_PATH_PREFIX           "/" TEMP_TABLE_PREFIX
+diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc
+index 499c0fc..cf8b288 100644
+--- a/storage/innobase/srv/srv0srv.cc
++++ b/storage/innobase/srv/srv0srv.cc
+@@ -979,6 +979,8 @@ srv_init(void)
+       trx_i_s_cache_init(trx_i_s_cache);
+       ut_crc32_init();
++
++      dict_mem_init();
+ }
+ /*********************************************************************//**
+From da00483beb3fe1375fc1ebeaac7943f73b56637e Mon Sep 17 00:00:00 2001
+From: MySQL Build Team <mysql-build@oss.oracle.com>
+Date: Mon, 8 Sep 2014 12:33:48 +0200
+Subject: [PATCH] bug19471516 for mysql-5.6
+
+---
+ mysql-test/suite/innodb/r/add_foreign_key.result | 31 +++++++++++++
+ mysql-test/suite/innodb/t/add_foreign_key.test   | 38 +++++++++++++++
+ storage/innobase/dict/dict0dict.cc               | 11 +++++
+ storage/innobase/dict/dict0load.cc               |  2 +
+ storage/innobase/dict/dict0mem.cc                | 59 ++++++++++++++++++++++++
+ storage/innobase/include/dict0mem.h              | 51 ++++++++++++++++++++
+ 6 files changed, 192 insertions(+)
+ create mode 100644 mysql-test/suite/innodb/r/add_foreign_key.result
+ create mode 100644 mysql-test/suite/innodb/t/add_foreign_key.test
+
+diff --git a/mysql-test/suite/innodb/r/add_foreign_key.result b/mysql-test/suite/innodb/r/add_foreign_key.result
+new file mode 100644
+index 0000000..7517747
+--- /dev/null
++++ b/mysql-test/suite/innodb/r/add_foreign_key.result
+@@ -0,0 +1,31 @@
++#
++# Bug #19471516 SERVER CRASHES WHEN EXECUTING ALTER TABLE ADD
++# FOREIGN KEY
++#
++CREATE TABLE `parent` (`parent_id` INT, PRIMARY KEY (`parent_id`));
++CREATE TABLE `child1` (`id` INT ,`child1_fk1` INT, `child1_fk2` INT,
++PRIMARY KEY (`id`));
++CREATE TABLE `child2` (`id` INT, `child2_fk1` INT, `child2_fk2` INT,
++PRIMARY KEY (`id`));
++CREATE TABLE `child3` (`id` INT , `child3_fk1` INT, PRIMARY KEY (`id`));
++ALTER TABLE `child1` ADD FOREIGN KEY (`child1_fk1`) REFERENCES `parent`
++(`parent_id`);
++ALTER TABLE `child1` ADD FOREIGN KEY (`child1_fk1`) REFERENCES
++`parent` (`parent_id`);
++ALTER TABLE `child1` ADD FOREIGN KEY (`child1_fk2`) REFERENCES `parent`
++(`parent_id`);
++ALTER TABLE `child2` ADD FOREIGN KEY (`child2_fk1`) REFERENCES `parent`
++(`parent_id`);
++ALTER TABLE `child2` ADD FOREIGN KEY (`child2_fk2`) REFERENCES `parent`
++(`parent_id`);
++ALTER TABLE `child3` ADD FOREIGN KEY (`child3_fk1`) REFERENCES `parent`
++(`parent_id`);
++ALTER TABLE `child1` ADD FOREIGN KEY (`child1_fk2`) REFERENCES
++`parent` (`parent_id`);
++ALTER TABLE `child2` ADD FOREIGN KEY (`child2_fk1`) REFERENCES
++`parent` (`parent_id`);
++ALTER TABLE `child2` ADD FOREIGN KEY (`child2_fk2`) REFERENCES
++`parent` (`parent_id`);
++ALTER TABLE `child3` ADD FOREIGN KEY (`child3_fk1`) REFERENCES
++`parent` (`parent_id`);
++drop table child3, child2, child1, parent;
+diff --git a/mysql-test/suite/innodb/t/add_foreign_key.test b/mysql-test/suite/innodb/t/add_foreign_key.test
+new file mode 100644
+index 0000000..d0febfd
+--- /dev/null
++++ b/mysql-test/suite/innodb/t/add_foreign_key.test
+@@ -0,0 +1,38 @@
++--source include/have_innodb.inc
++
++--echo #
++--echo # Bug #19471516 SERVER CRASHES WHEN EXECUTING ALTER TABLE ADD
++--echo # FOREIGN KEY
++--echo #
++
++CREATE TABLE `parent` (`parent_id` INT, PRIMARY KEY (`parent_id`));
++CREATE TABLE `child1` (`id` INT ,`child1_fk1` INT, `child1_fk2` INT,
++PRIMARY KEY (`id`));
++CREATE TABLE `child2` (`id` INT, `child2_fk1` INT, `child2_fk2` INT,
++PRIMARY KEY (`id`));
++CREATE TABLE `child3` (`id` INT , `child3_fk1` INT, PRIMARY KEY (`id`));
++ALTER TABLE `child1` ADD FOREIGN KEY (`child1_fk1`) REFERENCES `parent`
++(`parent_id`);
++ALTER TABLE `child1` ADD FOREIGN KEY (`child1_fk1`) REFERENCES
++`parent` (`parent_id`);
++ALTER TABLE `child1` ADD FOREIGN KEY (`child1_fk2`) REFERENCES `parent`
++(`parent_id`);
++
++ALTER TABLE `child2` ADD FOREIGN KEY (`child2_fk1`) REFERENCES `parent`
++(`parent_id`);
++
++ALTER TABLE `child2` ADD FOREIGN KEY (`child2_fk2`) REFERENCES `parent`
++(`parent_id`);
++
++ALTER TABLE `child3` ADD FOREIGN KEY (`child3_fk1`) REFERENCES `parent`
++(`parent_id`);
++ALTER TABLE `child1` ADD FOREIGN KEY (`child1_fk2`) REFERENCES
++`parent` (`parent_id`);
++ALTER TABLE `child2` ADD FOREIGN KEY (`child2_fk1`) REFERENCES
++`parent` (`parent_id`);
++ALTER TABLE `child2` ADD FOREIGN KEY (`child2_fk2`) REFERENCES
++`parent` (`parent_id`);
++ALTER TABLE `child3` ADD FOREIGN KEY (`child3_fk1`) REFERENCES
++`parent` (`parent_id`);
++
++drop table child3, child2, child1, parent;
+diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc
+index 5b0d7da..6acd6b6 100644
+--- a/storage/innobase/dict/dict0dict.cc
++++ b/storage/innobase/dict/dict0dict.cc
+@@ -1694,6 +1694,10 @@ dict_table_rename_in_cache(
+               foreign = *it;
++              if (foreign->referenced_table) {
++                      foreign->referenced_table->referenced_set.erase(foreign);
++              }
++
+               if (ut_strlen(foreign->foreign_table_name)
+                   < ut_strlen(table->name)) {
+                       /* Allocate a longer name buffer;
+@@ -1845,6 +1849,10 @@ dict_table_rename_in_cache(
+               table->foreign_set.erase(it);
+               fk_set.insert(foreign);
++
++              if (foreign->referenced_table) {
++                      foreign->referenced_table->referenced_set.insert(foreign);
++              }
+       }
+       ut_a(table->foreign_set.empty());
+@@ -3253,6 +3261,9 @@ dict_foreign_find(
+ {
+       ut_ad(mutex_own(&(dict_sys->mutex)));
++      ut_ad(dict_foreign_set_validate(table->foreign_set));
++      ut_ad(dict_foreign_set_validate(table->referenced_set));
++
+       dict_foreign_set::iterator it = table->foreign_set.find(foreign);
+       if (it != table->foreign_set.end()) {
+diff --git a/storage/innobase/dict/dict0load.cc b/storage/innobase/dict/dict0load.cc
+index 272467e..6921199 100644
+--- a/storage/innobase/dict/dict0load.cc
++++ b/storage/innobase/dict/dict0load.cc
+@@ -2537,6 +2537,8 @@ dict_load_table(
+               }
+       }
++      ut_ad(err != DB_SUCCESS || dict_foreign_set_validate(*table));
++
+       return(table);
+ }
+diff --git a/storage/innobase/dict/dict0mem.cc b/storage/innobase/dict/dict0mem.cc
+index cd9eed9..979c18e 100644
+--- a/storage/innobase/dict/dict0mem.cc
++++ b/storage/innobase/dict/dict0mem.cc
+@@ -45,6 +45,7 @@ Created 1/8/1996 Heikki Tuuri
+ #ifdef UNIV_BLOB_DEBUG
+ # include "ut0rbt.h"
+ #endif /* UNIV_BLOB_DEBUG */
++#include <iostream>
+ #define       DICT_HEAP_SIZE          100     /*!< initial memory heap size when
+                                       creating a table or index object */
+@@ -678,3 +679,61 @@ dict_mem_init(void)
+                  ("Starting Temporary file number is " UINT32PF,
+                  dict_temp_file_num));
+ }
++
++/** Validate the search order in the foreign key set.
++@param[in]    fk_set  the foreign key set to be validated
++@return true if search order is fine in the set, false otherwise. */
++bool
++dict_foreign_set_validate(
++      const dict_foreign_set& fk_set)
++{
++      dict_foreign_not_exists not_exists(fk_set);
++
++      dict_foreign_set::iterator it = std::find_if(
++              fk_set.begin(), fk_set.end(), not_exists);
++
++      if (it == fk_set.end()) {
++              return(true);
++      }
++
++      dict_foreign_t* foreign = *it;
++      std::cerr << "Foreign key lookup failed: " << *foreign;
++      std::cerr << fk_set;
++      ut_ad(0);
++      return(false);
++}
++
++/** Validate the search order in the foreign key sets of the table
++(foreign_set and referenced_set).
++@param[in]    table   table whose foreign key sets are to be validated
++@return true if foreign key sets are fine, false otherwise. */
++bool
++dict_foreign_set_validate(
++      const dict_table_t&     table)
++{
++      return(dict_foreign_set_validate(table.foreign_set)
++             && dict_foreign_set_validate(table.referenced_set));
++}
++
++std::ostream&
++operator<< (std::ostream& out, const dict_foreign_t& foreign)
++{
++      out << "[dict_foreign_t: id='" << foreign.id << "'";
++
++      if (foreign.foreign_table_name != NULL) {
++              out << ",for: '" << foreign.foreign_table_name << "'";
++      }
++
++      out << "]";
++      return(out);
++}
++
++std::ostream&
++operator<< (std::ostream& out, const dict_foreign_set& fk_set)
++{
++      out << "[dict_foreign_set:";
++      std::for_each(fk_set.begin(), fk_set.end(), dict_foreign_print(out));
++      out << "]" << std::endl;
++      return(out);
++}
++
+diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h
+index e2977ca..460a7e1 100644
+--- a/storage/innobase/include/dict0mem.h
++++ b/storage/innobase/include/dict0mem.h
+@@ -49,6 +49,7 @@ Created 1/8/1996 Heikki Tuuri
+ #include "os0once.h"
+ #include <set>
+ #include <algorithm>
++#include <iterator>
+ /* Forward declaration. */
+ struct ib_rbt_t;
+@@ -720,6 +721,22 @@ struct dict_foreign_t{
+       dict_index_t*   referenced_index;/*!< referenced index */
+ };
++std::ostream&
++operator<< (std::ostream& out, const dict_foreign_t& foreign);
++
++struct dict_foreign_print {
++
++      dict_foreign_print(std::ostream& out)
++              : m_out(out)
++      {}
++
++      void operator()(const dict_foreign_t* foreign) {
++              m_out << *foreign;
++      }
++private:
++      std::ostream&   m_out;
++};
++
+ /** Compare two dict_foreign_t objects using their ids. Used in the ordering
+ of dict_table_t::foreign_set and dict_table_t::referenced_set.  It returns
+ true if the first argument is considered to go before the second in the
+@@ -789,6 +806,40 @@ struct dict_foreign_matches_id {
+ typedef std::set<dict_foreign_t*, dict_foreign_compare> dict_foreign_set;
++std::ostream&
++operator<< (std::ostream& out, const dict_foreign_set& fk_set);
++
++/** Function object to check if a foreign key object is there
++in the given foreign key set or not.  It returns true if the
++foreign key is not found, false otherwise */
++struct dict_foreign_not_exists {
++      dict_foreign_not_exists(const dict_foreign_set& obj_)
++              : m_foreigns(obj_)
++      {}
++
++      /* Return true if the given foreign key is not found */
++      bool operator()(dict_foreign_t* const & foreign) const {
++              return(m_foreigns.find(foreign) == m_foreigns.end());
++      }
++private:
++      const dict_foreign_set& m_foreigns;
++};
++
++/** Validate the search order in the foreign key set.
++@param[in]    fk_set  the foreign key set to be validated
++@return true if search order is fine in the set, false otherwise. */
++bool
++dict_foreign_set_validate(
++      const dict_foreign_set& fk_set);
++
++/** Validate the search order in the foreign key sets of the table
++(foreign_set and referenced_set).
++@param[in]    table   table whose foreign key sets are to be validated
++@return true if foreign key sets are fine, false otherwise. */
++bool
++dict_foreign_set_validate(
++      const dict_table_t&     table);
++
+ /*********************************************************************//**
+ Frees a foreign key struct. */
+ inline
index 5e6ea3acbb9354cdb0896be40dfde63d0c0a45f1..21183215820bb0e00627b71421a42e7b55e658ae 100644 (file)
@@ -23,7 +23,7 @@
 %bcond_with    tests           # FIXME: don't run correctly
 %bcond_with    ndb             # NDB is now a separate product, this here is broken, so disable it
 
-%define                rel     3
+%define                rel     4
 %define                percona_rel     68.0
 %include       /usr/lib/rpm/macros.perl
 Summary:       MySQL: a very fast and reliable SQL database engine
@@ -65,6 +65,7 @@ Patch4:               %{name}-no-default-secure-auth.patch
 Patch5:                %{name}-system-libhsclient.patch
 # from fedora
 Patch6:                %{name}-system-users.patch
+Patch7:                bug-73834.patch
 
 Patch9:                %{name}-build.patch
 Patch11:       %{name}-upgrade.patch
@@ -512,6 +513,7 @@ mv sphinx-*/mysqlse storage/sphinx
 %patch4 -p1
 %patch5 -p1
 %patch6 -p1
+%patch7 -p1
 
 %patch9 -p1
 %patch11 -p1
This page took 0.180179 seconds and 4 git commands to generate.