[packages/mysql] - rel 4; fix for SECURITY bug that allows any user to crash entire server (also fixes upstream #1873
arekm
arekm at pld-linux.org
Fri Sep 26 19:35:48 CEST 2014
commit 97e12482fabfccbdf4c8952317b1219b6419f15e
Author: Arkadiusz Miśkiewicz <arekm at maven.pl>
Date: Fri Sep 26 19:35:42 2014 +0200
- rel 4; fix for SECURITY bug that allows any user to crash entire server (also fixes upstream #18734396)
bug-73834.patch | 607 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
mysql.spec | 4 +-
2 files changed, 610 insertions(+), 1 deletion(-)
---
diff --git a/mysql.spec b/mysql.spec
index 5e6ea3a..2118321 100644
--- a/mysql.spec
+++ b/mysql.spec
@@ -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
diff --git a/bug-73834.patch b/bug-73834.patch
new file mode 100644
index 0000000..4f10824
--- /dev/null
+++ b/bug-73834.patch
@@ -0,0 +1,607 @@
+commit b54c850236f23c2aeb087bde53a9d975d0355486
+Author: Thirunarayanan B <thirunarayanan.balathandayuth at 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.
+- at 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.
++ at param[in] heap A memory heap
++ at param[in] dbtab Table name in the form database/table name
++ at param[in] id Table id
++ at 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.
+- at 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.
++ at param[in] heap A memory heap
++ at param[in] dbtab Table name in the form database/table name
++ at param[in] id Table id
++ at 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 at 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.
++ at param[in] fk_set the foreign key set to be validated
++ at 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).
++ at param[in] table table whose foreign key sets are to be validated
++ at 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.
++ at param[in] fk_set the foreign key set to be validated
++ at 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).
++ at param[in] table table whose foreign key sets are to be validated
++ at 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
================================================================
---- gitweb:
http://git.pld-linux.org/gitweb.cgi/packages/mysql.git/commitdiff/97e12482fabfccbdf4c8952317b1219b6419f15e
More information about the pld-cvs-commit
mailing list