summaryrefslogtreecommitdiff
path: root/storage/innobase/dict/dict0mem.cc
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase/dict/dict0mem.cc')
-rw-r--r--storage/innobase/dict/dict0mem.cc163
1 files changed, 151 insertions, 12 deletions
diff --git a/storage/innobase/dict/dict0mem.cc b/storage/innobase/dict/dict0mem.cc
index 885627a61bc..58781fce1d4 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 */
@@ -44,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 */
@@ -53,6 +55,18 @@ Created 1/8/1996 Heikki Tuuri
UNIV_INTERN mysql_pfs_key_t autoinc_mutex_key;
#endif /* UNIV_PFS_MUTEX */
+/** System databases */
+static const char* innobase_system_databases[] = {
+ "mysql/",
+ "information_schema/",
+ "performance_schema/",
+ NullS
+};
+
+/** 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 */
@@ -85,6 +99,7 @@ dict_mem_table_create(
table->flags2 = (unsigned int) flags2;
table->name = static_cast<char*>(ut_malloc(strlen(name) + 1));
memcpy(table->name, name, strlen(name) + 1);
+ table->is_system_db = dict_mem_table_is_system(table->name);
table->space = (unsigned int) space;
table->n_cols = (unsigned int) (n_cols + DATA_N_SYS_COLS);
@@ -131,6 +146,36 @@ dict_mem_table_create(
}
/****************************************************************//**
+Determines if a table belongs to a system database
+@return */
+UNIV_INTERN
+bool
+dict_mem_table_is_system(
+/*================*/
+ char *name) /*!< in: table name */
+{
+ ut_ad(name);
+
+ /* table has the following format: database/table
+ and some system table are of the form SYS_* */
+ if (strchr(name, '/')) {
+ int table_len = strlen(name);
+ const char *system_db;
+ int i = 0;
+ while ((system_db = innobase_system_databases[i++])
+ && (system_db != NullS)) {
+ int len = strlen(system_db);
+ if (table_len > len && !strncmp(name, system_db, len)) {
+ return true;
+ }
+ }
+ return false;
+ } else {
+ return true;
+ }
+}
+
+/****************************************************************//**
Free a table memory object. */
UNIV_INTERN
void
@@ -614,26 +659,120 @@ 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;
- char* name = static_cast<char*>(mem_heap_alloc(heap, size));
+#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 */
+
+ 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));
+}
+
+/** 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);
+}
+