diff options
Diffstat (limited to 'storage/innobase/dict/dict0mem.cc')
-rw-r--r-- | storage/innobase/dict/dict0mem.cc | 393 |
1 files changed, 258 insertions, 135 deletions
diff --git a/storage/innobase/dict/dict0mem.cc b/storage/innobase/dict/dict0mem.cc index f8ea0005665..89e9861db45 100644 --- a/storage/innobase/dict/dict0mem.cc +++ b/storage/innobase/dict/dict0mem.cc @@ -24,6 +24,11 @@ Data dictionary memory object creation Created 1/8/1996 Heikki Tuuri ***********************************************************************/ +#ifndef UNIV_HOTBACKUP +#include "ha_prototypes.h" +#include <mysql_com.h> +#endif /* !UNIV_HOTBACKUP */ + #include "dict0mem.h" #ifdef UNIV_NONINL @@ -36,25 +41,17 @@ Created 1/8/1996 Heikki Tuuri #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 */ -# include "mysql_com.h" /* NAME_LEN */ # include "lock0lock.h" #endif /* !UNIV_HOTBACKUP */ -#ifdef UNIV_BLOB_DEBUG -# include "ut0rbt.h" -#endif /* UNIV_BLOB_DEBUG */ + +#include "sync0sync.h" #include <iostream> #define DICT_HEAP_SIZE 100 /*!< initial memory heap size when creating a table or index object */ -#ifdef UNIV_PFS_MUTEX -/* Key to register autoinc_mutex with performance schema */ -UNIV_INTERN mysql_pfs_key_t autoinc_mutex_key; -#endif /* UNIV_PFS_MUTEX */ - /** System databases */ static const char* innobase_system_databases[] = { "mysql/", @@ -64,20 +61,55 @@ static const char* innobase_system_databases[] = { }; /** An interger randomly initialized at startup used to make a temporary -table name as unique as possible. */ +table name as unuique as possible. */ static ib_uint32_t dict_temp_file_num; +/** Display an identifier. +@param[in,out] s output stream +@param[in] id_name SQL identifier (other than table name) +@return the output stream */ +std::ostream& +operator<<( + std::ostream& s, + const id_name_t& id_name) +{ + const char q = '`'; + const char* c = id_name; + s << q; + for (; *c != 0; c++) { + if (*c == q) { + s << *c; + } + s << *c; + } + s << q; + return(s); +} + +/** Display a table name. +@param[in,out] s output stream +@param[in] table_name table name +@return the output stream */ +std::ostream& +operator<<( + std::ostream& s, + const table_name_t& table_name) +{ + return(s << ut_get_name(NULL, table_name.m_name)); +} + /**********************************************************************//** Creates a table memory object. -@return own: table object */ -UNIV_INTERN +@return own: table object */ dict_table_t* dict_mem_table_create( /*==================*/ const char* name, /*!< in: table name */ ulint space, /*!< in: space where the clustered index of the table is placed */ - ulint n_cols, /*!< in: number of columns */ + ulint n_cols, /*!< in: total number of columns including + virtual and non-virtual columns */ + ulint n_v_cols,/*!< in: number of virtual columns */ ulint flags, /*!< in: table flags */ ulint flags2) /*!< in: table flags2 */ { @@ -85,30 +117,36 @@ dict_mem_table_create( mem_heap_t* heap; ut_ad(name); - ut_a(dict_tf_is_valid(flags)); - ut_a(!(flags2 & ~DICT_TF2_BIT_MASK)); + ut_a(dict_tf2_is_valid(flags, flags2)); + ut_a(!(flags2 & DICT_TF2_UNUSED_BIT_MASK)); heap = mem_heap_create(DICT_HEAP_SIZE); table = static_cast<dict_table_t*>( - mem_heap_zalloc(heap, sizeof(dict_table_t))); + mem_heap_zalloc(heap, sizeof(*table))); + + lock_table_lock_list_init(&table->locks); + + UT_LIST_INIT(table->indexes, &dict_index_t::indexes); table->heap = heap; + ut_d(table->magic_n = DICT_TABLE_MAGIC_N); + table->flags = (unsigned int) flags; 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->name.m_name = mem_strdup(name); + table->is_system_db = dict_mem_table_is_system(table->name.m_name); table->space = (unsigned int) space; - table->n_cols = (unsigned int) (n_cols + DATA_N_SYS_COLS); + table->n_t_cols = (unsigned int) (n_cols + + dict_table_get_n_sys_cols(table)); + table->n_v_cols = (unsigned int) (n_v_cols); + table->n_cols = table->n_t_cols - table->n_v_cols; table->cols = static_cast<dict_col_t*>( - mem_heap_alloc(heap, - (n_cols + DATA_N_SYS_COLS) - * sizeof(dict_col_t))); - - ut_d(table->magic_n = DICT_TABLE_MAGIC_N); + mem_heap_alloc(heap, table->n_cols * sizeof(dict_col_t))); + table->v_cols = static_cast<dict_v_col_t*>( + mem_heap_alloc(heap, n_v_cols * sizeof(*table->v_cols))); /* true means that the stats latch will be enabled - dict_table_stats_lock() will not be noop. */ @@ -118,9 +156,12 @@ dict_mem_table_create( table->autoinc_lock = static_cast<ib_lock_t*>( mem_heap_alloc(heap, lock_get_size())); + /* lazy creation of table autoinc latch */ dict_table_autoinc_create_lazy(table); table->autoinc = 0; + table->sess_row_id = 0; + table->sess_trx_id = 0; /* The number of transactions that are either waiting on the AUTOINC lock or have been granted the lock. */ @@ -138,6 +179,10 @@ dict_mem_table_create( } #endif /* !UNIV_HOTBACKUP */ + if (DICT_TF_HAS_SHARED_SPACE(table->flags)) { + dict_get_and_save_space_name(table, true); + } + new(&table->foreign_set) dict_foreign_set(); new(&table->referenced_set) dict_foreign_set(); @@ -176,7 +221,6 @@ dict_mem_table_is_system( /****************************************************************//** Free a table memory object. */ -UNIV_INTERN void dict_mem_table_free( /*================*/ @@ -186,13 +230,11 @@ dict_mem_table_free( ut_ad(table->magic_n == DICT_TABLE_MAGIC_N); ut_d(table->cached = FALSE); - if (dict_table_has_fts_index(table) - || DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS_HAS_DOC_ID) - || DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS_ADD_DOC_ID)) { + if (dict_table_has_fts_index(table) + || DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS_HAS_DOC_ID) + || DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS_ADD_DOC_ID)) { if (table->fts) { - if (table->cached) { - fts_optimize_remove_table(table); - } + fts_optimize_remove_table(table); fts_free(table); } @@ -206,13 +248,24 @@ dict_mem_table_free( table->foreign_set.~dict_foreign_set(); table->referenced_set.~dict_foreign_set(); - ut_free(table->name); + ut_free(table->name.m_name); + table->name.m_name = NULL; + + /* Clean up virtual index info structures that are registered + with virtual columns */ + for (ulint i = 0; i < table->n_v_def; i++) { + dict_v_col_t* vcol + = dict_table_get_nth_v_col(table, i); + + UT_DELETE(vcol->v_indexes); + } + mem_heap_free(table->heap); } /****************************************************************//** Append 'name' to 'col_names'. @see dict_table_t::col_names -@return new column names array */ +@return new column names array */ static const char* dict_add_col_name( @@ -260,7 +313,6 @@ dict_add_col_name( /**********************************************************************//** Adds a column definition to a table. */ -UNIV_INTERN void dict_mem_table_add_col( /*===================*/ @@ -278,13 +330,17 @@ dict_mem_table_add_col( ut_ad(table->magic_n == DICT_TABLE_MAGIC_N); ut_ad(!heap == !name); + ut_ad(!(prtype & DATA_VIRTUAL)); + i = table->n_def++; + table->n_t_def++; + if (name) { - if (UNIV_UNLIKELY(table->n_def == table->n_cols)) { + if (table->n_def == table->n_cols) { heap = table->heap; } - if (UNIV_LIKELY(i != 0) && UNIV_UNLIKELY(table->col_names == NULL)) { + if (i && !table->col_names) { /* All preceding column names are empty. */ char* s = static_cast<char*>( mem_heap_zalloc(heap, table->n_def)); @@ -301,6 +357,82 @@ dict_mem_table_add_col( dict_mem_fill_column_struct(col, i, mtype, prtype, len); } +/** Adds a virtual column definition to a table. +@param[in,out] table table +@param[in,out] heap temporary memory heap, or NULL. It is + used to store name when we have not finished + adding all columns. When all columns are + added, the whole name will copy to memory from + table->heap +@param[in] name column name +@param[in] mtype main datatype +@param[in] prtype precise type +@param[in] len length +@param[in] pos position in a table +@param[in] num_base number of base columns +@return the virtual column definition */ +dict_v_col_t* +dict_mem_table_add_v_col( + dict_table_t* table, + mem_heap_t* heap, + const char* name, + ulint mtype, + ulint prtype, + ulint len, + ulint pos, + ulint num_base) +{ + dict_v_col_t* v_col; + ulint i; + + ut_ad(table); + ut_ad(table->magic_n == DICT_TABLE_MAGIC_N); + ut_ad(!heap == !name); + + ut_ad(prtype & DATA_VIRTUAL); + + i = table->n_v_def++; + + table->n_t_def++; + + if (name != NULL) { + if (table->n_v_def == table->n_v_cols) { + heap = table->heap; + } + + if (i && !table->v_col_names) { + /* All preceding column names are empty. */ + char* s = static_cast<char*>( + mem_heap_zalloc(heap, table->n_v_def)); + + table->v_col_names = s; + } + + table->v_col_names = dict_add_col_name(table->v_col_names, + i, name, heap); + } + + v_col = dict_table_get_nth_v_col(table, i); + + dict_mem_fill_column_struct(&v_col->m_col, pos, mtype, prtype, len); + v_col->v_pos = i; + + if (num_base != 0) { + v_col->base_col = static_cast<dict_col_t**>(mem_heap_zalloc( + table->heap, num_base * sizeof( + *v_col->base_col))); + } else { + v_col->base_col = NULL; + } + + v_col->num_base = num_base; + + /* Initialize the index list for virtual columns */ + v_col->v_indexes = UT_NEW_NOKEY(dict_v_idx_list()); + + return(v_col); +} + /**********************************************************************//** Renames a column of a table in the data dictionary cache. */ static MY_ATTRIBUTE((nonnull)) @@ -310,17 +442,20 @@ dict_mem_table_col_rename_low( dict_table_t* table, /*!< in/out: table */ unsigned i, /*!< in: column offset corresponding to s */ const char* to, /*!< in: new column name */ - const char* s) /*!< in: pointer to table->col_names */ + const char* s, /*!< in: pointer to table->col_names */ + bool is_virtual) + /*!< in: if this is a virtual column */ { + char* t_col_names = const_cast<char*>( + is_virtual ? table->v_col_names : table->col_names); + ulint n_col = is_virtual ? table->n_v_def : table->n_def; + size_t from_len = strlen(s), to_len = strlen(to); ut_ad(i < table->n_def); ut_ad(from_len <= NAME_LEN); ut_ad(to_len <= NAME_LEN); - char from[NAME_LEN]; - strncpy(from, s, NAME_LEN); - if (from_len == to_len) { /* The easy case: simply replace the column name in table->col_names. */ @@ -329,13 +464,13 @@ dict_mem_table_col_rename_low( /* We need to adjust all affected index->field pointers, as in dict_index_add_col(). First, copy table->col_names. */ - ulint prefix_len = s - table->col_names; + ulint prefix_len = s - t_col_names; - for (; i < table->n_def; i++) { + for (; i < n_col; i++) { s += strlen(s) + 1; } - ulint full_len = s - table->col_names; + ulint full_len = s - t_col_names; char* col_names; if (to_len > from_len) { @@ -344,14 +479,14 @@ dict_mem_table_col_rename_low( table->heap, full_len + to_len - from_len)); - memcpy(col_names, table->col_names, prefix_len); + memcpy(col_names, t_col_names, prefix_len); } else { - col_names = const_cast<char*>(table->col_names); + col_names = const_cast<char*>(t_col_names); } memcpy(col_names + prefix_len, to, to_len); memmove(col_names + prefix_len + to_len, - table->col_names + (prefix_len + from_len), + t_col_names + (prefix_len + from_len), full_len - (prefix_len + from_len)); /* Replace the field names in every index. */ @@ -364,8 +499,16 @@ dict_mem_table_col_rename_low( dict_field_t* field = dict_index_get_nth_field( index, i); + + /* if is_virtual and that in field->col does + not match, continue */ + if ((!is_virtual) != + (!dict_col_is_virtual(field->col))) { + continue; + } + ulint name_ofs - = field->name - table->col_names; + = field->name - t_col_names; if (name_ofs <= prefix_len) { field->name = col_names + name_ofs; } else { @@ -376,7 +519,16 @@ dict_mem_table_col_rename_low( } } - table->col_names = col_names; + if (is_virtual) { + table->v_col_names = col_names; + } else { + table->col_names = col_names; + } + } + + /* Virtual columns are not allowed for foreign key */ + if (is_virtual) { + return; } dict_foreign_t* foreign; @@ -388,54 +540,14 @@ dict_mem_table_col_rename_low( foreign = *it; - if (foreign->foreign_index == NULL) { - /* We may go here when we set foreign_key_checks to 0, - and then try to rename a column and modify the - corresponding foreign key constraint. The index - would have been dropped, we have to find an equivalent - one */ - for (unsigned f = 0; f < foreign->n_fields; f++) { - if (strcmp(foreign->foreign_col_names[f], from) - == 0) { - - char** rc = const_cast<char**>( - foreign->foreign_col_names - + f); - - if (to_len <= strlen(*rc)) { - memcpy(*rc, to, to_len + 1); - } else { - *rc = static_cast<char*>( - mem_heap_dup( - foreign->heap, - to, - to_len + 1)); - } - } - } - - dict_index_t* new_index = dict_foreign_find_index( - foreign->foreign_table, NULL, - foreign->foreign_col_names, - foreign->n_fields, NULL, true, false, - NULL, NULL, NULL); - /* There must be an equivalent index in this case. */ - ut_ad(new_index != NULL); - - foreign->foreign_index = new_index; - - } else { - - for (unsigned f = 0; f < foreign->n_fields; f++) { - /* These can point straight to - table->col_names, because the foreign key - constraints will be freed at the same time - when the table object is freed. */ - foreign->foreign_col_names[f] - = dict_index_get_nth_field( - foreign->foreign_index, - f)->name; - } + for (unsigned f = 0; f < foreign->n_fields; f++) { + /* These can point straight to + table->col_names, because the foreign key + constraints will be freed at the same time + when the table object is freed. */ + foreign->foreign_col_names[f] + = dict_index_get_nth_field( + foreign->foreign_index, f)->name; } } @@ -445,8 +557,6 @@ dict_mem_table_col_rename_low( foreign = *it; - ut_ad(foreign->referenced_index != NULL); - for (unsigned f = 0; f < foreign->n_fields; f++) { /* foreign->referenced_col_names[] need to be copies, because the constraint may become @@ -478,18 +588,20 @@ dict_mem_table_col_rename_low( /**********************************************************************//** Renames a column of a table in the data dictionary cache. */ -UNIV_INTERN void dict_mem_table_col_rename( /*======================*/ dict_table_t* table, /*!< in/out: table */ unsigned nth_col,/*!< in: column index */ const char* from, /*!< in: old column name */ - const char* to) /*!< in: new column name */ + const char* to, /*!< in: new column name */ + bool is_virtual) + /*!< in: if this is a virtual column */ { - const char* s = table->col_names; + const char* s = is_virtual ? table->v_col_names : table->col_names; - ut_ad(nth_col < table->n_def); + ut_ad((!is_virtual && nth_col < table->n_def) + || (is_virtual && nth_col < table->n_v_def)); for (unsigned i = 0; i < nth_col; i++) { size_t len = strlen(s); @@ -501,13 +613,12 @@ dict_mem_table_col_rename( Proceed with the renaming anyway. */ ut_ad(!strcmp(from, s)); - dict_mem_table_col_rename_low(table, nth_col, to, s); + dict_mem_table_col_rename_low(table, nth_col, to, s, is_virtual); } /**********************************************************************//** This function populates a dict_col_t memory structure with supplied information. */ -UNIV_INTERN void dict_mem_fill_column_struct( /*========================*/ @@ -537,8 +648,7 @@ dict_mem_fill_column_struct( /**********************************************************************//** Creates an index memory object. -@return own: index object */ -UNIV_INTERN +@return own: index object */ dict_index_t* dict_mem_index_create( /*==================*/ @@ -565,20 +675,32 @@ dict_mem_index_create( space, type, n_fields); dict_index_zip_pad_mutex_create_lazy(index); + + if (type & DICT_SPATIAL) { + mutex_create(LATCH_ID_RTR_SSN_MUTEX, &index->rtr_ssn.mutex); + index->rtr_track = static_cast<rtr_info_track_t*>( + mem_heap_alloc( + heap, + sizeof(*index->rtr_track))); + mutex_create(LATCH_ID_RTR_ACTIVE_MUTEX, + &index->rtr_track->rtr_active_mutex); + index->rtr_track->rtr_active = UT_NEW_NOKEY(rtr_info_active()); + } + return(index); } #ifndef UNIV_HOTBACKUP /**********************************************************************//** Creates and initializes a foreign constraint memory object. -@return own: foreign constraint struct */ -UNIV_INTERN +@return own: foreign constraint struct */ dict_foreign_t* dict_mem_foreign_create(void) /*=========================*/ { dict_foreign_t* foreign; mem_heap_t* heap; + DBUG_ENTER("dict_mem_foreign_create"); heap = mem_heap_create(100); @@ -587,7 +709,9 @@ dict_mem_foreign_create(void) foreign->heap = heap; - return(foreign); + DBUG_PRINT("dict_mem_foreign_create", ("heap: %p", heap)); + + DBUG_RETURN(foreign); } /**********************************************************************//** @@ -595,7 +719,6 @@ Sets the foreign_table_name_lookup pointer based on the value of lower_case_table_names. If that is 0 or 1, foreign_table_name_lookup will point to foreign_table_name. If 2, then another string is allocated from foreign->heap and set to lower case. */ -UNIV_INTERN void dict_mem_foreign_table_name_lookup_set( /*===================================*/ @@ -626,7 +749,6 @@ Sets the referenced_table_name_lookup pointer based on the value of lower_case_table_names. If that is 0 or 1, referenced_table_name_lookup will point to referenced_table_name. If 2, then another string is allocated from foreign->heap and set to lower case. */ -UNIV_INTERN void dict_mem_referenced_table_name_lookup_set( /*======================================*/ @@ -657,7 +779,6 @@ dict_mem_referenced_table_name_lookup_set( Adds a field definition to an index. NOTE: does not take a copy of the column name if the field is a column. The memory occupied by the column name may be released only after publishing the index. */ -UNIV_INTERN void dict_mem_index_add_field( /*=====================*/ @@ -682,7 +803,6 @@ dict_mem_index_add_field( /**********************************************************************//** Frees an index memory object. */ -UNIV_INTERN void dict_mem_index_free( /*================*/ @@ -690,15 +810,25 @@ dict_mem_index_free( { ut_ad(index); ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); -#ifdef UNIV_BLOB_DEBUG - if (index->blobs) { - mutex_free(&index->blobs_mutex); - rbt_free(index->blobs); - } -#endif /* UNIV_BLOB_DEBUG */ dict_index_zip_pad_mutex_destroy(index); + if (dict_index_is_spatial(index)) { + rtr_info_active::iterator it; + rtr_info_t* rtr_info; + + for (it = index->rtr_track->rtr_active->begin(); + it != index->rtr_track->rtr_active->end(); ++it) { + rtr_info = *it; + + rtr_info->index = NULL; + } + + mutex_destroy(&index->rtr_ssn.mutex); + mutex_destroy(&index->rtr_track->rtr_active_mutex); + UT_DELETE(index->rtr_track->rtr_active); + } + mem_heap_free(index->heap); } @@ -714,7 +844,6 @@ reasonably unique temporary file name. @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, @@ -723,18 +852,14 @@ dict_mem_create_temporary_tablename( { size_t size; char* name; - const char* dbend = strchr(dbtab, '/'); + const char* dbend = strchr(dbtab, '/'); ut_ad(dbend); - size_t dblen = dbend - dbtab + 1; + size_t dblen = dbend - dbtab + 1; -#ifdef HAVE_ATOMIC_BUILTINS - /* Increment a randomly initialized number for each temp file. */ + /* 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; + size = dblen + (sizeof(TEMP_FILE_PREFIX) + 3 + 20 + 1 + 10); name = static_cast<char*>(mem_heap_alloc(heap, size)); memcpy(name, dbtab, dblen); ut_snprintf(name + dblen, size - dblen, @@ -745,15 +870,13 @@ dict_mem_create_temporary_tablename( } /** 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()); + ib_uint32_t now = static_cast<ib_uint32_t>(ut_time()); - const byte* buf = reinterpret_cast<const byte*>(&now); - ut_ad(ut_crc32 != NULL); + const byte* buf = reinterpret_cast<const byte*>(&now); dict_temp_file_num = ut_crc32(buf, sizeof(now)); |