mariadb/storage/innobase/include/dict0dict.ic
aivanov@mysql.com 1d7de700e2 Applied innodb-5.1-ss594 snapshot.
Fixed BUG#19542 "InnoDB doesn't increase the Handler_read_prev couter".
 Fixed BUG#19609 "Case sensitivity of innodb_data_file_path gives stupid error".
 Fixed BUG#19727 "InnoDB crashed server and crashed tables are ot recoverable".
 Also:
 * Remove remnants of the obsolete concept of memoryfixing tables and indexes.
 * Remove unused dict_table_LRU_trim().
 * Remove unused 'trx' parameter from dict_table_get_on_id_low(),
   dict_table_get(), dict_table_get_and_increment_handle_count().
 * Add a normal linked list implementation.
 * Add a work queue implementation.
 * Add 'level' parameter to mutex_create() and rw_lock_create().
   Remove mutex_set_level() and rw_lock_set_level().
 * Rename SYNC_LEVEL_NONE to SYNC_LEVEL_VARYING.
 * Add support for bound ids in InnoDB's parser.
 * Define UNIV_BTR_DEBUG for enabling consistency checks of
   FIL_PAGE_NEXT and FIL_PAGE_PREV when accessing sibling
   pages of B-tree indexes.
   btr_validate_level(): Check the validity of the doubly linked
   list formed by FIL_PAGE_NEXT and FIL_PAGE_PREV.
 * Adapt InnoDB to the new tablename to filename encoding in MySQL 5.1.
   ut_print_name(), ut_print_name1(): Add parameter 'table_id' for
   distinguishing names of tables from other identifiers.
   New: innobase_convert_from_table_id(), innobase_convert_from_id(),
        innobase_convert_from_filename(), innobase_get_charset.
   dict_accept(), dict_scan_id(), dict_scan_col(), dict_scan_table_name(),
   dict_skip_word(), dict_create_foreign_constraints_low(): Add
   parameter 'cs' so that isspace() can be replaced with my_isspace(),
   whose operation depends on the connection character set.
   dict_scan_id(): Convert identifier to UTF-8.
   dict_str_starts_with_keyword(): New extern function, to replace
   dict_accept() in row_search_for_mysql().
   mysql_get_identifier_quote_char(): Replaced with innobase_print_identifier().
   ha_innobase::create(): Remove the thd->convert_strin() call. Pass the
   statement to InnoDB in the connection character set and let InnoDB
   convert the identifier to UTF-8.
 * Add max_row_size to dict_table_t.
 * btr0cur.c
   btr_copy_externally_stored_field(): Only set the 'offset' variable
   when needed.
 * buf0buf.c
   buf_page_io_complete(): Write to the error log if the page number or
   the space id o the disk do not match those in memory. Also write to
   the error log if a page was read from the doublewrite buffer. The
   doublewrite buffer should be only read by the lower-level function
   fil_io() at database startup.
 * dict0dict.c
   dict_scan_table_name(): Remove fallback to differently encoded name
   when the table is not found. The encoding is handled at a higher level.
 * ha_innodb.cc
   Increment statistic counter in ha_innobase::index_prev() (bug 19542).
   Add innobase_convert_string wrapper function and a new file
   ha_prototypes.h.
   innobase_print_identifier(): Remove TODO comment before calling
   get_quote_char_for_identifier(). That function apparently assumes
   the identifier to be encoded in UTF-8.
 * ibuf0ibuf.c|h
   ibuf_count_get(), ibuf_counts[], ibuf_count_inited(): Define these
   only #ifdef UNIV_IBUF_DEBUG. Previously, when compiled without
   UNIV_IBUF_DEBUG, invoking ibuf_count_get() would crash InnoDB.
   The function is only being called #ifdef UNIV_IBUF_DEBUG.
 * innodb.result
   Adjust the results for changes in the foreign key error messages.
 * mem0mem.c|h
   New: mem_heap_dup(), mem_heap_printf(), mem_heap_cat().
 * os0file.c
   Check the page trailers also after writing to disk. This improves
   chances of diagnosing bug 18886.
   os_file_check_page_trailers(): New function for checking that the
   two copies of the LSN stamped on the page match.
   os_aio_simulated_handle(): Call os_file_check_page_trailers()
   before and after os_file_write().
 * row0mysql.c
   Move trx_commit_for_mysql(trx) calls before calls to
   row_mysql_unlock_data_dictionary(trx) (bug 19727).
 * row0sel.c
   row_fetch_print(): Handle SQL NULL values without crashing.
   row_sel_store_mysql_rec(): Remove useless call to rec_get_nth_field
   when handling an externally stored column.
   Fetch externally stored fields when using InnoDB's internal SQL
   parser.
   Optimize BLOB selects by using prebuilt->blob_heap directly instead
   of first reading BLOB data to a temporary heap and then copying it
   to prebuilt->blob_heap.
 * srv0srv.c
   srv_master_thread(): Remove unreachable code.
 * srv0start.c
   srv_parse_data_file_paths_and_sizes(): Accept lower-case 'm' and
   'g' as abbreviations of megabyte and gigabyte (bug 19609).
   srv_parse_megabytes(): New fuction.
 * ut0dbg.c|h
   Implement InnoDB assertions (ut_a and ut_error) with abort() when
   the code is compiled with GCC 3 or later on other platforms than
   Windows or Netware. Also disable the variable ut_dbg_stop_threads
   and the function ut_dbg_stop_thread() i this case, unless
   UNIV_SYC_DEBUG is defined. This should allow the compiler to
   generate more compact code for assertions.
 * ut0list.c|h
   Add ib_list_create_heap().
2006-06-01 10:34:04 +04:00

601 lines
15 KiB
Text

/**********************************************************************
Data dictionary system
(c) 1996 Innobase Oy
Created 1/8/1996 Heikki Tuuri
***********************************************************************/
#include "dict0load.h"
#include "trx0undo.h"
#include "trx0sys.h"
/*************************************************************************
Gets the column data type. */
UNIV_INLINE
dtype_t*
dict_col_get_type(
/*==============*/
dict_col_t* col)
{
ut_ad(col);
return(&col->type);
}
/*************************************************************************
Gets the column number. */
UNIV_INLINE
ulint
dict_col_get_no(
/*============*/
dict_col_t* col)
{
ut_ad(col);
return(col->ind);
}
/*************************************************************************
Gets the column position in the clustered index. */
UNIV_INLINE
ulint
dict_col_get_clust_pos(
/*===================*/
dict_col_t* col)
{
ut_ad(col);
return(col->clust_pos);
}
/************************************************************************
Gets the first index on the table (the clustered index). */
UNIV_INLINE
dict_index_t*
dict_table_get_first_index(
/*=======================*/
/* out: index, NULL if none exists */
dict_table_t* table) /* in: table */
{
ut_ad(table);
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
return(UT_LIST_GET_FIRST(table->indexes));
}
/************************************************************************
Gets the next index on the table. */
UNIV_INLINE
dict_index_t*
dict_table_get_next_index(
/*======================*/
/* out: index, NULL if none left */
dict_index_t* index) /* in: index */
{
ut_ad(index);
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
return(UT_LIST_GET_NEXT(indexes, index));
}
/************************************************************************
Gets the number of user-defined columns in a table in the dictionary
cache. */
UNIV_INLINE
ulint
dict_table_get_n_user_cols(
/*=======================*/
/* out: number of user-defined (e.g., not
ROW_ID) columns of a table */
dict_table_t* table) /* in: table */
{
ut_ad(table);
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
return(table->n_cols - DATA_N_SYS_COLS);
}
/************************************************************************
Gets the number of system columns in a table in the dictionary cache. */
UNIV_INLINE
ulint
dict_table_get_n_sys_cols(
/*======================*/
/* out: number of system (e.g.,
ROW_ID) columns of a table */
dict_table_t* table __attribute__((unused))) /* in: table */
{
ut_ad(table);
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
ut_ad(table->cached);
return(DATA_N_SYS_COLS);
}
/************************************************************************
Gets the number of all columns (also system) in a table in the dictionary
cache. */
UNIV_INLINE
ulint
dict_table_get_n_cols(
/*==================*/
/* out: number of columns of a table */
dict_table_t* table) /* in: table */
{
ut_ad(table);
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
return(table->n_cols);
}
/************************************************************************
Gets the nth column of a table. */
UNIV_INLINE
dict_col_t*
dict_table_get_nth_col(
/*===================*/
/* out: pointer to column object */
dict_table_t* table, /* in: table */
ulint pos) /* in: position of column */
{
ut_ad(table);
ut_ad(pos < table->n_def);
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
return((table->cols) + pos);
}
/************************************************************************
Gets the given system column of a table. */
UNIV_INLINE
dict_col_t*
dict_table_get_sys_col(
/*===================*/
/* out: pointer to column object */
dict_table_t* table, /* in: table */
ulint sys) /* in: DATA_ROW_ID, ... */
{
dict_col_t* col;
ut_ad(table);
ut_ad(sys < DATA_N_SYS_COLS);
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
col = dict_table_get_nth_col(table, table->n_cols
- DATA_N_SYS_COLS + sys);
ut_ad(col->type.mtype == DATA_SYS);
ut_ad(col->type.prtype == (sys | DATA_NOT_NULL));
return(col);
}
/************************************************************************
Gets the given system column number of a table. */
UNIV_INLINE
ulint
dict_table_get_sys_col_no(
/*======================*/
/* out: column number */
dict_table_t* table, /* in: table */
ulint sys) /* in: DATA_ROW_ID, ... */
{
ut_ad(table);
ut_ad(sys < DATA_N_SYS_COLS);
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
return(table->n_cols - DATA_N_SYS_COLS + sys);
}
/************************************************************************
Check whether the table uses the compact page format. */
UNIV_INLINE
ibool
dict_table_is_comp(
/*===============*/
/* out: TRUE if table uses the
compact page format */
const dict_table_t* table) /* in: table */
{
ut_ad(table);
#if DICT_TF_COMPACT != TRUE
#error
#endif
return(UNIV_LIKELY(table->flags & DICT_TF_COMPACT));
}
/************************************************************************
Gets the number of fields in the internal representation of an index,
including fields added by the dictionary system. */
UNIV_INLINE
ulint
dict_index_get_n_fields(
/*====================*/
/* out: number of fields */
dict_index_t* index) /* in: an internal representation of index
(in the dictionary cache) */
{
ut_ad(index);
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
return(index->n_fields);
}
/************************************************************************
Gets the number of fields in the internal representation of an index
that uniquely determine the position of an index entry in the index, if
we do not take multiversioning into account: in the B-tree use the value
returned by dict_index_get_n_unique_in_tree. */
UNIV_INLINE
ulint
dict_index_get_n_unique(
/*====================*/
/* out: number of fields */
dict_index_t* index) /* in: an internal representation of index
(in the dictionary cache) */
{
ut_ad(index);
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
ut_ad(index->cached);
return(index->n_uniq);
}
/************************************************************************
Gets the number of fields in the internal representation of an index
which uniquely determine the position of an index entry in the index, if
we also take multiversioning into account. */
UNIV_INLINE
ulint
dict_index_get_n_unique_in_tree(
/*============================*/
/* out: number of fields */
dict_index_t* index) /* in: an internal representation of index
(in the dictionary cache) */
{
ut_ad(index);
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
ut_ad(index->cached);
if (index->type & DICT_CLUSTERED) {
return(dict_index_get_n_unique(index));
}
return(dict_index_get_n_fields(index));
}
/************************************************************************
Gets the number of user-defined ordering fields in the index. In the internal
representation of clustered indexes we add the row id to the ordering fields
to make a clustered index unique, but this function returns the number of
fields the user defined in the index as ordering fields. */
UNIV_INLINE
ulint
dict_index_get_n_ordering_defined_by_user(
/*======================================*/
/* out: number of fields */
dict_index_t* index) /* in: an internal representation of index
(in the dictionary cache) */
{
return(index->n_user_defined_cols);
}
/************************************************************************
Gets the nth field of an index. */
UNIV_INLINE
dict_field_t*
dict_index_get_nth_field(
/*=====================*/
/* out: pointer to field object */
dict_index_t* index, /* in: index */
ulint pos) /* in: position of field */
{
ut_ad(index);
ut_ad(pos < index->n_def);
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
return((index->fields) + pos);
}
/************************************************************************
Returns the position of a system column in an index. */
UNIV_INLINE
ulint
dict_index_get_sys_col_pos(
/*=======================*/
/* out: position, ULINT_UNDEFINED if not
contained */
dict_index_t* index, /* in: index */
ulint type) /* in: DATA_ROW_ID, ... */
{
dict_col_t* col;
ut_ad(index);
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
ut_ad(!(index->type & DICT_UNIVERSAL));
col = dict_table_get_sys_col(index->table, type);
if (index->type & DICT_CLUSTERED) {
return(col->clust_pos);
}
return(dict_index_get_nth_col_pos(index,
dict_table_get_sys_col_no(index->table, type)));
}
/*************************************************************************
Gets the index tree where the index is stored. */
UNIV_INLINE
dict_tree_t*
dict_index_get_tree(
/*================*/
/* out: index tree */
dict_index_t* index) /* in: index */
{
ut_ad(index);
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
return(index->tree);
}
/*************************************************************************
Gets the field column. */
UNIV_INLINE
dict_col_t*
dict_field_get_col(
/*===============*/
dict_field_t* field)
{
ut_ad(field);
return(field->col);
}
/************************************************************************
Gets pointer to the nth field data type in an index. */
UNIV_INLINE
dtype_t*
dict_index_get_nth_type(
/*====================*/
/* out: data type */
dict_index_t* index, /* in: index */
ulint pos) /* in: position of the field */
{
return(dict_col_get_type(dict_field_get_col(
dict_index_get_nth_field(index, pos))));
}
/************************************************************************
Gets the column number the nth field in an index. */
UNIV_INLINE
ulint
dict_index_get_nth_col_no(
/*======================*/
/* out: column number */
dict_index_t* index, /* in: index */
ulint pos) /* in: position of the field */
{
return(dict_col_get_no(dict_field_get_col(
dict_index_get_nth_field(index, pos))));
}
/*************************************************************************
Gets the space id of the root of the index tree. */
UNIV_INLINE
ulint
dict_tree_get_space(
/*================*/
/* out: space id */
dict_tree_t* tree) /* in: tree */
{
ut_ad(tree);
ut_ad(tree->magic_n == DICT_TREE_MAGIC_N);
return(tree->space);
}
/*************************************************************************
Sets the space id of the root of the index tree. */
UNIV_INLINE
void
dict_tree_set_space(
/*================*/
dict_tree_t* tree, /* in: tree */
ulint space) /* in: space id */
{
ut_ad(tree);
ut_ad(tree->magic_n == DICT_TREE_MAGIC_N);
tree->space = space;
}
/*************************************************************************
Gets the page number of the root of the index tree. */
UNIV_INLINE
ulint
dict_tree_get_page(
/*===============*/
/* out: page number */
dict_tree_t* tree) /* in: tree */
{
ut_ad(tree);
ut_ad(tree->magic_n == DICT_TREE_MAGIC_N);
return(tree->page);
}
/*************************************************************************
Sets the page number of the root of index tree. */
UNIV_INLINE
void
dict_tree_set_page(
/*===============*/
dict_tree_t* tree, /* in: tree */
ulint page) /* in: page number */
{
ut_ad(tree);
ut_ad(tree->magic_n == DICT_TREE_MAGIC_N);
tree->page = page;
}
/*************************************************************************
Gets the type of the index tree. */
UNIV_INLINE
ulint
dict_tree_get_type(
/*===============*/
/* out: type */
dict_tree_t* tree) /* in: tree */
{
ut_ad(tree);
ut_ad(tree->magic_n == DICT_TREE_MAGIC_N);
return(tree->type);
}
/*************************************************************************
Gets the read-write lock of the index tree. */
UNIV_INLINE
rw_lock_t*
dict_tree_get_lock(
/*===============*/
/* out: read-write lock */
dict_tree_t* tree) /* in: tree */
{
ut_ad(tree);
ut_ad(tree->magic_n == DICT_TREE_MAGIC_N);
return(&(tree->lock));
}
/************************************************************************
Returns free space reserved for future updates of records. This is
relevant only in the case of many consecutive inserts, as updates
which make the records bigger might fragment the index. */
UNIV_INLINE
ulint
dict_tree_get_space_reserve(
/*========================*/
/* out: number of free bytes on page,
reserved for updates */
dict_tree_t* tree) /* in: a tree */
{
ut_ad(tree);
UT_NOT_USED(tree);
return(UNIV_PAGE_SIZE / 16);
}
/**************************************************************************
Checks if a table is in the dictionary cache. */
UNIV_INLINE
dict_table_t*
dict_table_check_if_in_cache_low(
/*=============================*/
/* out: table, NULL if not found */
const char* table_name) /* in: table name */
{
dict_table_t* table;
ulint table_fold;
ut_ad(table_name);
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
#endif /* UNIV_SYNC_DEBUG */
/* Look for the table name in the hash table */
table_fold = ut_fold_string(table_name);
HASH_SEARCH(name_hash, dict_sys->table_hash, table_fold, table,
ut_strcmp(table->name, table_name) == 0);
return(table);
}
/**************************************************************************
Gets a table; loads it to the dictionary cache if necessary. A low-level
function. */
UNIV_INLINE
dict_table_t*
dict_table_get_low(
/*===============*/
/* out: table, NULL if not found */
const char* table_name) /* in: table name */
{
dict_table_t* table;
ut_ad(table_name);
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
#endif /* UNIV_SYNC_DEBUG */
table = dict_table_check_if_in_cache_low(table_name);
if (table == NULL) {
table = dict_load_table(table_name);
}
return(table);
}
/**************************************************************************
Returns a table object based on table id. */
UNIV_INLINE
dict_table_t*
dict_table_get_on_id_low(
/*=====================*/
/* out: table, NULL if does not exist */
dulint table_id) /* in: table id */
{
dict_table_t* table;
ulint fold;
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
#endif /* UNIV_SYNC_DEBUG */
/* Look for the table name in the hash table */
fold = ut_fold_dulint(table_id);
HASH_SEARCH(id_hash, dict_sys->table_id_hash, fold, table,
ut_dulint_cmp(table->id, table_id) == 0);
if (table == NULL) {
table = dict_load_table_on_id(table_id);
}
/* TODO: should get the type information from MySQL */
return(table);
}
/**************************************************************************
Returns an index object. */
UNIV_INLINE
dict_index_t*
dict_table_get_index(
/*=================*/
/* out: index, NULL if does not exist */
dict_table_t* table, /* in: table */
const char* name) /* in: index name */
{
dict_index_t* index = NULL;
index = dict_table_get_first_index(table);
while (index != NULL) {
if (ut_strcmp(name, index->name) == 0) {
break;
}
index = dict_table_get_next_index(index);
}
return(index);
}