summaryrefslogtreecommitdiff
path: root/storage/innobase/dict/dict0crea.c
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase/dict/dict0crea.c')
-rw-r--r--storage/innobase/dict/dict0crea.c1450
1 files changed, 0 insertions, 1450 deletions
diff --git a/storage/innobase/dict/dict0crea.c b/storage/innobase/dict/dict0crea.c
deleted file mode 100644
index 4116230347d..00000000000
--- a/storage/innobase/dict/dict0crea.c
+++ /dev/null
@@ -1,1450 +0,0 @@
-/******************************************************
-Database object creation
-
-(c) 1996 Innobase Oy
-
-Created 1/8/1996 Heikki Tuuri
-*******************************************************/
-
-#include "dict0crea.h"
-
-#ifdef UNIV_NONINL
-#include "dict0crea.ic"
-#endif
-
-#include "btr0pcur.h"
-#include "btr0btr.h"
-#include "page0page.h"
-#include "mach0data.h"
-#include "dict0boot.h"
-#include "dict0dict.h"
-#include "que0que.h"
-#include "row0ins.h"
-#include "row0mysql.h"
-#include "pars0pars.h"
-#include "trx0roll.h"
-#include "usr0sess.h"
-#include "ut0vec.h"
-
-/*********************************************************************
-Based on a table object, this function builds the entry to be inserted
-in the SYS_TABLES system table. */
-static
-dtuple_t*
-dict_create_sys_tables_tuple(
-/*=========================*/
- /* out: the tuple which should be inserted */
- dict_table_t* table, /* in: table */
- mem_heap_t* heap) /* in: memory heap from which the memory for
- the built tuple is allocated */
-{
- dict_table_t* sys_tables;
- dtuple_t* entry;
- dfield_t* dfield;
- byte* ptr;
-
- ut_ad(table && heap);
-
- sys_tables = dict_sys->sys_tables;
-
- entry = dtuple_create(heap, 8 + DATA_N_SYS_COLS);
-
- /* 0: NAME -----------------------------*/
- dfield = dtuple_get_nth_field(entry, 0);
-
- dfield_set_data(dfield, table->name, ut_strlen(table->name));
- /* 3: ID -------------------------------*/
- dfield = dtuple_get_nth_field(entry, 1);
-
- ptr = mem_heap_alloc(heap, 8);
- mach_write_to_8(ptr, table->id);
-
- dfield_set_data(dfield, ptr, 8);
- /* 4: N_COLS ---------------------------*/
- dfield = dtuple_get_nth_field(entry, 2);
-
-#if DICT_TF_COMPACT != 1
-#error
-#endif
-
- ptr = mem_heap_alloc(heap, 4);
- mach_write_to_4(ptr, table->n_def
- | ((table->flags & DICT_TF_COMPACT) << 31));
- dfield_set_data(dfield, ptr, 4);
- /* 5: TYPE -----------------------------*/
- dfield = dtuple_get_nth_field(entry, 3);
-
- ptr = mem_heap_alloc(heap, 4);
- mach_write_to_4(ptr, DICT_TABLE_ORDINARY);
-
- dfield_set_data(dfield, ptr, 4);
- /* 6: MIX_ID (obsolete) ---------------------------*/
- dfield = dtuple_get_nth_field(entry, 4);
-
- ptr = mem_heap_alloc(heap, 8);
- memset(ptr, 0, 8);
-
- dfield_set_data(dfield, ptr, 8);
- /* 7: MIX_LEN (obsolete) --------------------------*/
-
- dfield = dtuple_get_nth_field(entry, 5);
-
- ptr = mem_heap_alloc(heap, 4);
- memset(ptr, 0, 4);
-
- dfield_set_data(dfield, ptr, 4);
- /* 8: CLUSTER_NAME ---------------------*/
- dfield = dtuple_get_nth_field(entry, 6);
- dfield_set_data(dfield, NULL, UNIV_SQL_NULL); /* not supported */
-
- /* 9: SPACE ----------------------------*/
- dfield = dtuple_get_nth_field(entry, 7);
-
- ptr = mem_heap_alloc(heap, 4);
- mach_write_to_4(ptr, table->space);
-
- dfield_set_data(dfield, ptr, 4);
- /*----------------------------------*/
-
- dict_table_copy_types(entry, sys_tables);
-
- return(entry);
-}
-
-/*********************************************************************
-Based on a table object, this function builds the entry to be inserted
-in the SYS_COLUMNS system table. */
-static
-dtuple_t*
-dict_create_sys_columns_tuple(
-/*==========================*/
- /* out: the tuple which should be inserted */
- dict_table_t* table, /* in: table */
- ulint i, /* in: column number */
- mem_heap_t* heap) /* in: memory heap from which the memory for
- the built tuple is allocated */
-{
- dict_table_t* sys_columns;
- dtuple_t* entry;
- const dict_col_t* column;
- dfield_t* dfield;
- byte* ptr;
- const char* col_name;
-
- ut_ad(table && heap);
-
- column = dict_table_get_nth_col(table, i);
-
- sys_columns = dict_sys->sys_columns;
-
- entry = dtuple_create(heap, 7 + DATA_N_SYS_COLS);
-
- /* 0: TABLE_ID -----------------------*/
- dfield = dtuple_get_nth_field(entry, 0);
-
- ptr = mem_heap_alloc(heap, 8);
- mach_write_to_8(ptr, table->id);
-
- dfield_set_data(dfield, ptr, 8);
- /* 1: POS ----------------------------*/
- dfield = dtuple_get_nth_field(entry, 1);
-
- ptr = mem_heap_alloc(heap, 4);
- mach_write_to_4(ptr, i);
-
- dfield_set_data(dfield, ptr, 4);
- /* 4: NAME ---------------------------*/
- dfield = dtuple_get_nth_field(entry, 2);
-
- col_name = dict_table_get_col_name(table, i);
- dfield_set_data(dfield, col_name, ut_strlen(col_name));
- /* 5: MTYPE --------------------------*/
- dfield = dtuple_get_nth_field(entry, 3);
-
- ptr = mem_heap_alloc(heap, 4);
- mach_write_to_4(ptr, column->mtype);
-
- dfield_set_data(dfield, ptr, 4);
- /* 6: PRTYPE -------------------------*/
- dfield = dtuple_get_nth_field(entry, 4);
-
- ptr = mem_heap_alloc(heap, 4);
- mach_write_to_4(ptr, column->prtype);
-
- dfield_set_data(dfield, ptr, 4);
- /* 7: LEN ----------------------------*/
- dfield = dtuple_get_nth_field(entry, 5);
-
- ptr = mem_heap_alloc(heap, 4);
- mach_write_to_4(ptr, column->len);
-
- dfield_set_data(dfield, ptr, 4);
- /* 8: PREC ---------------------------*/
- dfield = dtuple_get_nth_field(entry, 6);
-
- ptr = mem_heap_alloc(heap, 4);
- mach_write_to_4(ptr, 0/* unused */);
-
- dfield_set_data(dfield, ptr, 4);
- /*---------------------------------*/
-
- dict_table_copy_types(entry, sys_columns);
-
- return(entry);
-}
-
-/*******************************************************************
-Builds a table definition to insert. */
-static
-ulint
-dict_build_table_def_step(
-/*======================*/
- /* out: DB_SUCCESS or error code */
- que_thr_t* thr, /* in: query thread */
- tab_node_t* node) /* in: table create node */
-{
- dict_table_t* table;
- dtuple_t* row;
- ulint error;
- const char* path_or_name;
- ibool is_path;
- mtr_t mtr;
- ulint i;
- ulint row_len;
-
- ut_ad(mutex_own(&(dict_sys->mutex)));
-
- table = node->table;
-
- table->id = dict_hdr_get_new_id(DICT_HDR_TABLE_ID);
-
- thr_get_trx(thr)->table_id = table->id;
-
- row_len = 0;
- for (i = 0; i < table->n_def; i++) {
- row_len += dict_col_get_min_size(&table->cols[i]);
- }
- if (row_len > BTR_PAGE_MAX_REC_SIZE) {
- return(DB_TOO_BIG_RECORD);
- }
-
- if (srv_file_per_table) {
- /* We create a new single-table tablespace for the table.
- We initially let it be 4 pages:
- - page 0 is the fsp header and an extent descriptor page,
- - page 1 is an ibuf bitmap page,
- - page 2 is the first inode page,
- - page 3 will contain the root of the clustered index of the
- table we create here. */
-
- ulint space = 0; /* reset to zero for the call below */
-
- if (table->dir_path_of_temp_table) {
- /* We place tables created with CREATE TEMPORARY
- TABLE in the tmp dir of mysqld server */
-
- path_or_name = table->dir_path_of_temp_table;
- is_path = TRUE;
- } else {
- path_or_name = table->name;
- is_path = FALSE;
- }
-
- error = fil_create_new_single_table_tablespace(
- &space, path_or_name, is_path,
- FIL_IBD_FILE_INITIAL_SIZE);
- table->space = (unsigned int) space;
-
- if (error != DB_SUCCESS) {
-
- return(error);
- }
-
- mtr_start(&mtr);
-
- fsp_header_init(table->space, FIL_IBD_FILE_INITIAL_SIZE, &mtr);
-
- mtr_commit(&mtr);
- }
-
- row = dict_create_sys_tables_tuple(table, node->heap);
-
- ins_node_set_new_row(node->tab_def, row);
-
- return(DB_SUCCESS);
-}
-
-/*******************************************************************
-Builds a column definition to insert. */
-static
-ulint
-dict_build_col_def_step(
-/*====================*/
- /* out: DB_SUCCESS */
- tab_node_t* node) /* in: table create node */
-{
- dtuple_t* row;
-
- row = dict_create_sys_columns_tuple(node->table, node->col_no,
- node->heap);
- ins_node_set_new_row(node->col_def, row);
-
- return(DB_SUCCESS);
-}
-
-/*********************************************************************
-Based on an index object, this function builds the entry to be inserted
-in the SYS_INDEXES system table. */
-static
-dtuple_t*
-dict_create_sys_indexes_tuple(
-/*==========================*/
- /* out: the tuple which should be inserted */
- dict_index_t* index, /* in: index */
- mem_heap_t* heap) /* in: memory heap from which the memory for
- the built tuple is allocated */
-{
- dict_table_t* sys_indexes;
- dict_table_t* table;
- dtuple_t* entry;
- dfield_t* dfield;
- byte* ptr;
-
- ut_ad(mutex_own(&(dict_sys->mutex)));
- ut_ad(index && heap);
-
- sys_indexes = dict_sys->sys_indexes;
-
- table = dict_table_get_low(index->table_name);
-
- entry = dtuple_create(heap, 7 + DATA_N_SYS_COLS);
-
- /* 0: TABLE_ID -----------------------*/
- dfield = dtuple_get_nth_field(entry, 0);
-
- ptr = mem_heap_alloc(heap, 8);
- mach_write_to_8(ptr, table->id);
-
- dfield_set_data(dfield, ptr, 8);
- /* 1: ID ----------------------------*/
- dfield = dtuple_get_nth_field(entry, 1);
-
- ptr = mem_heap_alloc(heap, 8);
- mach_write_to_8(ptr, index->id);
-
- dfield_set_data(dfield, ptr, 8);
- /* 4: NAME --------------------------*/
- dfield = dtuple_get_nth_field(entry, 2);
-
- dfield_set_data(dfield, index->name, ut_strlen(index->name));
- /* 5: N_FIELDS ----------------------*/
- dfield = dtuple_get_nth_field(entry, 3);
-
- ptr = mem_heap_alloc(heap, 4);
- mach_write_to_4(ptr, index->n_fields);
-
- dfield_set_data(dfield, ptr, 4);
- /* 6: TYPE --------------------------*/
- dfield = dtuple_get_nth_field(entry, 4);
-
- ptr = mem_heap_alloc(heap, 4);
- mach_write_to_4(ptr, index->type);
-
- dfield_set_data(dfield, ptr, 4);
- /* 7: SPACE --------------------------*/
-
-#if DICT_SYS_INDEXES_SPACE_NO_FIELD != 7
-#error "DICT_SYS_INDEXES_SPACE_NO_FIELD != 7"
-#endif
-
- dfield = dtuple_get_nth_field(entry, 5);
-
- ptr = mem_heap_alloc(heap, 4);
- mach_write_to_4(ptr, index->space);
-
- dfield_set_data(dfield, ptr, 4);
- /* 8: PAGE_NO --------------------------*/
-
-#if DICT_SYS_INDEXES_PAGE_NO_FIELD != 8
-#error "DICT_SYS_INDEXES_PAGE_NO_FIELD != 8"
-#endif
-
- dfield = dtuple_get_nth_field(entry, 6);
-
- ptr = mem_heap_alloc(heap, 4);
- mach_write_to_4(ptr, FIL_NULL);
-
- dfield_set_data(dfield, ptr, 4);
- /*--------------------------------*/
-
- dict_table_copy_types(entry, sys_indexes);
-
- return(entry);
-}
-
-/*********************************************************************
-Based on an index object, this function builds the entry to be inserted
-in the SYS_FIELDS system table. */
-static
-dtuple_t*
-dict_create_sys_fields_tuple(
-/*=========================*/
- /* out: the tuple which should be inserted */
- dict_index_t* index, /* in: index */
- ulint i, /* in: field number */
- mem_heap_t* heap) /* in: memory heap from which the memory for
- the built tuple is allocated */
-{
- dict_table_t* sys_fields;
- dtuple_t* entry;
- dict_field_t* field;
- dfield_t* dfield;
- byte* ptr;
- ibool index_contains_column_prefix_field = FALSE;
- ulint j;
-
- ut_ad(index && heap);
-
- for (j = 0; j < index->n_fields; j++) {
- if (dict_index_get_nth_field(index, j)->prefix_len > 0) {
- index_contains_column_prefix_field = TRUE;
- }
- }
-
- field = dict_index_get_nth_field(index, i);
-
- sys_fields = dict_sys->sys_fields;
-
- entry = dtuple_create(heap, 3 + DATA_N_SYS_COLS);
-
- /* 0: INDEX_ID -----------------------*/
- dfield = dtuple_get_nth_field(entry, 0);
-
- ptr = mem_heap_alloc(heap, 8);
- mach_write_to_8(ptr, index->id);
-
- dfield_set_data(dfield, ptr, 8);
- /* 1: POS + PREFIX LENGTH ----------------------------*/
-
- dfield = dtuple_get_nth_field(entry, 1);
-
- ptr = mem_heap_alloc(heap, 4);
-
- if (index_contains_column_prefix_field) {
- /* If there are column prefix fields in the index, then
- we store the number of the field to the 2 HIGH bytes
- and the prefix length to the 2 low bytes, */
-
- mach_write_to_4(ptr, (i << 16) + field->prefix_len);
- } else {
- /* Else we store the number of the field to the 2 LOW bytes.
- This is to keep the storage format compatible with
- InnoDB versions < 4.0.14. */
-
- mach_write_to_4(ptr, i);
- }
-
- dfield_set_data(dfield, ptr, 4);
- /* 4: COL_NAME -------------------------*/
- dfield = dtuple_get_nth_field(entry, 2);
-
- dfield_set_data(dfield, field->name,
- ut_strlen(field->name));
- /*---------------------------------*/
-
- dict_table_copy_types(entry, sys_fields);
-
- return(entry);
-}
-
-/*********************************************************************
-Creates the tuple with which the index entry is searched for writing the index
-tree root page number, if such a tree is created. */
-static
-dtuple_t*
-dict_create_search_tuple(
-/*=====================*/
- /* out: the tuple for search */
- dtuple_t* tuple, /* in: the tuple inserted in the SYS_INDEXES
- table */
- mem_heap_t* heap) /* in: memory heap from which the memory for
- the built tuple is allocated */
-{
- dtuple_t* search_tuple;
- dfield_t* field1;
- dfield_t* field2;
-
- ut_ad(tuple && heap);
-
- search_tuple = dtuple_create(heap, 2);
-
- field1 = dtuple_get_nth_field(tuple, 0);
- field2 = dtuple_get_nth_field(search_tuple, 0);
-
- dfield_copy(field2, field1);
-
- field1 = dtuple_get_nth_field(tuple, 1);
- field2 = dtuple_get_nth_field(search_tuple, 1);
-
- dfield_copy(field2, field1);
-
- ut_ad(dtuple_validate(search_tuple));
-
- return(search_tuple);
-}
-
-/*******************************************************************
-Builds an index definition row to insert. */
-static
-ulint
-dict_build_index_def_step(
-/*======================*/
- /* out: DB_SUCCESS or error code */
- que_thr_t* thr, /* in: query thread */
- ind_node_t* node) /* in: index create node */
-{
- dict_table_t* table;
- dict_index_t* index;
- dtuple_t* row;
- trx_t* trx;
-
- ut_ad(mutex_own(&(dict_sys->mutex)));
-
- trx = thr_get_trx(thr);
-
- index = node->index;
-
- table = dict_table_get_low(index->table_name);
-
- if (table == NULL) {
- return(DB_TABLE_NOT_FOUND);
- }
-
- trx->table_id = table->id;
-
- node->table = table;
-
- ut_ad((UT_LIST_GET_LEN(table->indexes) > 0)
- || (index->type & DICT_CLUSTERED));
-
- index->id = dict_hdr_get_new_id(DICT_HDR_INDEX_ID);
-
- /* Inherit the space id from the table; we store all indexes of a
- table in the same tablespace */
-
- index->space = table->space;
- node->page_no = FIL_NULL;
- row = dict_create_sys_indexes_tuple(index, node->heap);
- node->ind_row = row;
-
- ins_node_set_new_row(node->ind_def, row);
-
- return(DB_SUCCESS);
-}
-
-/*******************************************************************
-Builds a field definition row to insert. */
-static
-ulint
-dict_build_field_def_step(
-/*======================*/
- /* out: DB_SUCCESS */
- ind_node_t* node) /* in: index create node */
-{
- dict_index_t* index;
- dtuple_t* row;
-
- index = node->index;
-
- row = dict_create_sys_fields_tuple(index, node->field_no, node->heap);
-
- ins_node_set_new_row(node->field_def, row);
-
- return(DB_SUCCESS);
-}
-
-/*******************************************************************
-Creates an index tree for the index if it is not a member of a cluster. */
-static
-ulint
-dict_create_index_tree_step(
-/*========================*/
- /* out: DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
- ind_node_t* node) /* in: index create node */
-{
- dict_index_t* index;
- dict_table_t* sys_indexes;
- dict_table_t* table;
- dtuple_t* search_tuple;
- btr_pcur_t pcur;
- mtr_t mtr;
-
- ut_ad(mutex_own(&(dict_sys->mutex)));
-
- index = node->index;
- table = node->table;
-
- sys_indexes = dict_sys->sys_indexes;
-
- /* Run a mini-transaction in which the index tree is allocated for
- the index and its root address is written to the index entry in
- sys_indexes */
-
- mtr_start(&mtr);
-
- search_tuple = dict_create_search_tuple(node->ind_row, node->heap);
-
- btr_pcur_open(UT_LIST_GET_FIRST(sys_indexes->indexes),
- search_tuple, PAGE_CUR_L, BTR_MODIFY_LEAF,
- &pcur, &mtr);
-
- btr_pcur_move_to_next_user_rec(&pcur, &mtr);
-
- node->page_no = btr_create(index->type, index->space, index->id,
- dict_table_is_comp(table), &mtr);
- /* printf("Created a new index tree in space %lu root page %lu\n",
- index->space, index->page_no); */
-
- page_rec_write_index_page_no(btr_pcur_get_rec(&pcur),
- DICT_SYS_INDEXES_PAGE_NO_FIELD,
- node->page_no, &mtr);
- btr_pcur_close(&pcur);
- mtr_commit(&mtr);
-
- if (node->page_no == FIL_NULL) {
-
- return(DB_OUT_OF_FILE_SPACE);
- }
-
- return(DB_SUCCESS);
-}
-
-/***********************************************************************
-Drops the index tree associated with a row in SYS_INDEXES table. */
-
-void
-dict_drop_index_tree(
-/*=================*/
- rec_t* rec, /* in: record in the clustered index of SYS_INDEXES
- table */
- mtr_t* mtr) /* in: mtr having the latch on the record page */
-{
- ulint root_page_no;
- ulint space;
- byte* ptr;
- ulint len;
-
- ut_ad(mutex_own(&(dict_sys->mutex)));
- ut_a(!dict_table_is_comp(dict_sys->sys_indexes));
- ptr = rec_get_nth_field_old(rec, DICT_SYS_INDEXES_PAGE_NO_FIELD, &len);
-
- ut_ad(len == 4);
-
- root_page_no = mtr_read_ulint(ptr, MLOG_4BYTES, mtr);
-
- if (root_page_no == FIL_NULL) {
- /* The tree has already been freed */
-
- return;
- }
-
- ptr = rec_get_nth_field_old(rec,
- DICT_SYS_INDEXES_SPACE_NO_FIELD, &len);
-
- ut_ad(len == 4);
-
- space = mtr_read_ulint(ptr, MLOG_4BYTES, mtr);
-
- if (!fil_tablespace_exists_in_mem(space)) {
- /* It is a single table tablespace and the .ibd file is
- missing: do nothing */
-
- return;
- }
-
- /* We free all the pages but the root page first; this operation
- may span several mini-transactions */
-
- btr_free_but_not_root(space, root_page_no);
-
- /* Then we free the root page in the same mini-transaction where
- we write FIL_NULL to the appropriate field in the SYS_INDEXES
- record: this mini-transaction marks the B-tree totally freed */
-
- /* printf("Dropping index tree in space %lu root page %lu\n", space,
- root_page_no); */
- btr_free_root(space, root_page_no, mtr);
-
- page_rec_write_index_page_no(rec,
- DICT_SYS_INDEXES_PAGE_NO_FIELD,
- FIL_NULL, mtr);
-}
-
-/***********************************************************************
-Truncates the index tree associated with a row in SYS_INDEXES table. */
-
-ulint
-dict_truncate_index_tree(
-/*=====================*/
- /* out: new root page number, or
- FIL_NULL on failure */
- dict_table_t* table, /* in: the table the index belongs to */
- btr_pcur_t* pcur, /* in/out: persistent cursor pointing to
- record in the clustered index of
- SYS_INDEXES table. The cursor may be
- repositioned in this call. */
- mtr_t* mtr) /* in: mtr having the latch
- on the record page. The mtr may be
- committed and restarted in this call. */
-{
- ulint root_page_no;
- ulint space;
- ulint type;
- dulint index_id;
- rec_t* rec;
- byte* ptr;
- ulint len;
- ulint comp;
- dict_index_t* index;
-
- ut_ad(mutex_own(&(dict_sys->mutex)));
- ut_a(!dict_table_is_comp(dict_sys->sys_indexes));
- rec = btr_pcur_get_rec(pcur);
- ptr = rec_get_nth_field_old(rec, DICT_SYS_INDEXES_PAGE_NO_FIELD, &len);
-
- ut_ad(len == 4);
-
- root_page_no = mtr_read_ulint(ptr, MLOG_4BYTES, mtr);
-
- if (root_page_no == FIL_NULL) {
- /* The tree has been freed. */
-
- ut_print_timestamp(stderr);
- fprintf(stderr, " InnoDB: Trying to TRUNCATE"
- " a missing index of table %s!\n", table->name);
- return(FIL_NULL);
- }
-
- ptr = rec_get_nth_field_old(rec,
- DICT_SYS_INDEXES_SPACE_NO_FIELD, &len);
-
- ut_ad(len == 4);
-
- space = mtr_read_ulint(ptr, MLOG_4BYTES, mtr);
-
- if (!fil_tablespace_exists_in_mem(space)) {
- /* It is a single table tablespace and the .ibd file is
- missing: do nothing */
-
- ut_print_timestamp(stderr);
- fprintf(stderr, " InnoDB: Trying to TRUNCATE"
- " a missing .ibd file of table %s!\n", table->name);
- return(FIL_NULL);
- }
-
- ptr = rec_get_nth_field_old(rec,
- DICT_SYS_INDEXES_TYPE_FIELD, &len);
- ut_ad(len == 4);
- type = mach_read_from_4(ptr);
-
- ptr = rec_get_nth_field_old(rec, 1, &len);
- ut_ad(len == 8);
- index_id = mach_read_from_8(ptr);
-
- /* We free all the pages but the root page first; this operation
- may span several mini-transactions */
-
- btr_free_but_not_root(space, root_page_no);
-
- /* Then we free the root page in the same mini-transaction where
- we create the b-tree and write its new root page number to the
- appropriate field in the SYS_INDEXES record: this mini-transaction
- marks the B-tree totally truncated */
-
- comp = page_is_comp(btr_page_get(space, root_page_no, RW_X_LATCH,
- mtr));
-
- btr_free_root(space, root_page_no, mtr);
- /* We will temporarily write FIL_NULL to the PAGE_NO field
- in SYS_INDEXES, so that the database will not get into an
- inconsistent state in case it crashes between the mtr_commit()
- below and the following mtr_commit() call. */
- page_rec_write_index_page_no(rec, DICT_SYS_INDEXES_PAGE_NO_FIELD,
- FIL_NULL, mtr);
-
- /* We will need to commit the mini-transaction in order to avoid
- deadlocks in the btr_create() call, because otherwise we would
- be freeing and allocating pages in the same mini-transaction. */
- btr_pcur_store_position(pcur, mtr);
- mtr_commit(mtr);
-
- mtr_start(mtr);
- btr_pcur_restore_position(BTR_MODIFY_LEAF, pcur, mtr);
-
- /* Find the index corresponding to this SYS_INDEXES record. */
- for (index = UT_LIST_GET_FIRST(table->indexes);
- index;
- index = UT_LIST_GET_NEXT(indexes, index)) {
- if (!ut_dulint_cmp(index->id, index_id)) {
- break;
- }
- }
-
- root_page_no = btr_create(type, space, index_id, comp, mtr);
- if (index) {
- index->page = (unsigned int) root_page_no;
- } else {
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Index %lu %lu of table %s is missing\n"
- "InnoDB: from the data dictionary during TRUNCATE!\n",
- ut_dulint_get_high(index_id),
- ut_dulint_get_low(index_id),
- table->name);
- }
-
- return(root_page_no);
-}
-
-/*************************************************************************
-Creates a table create graph. */
-
-tab_node_t*
-tab_create_graph_create(
-/*====================*/
- /* out, own: table create node */
- dict_table_t* table, /* in: table to create, built as a memory data
- structure */
- mem_heap_t* heap) /* in: heap where created */
-{
- tab_node_t* node;
-
- node = mem_heap_alloc(heap, sizeof(tab_node_t));
-
- node->common.type = QUE_NODE_CREATE_TABLE;
-
- node->table = table;
-
- node->state = TABLE_BUILD_TABLE_DEF;
- node->heap = mem_heap_create(256);
-
- node->tab_def = ins_node_create(INS_DIRECT, dict_sys->sys_tables,
- heap);
- node->tab_def->common.parent = node;
-
- node->col_def = ins_node_create(INS_DIRECT, dict_sys->sys_columns,
- heap);
- node->col_def->common.parent = node;
-
- node->commit_node = commit_node_create(heap);
- node->commit_node->common.parent = node;
-
- return(node);
-}
-
-/*************************************************************************
-Creates an index create graph. */
-
-ind_node_t*
-ind_create_graph_create(
-/*====================*/
- /* out, own: index create node */
- dict_index_t* index, /* in: index to create, built as a memory data
- structure */
- mem_heap_t* heap) /* in: heap where created */
-{
- ind_node_t* node;
-
- node = mem_heap_alloc(heap, sizeof(ind_node_t));
-
- node->common.type = QUE_NODE_CREATE_INDEX;
-
- node->index = index;
-
- node->state = INDEX_BUILD_INDEX_DEF;
- node->page_no = FIL_NULL;
- node->heap = mem_heap_create(256);
-
- node->ind_def = ins_node_create(INS_DIRECT,
- dict_sys->sys_indexes, heap);
- node->ind_def->common.parent = node;
-
- node->field_def = ins_node_create(INS_DIRECT,
- dict_sys->sys_fields, heap);
- node->field_def->common.parent = node;
-
- node->commit_node = commit_node_create(heap);
- node->commit_node->common.parent = node;
-
- return(node);
-}
-
-/***************************************************************
-Creates a table. This is a high-level function used in SQL execution graphs. */
-
-que_thr_t*
-dict_create_table_step(
-/*===================*/
- /* out: query thread to run next or NULL */
- que_thr_t* thr) /* in: query thread */
-{
- tab_node_t* node;
- ulint err = DB_ERROR;
- trx_t* trx;
-
- ut_ad(thr);
- ut_ad(mutex_own(&(dict_sys->mutex)));
-
- trx = thr_get_trx(thr);
-
- node = thr->run_node;
-
- ut_ad(que_node_get_type(node) == QUE_NODE_CREATE_TABLE);
-
- if (thr->prev_node == que_node_get_parent(node)) {
- node->state = TABLE_BUILD_TABLE_DEF;
- }
-
- if (node->state == TABLE_BUILD_TABLE_DEF) {
-
- /* DO THE CHECKS OF THE CONSISTENCY CONSTRAINTS HERE */
-
- err = dict_build_table_def_step(thr, node);
-
- if (err != DB_SUCCESS) {
-
- goto function_exit;
- }
-
- node->state = TABLE_BUILD_COL_DEF;
- node->col_no = 0;
-
- thr->run_node = node->tab_def;
-
- return(thr);
- }
-
- if (node->state == TABLE_BUILD_COL_DEF) {
-
- if (node->col_no < (node->table)->n_def) {
-
- err = dict_build_col_def_step(node);
-
- if (err != DB_SUCCESS) {
-
- goto function_exit;
- }
-
- node->col_no++;
-
- thr->run_node = node->col_def;
-
- return(thr);
- } else {
- node->state = TABLE_COMMIT_WORK;
- }
- }
-
- if (node->state == TABLE_COMMIT_WORK) {
-
- /* Table was correctly defined: do NOT commit the transaction
- (CREATE TABLE does NOT do an implicit commit of the current
- transaction) */
-
- node->state = TABLE_ADD_TO_CACHE;
-
- /* thr->run_node = node->commit_node;
-
- return(thr); */
- }
-
- if (node->state == TABLE_ADD_TO_CACHE) {
-
- dict_table_add_to_cache(node->table, node->heap);
-
- err = DB_SUCCESS;
- }
-
-function_exit:
- trx->error_state = err;
-
- if (err == DB_SUCCESS) {
- /* Ok: do nothing */
-
- } else if (err == DB_LOCK_WAIT) {
-
- return(NULL);
- } else {
- /* SQL error detected */
-
- return(NULL);
- }
-
- thr->run_node = que_node_get_parent(node);
-
- return(thr);
-}
-
-/***************************************************************
-Creates an index. This is a high-level function used in SQL execution
-graphs. */
-
-que_thr_t*
-dict_create_index_step(
-/*===================*/
- /* out: query thread to run next or NULL */
- que_thr_t* thr) /* in: query thread */
-{
- ind_node_t* node;
- ulint err = DB_ERROR;
- trx_t* trx;
-
- ut_ad(thr);
- ut_ad(mutex_own(&(dict_sys->mutex)));
-
- trx = thr_get_trx(thr);
-
- node = thr->run_node;
-
- ut_ad(que_node_get_type(node) == QUE_NODE_CREATE_INDEX);
-
- if (thr->prev_node == que_node_get_parent(node)) {
- node->state = INDEX_BUILD_INDEX_DEF;
- }
-
- if (node->state == INDEX_BUILD_INDEX_DEF) {
- /* DO THE CHECKS OF THE CONSISTENCY CONSTRAINTS HERE */
- err = dict_build_index_def_step(thr, node);
-
- if (err != DB_SUCCESS) {
-
- goto function_exit;
- }
-
- node->state = INDEX_BUILD_FIELD_DEF;
- node->field_no = 0;
-
- thr->run_node = node->ind_def;
-
- return(thr);
- }
-
- if (node->state == INDEX_BUILD_FIELD_DEF) {
-
- if (node->field_no < (node->index)->n_fields) {
-
- err = dict_build_field_def_step(node);
-
- if (err != DB_SUCCESS) {
-
- goto function_exit;
- }
-
- node->field_no++;
-
- thr->run_node = node->field_def;
-
- return(thr);
- } else {
- node->state = INDEX_CREATE_INDEX_TREE;
- }
- }
-
- if (node->state == INDEX_CREATE_INDEX_TREE) {
-
- err = dict_create_index_tree_step(node);
-
- if (err != DB_SUCCESS) {
-
- goto function_exit;
- }
-
- node->state = INDEX_COMMIT_WORK;
- }
-
- if (node->state == INDEX_COMMIT_WORK) {
-
- /* Index was correctly defined: do NOT commit the transaction
- (CREATE INDEX does NOT currently do an implicit commit of
- the current transaction) */
-
- node->state = INDEX_ADD_TO_CACHE;
-
- /* thr->run_node = node->commit_node;
-
- return(thr); */
- }
-
- if (node->state == INDEX_ADD_TO_CACHE) {
-
- dict_index_add_to_cache(node->table, node->index,
- node->page_no);
-
- err = DB_SUCCESS;
- }
-
-function_exit:
- trx->error_state = err;
-
- if (err == DB_SUCCESS) {
- /* Ok: do nothing */
-
- } else if (err == DB_LOCK_WAIT) {
-
- return(NULL);
- } else {
- /* SQL error detected */
-
- return(NULL);
- }
-
- thr->run_node = que_node_get_parent(node);
-
- return(thr);
-}
-
-/********************************************************************
-Creates the foreign key constraints system tables inside InnoDB
-at database creation or database start if they are not found or are
-not of the right form. */
-
-ulint
-dict_create_or_check_foreign_constraint_tables(void)
-/*================================================*/
- /* out: DB_SUCCESS or error code */
-{
- dict_table_t* table1;
- dict_table_t* table2;
- ulint error;
- trx_t* trx;
-
- mutex_enter(&(dict_sys->mutex));
-
- table1 = dict_table_get_low("SYS_FOREIGN");
- table2 = dict_table_get_low("SYS_FOREIGN_COLS");
-
- if (table1 && table2
- && UT_LIST_GET_LEN(table1->indexes) == 3
- && UT_LIST_GET_LEN(table2->indexes) == 1) {
-
- /* Foreign constraint system tables have already been
- created, and they are ok */
-
- mutex_exit(&(dict_sys->mutex));
-
- return(DB_SUCCESS);
- }
-
- mutex_exit(&(dict_sys->mutex));
-
- trx = trx_allocate_for_mysql();
-
- trx->op_info = "creating foreign key sys tables";
-
- row_mysql_lock_data_dictionary(trx);
-
- if (table1) {
- fprintf(stderr,
- "InnoDB: dropping incompletely created"
- " SYS_FOREIGN table\n");
- row_drop_table_for_mysql("SYS_FOREIGN", trx, TRUE);
- }
-
- if (table2) {
- fprintf(stderr,
- "InnoDB: dropping incompletely created"
- " SYS_FOREIGN_COLS table\n");
- row_drop_table_for_mysql("SYS_FOREIGN_COLS", trx, TRUE);
- }
-
- fprintf(stderr,
- "InnoDB: Creating foreign key constraint system tables\n");
-
- /* NOTE: in dict_load_foreigns we use the fact that
- there are 2 secondary indexes on SYS_FOREIGN, and they
- are defined just like below */
-
- /* NOTE: when designing InnoDB's foreign key support in 2001, we made
- an error and made the table names and the foreign key id of type
- 'CHAR' (internally, really a VARCHAR). We should have made the type
- VARBINARY, like in other InnoDB system tables, to get a clean
- design. */
-
- error = que_eval_sql(NULL,
- "PROCEDURE CREATE_FOREIGN_SYS_TABLES_PROC () IS\n"
- "BEGIN\n"
- "CREATE TABLE\n"
- "SYS_FOREIGN(ID CHAR, FOR_NAME CHAR,"
- " REF_NAME CHAR, N_COLS INT);\n"
- "CREATE UNIQUE CLUSTERED INDEX ID_IND"
- " ON SYS_FOREIGN (ID);\n"
- "CREATE INDEX FOR_IND"
- " ON SYS_FOREIGN (FOR_NAME);\n"
- "CREATE INDEX REF_IND"
- " ON SYS_FOREIGN (REF_NAME);\n"
- "CREATE TABLE\n"
- "SYS_FOREIGN_COLS(ID CHAR, POS INT,"
- " FOR_COL_NAME CHAR, REF_COL_NAME CHAR);\n"
- "CREATE UNIQUE CLUSTERED INDEX ID_IND"
- " ON SYS_FOREIGN_COLS (ID, POS);\n"
- "COMMIT WORK;\n"
- "END;\n"
- , FALSE, trx);
-
- if (error != DB_SUCCESS) {
- fprintf(stderr, "InnoDB: error %lu in creation\n",
- (ulong) error);
-
- ut_a(error == DB_OUT_OF_FILE_SPACE
- || error == DB_TOO_MANY_CONCURRENT_TRXS);
-
- fprintf(stderr,
- "InnoDB: creation failed\n"
- "InnoDB: tablespace is full\n"
- "InnoDB: dropping incompletely created"
- " SYS_FOREIGN tables\n");
-
- row_drop_table_for_mysql("SYS_FOREIGN", trx, TRUE);
- row_drop_table_for_mysql("SYS_FOREIGN_COLS", trx, TRUE);
-
- error = DB_MUST_GET_MORE_FILE_SPACE;
- }
-
- trx->op_info = "";
-
- row_mysql_unlock_data_dictionary(trx);
-
- trx_free_for_mysql(trx);
-
- if (error == DB_SUCCESS) {
- fprintf(stderr,
- "InnoDB: Foreign key constraint system tables"
- " created\n");
- }
-
- return(error);
-}
-
-/********************************************************************
-Evaluate the given foreign key SQL statement. */
-
-ulint
-dict_foreign_eval_sql(
-/*==================*/
- /* out: error code or DB_SUCCESS */
- pars_info_t* info, /* in: info struct, or NULL */
- const char* sql, /* in: SQL string to evaluate */
- dict_table_t* table, /* in: table */
- dict_foreign_t* foreign,/* in: foreign */
- trx_t* trx) /* in: transaction */
-{
- ulint error;
- FILE* ef = dict_foreign_err_file;
-
- error = que_eval_sql(info, sql, FALSE, trx);
-
- if (error == DB_DUPLICATE_KEY) {
- mutex_enter(&dict_foreign_err_mutex);
- rewind(ef);
- ut_print_timestamp(ef);
- fputs(" Error in foreign key constraint creation for table ",
- ef);
- ut_print_name(ef, trx, TRUE, table->name);
- fputs(".\nA foreign key constraint of name ", ef);
- ut_print_name(ef, trx, FALSE, foreign->id);
- fputs("\nalready exists."
- " (Note that internally InnoDB adds 'databasename/'\n"
- "in front of the user-defined constraint name).\n",
- ef);
- fputs("Note that InnoDB's FOREIGN KEY system tables store\n"
- "constraint names as case-insensitive, with the\n"
- "MySQL standard latin1_swedish_ci collation. If you\n"
- "create tables or databases whose names differ only in\n"
- "the character case, then collisions in constraint\n"
- "names can occur. Workaround: name your constraints\n"
- "explicitly with unique names.\n",
- ef);
-
- mutex_exit(&dict_foreign_err_mutex);
-
- return(error);
- }
-
- if (error != DB_SUCCESS) {
- fprintf(stderr,
- "InnoDB: Foreign key constraint creation failed:\n"
- "InnoDB: internal error number %lu\n", (ulong) error);
-
- mutex_enter(&dict_foreign_err_mutex);
- ut_print_timestamp(ef);
- fputs(" Internal error in foreign key constraint creation"
- " for table ", ef);
- ut_print_name(ef, trx, TRUE, table->name);
- fputs(".\n"
- "See the MySQL .err log in the datadir"
- " for more information.\n", ef);
- mutex_exit(&dict_foreign_err_mutex);
-
- return(error);
- }
-
- return(DB_SUCCESS);
-}
-
-/************************************************************************
-Add a single foreign key field definition to the data dictionary tables in
-the database. */
-static
-ulint
-dict_create_add_foreign_field_to_dictionary(
-/*========================================*/
- /* out: error code or DB_SUCCESS */
- ulint field_nr, /* in: foreign field number */
- dict_table_t* table, /* in: table */
- dict_foreign_t* foreign, /* in: foreign */
- trx_t* trx) /* in: transaction */
-{
- pars_info_t* info = pars_info_create();
-
- pars_info_add_str_literal(info, "id", foreign->id);
-
- pars_info_add_int4_literal(info, "pos", field_nr);
-
- pars_info_add_str_literal(info, "for_col_name",
- foreign->foreign_col_names[field_nr]);
-
- pars_info_add_str_literal(info, "ref_col_name",
- foreign->referenced_col_names[field_nr]);
-
- return(dict_foreign_eval_sql(
- info,
- "PROCEDURE P () IS\n"
- "BEGIN\n"
- "INSERT INTO SYS_FOREIGN_COLS VALUES"
- "(:id, :pos, :for_col_name, :ref_col_name);\n"
- "END;\n",
- table, foreign, trx));
-}
-
-/************************************************************************
-Add a single foreign key definition to the data dictionary tables in the
-database. We also generate names to constraints that were not named by the
-user. A generated constraint has a name of the format
-databasename/tablename_ibfk_<number>, where the numbers start from 1, and
-are given locally for this table, that is, the number is not global, as in
-the old format constraints < 4.0.18 it used to be. */
-static
-ulint
-dict_create_add_foreign_to_dictionary(
-/*==================================*/
- /* out: error code or DB_SUCCESS */
- ulint* id_nr, /* in/out: number to use in id generation;
- incremented if used */
- dict_table_t* table, /* in: table */
- dict_foreign_t* foreign,/* in: foreign */
- trx_t* trx) /* in: transaction */
-{
- ulint error;
- ulint i;
-
- pars_info_t* info = pars_info_create();
-
- if (foreign->id == NULL) {
- /* Generate a new constraint id */
- ulint namelen = strlen(table->name);
- char* id = mem_heap_alloc(foreign->heap, namelen + 20);
- /* no overflow if number < 1e13 */
- sprintf(id, "%s_ibfk_%lu", table->name, (ulong) (*id_nr)++);
- foreign->id = id;
- }
-
- pars_info_add_str_literal(info, "id", foreign->id);
-
- pars_info_add_str_literal(info, "for_name", table->name);
-
- pars_info_add_str_literal(info, "ref_name",
- foreign->referenced_table_name);
-
- pars_info_add_int4_literal(info, "n_cols",
- foreign->n_fields + (foreign->type << 24));
-
- error = dict_foreign_eval_sql(info,
- "PROCEDURE P () IS\n"
- "BEGIN\n"
- "INSERT INTO SYS_FOREIGN VALUES"
- "(:id, :for_name, :ref_name, :n_cols);\n"
- "END;\n"
- , table, foreign, trx);
-
- if (error != DB_SUCCESS) {
-
- return(error);
- }
-
- for (i = 0; i < foreign->n_fields; i++) {
- error = dict_create_add_foreign_field_to_dictionary(
- i, table, foreign, trx);
-
- if (error != DB_SUCCESS) {
-
- return(error);
- }
- }
-
- error = dict_foreign_eval_sql(NULL,
- "PROCEDURE P () IS\n"
- "BEGIN\n"
- "COMMIT WORK;\n"
- "END;\n"
- , table, foreign, trx);
-
- return(error);
-}
-
-/************************************************************************
-Adds foreign key definitions to data dictionary tables in the database. */
-
-ulint
-dict_create_add_foreigns_to_dictionary(
-/*===================================*/
- /* out: error code or DB_SUCCESS */
- ulint start_id,/* in: if we are actually doing ALTER TABLE
- ADD CONSTRAINT, we want to generate constraint
- numbers which are bigger than in the table so
- far; we number the constraints from
- start_id + 1 up; start_id should be set to 0 if
- we are creating a new table, or if the table
- so far has no constraints for which the name
- was generated here */
- dict_table_t* table, /* in: table */
- trx_t* trx) /* in: transaction */
-{
- dict_foreign_t* foreign;
- ulint number = start_id + 1;
- ulint error;
-
- ut_ad(mutex_own(&(dict_sys->mutex)));
-
- if (NULL == dict_table_get_low("SYS_FOREIGN")) {
- fprintf(stderr,
- "InnoDB: table SYS_FOREIGN not found"
- " in internal data dictionary\n");
-
- return(DB_ERROR);
- }
-
- for (foreign = UT_LIST_GET_FIRST(table->foreign_list);
- foreign;
- foreign = UT_LIST_GET_NEXT(foreign_list, foreign)) {
-
- error = dict_create_add_foreign_to_dictionary(&number, table,
- foreign, trx);
-
- if (error != DB_SUCCESS) {
-
- return(error);
- }
- }
-
- return(DB_SUCCESS);
-}