summaryrefslogtreecommitdiff
path: root/innobase/dict
diff options
context:
space:
mode:
Diffstat (limited to 'innobase/dict')
-rw-r--r--innobase/dict/Makefile.am25
-rw-r--r--innobase/dict/dict0boot.c423
-rw-r--r--innobase/dict/dict0crea.c1468
-rw-r--r--innobase/dict/dict0dict.c4474
-rw-r--r--innobase/dict/dict0load.c1355
-rw-r--r--innobase/dict/dict0mem.c293
-rw-r--r--innobase/dict/makefilewin21
7 files changed, 0 insertions, 8059 deletions
diff --git a/innobase/dict/Makefile.am b/innobase/dict/Makefile.am
deleted file mode 100644
index 0034d2f8f1e..00000000000
--- a/innobase/dict/Makefile.am
+++ /dev/null
@@ -1,25 +0,0 @@
-# Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-# & Innobase Oy
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-include ../include/Makefile.i
-
-noinst_LIBRARIES = libdict.a
-
-libdict_a_SOURCES = dict0boot.c dict0crea.c dict0dict.c dict0load.c\
- dict0mem.c
-
-EXTRA_PROGRAMS =
diff --git a/innobase/dict/dict0boot.c b/innobase/dict/dict0boot.c
deleted file mode 100644
index 0f6d55c9341..00000000000
--- a/innobase/dict/dict0boot.c
+++ /dev/null
@@ -1,423 +0,0 @@
-/******************************************************
-Data dictionary creation and booting
-
-(c) 1996 Innobase Oy
-
-Created 4/18/1996 Heikki Tuuri
-*******************************************************/
-
-#include "dict0boot.h"
-
-#ifdef UNIV_NONINL
-#include "dict0boot.ic"
-#endif
-
-#include "dict0crea.h"
-#include "btr0btr.h"
-#include "dict0load.h"
-#include "dict0load.h"
-#include "trx0trx.h"
-#include "srv0srv.h"
-#include "ibuf0ibuf.h"
-#include "buf0flu.h"
-#include "log0recv.h"
-#include "os0file.h"
-
-/**************************************************************************
-Gets a pointer to the dictionary header and x-latches its page. */
-
-dict_hdr_t*
-dict_hdr_get(
-/*=========*/
- /* out: pointer to the dictionary header,
- page x-latched */
- mtr_t* mtr) /* in: mtr */
-{
- dict_hdr_t* header;
-
- ut_ad(mtr);
-
- header = DICT_HDR + buf_page_get(DICT_HDR_SPACE, DICT_HDR_PAGE_NO,
- RW_X_LATCH, mtr);
-#ifdef UNIV_SYNC_DEBUG
- buf_page_dbg_add_level(header, SYNC_DICT_HEADER);
-#endif /* UNIV_SYNC_DEBUG */
- return(header);
-}
-
-/**************************************************************************
-Returns a new table, index, or tree id. */
-
-dulint
-dict_hdr_get_new_id(
-/*================*/
- /* out: the new id */
- ulint type) /* in: DICT_HDR_ROW_ID, ... */
-{
- dict_hdr_t* dict_hdr;
- dulint id;
- mtr_t mtr;
-
- ut_ad((type == DICT_HDR_TABLE_ID) || (type == DICT_HDR_INDEX_ID)
- || (type == DICT_HDR_MIX_ID));
-
- mtr_start(&mtr);
-
- dict_hdr = dict_hdr_get(&mtr);
-
- id = mtr_read_dulint(dict_hdr + type, &mtr);
-
- /* Add some dummy code here because otherwise pgcc seems to
- compile wrong */
-
- if (0 == ut_dulint_cmp(id, ut_dulint_max)) {
- /* TO DO: remove this code, or make it conditional */
- ut_dbg_null_ptr = 0;
- }
-
- id = ut_dulint_add(id, 1);
-
- mlog_write_dulint(dict_hdr + type, id, &mtr);
-
- mtr_commit(&mtr);
-
- return(id);
-}
-
-/**************************************************************************
-Writes the current value of the row id counter to the dictionary header file
-page. */
-
-void
-dict_hdr_flush_row_id(void)
-/*=======================*/
-{
- dict_hdr_t* dict_hdr;
- dulint id;
- mtr_t mtr;
-
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(mutex_own(&(dict_sys->mutex)));
-#endif /* UNIV_SYNC_DEBUG */
-
- id = dict_sys->row_id;
-
- mtr_start(&mtr);
-
- dict_hdr = dict_hdr_get(&mtr);
-
- mlog_write_dulint(dict_hdr + DICT_HDR_ROW_ID, id, &mtr);
-
- mtr_commit(&mtr);
-}
-
-/*********************************************************************
-Creates the file page for the dictionary header. This function is
-called only at the database creation. */
-static
-ibool
-dict_hdr_create(
-/*============*/
- /* out: TRUE if succeed */
- mtr_t* mtr) /* in: mtr */
-{
- dict_hdr_t* dict_header;
- ulint hdr_page_no;
- ulint root_page_no;
- page_t* page;
-
- ut_ad(mtr);
-
- /* Create the dictionary header file block in a new, allocated file
- segment in the system tablespace */
- page = fseg_create(DICT_HDR_SPACE, 0,
- DICT_HDR + DICT_HDR_FSEG_HEADER, mtr);
-
- hdr_page_no = buf_frame_get_page_no(page);
-
- ut_a(DICT_HDR_PAGE_NO == hdr_page_no);
-
- dict_header = dict_hdr_get(mtr);
-
- /* Start counting row, table, index, and tree ids from
- DICT_HDR_FIRST_ID */
- mlog_write_dulint(dict_header + DICT_HDR_ROW_ID,
- ut_dulint_create(0, DICT_HDR_FIRST_ID), mtr);
-
- mlog_write_dulint(dict_header + DICT_HDR_TABLE_ID,
- ut_dulint_create(0, DICT_HDR_FIRST_ID), mtr);
-
- mlog_write_dulint(dict_header + DICT_HDR_INDEX_ID,
- ut_dulint_create(0, DICT_HDR_FIRST_ID), mtr);
-
- mlog_write_dulint(dict_header + DICT_HDR_MIX_ID,
- ut_dulint_create(0, DICT_HDR_FIRST_ID), mtr);
-
- /* Create the B-tree roots for the clustered indexes of the basic
- system tables */
-
- /*--------------------------*/
- root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
- DICT_HDR_SPACE, DICT_TABLES_ID, FALSE, mtr);
- if (root_page_no == FIL_NULL) {
-
- return(FALSE);
- }
-
- mlog_write_ulint(dict_header + DICT_HDR_TABLES, root_page_no,
- MLOG_4BYTES, mtr);
- /*--------------------------*/
- root_page_no = btr_create(DICT_UNIQUE, DICT_HDR_SPACE,
- DICT_TABLE_IDS_ID, FALSE, mtr);
- if (root_page_no == FIL_NULL) {
-
- return(FALSE);
- }
-
- mlog_write_ulint(dict_header + DICT_HDR_TABLE_IDS, root_page_no,
- MLOG_4BYTES, mtr);
- /*--------------------------*/
- root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
- DICT_HDR_SPACE, DICT_COLUMNS_ID, FALSE, mtr);
- if (root_page_no == FIL_NULL) {
-
- return(FALSE);
- }
-
- mlog_write_ulint(dict_header + DICT_HDR_COLUMNS, root_page_no,
- MLOG_4BYTES, mtr);
- /*--------------------------*/
- root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
- DICT_HDR_SPACE, DICT_INDEXES_ID, FALSE, mtr);
- if (root_page_no == FIL_NULL) {
-
- return(FALSE);
- }
-
- mlog_write_ulint(dict_header + DICT_HDR_INDEXES, root_page_no,
- MLOG_4BYTES, mtr);
- /*--------------------------*/
- root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
- DICT_HDR_SPACE, DICT_FIELDS_ID, FALSE, mtr);
- if (root_page_no == FIL_NULL) {
-
- return(FALSE);
- }
-
- mlog_write_ulint(dict_header + DICT_HDR_FIELDS, root_page_no,
- MLOG_4BYTES, mtr);
- /*--------------------------*/
-
- return(TRUE);
-}
-
-/*********************************************************************
-Initializes the data dictionary memory structures when the database is
-started. This function is also called when the data dictionary is created. */
-
-void
-dict_boot(void)
-/*===========*/
-{
- dict_table_t* table;
- dict_index_t* index;
- dict_hdr_t* dict_hdr;
- mtr_t mtr;
- ibool success;
-
- mtr_start(&mtr);
-
- /* Create the hash tables etc. */
- dict_init();
-
- mutex_enter(&(dict_sys->mutex));
-
- /* Get the dictionary header */
- dict_hdr = dict_hdr_get(&mtr);
-
- /* Because we only write new row ids to disk-based data structure
- (dictionary header) when it is divisible by
- DICT_HDR_ROW_ID_WRITE_MARGIN, in recovery we will not recover
- the latest value of the row id counter. Therefore we advance
- the counter at the database startup to avoid overlapping values.
- Note that when a user after database startup first time asks for
- a new row id, then because the counter is now divisible by
- ..._MARGIN, it will immediately be updated to the disk-based
- header. */
-
- dict_sys->row_id = ut_dulint_add(
- ut_dulint_align_up(
- mtr_read_dulint(dict_hdr + DICT_HDR_ROW_ID,
- &mtr),
- DICT_HDR_ROW_ID_WRITE_MARGIN),
- DICT_HDR_ROW_ID_WRITE_MARGIN);
-
- /* Insert into the dictionary cache the descriptions of the basic
- system tables */
- /*-------------------------*/
- table = dict_mem_table_create("SYS_TABLES", DICT_HDR_SPACE, 8, FALSE);
-
- dict_mem_table_add_col(table, "NAME", DATA_BINARY, 0, 0, 0);
- dict_mem_table_add_col(table, "ID", DATA_BINARY, 0, 0, 0);
- dict_mem_table_add_col(table, "N_COLS", DATA_INT, 0, 4, 0);
- dict_mem_table_add_col(table, "TYPE", DATA_INT, 0, 4, 0);
- dict_mem_table_add_col(table, "MIX_ID", DATA_BINARY, 0, 0, 0);
- dict_mem_table_add_col(table, "MIX_LEN", DATA_INT, 0, 4, 0);
- dict_mem_table_add_col(table, "CLUSTER_NAME", DATA_BINARY, 0, 0, 0);
- dict_mem_table_add_col(table, "SPACE", DATA_INT, 0, 4, 0);
-
- table->id = DICT_TABLES_ID;
-
- dict_table_add_to_cache(table);
- dict_sys->sys_tables = table;
-
- index = dict_mem_index_create("SYS_TABLES", "CLUST_IND",
- DICT_HDR_SPACE, DICT_UNIQUE | DICT_CLUSTERED, 1);
-
- dict_mem_index_add_field(index, "NAME", 0, 0);
-
- index->id = DICT_TABLES_ID;
-
- success = dict_index_add_to_cache(table, index, mtr_read_ulint(
- dict_hdr + DICT_HDR_TABLES, MLOG_4BYTES, &mtr));
- ut_a(success);
- /*-------------------------*/
- index = dict_mem_index_create("SYS_TABLES", "ID_IND",
- DICT_HDR_SPACE, DICT_UNIQUE, 1);
- dict_mem_index_add_field(index, "ID", 0, 0);
-
- index->id = DICT_TABLE_IDS_ID;
- success = dict_index_add_to_cache(table, index, mtr_read_ulint(
- dict_hdr + DICT_HDR_TABLE_IDS, MLOG_4BYTES, &mtr));
- ut_a(success);
- /*-------------------------*/
- table = dict_mem_table_create("SYS_COLUMNS", DICT_HDR_SPACE, 7, FALSE);
-
- dict_mem_table_add_col(table, "TABLE_ID", DATA_BINARY,0,0,0);
- dict_mem_table_add_col(table, "POS", DATA_INT, 0, 4, 0);
- dict_mem_table_add_col(table, "NAME", DATA_BINARY, 0, 0, 0);
- dict_mem_table_add_col(table, "MTYPE", DATA_INT, 0, 4, 0);
- dict_mem_table_add_col(table, "PRTYPE", DATA_INT, 0, 4, 0);
- dict_mem_table_add_col(table, "LEN", DATA_INT, 0, 4, 0);
- dict_mem_table_add_col(table, "PREC", DATA_INT, 0, 4, 0);
-
- table->id = DICT_COLUMNS_ID;
-
- dict_table_add_to_cache(table);
- dict_sys->sys_columns = table;
-
- index = dict_mem_index_create("SYS_COLUMNS", "CLUST_IND",
- DICT_HDR_SPACE, DICT_UNIQUE | DICT_CLUSTERED, 2);
-
- dict_mem_index_add_field(index, "TABLE_ID", 0, 0);
- dict_mem_index_add_field(index, "POS", 0, 0);
-
- index->id = DICT_COLUMNS_ID;
- success = dict_index_add_to_cache(table, index, mtr_read_ulint(
- dict_hdr + DICT_HDR_COLUMNS, MLOG_4BYTES, &mtr));
- ut_a(success);
- /*-------------------------*/
- table = dict_mem_table_create("SYS_INDEXES", DICT_HDR_SPACE, 7, FALSE);
-
- dict_mem_table_add_col(table, "TABLE_ID", DATA_BINARY, 0,0,0);
- dict_mem_table_add_col(table, "ID", DATA_BINARY, 0, 0, 0);
- dict_mem_table_add_col(table, "NAME", DATA_BINARY, 0, 0, 0);
- dict_mem_table_add_col(table, "N_FIELDS", DATA_INT, 0, 4, 0);
- dict_mem_table_add_col(table, "TYPE", DATA_INT, 0, 4, 0);
- dict_mem_table_add_col(table, "SPACE", DATA_INT, 0, 4, 0);
- dict_mem_table_add_col(table, "PAGE_NO", DATA_INT, 0, 4, 0);
-
- /* The '+ 2' below comes from the 2 system fields */
-#if DICT_SYS_INDEXES_PAGE_NO_FIELD != 6 + 2
-#error "DICT_SYS_INDEXES_PAGE_NO_FIELD != 6 + 2"
-#endif
-#if DICT_SYS_INDEXES_SPACE_NO_FIELD != 5 + 2
-#error "DICT_SYS_INDEXES_SPACE_NO_FIELD != 5 + 2"
-#endif
-#if DICT_SYS_INDEXES_TYPE_FIELD != 4 + 2
-#error "DICT_SYS_INDEXES_TYPE_FIELD != 4 + 2"
-#endif
-
- table->id = DICT_INDEXES_ID;
- dict_table_add_to_cache(table);
- dict_sys->sys_indexes = table;
-
- index = dict_mem_index_create("SYS_INDEXES", "CLUST_IND",
- DICT_HDR_SPACE, DICT_UNIQUE | DICT_CLUSTERED, 2);
-
- dict_mem_index_add_field(index, "TABLE_ID", 0, 0);
- dict_mem_index_add_field(index, "ID", 0, 0);
-
- index->id = DICT_INDEXES_ID;
- success = dict_index_add_to_cache(table, index, mtr_read_ulint(
- dict_hdr + DICT_HDR_INDEXES, MLOG_4BYTES, &mtr));
- ut_a(success);
- /*-------------------------*/
- table = dict_mem_table_create("SYS_FIELDS", DICT_HDR_SPACE, 3, FALSE);
-
- dict_mem_table_add_col(table, "INDEX_ID", DATA_BINARY, 0,0,0);
- dict_mem_table_add_col(table, "POS", DATA_INT, 0, 4, 0);
- dict_mem_table_add_col(table, "COL_NAME", DATA_BINARY, 0,0,0);
-
- table->id = DICT_FIELDS_ID;
- dict_table_add_to_cache(table);
- dict_sys->sys_fields = table;
-
- index = dict_mem_index_create("SYS_FIELDS", "CLUST_IND",
- DICT_HDR_SPACE, DICT_UNIQUE | DICT_CLUSTERED, 2);
-
- dict_mem_index_add_field(index, "INDEX_ID", 0, 0);
- dict_mem_index_add_field(index, "POS", 0, 0);
-
- index->id = DICT_FIELDS_ID;
- success = dict_index_add_to_cache(table, index, mtr_read_ulint(
- dict_hdr + DICT_HDR_FIELDS, MLOG_4BYTES, &mtr));
- ut_a(success);
-
- mtr_commit(&mtr);
- /*-------------------------*/
-
- /* Initialize the insert buffer table and index for each tablespace */
-
- ibuf_init_at_db_start();
-
- /* Load definitions of other indexes on system tables */
-
- dict_load_sys_table(dict_sys->sys_tables);
- dict_load_sys_table(dict_sys->sys_columns);
- dict_load_sys_table(dict_sys->sys_indexes);
- dict_load_sys_table(dict_sys->sys_fields);
-
- mutex_exit(&(dict_sys->mutex));
-}
-
-/*********************************************************************
-Inserts the basic system table data into themselves in the database
-creation. */
-static
-void
-dict_insert_initial_data(void)
-/*==========================*/
-{
- /* Does nothing yet */
-}
-
-/*********************************************************************
-Creates and initializes the data dictionary at the database creation. */
-
-void
-dict_create(void)
-/*=============*/
-{
- mtr_t mtr;
-
- mtr_start(&mtr);
-
- dict_hdr_create(&mtr);
-
- mtr_commit(&mtr);
-
- dict_boot();
-
- dict_insert_initial_data();
-}
diff --git a/innobase/dict/dict0crea.c b/innobase/dict/dict0crea.c
deleted file mode 100644
index 1f12386e413..00000000000
--- a/innobase/dict/dict0crea.c
+++ /dev/null
@@ -1,1468 +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"
-
-/*********************************************************************
-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);
-
- ptr = mem_heap_alloc(heap, 4);
- mach_write_to_4(ptr, table->n_def
- | ((ulint) table->comp << 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, table->type);
-
- dfield_set_data(dfield, ptr, 4);
- /* 6: MIX_ID ---------------------------*/
- dfield = dtuple_get_nth_field(entry, 4);
-
- ptr = mem_heap_alloc(heap, 8);
- mach_write_to_8(ptr, table->mix_id);
-
- dfield_set_data(dfield, ptr, 8);
- /* 7: MIX_LEN --------------------------*/
-
- dfield = dtuple_get_nth_field(entry, 5);
-
- ptr = mem_heap_alloc(heap, 4);
- mach_write_to_4(ptr, table->mix_len);
-
- dfield_set_data(dfield, ptr, 4);
- /* 8: CLUSTER_NAME ---------------------*/
- dfield = dtuple_get_nth_field(entry, 6);
-
- if (table->type == DICT_TABLE_CLUSTER_MEMBER) {
- dfield_set_data(dfield, table->cluster_name,
- ut_strlen(table->cluster_name));
- ut_error; /* Oracle-style clusters are not supported yet */
- } else {
- dfield_set_data(dfield, NULL, UNIV_SQL_NULL);
- }
- /* 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;
- dict_col_t* column;
- dfield_t* dfield;
- byte* ptr;
-
- 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);
-
- dfield_set_data(dfield, column->name, ut_strlen(column->name));
- /* 5: MTYPE --------------------------*/
- dfield = dtuple_get_nth_field(entry, 3);
-
- ptr = mem_heap_alloc(heap, 4);
- mach_write_to_4(ptr, (column->type).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->type).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->type).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, (column->type).prec);
-
- 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;
- dict_table_t* cluster_table;
- dtuple_t* row;
- ulint error;
- const char* path_or_name;
- ibool is_path;
- mtr_t mtr;
- ulint i;
- ulint row_len;
-
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(mutex_own(&(dict_sys->mutex)));
-#endif /* UNIV_SYNC_DEBUG */
-
- 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 += dtype_get_min_size(dict_col_get_type(
- &table->cols[i]));
- }
- if (row_len > BTR_PAGE_MAX_REC_SIZE) {
- return(DB_TOO_BIG_RECORD);
- }
-
- if (table->type == DICT_TABLE_CLUSTER_MEMBER) {
-
- cluster_table = dict_table_get_low(table->cluster_name);
-
- if (cluster_table == NULL) {
-
- return(DB_CLUSTER_NOT_FOUND);
- }
-
- /* Inherit space and mix len from the cluster */
-
- table->space = cluster_table->space;
- table->mix_len = cluster_table->mix_len;
-
- table->mix_id = dict_hdr_get_new_id(DICT_HDR_MIX_ID);
- }
-
- 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. */
-
- table->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(
- &(table->space), path_or_name, is_path,
- FIL_IBD_FILE_INITIAL_SIZE);
- 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;
-
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(mutex_own(&(dict_sys->mutex)));
-#endif /* UNIV_SYNC_DEBUG */
- 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;
-
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(mutex_own(&(dict_sys->mutex)));
-#endif /* UNIV_SYNC_DEBUG */
-
- 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;
-
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(mutex_own(&(dict_sys->mutex)));
-#endif /* UNIV_SYNC_DEBUG */
-
- index = node->index;
- table = node->table;
-
- sys_indexes = dict_sys->sys_indexes;
-
- if (index->type & DICT_CLUSTERED
- && table->type == DICT_TABLE_CLUSTER_MEMBER) {
-
- /* Do not create a new index tree: entries are put to the
- cluster tree */
-
- return(DB_SUCCESS);
- }
-
- /* 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,
- table->comp, &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;
-
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(mutex_own(&(dict_sys->mutex)));
-#endif /* UNIV_SYNC_DEBUG */
-
- ut_a(!dict_sys->sys_indexes->comp);
- 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 */
- 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. The mtr may be
- committed and restarted in this call. */
-{
- ulint root_page_no;
- ulint space;
- ulint type;
- dulint index_id;
- byte* ptr;
- ulint len;
- ibool comp;
- dict_index_t* index;
-
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(mutex_own(&(dict_sys->mutex)));
-#endif /* UNIV_SYNC_DEBUG */
-
- ut_a(!dict_sys->sys_indexes->comp);
- 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. */
- mtr_commit(mtr);
- /* mtr_commit() will invalidate rec. */
- rec = NULL;
- mtr_start(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->tree->page = 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);
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(mutex_own(&(dict_sys->mutex)));
-#endif /* UNIV_SYNC_DEBUG */
-
- 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);
-
- 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;
- ibool success;
- ulint err = DB_ERROR;
- trx_t* trx;
-
- ut_ad(thr);
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(mutex_own(&(dict_sys->mutex)));
-#endif /* UNIV_SYNC_DEBUG */
-
- 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) {
-
- success = dict_index_add_to_cache(node->table, node->index,
- node->page_no);
-
- ut_a(success);
-
- 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;
- que_thr_t* thr;
- que_t* graph;
- ulint error;
- trx_t* trx;
- const char* str;
-
- 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. */
-
- str =
- "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";
-
- graph = pars_sql(str);
-
- ut_a(graph);
-
- graph->trx = trx;
- trx->graph = NULL;
-
- graph->fork_type = QUE_FORK_MYSQL_INTERFACE;
-
- ut_a(thr = que_fork_start_command(graph));
-
- que_run_threads(thr);
-
- error = trx->error_state;
-
- if (error != DB_SUCCESS) {
- fprintf(stderr, "InnoDB: error %lu in creation\n",
- (ulong) error);
-
- ut_a(error == DB_OUT_OF_FILE_SPACE);
-
- fprintf(stderr, "InnoDB: creation failed\n");
- fprintf(stderr, "InnoDB: tablespace is full\n");
- fprintf(stderr,
- "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;
- }
-
- que_graph_free(graph);
-
- 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);
-}
-
-/************************************************************************
-Adds foreign key definitions to data dictionary tables in the database. We
-look at table->foreign_list, and 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. */
-
-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;
- que_thr_t* thr;
- que_t* graph;
- ulint number = start_id + 1;
- ulint len;
- ulint error;
- FILE* ef = dict_foreign_err_file;
- ulint i;
- char* sql;
- char* sqlend;
- /* This procedure builds an InnoDB stored procedure which will insert
- the necessary rows into SYS_FOREIGN and SYS_FOREIGN_COLS. */
- static const char str1[] = "PROCEDURE ADD_FOREIGN_DEFS_PROC () IS\n"
- "BEGIN\n"
- "INSERT INTO SYS_FOREIGN VALUES(";
- static const char str2[] = ");\n";
- static const char str3[] =
- "INSERT INTO SYS_FOREIGN_COLS VALUES(";
- static const char str4[] =
- "COMMIT WORK;\n"
- "END;\n";
-
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(mutex_own(&(dict_sys->mutex)));
-#endif /* UNIV_SYNC_DEBUG */
-
- if (NULL == dict_table_get_low("SYS_FOREIGN")) {
- fprintf(stderr,
- "InnoDB: table SYS_FOREIGN not found from internal data dictionary\n");
-
- return(DB_ERROR);
- }
-
- foreign = UT_LIST_GET_FIRST(table->foreign_list);
-loop:
- if (foreign == NULL) {
-
- return(DB_SUCCESS);
- }
-
- 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) number++);
- foreign->id = id;
- }
-
- len = (sizeof str1) + (sizeof str2) + (sizeof str4) - 3
- + 9/* ' and , chars */ + 10/* 32-bit integer */
- + ut_strlenq(foreign->id, '\'') * (foreign->n_fields + 1)
- + ut_strlenq(table->name, '\'')
- + ut_strlenq(foreign->referenced_table_name, '\'');
-
- for (i = 0; i < foreign->n_fields; i++) {
- len += 9/* ' and , chars */ + 10/* 32-bit integer */
- + (sizeof str3) + (sizeof str2) - 2
- + ut_strlenq(foreign->foreign_col_names[i], '\'')
- + ut_strlenq(foreign->referenced_col_names[i], '\'');
- }
-
- sql = sqlend = mem_alloc(len + 1);
-
- /* INSERT INTO SYS_FOREIGN VALUES(...); */
- memcpy(sqlend, str1, (sizeof str1) - 1);
- sqlend += (sizeof str1) - 1;
- *sqlend++ = '\'';
- sqlend = ut_strcpyq(sqlend, '\'', foreign->id);
- *sqlend++ = '\'', *sqlend++ = ',', *sqlend++ = '\'';
- sqlend = ut_strcpyq(sqlend, '\'', table->name);
- *sqlend++ = '\'', *sqlend++ = ',', *sqlend++ = '\'';
- sqlend = ut_strcpyq(sqlend, '\'', foreign->referenced_table_name);
- *sqlend++ = '\'', *sqlend++ = ',';
- sqlend += sprintf(sqlend, "%010lu",
- foreign->n_fields + (foreign->type << 24));
- memcpy(sqlend, str2, (sizeof str2) - 1);
- sqlend += (sizeof str2) - 1;
-
- for (i = 0; i < foreign->n_fields; i++) {
- /* INSERT INTO SYS_FOREIGN_COLS VALUES(...); */
- memcpy(sqlend, str3, (sizeof str3) - 1);
- sqlend += (sizeof str3) - 1;
- *sqlend++ = '\'';
- sqlend = ut_strcpyq(sqlend, '\'', foreign->id);
- *sqlend++ = '\''; *sqlend++ = ',';
- sqlend += sprintf(sqlend, "%010lu", (ulong) i);
- *sqlend++ = ','; *sqlend++ = '\'';
- sqlend = ut_strcpyq(sqlend, '\'',
- foreign->foreign_col_names[i]);
- *sqlend++ = '\''; *sqlend++ = ','; *sqlend++ = '\'';
- sqlend = ut_strcpyq(sqlend, '\'',
- foreign->referenced_col_names[i]);
- *sqlend++ = '\'';
- memcpy(sqlend, str2, (sizeof str2) - 1);
- sqlend += (sizeof str2) - 1;
- }
-
- memcpy(sqlend, str4, sizeof str4);
- sqlend += sizeof str4;
-
- ut_a(sqlend == sql + len + 1);
-
- graph = pars_sql(sql);
-
- ut_a(graph);
-
- mem_free(sql);
-
- graph->trx = trx;
- trx->graph = NULL;
-
- graph->fork_type = QUE_FORK_MYSQL_INTERFACE;
-
- ut_a(thr = que_fork_start_command(graph));
-
- que_run_threads(thr);
-
- error = trx->error_state;
-
- que_graph_free(graph);
-
- 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, table->name);
- fputs(".\nA foreign key constraint of name ", ef);
- ut_print_name(ef, trx, 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, 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);
- }
-
- foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
-
- goto loop;
-}
diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c
deleted file mode 100644
index 02f46ea7b18..00000000000
--- a/innobase/dict/dict0dict.c
+++ /dev/null
@@ -1,4474 +0,0 @@
-/**********************************************************************
-Data dictionary system
-
-(c) 1996 Innobase Oy
-
-Created 1/8/1996 Heikki Tuuri
-***********************************************************************/
-
-#include "dict0dict.h"
-
-#ifdef UNIV_NONINL
-#include "dict0dict.ic"
-#endif
-
-#include "buf0buf.h"
-#include "data0type.h"
-#include "mach0data.h"
-#include "dict0boot.h"
-#include "dict0mem.h"
-#include "dict0crea.h"
-#include "trx0undo.h"
-#include "btr0btr.h"
-#include "btr0cur.h"
-#include "btr0sea.h"
-#include "pars0pars.h"
-#include "pars0sym.h"
-#include "que0que.h"
-#include "rem0cmp.h"
-
-dict_sys_t* dict_sys = NULL; /* the dictionary system */
-
-rw_lock_t dict_operation_lock; /* table create, drop, etc. reserve
- this in X-mode; implicit or backround
- operations purge, rollback, foreign
- key checks reserve this in S-mode; we
- cannot trust that MySQL protects
- implicit or background operations
- a table drop since MySQL does not
- know of them; therefore we need this;
- NOTE: a transaction which reserves
- this must keep book on the mode in
- trx->dict_operation_lock_mode */
-
-#define DICT_HEAP_SIZE 100 /* initial memory heap size when
- creating a table or index object */
-#define DICT_POOL_PER_TABLE_HASH 512 /* buffer pool max size per table
- hash table fixed size in bytes */
-#define DICT_POOL_PER_COL_HASH 128 /* buffer pool max size per column
- hash table fixed size in bytes */
-#define DICT_POOL_PER_VARYING 4 /* buffer pool max size per data
- dictionary varying size in bytes */
-
-/* Identifies generated InnoDB foreign key names */
-static char dict_ibfk[] = "_ibfk_";
-
-#ifndef UNIV_HOTBACKUP
-/**********************************************************************
-Compares NUL-terminated UTF-8 strings case insensitively.
-
-NOTE: the prototype of this function is copied from ha_innodb.cc! If you change
-this function, you MUST change also the prototype here! */
-extern
-int
-innobase_strcasecmp(
-/*================*/
- /* out: 0 if a=b, <0 if a<b, >1 if a>b */
- const char* a, /* in: first string to compare */
- const char* b); /* in: second string to compare */
-
-/**********************************************************************
-Makes all characters in a NUL-terminated UTF-8 string lower case.
-
-NOTE: the prototype of this function is copied from ha_innodb.cc! If you change
-this function, you MUST change also the prototype here! */
-extern
-void
-innobase_casedn_str(
-/*================*/
- char* a); /* in/out: string to put in lower case */
-#endif /* !UNIV_HOTBACKUP */
-
-/**************************************************************************
-Adds a column to the data dictionary hash table. */
-static
-void
-dict_col_add_to_cache(
-/*==================*/
- dict_table_t* table, /* in: table */
- dict_col_t* col); /* in: column */
-/**************************************************************************
-Repositions a column in the data dictionary hash table when the table name
-changes. */
-static
-void
-dict_col_reposition_in_cache(
-/*=========================*/
- dict_table_t* table, /* in: table */
- dict_col_t* col, /* in: column */
- const char* new_name); /* in: new table name */
-/**************************************************************************
-Removes a column from the data dictionary hash table. */
-static
-void
-dict_col_remove_from_cache(
-/*=======================*/
- dict_table_t* table, /* in: table */
- dict_col_t* col); /* in: column */
-/**************************************************************************
-Removes an index from the dictionary cache. */
-static
-void
-dict_index_remove_from_cache(
-/*=========================*/
- dict_table_t* table, /* in: table */
- dict_index_t* index); /* in, own: index */
-/***********************************************************************
-Copies fields contained in index2 to index1. */
-static
-void
-dict_index_copy(
-/*============*/
- dict_index_t* index1, /* in: index to copy to */
- dict_index_t* index2, /* in: index to copy from */
- ulint start, /* in: first position to copy */
- ulint end); /* in: last position to copy */
-/***********************************************************************
-Tries to find column names for the index in the column hash table and
-sets the col field of the index. */
-static
-ibool
-dict_index_find_cols(
-/*=================*/
- /* out: TRUE if success */
- dict_table_t* table, /* in: table */
- dict_index_t* index); /* in: index */
-/***********************************************************************
-Builds the internal dictionary cache representation for a clustered
-index, containing also system fields not defined by the user. */
-static
-dict_index_t*
-dict_index_build_internal_clust(
-/*============================*/
- /* out, own: the internal representation
- of the clustered index */
- dict_table_t* table, /* in: table */
- dict_index_t* index); /* in: user representation of a clustered
- index */
-/***********************************************************************
-Builds the internal dictionary cache representation for a non-clustered
-index, containing also system fields not defined by the user. */
-static
-dict_index_t*
-dict_index_build_internal_non_clust(
-/*================================*/
- /* out, own: the internal representation
- of the non-clustered index */
- dict_table_t* table, /* in: table */
- dict_index_t* index); /* in: user representation of a non-clustered
- index */
-/**************************************************************************
-Removes a foreign constraint struct from the dictionary cache. */
-static
-void
-dict_foreign_remove_from_cache(
-/*===========================*/
- dict_foreign_t* foreign); /* in, own: foreign constraint */
-/**************************************************************************
-Prints a column data. */
-static
-void
-dict_col_print_low(
-/*===============*/
- dict_col_t* col); /* in: column */
-/**************************************************************************
-Prints an index data. */
-static
-void
-dict_index_print_low(
-/*=================*/
- dict_index_t* index); /* in: index */
-/**************************************************************************
-Prints a field data. */
-static
-void
-dict_field_print_low(
-/*=================*/
- dict_field_t* field); /* in: field */
-/*************************************************************************
-Frees a foreign key struct. */
-static
-void
-dict_foreign_free(
-/*==============*/
- dict_foreign_t* foreign); /* in, own: foreign key struct */
-
-/* Stream for storing detailed information about the latest foreign key
-and unique key errors */
-FILE* dict_foreign_err_file = NULL;
-mutex_t dict_foreign_err_mutex; /* mutex protecting the foreign
- and unique error buffers */
-
-
-/************************************************************************
-Checks if the database name in two table names is the same. */
-
-ibool
-dict_tables_have_same_db(
-/*=====================*/
- /* out: TRUE if same db name */
- const char* name1, /* in: table name in the form
- dbname '/' tablename */
- const char* name2) /* in: table name in the form
- dbname '/' tablename */
-{
- for (; *name1 == *name2; name1++, name2++) {
- if (*name1 == '/') {
- return(TRUE);
- }
- ut_a(*name1); /* the names must contain '/' */
- }
- return(FALSE);
-}
-
-/************************************************************************
-Return the end of table name where we have removed dbname and '/'. */
-static
-const char*
-dict_remove_db_name(
-/*================*/
- /* out: table name */
- const char* name) /* in: table name in the form
- dbname '/' tablename */
-{
- const char* s;
- s = strchr(name, '/');
- ut_a(s);
- if (s) s++;
- return(s);
-}
-
-/************************************************************************
-Get the database name length in a table name. */
-
-ulint
-dict_get_db_name_len(
-/*=================*/
- /* out: database name length */
- const char* name) /* in: table name in the form
- dbname '/' tablename */
-{
- const char* s;
- s = strchr(name, '/');
- ut_a(s);
- return(s - name);
-}
-
-/************************************************************************
-Reserves the dictionary system mutex for MySQL. */
-
-void
-dict_mutex_enter_for_mysql(void)
-/*============================*/
-{
- mutex_enter(&(dict_sys->mutex));
-}
-
-/************************************************************************
-Releases the dictionary system mutex for MySQL. */
-
-void
-dict_mutex_exit_for_mysql(void)
-/*===========================*/
-{
- mutex_exit(&(dict_sys->mutex));
-}
-
-/************************************************************************
-Decrements the count of open MySQL handles to a table. */
-
-void
-dict_table_decrement_handle_count(
-/*==============================*/
- dict_table_t* table) /* in: table */
-{
- mutex_enter(&(dict_sys->mutex));
-
- ut_a(table->n_mysql_handles_opened > 0);
-
- table->n_mysql_handles_opened--;
-
- mutex_exit(&(dict_sys->mutex));
-}
-
-/************************************************************************
-Gets the nth column of a table. */
-
-dict_col_t*
-dict_table_get_nth_col_noninline(
-/*=============================*/
- /* out: pointer to column object */
- dict_table_t* table, /* in: table */
- ulint pos) /* in: position of column */
-{
- return(dict_table_get_nth_col(table, pos));
-}
-
-/************************************************************************
-Gets the first index on the table (the clustered index). */
-
-dict_index_t*
-dict_table_get_first_index_noninline(
-/*=================================*/
- /* out: index, NULL if none exists */
- dict_table_t* table) /* in: table */
-{
- return(dict_table_get_first_index(table));
-}
-
-/************************************************************************
-Gets the next index on the table. */
-
-dict_index_t*
-dict_table_get_next_index_noninline(
-/*================================*/
- /* out: index, NULL if none left */
- dict_index_t* index) /* in: index */
-{
- return(dict_table_get_next_index(index));
-}
-
-/**************************************************************************
-Returns an index object. */
-
-dict_index_t*
-dict_table_get_index_noninline(
-/*===========================*/
- /* out: index, NULL if does not exist */
- dict_table_t* table, /* in: table */
- const char* name) /* in: index name */
-{
- return(dict_table_get_index(table, name));
-}
-
-/************************************************************************
-Initializes the autoinc counter. It is not an error to initialize an already
-initialized counter. */
-
-void
-dict_table_autoinc_initialize(
-/*==========================*/
- dict_table_t* table, /* in: table */
- ib_longlong value) /* in: next value to assign to a row */
-{
- mutex_enter(&(table->autoinc_mutex));
-
- table->autoinc_inited = TRUE;
- table->autoinc = value;
-
- mutex_exit(&(table->autoinc_mutex));
-}
-
-/************************************************************************
-Gets the next autoinc value (== autoinc counter value), 0 if not yet
-initialized. If initialized, increments the counter by 1. */
-
-ib_longlong
-dict_table_autoinc_get(
-/*===================*/
- /* out: value for a new row, or 0 */
- dict_table_t* table) /* in: table */
-{
- ib_longlong value;
-
- mutex_enter(&(table->autoinc_mutex));
-
- if (!table->autoinc_inited) {
-
- value = 0;
- } else {
- value = table->autoinc;
- table->autoinc = table->autoinc + 1;
- }
-
- mutex_exit(&(table->autoinc_mutex));
-
- return(value);
-}
-
-/************************************************************************
-Decrements the autoinc counter value by 1. */
-
-void
-dict_table_autoinc_decrement(
-/*=========================*/
- dict_table_t* table) /* in: table */
-{
- mutex_enter(&(table->autoinc_mutex));
-
- table->autoinc = table->autoinc - 1;
-
- mutex_exit(&(table->autoinc_mutex));
-}
-
-/************************************************************************
-Reads the next autoinc value (== autoinc counter value), 0 if not yet
-initialized. */
-
-ib_longlong
-dict_table_autoinc_read(
-/*====================*/
- /* out: value for a new row, or 0 */
- dict_table_t* table) /* in: table */
-{
- ib_longlong value;
-
- mutex_enter(&(table->autoinc_mutex));
-
- if (!table->autoinc_inited) {
-
- value = 0;
- } else {
- value = table->autoinc;
- }
-
- mutex_exit(&(table->autoinc_mutex));
-
- return(value);
-}
-
-/************************************************************************
-Peeks the autoinc counter value, 0 if not yet initialized. Does not
-increment the counter. The read not protected by any mutex! */
-
-ib_longlong
-dict_table_autoinc_peek(
-/*====================*/
- /* out: value of the counter */
- dict_table_t* table) /* in: table */
-{
- ib_longlong value;
-
- if (!table->autoinc_inited) {
-
- value = 0;
- } else {
- value = table->autoinc;
- }
-
- return(value);
-}
-
-/************************************************************************
-Updates the autoinc counter if the value supplied is equal or bigger than the
-current value. If not inited, does nothing. */
-
-void
-dict_table_autoinc_update(
-/*======================*/
-
- dict_table_t* table, /* in: table */
- ib_longlong value) /* in: value which was assigned to a row */
-{
- mutex_enter(&(table->autoinc_mutex));
-
- if (table->autoinc_inited) {
- if (value >= table->autoinc) {
- table->autoinc = value + 1;
- }
- }
-
- mutex_exit(&(table->autoinc_mutex));
-}
-
-/************************************************************************
-Looks for column n in an index. */
-
-ulint
-dict_index_get_nth_col_pos(
-/*=======================*/
- /* out: position in internal representation
- of the index; if not contained, returns
- ULINT_UNDEFINED */
- dict_index_t* index, /* in: index */
- ulint n) /* in: column number */
-{
- dict_field_t* field;
- dict_col_t* col;
- ulint pos;
- ulint n_fields;
-
- ut_ad(index);
- ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
-
- col = dict_table_get_nth_col(index->table, n);
-
- if (index->type & DICT_CLUSTERED) {
-
- return(col->clust_pos);
- }
-
- n_fields = dict_index_get_n_fields(index);
-
- for (pos = 0; pos < n_fields; pos++) {
- field = dict_index_get_nth_field(index, pos);
-
- if (col == field->col && field->prefix_len == 0) {
-
- return(pos);
- }
- }
-
- return(ULINT_UNDEFINED);
-}
-
-/************************************************************************
-Returns TRUE if the index contains a column or a prefix of that column. */
-
-ibool
-dict_index_contains_col_or_prefix(
-/*==============================*/
- /* out: TRUE if contains the column or its
- prefix */
- dict_index_t* index, /* in: index */
- ulint n) /* in: column number */
-{
- dict_field_t* field;
- dict_col_t* col;
- ulint pos;
- ulint n_fields;
-
- ut_ad(index);
- ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
-
- if (index->type & DICT_CLUSTERED) {
-
- return(TRUE);
- }
-
- col = dict_table_get_nth_col(index->table, n);
-
- n_fields = dict_index_get_n_fields(index);
-
- for (pos = 0; pos < n_fields; pos++) {
- field = dict_index_get_nth_field(index, pos);
-
- if (col == field->col) {
-
- return(TRUE);
- }
- }
-
- return(FALSE);
-}
-
-/************************************************************************
-Looks for a matching field in an index. The column has to be the same. The
-column in index must be complete, or must contain a prefix longer than the
-column in index2. That is, we must be able to construct the prefix in index2
-from the prefix in index. */
-
-ulint
-dict_index_get_nth_field_pos(
-/*=========================*/
- /* out: position in internal representation
- of the index; if not contained, returns
- ULINT_UNDEFINED */
- dict_index_t* index, /* in: index from which to search */
- dict_index_t* index2, /* in: index */
- ulint n) /* in: field number in index2 */
-{
- dict_field_t* field;
- dict_field_t* field2;
- ulint n_fields;
- ulint pos;
-
- ut_ad(index);
- ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
-
- field2 = dict_index_get_nth_field(index2, n);
-
- n_fields = dict_index_get_n_fields(index);
-
- for (pos = 0; pos < n_fields; pos++) {
- field = dict_index_get_nth_field(index, pos);
-
- if (field->col == field2->col
- && (field->prefix_len == 0
- || (field->prefix_len >= field2->prefix_len
- && field2->prefix_len != 0))) {
-
- return(pos);
- }
- }
-
- return(ULINT_UNDEFINED);
-}
-
-/**************************************************************************
-Returns a table object, based on table id, and memoryfixes it. */
-
-dict_table_t*
-dict_table_get_on_id(
-/*=================*/
- /* out: table, NULL if does not exist */
- dulint table_id, /* in: table id */
- trx_t* trx) /* in: transaction handle */
-{
- dict_table_t* table;
-
- if (ut_dulint_cmp(table_id, DICT_FIELDS_ID) <= 0
- || trx->dict_operation_lock_mode == RW_X_LATCH) {
- /* It is a system table which will always exist in the table
- cache: we avoid acquiring the dictionary mutex, because
- if we are doing a rollback to handle an error in TABLE
- CREATE, for example, we already have the mutex! */
-
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(mutex_own(&(dict_sys->mutex)));
-#endif /* UNIV_SYNC_DEBUG */
-
- return(dict_table_get_on_id_low(table_id, trx));
- }
-
- mutex_enter(&(dict_sys->mutex));
-
- table = dict_table_get_on_id_low(table_id, trx);
-
- mutex_exit(&(dict_sys->mutex));
-
- return(table);
-}
-
-/************************************************************************
-Looks for column n position in the clustered index. */
-
-ulint
-dict_table_get_nth_col_pos(
-/*=======================*/
- /* out: position in internal representation
- of the clustered index */
- dict_table_t* table, /* in: table */
- ulint n) /* in: column number */
-{
- return(dict_index_get_nth_col_pos(dict_table_get_first_index(table),
- n));
-}
-
-/************************************************************************
-Checks if a column is in the ordering columns of the clustered index of a
-table. Column prefixes are treated like whole columns. */
-
-ibool
-dict_table_col_in_clustered_key(
-/*============================*/
- /* out: TRUE if the column, or its prefix, is
- in the clustered key */
- dict_table_t* table, /* in: table */
- ulint n) /* in: column number */
-{
- dict_index_t* index;
- dict_field_t* field;
- dict_col_t* col;
- ulint pos;
- ulint n_fields;
-
- ut_ad(table);
-
- col = dict_table_get_nth_col(table, n);
-
- index = dict_table_get_first_index(table);
-
- n_fields = dict_index_get_n_unique(index);
-
- for (pos = 0; pos < n_fields; pos++) {
- field = dict_index_get_nth_field(index, pos);
-
- if (col == field->col) {
-
- return(TRUE);
- }
- }
-
- return(FALSE);
-}
-
-/**************************************************************************
-Inits the data dictionary module. */
-
-void
-dict_init(void)
-/*===========*/
-{
- dict_sys = mem_alloc(sizeof(dict_sys_t));
-
- mutex_create(&(dict_sys->mutex));
- mutex_set_level(&(dict_sys->mutex), SYNC_DICT);
-
- dict_sys->table_hash = hash_create(buf_pool_get_max_size() /
- (DICT_POOL_PER_TABLE_HASH *
- UNIV_WORD_SIZE));
- dict_sys->table_id_hash = hash_create(buf_pool_get_max_size() /
- (DICT_POOL_PER_TABLE_HASH *
- UNIV_WORD_SIZE));
- dict_sys->col_hash = hash_create(buf_pool_get_max_size() /
- (DICT_POOL_PER_COL_HASH *
- UNIV_WORD_SIZE));
- dict_sys->size = 0;
-
- UT_LIST_INIT(dict_sys->table_LRU);
-
- rw_lock_create(&dict_operation_lock);
- rw_lock_set_level(&dict_operation_lock, SYNC_DICT_OPERATION);
-
- dict_foreign_err_file = os_file_create_tmpfile();
- ut_a(dict_foreign_err_file);
- mutex_create(&dict_foreign_err_mutex);
- mutex_set_level(&dict_foreign_err_mutex, SYNC_ANY_LATCH);
-}
-
-/**************************************************************************
-Returns a table object and memoryfixes it. NOTE! This is a high-level
-function to be used mainly from outside the 'dict' directory. Inside this
-directory dict_table_get_low is usually the appropriate function. */
-
-dict_table_t*
-dict_table_get(
-/*===========*/
- /* out: table, NULL if
- does not exist */
- const char* table_name, /* in: table name */
- trx_t* trx) /* in: transaction handle or NULL */
-{
- dict_table_t* table;
-
- UT_NOT_USED(trx);
-
- mutex_enter(&(dict_sys->mutex));
-
- table = dict_table_get_low(table_name);
-
- mutex_exit(&(dict_sys->mutex));
-
- if (table != NULL) {
- if (!table->stat_initialized) {
- dict_update_statistics(table);
- }
- }
-
- return(table);
-}
-
-/**************************************************************************
-Returns a table object and increments MySQL open handle count on the table. */
-
-dict_table_t*
-dict_table_get_and_increment_handle_count(
-/*======================================*/
- /* out: table, NULL if
- does not exist */
- const char* table_name, /* in: table name */
- trx_t* trx) /* in: transaction handle or NULL */
-{
- dict_table_t* table;
-
- UT_NOT_USED(trx);
-
- mutex_enter(&(dict_sys->mutex));
-
- table = dict_table_get_low(table_name);
-
- if (table != NULL) {
-
- table->n_mysql_handles_opened++;
- }
-
- mutex_exit(&(dict_sys->mutex));
-
- if (table != NULL) {
- if (!table->stat_initialized && !table->ibd_file_missing) {
- dict_update_statistics(table);
- }
- }
-
- return(table);
-}
-
-/**************************************************************************
-Adds a table object to the dictionary cache. */
-
-void
-dict_table_add_to_cache(
-/*====================*/
- dict_table_t* table) /* in: table */
-{
- ulint fold;
- ulint id_fold;
- ulint i;
-
- ut_ad(table);
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(mutex_own(&(dict_sys->mutex)));
-#endif /* UNIV_SYNC_DEBUG */
- ut_ad(table->n_def == table->n_cols - DATA_N_SYS_COLS);
- ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
- ut_ad(table->cached == FALSE);
-
- fold = ut_fold_string(table->name);
- id_fold = ut_fold_dulint(table->id);
-
- table->cached = TRUE;
-
- /* NOTE: the system columns MUST be added in the following order
- (so that they can be indexed by the numerical value of DATA_ROW_ID,
- etc.) and as the last columns of the table memory object.
- The clustered index will not always physically contain all
- system columns. */
-
- dict_mem_table_add_col(table, "DB_ROW_ID", DATA_SYS,
- DATA_ROW_ID | DATA_NOT_NULL, DATA_ROW_ID_LEN, 0);
-#if DATA_ROW_ID != 0
-#error "DATA_ROW_ID != 0"
-#endif
- dict_mem_table_add_col(table, "DB_TRX_ID", DATA_SYS,
- DATA_TRX_ID | DATA_NOT_NULL, DATA_TRX_ID_LEN, 0);
-#if DATA_TRX_ID != 1
-#error "DATA_TRX_ID != 1"
-#endif
- dict_mem_table_add_col(table, "DB_ROLL_PTR", DATA_SYS,
- DATA_ROLL_PTR | DATA_NOT_NULL, DATA_ROLL_PTR_LEN, 0);
-#if DATA_ROLL_PTR != 2
-#error "DATA_ROLL_PTR != 2"
-#endif
- dict_mem_table_add_col(table, "DB_MIX_ID", DATA_SYS,
- DATA_MIX_ID | DATA_NOT_NULL, DATA_MIX_ID_LEN, 0);
-#if DATA_MIX_ID != 3
-#error "DATA_MIX_ID != 3"
-#endif
-
- /* This check reminds that if a new system column is added to
- the program, it should be dealt with here */
-#if DATA_N_SYS_COLS != 4
-#error "DATA_N_SYS_COLS != 4"
-#endif
-
- /* Look for a table with the same name: error if such exists */
- {
- dict_table_t* table2;
- HASH_SEARCH(name_hash, dict_sys->table_hash, fold, table2,
- (ut_strcmp(table2->name, table->name) == 0));
- ut_a(table2 == NULL);
- }
-
- /* Look for a table with the same id: error if such exists */
- {
- dict_table_t* table2;
- HASH_SEARCH(id_hash, dict_sys->table_id_hash, id_fold, table2,
- (ut_dulint_cmp(table2->id, table->id) == 0));
- ut_a(table2 == NULL);
- }
-
- if (table->type == DICT_TABLE_CLUSTER_MEMBER) {
-
- table->mix_id_len = mach_dulint_get_compressed_size(
- table->mix_id);
- mach_dulint_write_compressed(table->mix_id_buf, table->mix_id);
- }
-
- /* Add the columns to the column hash table */
- for (i = 0; i < table->n_cols; i++) {
- dict_col_add_to_cache(table, dict_table_get_nth_col(table, i));
- }
-
- /* Add table to hash table of tables */
- HASH_INSERT(dict_table_t, name_hash, dict_sys->table_hash, fold,
- table);
-
- /* Add table to hash table of tables based on table id */
- HASH_INSERT(dict_table_t, id_hash, dict_sys->table_id_hash, id_fold,
- table);
- /* Add table to LRU list of tables */
- UT_LIST_ADD_FIRST(table_LRU, dict_sys->table_LRU, table);
-
- /* If the dictionary cache grows too big, trim the table LRU list */
-
- dict_sys->size += mem_heap_get_size(table->heap);
- /* dict_table_LRU_trim(); */
-}
-
-/**************************************************************************
-Looks for an index with the given id. NOTE that we do not reserve
-the dictionary mutex: this function is for emergency purposes like
-printing info of a corrupt database page! */
-
-dict_index_t*
-dict_index_find_on_id_low(
-/*======================*/
- /* out: index or NULL if not found from cache */
- dulint id) /* in: index id */
-{
- dict_table_t* table;
- dict_index_t* index;
-
- table = UT_LIST_GET_FIRST(dict_sys->table_LRU);
-
- while (table) {
- index = dict_table_get_first_index(table);
-
- while (index) {
- if (0 == ut_dulint_cmp(id, index->tree->id)) {
- /* Found */
-
- return(index);
- }
-
- index = dict_table_get_next_index(index);
- }
-
- table = UT_LIST_GET_NEXT(table_LRU, table);
- }
-
- return(NULL);
-}
-
-/**************************************************************************
-Renames a table object. */
-
-ibool
-dict_table_rename_in_cache(
-/*=======================*/
- /* out: TRUE if success */
- dict_table_t* table, /* in: table */
- const char* new_name, /* in: new name */
- ibool rename_also_foreigns)/* in: in ALTER TABLE we want
- to preserve the original table name
- in constraints which reference it */
-{
- dict_foreign_t* foreign;
- dict_index_t* index;
- ulint fold;
- ulint old_size;
- char* old_name;
- ibool success;
- ulint i;
-
- ut_ad(table);
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(mutex_own(&(dict_sys->mutex)));
-#endif /* UNIV_SYNC_DEBUG */
-
- old_size = mem_heap_get_size(table->heap);
-
- fold = ut_fold_string(new_name);
-
- /* Look for a table with the same name: error if such exists */
- {
- dict_table_t* table2;
- HASH_SEARCH(name_hash, dict_sys->table_hash, fold, table2,
- (ut_strcmp(table2->name, new_name) == 0));
- if (table2) {
- fprintf(stderr,
-"InnoDB: Error: dictionary cache already contains a table of name %s\n",
- new_name);
- return(FALSE);
- }
- }
-
- /* If the table is stored in a single-table tablespace, rename the
- .ibd file */
-
- if (table->space != 0) {
- if (table->dir_path_of_temp_table != NULL) {
- fprintf(stderr,
-"InnoDB: Error: trying to rename a table %s (%s) created with CREATE\n"
-"InnoDB: TEMPORARY TABLE\n", table->name, table->dir_path_of_temp_table);
- success = FALSE;
- } else {
- success = fil_rename_tablespace(table->name,
- table->space, new_name);
- }
-
- if (!success) {
-
- return(FALSE);
- }
- }
-
- /* Reposition the columns in the column hash table; they are hashed
- according to the pair (table name, column name) */
-
- for (i = 0; i < table->n_cols; i++) {
- dict_col_reposition_in_cache(table,
- dict_table_get_nth_col(table, i), new_name);
- }
-
- /* Remove table from the hash tables of tables */
- HASH_DELETE(dict_table_t, name_hash, dict_sys->table_hash,
- ut_fold_string(table->name), table);
- old_name = mem_heap_strdup(table->heap, table->name);
- table->name = mem_heap_strdup(table->heap, new_name);
-
- /* Add table to hash table of tables */
- HASH_INSERT(dict_table_t, name_hash, dict_sys->table_hash, fold,
- table);
- dict_sys->size += (mem_heap_get_size(table->heap) - old_size);
-
- /* Update the table_name field in indexes */
- index = dict_table_get_first_index(table);
-
- while (index != NULL) {
- index->table_name = table->name;
-
- index = dict_table_get_next_index(index);
- }
-
- if (!rename_also_foreigns) {
- /* In ALTER TABLE we think of the rename table operation
- in the direction table -> temporary table (#sql...)
- as dropping the table with the old name and creating
- a new with the new name. Thus we kind of drop the
- constraints from the dictionary cache here. The foreign key
- constraints will be inherited to the new table from the
- system tables through a call of dict_load_foreigns. */
-
- /* Remove the foreign constraints from the cache */
- foreign = UT_LIST_GET_LAST(table->foreign_list);
-
- while (foreign != NULL) {
- dict_foreign_remove_from_cache(foreign);
- foreign = UT_LIST_GET_LAST(table->foreign_list);
- }
-
- /* Reset table field in referencing constraints */
-
- foreign = UT_LIST_GET_FIRST(table->referenced_list);
-
- while (foreign != NULL) {
- foreign->referenced_table = NULL;
- foreign->referenced_index = NULL;
-
- foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
- }
-
- /* Make the list of referencing constraints empty */
-
- UT_LIST_INIT(table->referenced_list);
-
- return(TRUE);
- }
-
- /* Update the table name fields in foreign constraints, and update also
- the constraint id of new format >= 4.0.18 constraints. Note that at
- this point we have already changed table->name to the new name. */
-
- foreign = UT_LIST_GET_FIRST(table->foreign_list);
-
- while (foreign != NULL) {
- if (ut_strlen(foreign->foreign_table_name) <
- ut_strlen(table->name)) {
- /* Allocate a longer name buffer;
- TODO: store buf len to save memory */
-
- foreign->foreign_table_name = mem_heap_alloc(
- foreign->heap,
- ut_strlen(table->name) + 1);
- }
-
- strcpy(foreign->foreign_table_name, table->name);
-
- if (strchr(foreign->id, '/')) {
- ulint db_len;
- char* old_id;
-
- /* This is a >= 4.0.18 format id */
-
- old_id = mem_strdup(foreign->id);
-
- if (ut_strlen(foreign->id) > ut_strlen(old_name)
- + ((sizeof dict_ibfk) - 1)
- && 0 == ut_memcmp(foreign->id, old_name,
- ut_strlen(old_name))
- && 0 == ut_memcmp(
- foreign->id + ut_strlen(old_name),
- dict_ibfk, (sizeof dict_ibfk) - 1)) {
-
- /* This is a generated >= 4.0.18 format id */
-
- if (ut_strlen(table->name) > ut_strlen(old_name)) {
- foreign->id = mem_heap_alloc(
- foreign->heap,
- ut_strlen(table->name)
- + ut_strlen(old_id) + 1);
- }
-
- /* Replace the prefix 'databasename/tablename'
- with the new names */
- strcpy(foreign->id, table->name);
- strcat(foreign->id,
- old_id + ut_strlen(old_name));
- } else {
- /* This is a >= 4.0.18 format id where the user
- gave the id name */
- db_len = dict_get_db_name_len(table->name) + 1;
-
- if (dict_get_db_name_len(table->name)
- > dict_get_db_name_len(foreign->id)) {
-
- foreign->id = mem_heap_alloc(
- foreign->heap,
- db_len + ut_strlen(old_id) + 1);
- }
-
- /* Replace the database prefix in id with the
- one from table->name */
-
- ut_memcpy(foreign->id, table->name, db_len);
-
- strcpy(foreign->id + db_len,
- dict_remove_db_name(old_id));
- }
-
- mem_free(old_id);
- }
-
- foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
- }
-
- foreign = UT_LIST_GET_FIRST(table->referenced_list);
-
- while (foreign != NULL) {
- if (ut_strlen(foreign->referenced_table_name) <
- ut_strlen(table->name)) {
- /* Allocate a longer name buffer;
- TODO: store buf len to save memory */
-
- foreign->referenced_table_name = mem_heap_alloc(
- foreign->heap,
- ut_strlen(table->name) + 1);
- }
-
- strcpy(foreign->referenced_table_name, table->name);
-
- foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
- }
-
- return(TRUE);
-}
-
-/**************************************************************************
-Change the id of a table object in the dictionary cache. This is used in
-DISCARD TABLESPACE. */
-
-void
-dict_table_change_id_in_cache(
-/*==========================*/
- dict_table_t* table, /* in: table object already in cache */
- dulint new_id) /* in: new id to set */
-{
- ut_ad(table);
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(mutex_own(&(dict_sys->mutex)));
-#endif /* UNIV_SYNC_DEBUG */
- ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
-
- /* Remove the table from the hash table of id's */
-
- HASH_DELETE(dict_table_t, id_hash, dict_sys->table_id_hash,
- ut_fold_dulint(table->id), table);
- table->id = new_id;
-
- /* Add the table back to the hash table */
- HASH_INSERT(dict_table_t, id_hash, dict_sys->table_id_hash,
- ut_fold_dulint(table->id), table);
-}
-
-/**************************************************************************
-Removes a table object from the dictionary cache. */
-
-void
-dict_table_remove_from_cache(
-/*=========================*/
- dict_table_t* table) /* in, own: table */
-{
- dict_foreign_t* foreign;
- dict_index_t* index;
- ulint size;
- ulint i;
-
- ut_ad(table);
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(mutex_own(&(dict_sys->mutex)));
-#endif /* UNIV_SYNC_DEBUG */
- ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
-
-#if 0
- fputs("Removing table ", stderr);
- ut_print_name(stderr, table->name, ULINT_UNDEFINED);
- fputs(" from dictionary cache\n", stderr);
-#endif
-
- /* Remove the foreign constraints from the cache */
- foreign = UT_LIST_GET_LAST(table->foreign_list);
-
- while (foreign != NULL) {
- dict_foreign_remove_from_cache(foreign);
- foreign = UT_LIST_GET_LAST(table->foreign_list);
- }
-
- /* Reset table field in referencing constraints */
-
- foreign = UT_LIST_GET_FIRST(table->referenced_list);
-
- while (foreign != NULL) {
- foreign->referenced_table = NULL;
- foreign->referenced_index = NULL;
-
- foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
- }
-
- /* Remove the indexes from the cache */
- index = UT_LIST_GET_LAST(table->indexes);
-
- while (index != NULL) {
- dict_index_remove_from_cache(table, index);
- index = UT_LIST_GET_LAST(table->indexes);
- }
-
- /* Remove the columns of the table from the cache */
- for (i = 0; i < table->n_cols; i++) {
- dict_col_remove_from_cache(table,
- dict_table_get_nth_col(table, i));
- }
-
- /* Remove table from the hash tables of tables */
- HASH_DELETE(dict_table_t, name_hash, dict_sys->table_hash,
- ut_fold_string(table->name), table);
- HASH_DELETE(dict_table_t, id_hash, dict_sys->table_id_hash,
- ut_fold_dulint(table->id), table);
-
- /* Remove table from LRU list of tables */
- UT_LIST_REMOVE(table_LRU, dict_sys->table_LRU, table);
-
- mutex_free(&(table->autoinc_mutex));
-
- size = mem_heap_get_size(table->heap);
-
- ut_ad(dict_sys->size >= size);
-
- dict_sys->size -= size;
-
- mem_heap_free(table->heap);
-}
-
-/**************************************************************************
-Frees tables from the end of table_LRU if the dictionary cache occupies
-too much space. Currently not used! */
-
-void
-dict_table_LRU_trim(void)
-/*=====================*/
-{
- dict_table_t* table;
- dict_table_t* prev_table;
-
- ut_error;
-
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(mutex_own(&(dict_sys->mutex)));
-#endif /* UNIV_SYNC_DEBUG */
-
- table = UT_LIST_GET_LAST(dict_sys->table_LRU);
-
- while (table && (dict_sys->size >
- buf_pool_get_max_size() / DICT_POOL_PER_VARYING)) {
-
- prev_table = UT_LIST_GET_PREV(table_LRU, table);
-
- if (table->mem_fix == 0) {
- dict_table_remove_from_cache(table);
- }
-
- table = prev_table;
- }
-}
-
-/**************************************************************************
-Adds a column to the data dictionary hash table. */
-static
-void
-dict_col_add_to_cache(
-/*==================*/
- dict_table_t* table, /* in: table */
- dict_col_t* col) /* in: column */
-{
- ulint fold;
-
- ut_ad(table && col);
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(mutex_own(&(dict_sys->mutex)));
-#endif /* UNIV_SYNC_DEBUG */
- ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
-
- fold = ut_fold_ulint_pair(ut_fold_string(table->name),
- ut_fold_string(col->name));
-
- /* Look for a column with same table name and column name: error */
- {
- dict_col_t* col2;
- HASH_SEARCH(hash, dict_sys->col_hash, fold, col2,
- (ut_strcmp(col->name, col2->name) == 0)
- && (ut_strcmp((col2->table)->name, table->name)
- == 0));
- ut_a(col2 == NULL);
- }
-
- HASH_INSERT(dict_col_t, hash, dict_sys->col_hash, fold, col);
-}
-
-/**************************************************************************
-Removes a column from the data dictionary hash table. */
-static
-void
-dict_col_remove_from_cache(
-/*=======================*/
- dict_table_t* table, /* in: table */
- dict_col_t* col) /* in: column */
-{
- ulint fold;
-
- ut_ad(table && col);
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(mutex_own(&(dict_sys->mutex)));
-#endif /* UNIV_SYNC_DEBUG */
- ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
-
- fold = ut_fold_ulint_pair(ut_fold_string(table->name),
- ut_fold_string(col->name));
-
- HASH_DELETE(dict_col_t, hash, dict_sys->col_hash, fold, col);
-}
-
-/**************************************************************************
-Repositions a column in the data dictionary hash table when the table name
-changes. */
-static
-void
-dict_col_reposition_in_cache(
-/*=========================*/
- dict_table_t* table, /* in: table */
- dict_col_t* col, /* in: column */
- const char* new_name) /* in: new table name */
-{
- ulint fold;
-
- ut_ad(table && col);
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(mutex_own(&(dict_sys->mutex)));
-#endif /* UNIV_SYNC_DEBUG */
- ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
-
- fold = ut_fold_ulint_pair(ut_fold_string(table->name),
- ut_fold_string(col->name));
-
- HASH_DELETE(dict_col_t, hash, dict_sys->col_hash, fold, col);
-
- fold = ut_fold_ulint_pair(ut_fold_string(new_name),
- ut_fold_string(col->name));
-
- HASH_INSERT(dict_col_t, hash, dict_sys->col_hash, fold, col);
-}
-
-/**************************************************************************
-Adds an index to the dictionary cache. */
-
-ibool
-dict_index_add_to_cache(
-/*====================*/
- /* out: TRUE if success */
- dict_table_t* table, /* in: table on which the index is */
- dict_index_t* index, /* in, own: index; NOTE! The index memory
- object is freed in this function! */
- ulint page_no)/* in: root page number of the index */
-{
- dict_index_t* new_index;
- dict_tree_t* tree;
- dict_table_t* cluster;
- dict_field_t* field;
- ulint n_ord;
- ibool success;
- ulint i;
-
- ut_ad(index);
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(mutex_own(&(dict_sys->mutex)));
-#endif /* UNIV_SYNC_DEBUG */
- ut_ad(index->n_def == index->n_fields);
- ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
-
- ut_ad(mem_heap_validate(index->heap));
-
- {
- dict_index_t* index2;
- index2 = UT_LIST_GET_FIRST(table->indexes);
-
- while (index2 != NULL) {
- ut_ad(ut_strcmp(index->name, index2->name) != 0);
-
- index2 = UT_LIST_GET_NEXT(indexes, index2);
- }
-
- ut_a(UT_LIST_GET_LEN(table->indexes) == 0
- || (index->type & DICT_CLUSTERED) == 0);
- }
-
- success = dict_index_find_cols(table, index);
-
- if (!success) {
- dict_mem_index_free(index);
-
- return(FALSE);
- }
-
- /* Build the cache internal representation of the index,
- containing also the added system fields */
-
- if (index->type & DICT_CLUSTERED) {
- new_index = dict_index_build_internal_clust(table, index);
- } else {
- new_index = dict_index_build_internal_non_clust(table, index);
- }
-
- new_index->search_info = btr_search_info_create(new_index->heap);
-
- /* Set the n_fields value in new_index to the actual defined
- number of fields in the cache internal representation */
-
- new_index->n_fields = new_index->n_def;
-
- /* Add the new index as the last index for the table */
-
- UT_LIST_ADD_LAST(indexes, table->indexes, new_index);
- new_index->table = table;
- new_index->table_name = table->name;
-
- /* Increment the ord_part counts in columns which are ordering */
-
- if (index->type & DICT_UNIVERSAL) {
- n_ord = new_index->n_fields;
- } else {
- n_ord = dict_index_get_n_unique(new_index);
- }
-
- for (i = 0; i < n_ord; i++) {
-
- field = dict_index_get_nth_field(new_index, i);
-
- dict_field_get_col(field)->ord_part++;
- }
-
- if (table->type == DICT_TABLE_CLUSTER_MEMBER) {
- /* The index tree is found from the cluster object */
-
- cluster = dict_table_get_low(table->cluster_name);
-
- tree = dict_index_get_tree(
- UT_LIST_GET_FIRST(cluster->indexes));
- new_index->tree = tree;
- } else {
- /* Create an index tree memory object for the index */
- tree = dict_tree_create(new_index, page_no);
- ut_ad(tree);
-
- new_index->tree = tree;
- }
-
- if (!(new_index->type & DICT_UNIVERSAL)) {
-
- new_index->stat_n_diff_key_vals =
- mem_heap_alloc(new_index->heap,
- (1 + dict_index_get_n_unique(new_index))
- * sizeof(ib_longlong));
- /* Give some sensible values to stat_n_... in case we do
- not calculate statistics quickly enough */
-
- for (i = 0; i <= dict_index_get_n_unique(new_index); i++) {
-
- new_index->stat_n_diff_key_vals[i] = 100;
- }
- }
-
- /* Add the index to the list of indexes stored in the tree */
- UT_LIST_ADD_LAST(tree_indexes, tree->tree_indexes, new_index);
-
- /* If the dictionary cache grows too big, trim the table LRU list */
-
- dict_sys->size += mem_heap_get_size(new_index->heap);
- /* dict_table_LRU_trim(); */
-
- dict_mem_index_free(index);
-
- return(TRUE);
-}
-
-/**************************************************************************
-Removes an index from the dictionary cache. */
-static
-void
-dict_index_remove_from_cache(
-/*=========================*/
- dict_table_t* table, /* in: table */
- dict_index_t* index) /* in, own: index */
-{
- dict_field_t* field;
- ulint size;
- ulint i;
-
- ut_ad(table && index);
- ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
- ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(mutex_own(&(dict_sys->mutex)));
-#endif /* UNIV_SYNC_DEBUG */
-
- ut_ad(UT_LIST_GET_LEN((index->tree)->tree_indexes) == 1);
- dict_tree_free(index->tree);
-
- /* Decrement the ord_part counts in columns which are ordering */
- for (i = 0; i < dict_index_get_n_unique(index); i++) {
-
- field = dict_index_get_nth_field(index, i);
-
- ut_ad(dict_field_get_col(field)->ord_part > 0);
- (dict_field_get_col(field)->ord_part)--;
- }
-
- /* Remove the index from the list of indexes of the table */
- UT_LIST_REMOVE(indexes, table->indexes, index);
-
- size = mem_heap_get_size(index->heap);
-
- ut_ad(dict_sys->size >= size);
-
- dict_sys->size -= size;
-
- mem_heap_free(index->heap);
-}
-
-/***********************************************************************
-Tries to find column names for the index in the column hash table and
-sets the col field of the index. */
-static
-ibool
-dict_index_find_cols(
-/*=================*/
- /* out: TRUE if success */
- dict_table_t* table, /* in: table */
- dict_index_t* index) /* in: index */
-{
- dict_col_t* col;
- dict_field_t* field;
- ulint fold;
- ulint i;
-
- ut_ad(table && index);
- ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(mutex_own(&(dict_sys->mutex)));
-#endif /* UNIV_SYNC_DEBUG */
-
- for (i = 0; i < index->n_fields; i++) {
- field = dict_index_get_nth_field(index, i);
-
- fold = ut_fold_ulint_pair(ut_fold_string(table->name),
- ut_fold_string(field->name));
-
- HASH_SEARCH(hash, dict_sys->col_hash, fold, col,
- (ut_strcmp(col->name, field->name) == 0)
- && (ut_strcmp((col->table)->name, table->name)
- == 0));
- if (col == NULL) {
-
- return(FALSE);
- } else {
- field->col = col;
- }
- }
-
- return(TRUE);
-}
-
-/***********************************************************************
-Adds a column to index. */
-
-void
-dict_index_add_col(
-/*===============*/
- dict_index_t* index, /* in: index */
- dict_col_t* col, /* in: column */
- ulint order, /* in: order criterion */
- ulint prefix_len) /* in: column prefix length */
-{
- dict_field_t* field;
-
- dict_mem_index_add_field(index, col->name, order, prefix_len);
-
- field = dict_index_get_nth_field(index, index->n_def - 1);
-
- field->col = col;
- field->fixed_len = dtype_get_fixed_size(&col->type);
-
- if (prefix_len && field->fixed_len > prefix_len) {
- field->fixed_len = prefix_len;
- }
-
- /* Long fixed-length fields that need external storage are treated as
- variable-length fields, so that the extern flag can be embedded in
- the length word. */
-
- if (field->fixed_len > DICT_MAX_COL_PREFIX_LEN) {
- field->fixed_len = 0;
- }
-
- if (!(dtype_get_prtype(&col->type) & DATA_NOT_NULL)) {
- index->n_nullable++;
- }
-
- if (index->n_def > 1) {
- const dict_field_t* field2 =
- dict_index_get_nth_field(index, index->n_def - 2);
- field->fixed_offs = (!field2->fixed_len ||
- field2->fixed_offs == ULINT_UNDEFINED)
- ? ULINT_UNDEFINED
- : field2->fixed_len + field2->fixed_offs;
- } else {
- field->fixed_offs = 0;
- }
-}
-
-/***********************************************************************
-Copies fields contained in index2 to index1. */
-static
-void
-dict_index_copy(
-/*============*/
- dict_index_t* index1, /* in: index to copy to */
- dict_index_t* index2, /* in: index to copy from */
- ulint start, /* in: first position to copy */
- ulint end) /* in: last position to copy */
-{
- dict_field_t* field;
- ulint i;
-
- /* Copy fields contained in index2 */
-
- for (i = start; i < end; i++) {
-
- field = dict_index_get_nth_field(index2, i);
- dict_index_add_col(index1, field->col, field->order,
- field->prefix_len);
- }
-}
-
-/***********************************************************************
-Copies types of fields contained in index to tuple. */
-
-void
-dict_index_copy_types(
-/*==================*/
- dtuple_t* tuple, /* in: data tuple */
- dict_index_t* index, /* in: index */
- ulint n_fields) /* in: number of field types to copy */
-{
- dtype_t* dfield_type;
- dtype_t* type;
- ulint i;
-
- if (index->type & DICT_UNIVERSAL) {
- dtuple_set_types_binary(tuple, n_fields);
-
- return;
- }
-
- for (i = 0; i < n_fields; i++) {
- dfield_type = dfield_get_type(dtuple_get_nth_field(tuple, i));
- type = dict_col_get_type(dict_field_get_col(
- dict_index_get_nth_field(index, i)));
- *dfield_type = *type;
- }
-}
-
-/***********************************************************************
-Copies types of columns contained in table to tuple. */
-
-void
-dict_table_copy_types(
-/*==================*/
- dtuple_t* tuple, /* in: data tuple */
- dict_table_t* table) /* in: index */
-{
- dtype_t* dfield_type;
- dtype_t* type;
- ulint i;
-
- ut_ad(!(table->type & DICT_UNIVERSAL));
-
- for (i = 0; i < dtuple_get_n_fields(tuple); i++) {
-
- dfield_type = dfield_get_type(dtuple_get_nth_field(tuple, i));
- type = dict_col_get_type(dict_table_get_nth_col(table, i));
-
- *dfield_type = *type;
- }
-}
-
-/***********************************************************************
-Builds the internal dictionary cache representation for a clustered
-index, containing also system fields not defined by the user. */
-static
-dict_index_t*
-dict_index_build_internal_clust(
-/*============================*/
- /* out, own: the internal representation
- of the clustered index */
- dict_table_t* table, /* in: table */
- dict_index_t* index) /* in: user representation of a clustered
- index */
-{
- dict_index_t* new_index;
- dict_field_t* field;
- dict_col_t* col;
- ulint fixed_size;
- ulint trx_id_pos;
- ulint i;
-
- ut_ad(table && index);
- ut_ad(index->type & DICT_CLUSTERED);
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(mutex_own(&(dict_sys->mutex)));
-#endif /* UNIV_SYNC_DEBUG */
- ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
-
- /* Create a new index object with certainly enough fields */
- new_index = dict_mem_index_create(table->name,
- index->name,
- table->space,
- index->type,
- index->n_fields + table->n_cols);
-
- /* Copy other relevant data from the old index struct to the new
- struct: it inherits the values */
-
- new_index->n_user_defined_cols = index->n_fields;
-
- new_index->id = index->id;
-
- if (table->type != DICT_TABLE_ORDINARY) {
- /* The index is mixed: copy common key prefix fields */
-
- dict_index_copy(new_index, index, 0, table->mix_len);
-
- /* Add the mix id column */
- dict_index_add_col(new_index,
- dict_table_get_sys_col(table, DATA_MIX_ID), 0, 0);
-
- /* Copy the rest of fields */
- dict_index_copy(new_index, index, table->mix_len,
- index->n_fields);
- } else {
- /* Copy the fields of index */
- dict_index_copy(new_index, index, 0, index->n_fields);
- }
-
- if (index->type & DICT_UNIVERSAL) {
- /* No fixed number of fields determines an entry uniquely */
-
- new_index->n_uniq = ULINT_MAX;
-
- } else if (index->type & DICT_UNIQUE) {
- /* Only the fields defined so far are needed to identify
- the index entry uniquely */
-
- new_index->n_uniq = new_index->n_def;
- } else {
- /* Also the row id is needed to identify the entry */
- new_index->n_uniq = 1 + new_index->n_def;
- }
-
- new_index->trx_id_offset = 0;
-
- if (!(index->type & DICT_IBUF)) {
- /* Add system columns, trx id first */
-
- trx_id_pos = new_index->n_def;
-
- ut_ad(DATA_ROW_ID == 0);
- ut_ad(DATA_TRX_ID == 1);
- ut_ad(DATA_ROLL_PTR == 2);
-
- if (!(index->type & DICT_UNIQUE)) {
- dict_index_add_col(new_index,
- dict_table_get_sys_col(table, DATA_ROW_ID), 0, 0);
- trx_id_pos++;
- }
-
- dict_index_add_col(new_index,
- dict_table_get_sys_col(table, DATA_TRX_ID), 0, 0);
-
- dict_index_add_col(new_index,
- dict_table_get_sys_col(table, DATA_ROLL_PTR), 0, 0);
-
- for (i = 0; i < trx_id_pos; i++) {
-
- fixed_size = dtype_get_fixed_size(
- dict_index_get_nth_type(new_index, i));
-
- if (fixed_size == 0) {
- new_index->trx_id_offset = 0;
-
- break;
- }
-
- if (dict_index_get_nth_field(new_index, i)->prefix_len
- > 0) {
- new_index->trx_id_offset = 0;
-
- break;
- }
-
- new_index->trx_id_offset += fixed_size;
- }
-
- }
-
- /* Set auxiliary variables in table columns as undefined */
- for (i = 0; i < table->n_cols; i++) {
-
- col = dict_table_get_nth_col(table, i);
- col->aux = ULINT_UNDEFINED;
- }
-
- /* Mark with 0 the table columns already contained in new_index */
- for (i = 0; i < new_index->n_def; i++) {
-
- field = dict_index_get_nth_field(new_index, i);
-
- /* If there is only a prefix of the column in the index
- field, do not mark the column as contained in the index */
-
- if (field->prefix_len == 0) {
-
- field->col->aux = 0;
- }
- }
-
- /* Add to new_index non-system columns of table not yet included
- there */
- for (i = 0; i < table->n_cols - DATA_N_SYS_COLS; i++) {
-
- col = dict_table_get_nth_col(table, i);
- ut_ad(col->type.mtype != DATA_SYS);
-
- if (col->aux == ULINT_UNDEFINED) {
- dict_index_add_col(new_index, col, 0, 0);
- }
- }
-
- ut_ad((index->type & DICT_IBUF)
- || (UT_LIST_GET_LEN(table->indexes) == 0));
-
- /* Store to the column structs the position of the table columns
- in the clustered index */
-
- for (i = 0; i < new_index->n_def; i++) {
- field = dict_index_get_nth_field(new_index, i);
-
- if (field->prefix_len == 0) {
-
- field->col->clust_pos = i;
- }
- }
-
- new_index->cached = TRUE;
-
- return(new_index);
-}
-
-/***********************************************************************
-Builds the internal dictionary cache representation for a non-clustered
-index, containing also system fields not defined by the user. */
-static
-dict_index_t*
-dict_index_build_internal_non_clust(
-/*================================*/
- /* out, own: the internal representation
- of the non-clustered index */
- dict_table_t* table, /* in: table */
- dict_index_t* index) /* in: user representation of a non-clustered
- index */
-{
- dict_field_t* field;
- dict_index_t* new_index;
- dict_index_t* clust_index;
- ulint i;
-
- ut_ad(table && index);
- ut_ad(0 == (index->type & DICT_CLUSTERED));
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(mutex_own(&(dict_sys->mutex)));
-#endif /* UNIV_SYNC_DEBUG */
- ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
-
- /* The clustered index should be the first in the list of indexes */
- clust_index = UT_LIST_GET_FIRST(table->indexes);
-
- ut_ad(clust_index);
- ut_ad(clust_index->type & DICT_CLUSTERED);
- ut_ad(!(clust_index->type & DICT_UNIVERSAL));
-
- /* Create a new index */
- new_index = dict_mem_index_create(table->name,
- index->name,
- index->space,
- index->type,
- index->n_fields
- + 1 + clust_index->n_uniq);
-
- /* Copy other relevant data from the old index
- struct to the new struct: it inherits the values */
-
- new_index->n_user_defined_cols = index->n_fields;
-
- new_index->id = index->id;
-
- /* Copy fields from index to new_index */
- dict_index_copy(new_index, index, 0, index->n_fields);
-
- /* Set the auxiliary variables in the clust_index unique columns
- as undefined */
- for (i = 0; i < clust_index->n_uniq; i++) {
-
- field = dict_index_get_nth_field(clust_index, i);
- field->col->aux = ULINT_UNDEFINED;
- }
-
- /* Mark with 0 table columns already contained in new_index */
- for (i = 0; i < new_index->n_def; i++) {
-
- field = dict_index_get_nth_field(new_index, i);
-
- /* If there is only a prefix of the column in the index
- field, do not mark the column as contained in the index */
-
- if (field->prefix_len == 0) {
-
- field->col->aux = 0;
- }
- }
-
- /* Add to new_index the columns necessary to determine the clustered
- index entry uniquely */
-
- for (i = 0; i < clust_index->n_uniq; i++) {
-
- field = dict_index_get_nth_field(clust_index, i);
-
- if (field->col->aux == ULINT_UNDEFINED) {
- dict_index_add_col(new_index, field->col, 0,
- field->prefix_len);
- }
- }
-
- if ((index->type) & DICT_UNIQUE) {
- new_index->n_uniq = index->n_fields;
- } else {
- new_index->n_uniq = new_index->n_def;
- }
-
- /* Set the n_fields value in new_index to the actual defined
- number of fields */
-
- new_index->n_fields = new_index->n_def;
-
- new_index->cached = TRUE;
-
- return(new_index);
-}
-
-/*====================== FOREIGN KEY PROCESSING ========================*/
-
-/*************************************************************************
-Checks if a table is referenced by foreign keys. */
-
-ibool
-dict_table_referenced_by_foreign_key(
-/*=================================*/
- /* out: TRUE if table is referenced by a
- foreign key */
- dict_table_t* table) /* in: InnoDB table */
-{
- if (UT_LIST_GET_LEN(table->referenced_list) > 0) {
-
- return(TRUE);
- }
-
- return(FALSE);
-}
-
-/*************************************************************************
-Frees a foreign key struct. */
-static
-void
-dict_foreign_free(
-/*==============*/
- dict_foreign_t* foreign) /* in, own: foreign key struct */
-{
- mem_heap_free(foreign->heap);
-}
-
-/**************************************************************************
-Removes a foreign constraint struct from the dictionary cache. */
-static
-void
-dict_foreign_remove_from_cache(
-/*===========================*/
- dict_foreign_t* foreign) /* in, own: foreign constraint */
-{
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(mutex_own(&(dict_sys->mutex)));
-#endif /* UNIV_SYNC_DEBUG */
- ut_a(foreign);
-
- if (foreign->referenced_table) {
- UT_LIST_REMOVE(referenced_list,
- foreign->referenced_table->referenced_list, foreign);
- }
-
- if (foreign->foreign_table) {
- UT_LIST_REMOVE(foreign_list,
- foreign->foreign_table->foreign_list, foreign);
- }
-
- dict_foreign_free(foreign);
-}
-
-/**************************************************************************
-Looks for the foreign constraint from the foreign and referenced lists
-of a table. */
-static
-dict_foreign_t*
-dict_foreign_find(
-/*==============*/
- /* out: foreign constraint */
- dict_table_t* table, /* in: table object */
- const char* id) /* in: foreign constraint id */
-{
- dict_foreign_t* foreign;
-
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(mutex_own(&(dict_sys->mutex)));
-#endif /* UNIV_SYNC_DEBUG */
-
- foreign = UT_LIST_GET_FIRST(table->foreign_list);
-
- while (foreign) {
- if (ut_strcmp(id, foreign->id) == 0) {
-
- return(foreign);
- }
-
- foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
- }
-
- foreign = UT_LIST_GET_FIRST(table->referenced_list);
-
- while (foreign) {
- if (ut_strcmp(id, foreign->id) == 0) {
-
- return(foreign);
- }
-
- foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
- }
-
- return(NULL);
-}
-
-/*************************************************************************
-Tries to find an index whose first fields are the columns in the array,
-in the same order. */
-static
-dict_index_t*
-dict_foreign_find_index(
-/*====================*/
- /* out: matching index, NULL if not found */
- dict_table_t* table, /* in: table */
- const char** columns,/* in: array of column names */
- ulint n_cols, /* in: number of columns */
- dict_index_t* types_idx)/* in: NULL or an index to whose types the
- column types must match */
-{
-#ifndef UNIV_HOTBACKUP
- dict_index_t* index;
- const char* col_name;
- ulint i;
-
- index = dict_table_get_first_index(table);
-
- while (index != NULL) {
- if (dict_index_get_n_fields(index) >= n_cols) {
-
- for (i = 0; i < n_cols; i++) {
- col_name = dict_index_get_nth_field(index, i)
- ->col->name;
- if (dict_index_get_nth_field(index, i)
- ->prefix_len != 0) {
- /* We do not accept column prefix
- indexes here */
-
- break;
- }
-
- if (0 != innobase_strcasecmp(columns[i],
- col_name)) {
- break;
- }
-
- if (types_idx && !cmp_types_are_equal(
- dict_index_get_nth_type(index, i),
- dict_index_get_nth_type(types_idx, i))) {
-
- break;
- }
- }
-
- if (i == n_cols) {
- /* We found a matching index */
-
- return(index);
- }
- }
-
- index = dict_table_get_next_index(index);
- }
-
- return(NULL);
-#else /* UNIV_HOTBACKUP */
- /* This function depends on MySQL code that is not included in
- InnoDB Hot Backup builds. Besides, this function should never
- be called in InnoDB Hot Backup. */
- ut_error;
-#endif /* UNIV_HOTBACKUP */
-}
-
-/**************************************************************************
-Report an error in a foreign key definition. */
-static
-void
-dict_foreign_error_report_low(
-/*==========================*/
- FILE* file, /* in: output stream */
- const char* name) /* in: table name */
-{
- rewind(file);
- ut_print_timestamp(file);
- fprintf(file, " Error in foreign key constraint of table %s:\n",
- name);
-}
-
-/**************************************************************************
-Report an error in a foreign key definition. */
-static
-void
-dict_foreign_error_report(
-/*======================*/
- FILE* file, /* in: output stream */
- dict_foreign_t* fk, /* in: foreign key constraint */
- const char* msg) /* in: the error message */
-{
- mutex_enter(&dict_foreign_err_mutex);
- dict_foreign_error_report_low(file, fk->foreign_table_name);
- fputs(msg, file);
- fputs(" Constraint:\n", file);
- dict_print_info_on_foreign_key_in_create_format(file, NULL, fk);
- if (fk->foreign_index) {
- fputs("\nThe index in the foreign key in table is ", file);
- ut_print_name(file, NULL, fk->foreign_index->name);
- fputs(
-"\nSee http://dev.mysql.com/doc/mysql/en/InnoDB_foreign_key_constraints.html\n"
-"for correct foreign key definition.\n",
- file);
- }
- mutex_exit(&dict_foreign_err_mutex);
-}
-
-/**************************************************************************
-Adds a foreign key constraint object to the dictionary cache. May free
-the object if there already is an object with the same identifier in.
-At least one of the foreign table and the referenced table must already
-be in the dictionary cache! */
-
-ulint
-dict_foreign_add_to_cache(
-/*======================*/
- /* out: DB_SUCCESS or error code */
- dict_foreign_t* foreign) /* in, own: foreign key constraint */
-{
- dict_table_t* for_table;
- dict_table_t* ref_table;
- dict_foreign_t* for_in_cache = NULL;
- dict_index_t* index;
- ibool added_to_referenced_list= FALSE;
- FILE* ef = dict_foreign_err_file;
-
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(mutex_own(&(dict_sys->mutex)));
-#endif /* UNIV_SYNC_DEBUG */
-
- for_table = dict_table_check_if_in_cache_low(
- foreign->foreign_table_name);
-
- ref_table = dict_table_check_if_in_cache_low(
- foreign->referenced_table_name);
- ut_a(for_table || ref_table);
-
- if (for_table) {
- for_in_cache = dict_foreign_find(for_table, foreign->id);
- }
-
- if (!for_in_cache && ref_table) {
- for_in_cache = dict_foreign_find(ref_table, foreign->id);
- }
-
- if (for_in_cache) {
- /* Free the foreign object */
- mem_heap_free(foreign->heap);
- } else {
- for_in_cache = foreign;
- }
-
- if (for_in_cache->referenced_table == NULL && ref_table) {
- index = dict_foreign_find_index(ref_table,
- (const char**) for_in_cache->referenced_col_names,
- for_in_cache->n_fields,
- for_in_cache->foreign_index);
-
- if (index == NULL) {
- dict_foreign_error_report(ef, for_in_cache,
-"there is no index in referenced table which would contain\n"
-"the columns as the first columns, or the data types in the\n"
-"referenced table do not match to the ones in table.");
-
- if (for_in_cache == foreign) {
- mem_heap_free(foreign->heap);
- }
-
- return(DB_CANNOT_ADD_CONSTRAINT);
- }
-
- for_in_cache->referenced_table = ref_table;
- for_in_cache->referenced_index = index;
- UT_LIST_ADD_LAST(referenced_list,
- ref_table->referenced_list,
- for_in_cache);
- added_to_referenced_list = TRUE;
- }
-
- if (for_in_cache->foreign_table == NULL && for_table) {
- index = dict_foreign_find_index(for_table,
- (const char**) for_in_cache->foreign_col_names,
- for_in_cache->n_fields,
- for_in_cache->referenced_index);
-
- if (index == NULL) {
- dict_foreign_error_report(ef, for_in_cache,
-"there is no index in the table which would contain\n"
-"the columns as the first columns, or the data types in the\n"
-"table do not match to the ones in the referenced table.");
-
- if (for_in_cache == foreign) {
- if (added_to_referenced_list) {
- UT_LIST_REMOVE(referenced_list,
- ref_table->referenced_list,
- for_in_cache);
- }
-
- mem_heap_free(foreign->heap);
- }
-
- return(DB_CANNOT_ADD_CONSTRAINT);
- }
-
- for_in_cache->foreign_table = for_table;
- for_in_cache->foreign_index = index;
- UT_LIST_ADD_LAST(foreign_list,
- for_table->foreign_list,
- for_in_cache);
- }
-
- return(DB_SUCCESS);
-}
-
-/*************************************************************************
-Scans from pointer onwards. Stops if is at the start of a copy of
-'string' where characters are compared without case sensitivity, and
-only outside `` or "" quotes. Stops also at '\0'. */
-
-const char*
-dict_scan_to(
-/*=========*/
- /* out: scanned up to this */
- const char* ptr, /* in: scan from */
- const char* string) /* in: look for this */
-{
- char quote = '\0';
-
- for (; *ptr; ptr++) {
- if (*ptr == quote) {
- /* Closing quote character: do not look for
- starting quote or the keyword. */
- quote = '\0';
- } else if (quote) {
- /* Within quotes: do nothing. */
- } else if (*ptr == '`' || *ptr == '"') {
- /* Starting quote: remember the quote character. */
- quote = *ptr;
- } else {
- /* Outside quotes: look for the keyword. */
- ulint i;
- for (i = 0; string[i]; i++) {
- if (toupper((int)(unsigned char)(ptr[i]))
- != toupper((int)(unsigned char)
- (string[i]))) {
- goto nomatch;
- }
- }
- break;
- nomatch:
- ;
- }
- }
-
- return(ptr);
-}
-
-/*************************************************************************
-Accepts a specified string. Comparisons are case-insensitive. */
-
-const char*
-dict_accept(
-/*========*/
- /* out: if string was accepted, the pointer
- is moved after that, else ptr is returned */
- const char* ptr, /* in: scan from this */
- const char* string, /* in: accept only this string as the next
- non-whitespace string */
- ibool* success)/* out: TRUE if accepted */
-{
- const char* old_ptr = ptr;
- const char* old_ptr2;
-
- *success = FALSE;
-
- while (isspace(*ptr)) {
- ptr++;
- }
-
- old_ptr2 = ptr;
-
- ptr = dict_scan_to(ptr, string);
-
- if (*ptr == '\0' || old_ptr2 != ptr) {
- return(old_ptr);
- }
-
- *success = TRUE;
-
- return(ptr + ut_strlen(string));
-}
-
-/*************************************************************************
-Scans an id. For the lexical definition of an 'id', see the code below.
-Strips backquotes or double quotes from around the id. */
-static
-const char*
-dict_scan_id(
-/*=========*/
- /* out: scanned to */
- const char* ptr, /* in: scanned to */
- mem_heap_t* heap, /* in: heap where to allocate the id
- (NULL=id will not be allocated, but it
- will point to string near ptr) */
- const char** id, /* out,own: the id; NULL if no id was
- scannable */
- ibool accept_also_dot)
- /* in: TRUE if also a dot can appear in a
- non-quoted id; in a quoted id it can appear
- always */
-{
- char quote = '\0';
- ulint len = 0;
- const char* s;
- char* d;
- ulint id_len;
- byte* b;
-
- *id = NULL;
-
- while (isspace(*ptr)) {
- ptr++;
- }
-
- if (*ptr == '\0') {
-
- return(ptr);
- }
-
- if (*ptr == '`' || *ptr == '"') {
- quote = *ptr++;
- }
-
- s = ptr;
-
- if (quote) {
- for (;;) {
- if (!*ptr) {
- /* Syntax error */
- return(ptr);
- }
- if (*ptr == quote) {
- ptr++;
- if (*ptr != quote) {
- break;
- }
- }
- ptr++;
- len++;
- }
- } else {
- while (!isspace(*ptr) && *ptr != '(' && *ptr != ')'
- && (accept_also_dot || *ptr != '.')
- && *ptr != ',' && *ptr != '\0') {
-
- ptr++;
- }
-
- len = ptr - s;
- }
-
- if (quote && heap) {
- *id = d = mem_heap_alloc(heap, len + 1);
- while (len--) {
- if ((*d++ = *s++) == quote) {
- s++;
- }
- }
- *d++ = 0;
- ut_a(*s == quote);
- ut_a(s + 1 == ptr);
- } else if (heap) {
- *id = mem_heap_strdupl(heap, s, len);
- } else {
- /* no heap given: id will point to source string */
- *id = s;
- }
-
- if (heap && !quote) {
- /* EMS MySQL Manager sometimes adds characters 0xA0 (in
- latin1, a 'non-breakable space') to the end of a table name.
- But isspace(0xA0) is not true, which confuses our foreign key
- parser. After the UTF-8 conversion in ha_innodb.cc, bytes 0xC2
- and 0xA0 are at the end of the string.
-
- TODO: we should lex the string using thd->charset_info, and
- my_isspace(). Only after that, convert id names to UTF-8. */
-
- b = (byte*)(*id);
- id_len = strlen((char*) b);
-
- if (id_len >= 3 && b[id_len - 1] == 0xA0
- && b[id_len - 2] == 0xC2) {
-
- /* Strip the 2 last bytes */
-
- b[id_len - 2] = '\0';
- }
- }
-
- return(ptr);
-}
-
-/*************************************************************************
-Tries to scan a column name. */
-static
-const char*
-dict_scan_col(
-/*==========*/
- /* out: scanned to */
- const char* ptr, /* in: scanned to */
- ibool* success,/* out: TRUE if success */
- dict_table_t* table, /* in: table in which the column is */
- dict_col_t** column, /* out: pointer to column if success */
- mem_heap_t* heap, /* in: heap where to allocate the name */
- const char** name) /* out,own: the column name; NULL if no name
- was scannable */
-{
-#ifndef UNIV_HOTBACKUP
- dict_col_t* col;
- ulint i;
-
- *success = FALSE;
-
- ptr = dict_scan_id(ptr, heap, name, TRUE);
-
- if (*name == NULL) {
-
- return(ptr); /* Syntax error */
- }
-
- if (table == NULL) {
- *success = TRUE;
- *column = NULL;
- } else {
- for (i = 0; i < dict_table_get_n_cols(table); i++) {
-
- col = dict_table_get_nth_col(table, i);
-
- if (0 == innobase_strcasecmp(col->name, *name)) {
- /* Found */
-
- *success = TRUE;
- *column = col;
- strcpy((char*) *name, col->name);
-
- break;
- }
- }
- }
-
- return(ptr);
-#else /* UNIV_HOTBACKUP */
- /* This function depends on MySQL code that is not included in
- InnoDB Hot Backup builds. Besides, this function should never
- be called in InnoDB Hot Backup. */
- ut_error;
-#endif /* UNIV_HOTBACKUP */
-}
-
-/*************************************************************************
-Scans a table name from an SQL string. */
-static
-const char*
-dict_scan_table_name(
-/*=================*/
- /* out: scanned to */
- const char* ptr, /* in: scanned to */
- dict_table_t** table, /* out: table object or NULL */
- const char* name, /* in: foreign key table name */
- ibool* success,/* out: TRUE if ok name found */
- mem_heap_t* heap, /* in: heap where to allocate the id */
- const char** ref_name)/* out,own: the table name;
- NULL if no name was scannable */
-{
-#ifndef UNIV_HOTBACKUP
- const char* database_name = NULL;
- ulint database_name_len = 0;
- const char* table_name = NULL;
- ulint table_name_len;
- const char* scan_name;
- char* ref;
-
- *success = FALSE;
- *table = NULL;
-
- ptr = dict_scan_id(ptr, heap, &scan_name, FALSE);
-
- if (scan_name == NULL) {
-
- return(ptr); /* Syntax error */
- }
-
- if (*ptr == '.') {
- /* We scanned the database name; scan also the table name */
-
- ptr++;
-
- database_name = scan_name;
- database_name_len = strlen(database_name);
-
- ptr = dict_scan_id(ptr, heap, &table_name, FALSE);
-
- if (table_name == NULL) {
-
- return(ptr); /* Syntax error */
- }
- } else {
- /* To be able to read table dumps made with InnoDB-4.0.17 or
- earlier, we must allow the dot separator between the database
- name and the table name also to appear within a quoted
- identifier! InnoDB used to print a constraint as:
- ... REFERENCES `databasename.tablename` ...
- starting from 4.0.18 it is
- ... REFERENCES `databasename`.`tablename` ... */
- const char* s;
-
- for (s = scan_name; *s; s++) {
- if (*s == '.') {
- database_name = scan_name;
- database_name_len = s - scan_name;
- scan_name = ++s;
- break;/* to do: multiple dots? */
- }
- }
-
- table_name = scan_name;
- }
-
- if (database_name == NULL) {
- /* Use the database name of the foreign key table */
-
- database_name = name;
- database_name_len = dict_get_db_name_len(name);
- }
-
- table_name_len = strlen(table_name);
-
- /* Copy database_name, '/', table_name, '\0' */
- ref = mem_heap_alloc(heap, database_name_len + table_name_len + 2);
- memcpy(ref, database_name, database_name_len);
- ref[database_name_len] = '/';
- memcpy(ref + database_name_len + 1, table_name, table_name_len + 1);
-#ifndef __WIN__
- if (srv_lower_case_table_names) {
-#endif /* !__WIN__ */
- /* The table name is always put to lower case on Windows. */
- innobase_casedn_str(ref);
-#ifndef __WIN__
- }
-#endif /* !__WIN__ */
-
- *success = TRUE;
- *ref_name = ref;
- *table = dict_table_get_low(ref);
-
- return(ptr);
-#else /* UNIV_HOTBACKUP */
- /* This function depends on MySQL code that is not included in
- InnoDB Hot Backup builds. Besides, this function should never
- be called in InnoDB Hot Backup. */
- ut_error;
-#endif /* UNIV_HOTBACKUP */
-}
-
-/*************************************************************************
-Skips one id. The id is allowed to contain also '.'. */
-static
-const char*
-dict_skip_word(
-/*===========*/
- /* out: scanned to */
- const char* ptr, /* in: scanned to */
- ibool* success)/* out: TRUE if success, FALSE if just spaces
- left in string or a syntax error */
-{
- const char* start;
-
- *success = FALSE;
-
- ptr = dict_scan_id(ptr, NULL, &start, TRUE);
-
- if (start) {
- *success = TRUE;
- }
-
- return(ptr);
-}
-
-/*************************************************************************
-Removes MySQL comments from an SQL string. A comment is either
-(a) '#' to the end of the line,
-(b) '--<space>' to the end of the line, or
-(c) '<slash><asterisk>' till the next '<asterisk><slash>' (like the familiar
-C comment syntax). */
-static
-char*
-dict_strip_comments(
-/*================*/
- /* out, own: SQL string stripped from
- comments; the caller must free this
- with mem_free()! */
- const char* sql_string) /* in: SQL string */
-{
- char* str;
- const char* sptr;
- char* ptr;
- /* unclosed quote character (0 if none) */
- char quote = 0;
-
- str = mem_alloc(strlen(sql_string) + 1);
-
- sptr = sql_string;
- ptr = str;
-
- for (;;) {
-scan_more:
- if (*sptr == '\0') {
- *ptr = '\0';
-
- ut_a(ptr <= str + strlen(sql_string));
-
- return(str);
- }
-
- if (*sptr == quote) {
- /* Closing quote character: do not look for
- starting quote or comments. */
- quote = 0;
- } else if (quote) {
- /* Within quotes: do not look for
- starting quotes or comments. */
- } else if (*sptr == '"' || *sptr == '`') {
- /* Starting quote: remember the quote character. */
- quote = *sptr;
- } else if (*sptr == '#'
- || (sptr[0] == '-' && sptr[1] == '-' &&
- sptr[2] == ' ')) {
- for (;;) {
- /* In Unix a newline is 0x0A while in Windows
- it is 0x0D followed by 0x0A */
-
- if (*sptr == (char)0x0A
- || *sptr == (char)0x0D
- || *sptr == '\0') {
-
- goto scan_more;
- }
-
- sptr++;
- }
- } else if (!quote && *sptr == '/' && *(sptr + 1) == '*') {
- for (;;) {
- if (*sptr == '*' && *(sptr + 1) == '/') {
-
- sptr += 2;
-
- goto scan_more;
- }
-
- if (*sptr == '\0') {
-
- goto scan_more;
- }
-
- sptr++;
- }
- }
-
- *ptr = *sptr;
-
- ptr++;
- sptr++;
- }
-}
-
-/*************************************************************************
-Finds the highest <number> for foreign key constraints of the table. Looks
-only at the >= 4.0.18-format id's, which are of the form
-databasename/tablename_ibfk_<number>. */
-static
-ulint
-dict_table_get_highest_foreign_id(
-/*==============================*/
- /* out: highest number, 0 if table has no new
- format foreign key constraints */
- dict_table_t* table) /* in: table in the dictionary memory cache */
-{
- dict_foreign_t* foreign;
- char* endp;
- ulint biggest_id = 0;
- ulint id;
- ulint len;
-
- ut_a(table);
-
- len = ut_strlen(table->name);
- foreign = UT_LIST_GET_FIRST(table->foreign_list);
-
- while (foreign) {
- if (ut_strlen(foreign->id) > ((sizeof dict_ibfk) - 1) + len
- && 0 == ut_memcmp(foreign->id, table->name, len)
- && 0 == ut_memcmp(foreign->id + len,
- dict_ibfk, (sizeof dict_ibfk) - 1)) {
- /* It is of the >= 4.0.18 format */
-
- id = strtoul(foreign->id + len + ((sizeof dict_ibfk) - 1),
- &endp, 10);
- if (*endp == '\0') {
- ut_a(id != biggest_id);
-
- if (id > biggest_id) {
- biggest_id = id;
- }
- }
- }
-
- foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
- }
-
- return(biggest_id);
-}
-
-/*************************************************************************
-Reports a simple foreign key create clause syntax error. */
-static
-void
-dict_foreign_report_syntax_err(
-/*===========================*/
- const char* name, /* in: table name */
- const char* start_of_latest_foreign,
- /* in: start of the foreign key clause
- in the SQL string */
- const char* ptr) /* in: place of the syntax error */
-{
- FILE* ef = dict_foreign_err_file;
-
- mutex_enter(&dict_foreign_err_mutex);
- dict_foreign_error_report_low(ef, name);
- fprintf(ef, "%s:\nSyntax error close to:\n%s\n",
- start_of_latest_foreign, ptr);
- mutex_exit(&dict_foreign_err_mutex);
-}
-
-/*************************************************************************
-Scans a table create SQL string and adds to the data dictionary the foreign
-key constraints declared in the string. This function should be called after
-the indexes for a table have been created. Each foreign key constraint must
-be accompanied with indexes in both participating tables. The indexes are
-allowed to contain more fields than mentioned in the constraint. */
-static
-ulint
-dict_create_foreign_constraints_low(
-/*================================*/
- /* out: error code or DB_SUCCESS */
- trx_t* trx, /* in: transaction */
- mem_heap_t* heap, /* in: memory heap */
- const char* sql_string,
- /* in: CREATE TABLE or ALTER TABLE statement
- where foreign keys are declared like:
- FOREIGN KEY (a, b) REFERENCES table2(c, d),
- table2 can be written also with the database
- name before it: test.table2; the default
- database is the database of parameter name */
- const char* name) /* in: table full name in the normalized form
- database_name/table_name */
-{
- dict_table_t* table;
- dict_table_t* referenced_table;
- dict_table_t* table_to_alter;
- ulint highest_id_so_far = 0;
- dict_index_t* index;
- dict_foreign_t* foreign;
- const char* ptr = sql_string;
- const char* start_of_latest_foreign = sql_string;
- FILE* ef = dict_foreign_err_file;
- const char* constraint_name;
- ibool success;
- ulint error;
- const char* ptr1;
- const char* ptr2;
- ulint i;
- ulint j;
- ibool is_on_delete;
- ulint n_on_deletes;
- ulint n_on_updates;
- dict_col_t* columns[500];
- const char* column_names[500];
- const char* referenced_table_name;
-
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(mutex_own(&(dict_sys->mutex)));
-#endif /* UNIV_SYNC_DEBUG */
-
- table = dict_table_get_low(name);
-
- if (table == NULL) {
- mutex_enter(&dict_foreign_err_mutex);
- dict_foreign_error_report_low(ef, name);
- fprintf(ef,
-"Cannot find the table in the internal data dictionary of InnoDB.\n"
-"Create table statement:\n%s\n", sql_string);
- mutex_exit(&dict_foreign_err_mutex);
-
- return(DB_ERROR);
- }
-
- /* First check if we are actually doing an ALTER TABLE, and in that
- case look for the table being altered */
-
- ptr = dict_accept(ptr, "ALTER", &success);
-
- if (!success) {
-
- goto loop;
- }
-
- ptr = dict_accept(ptr, "TABLE", &success);
-
- if (!success) {
-
- goto loop;
- }
-
- /* We are doing an ALTER TABLE: scan the table name we are altering */
-
- ptr = dict_scan_table_name(ptr, &table_to_alter, name,
- &success, heap, &referenced_table_name);
- if (!success) {
- fprintf(stderr,
-"InnoDB: Error: could not find the table being ALTERED in:\n%s\n", sql_string);
-
- return(DB_ERROR);
- }
-
- /* Starting from 4.0.18 and 4.1.2, we generate foreign key id's in the
- format databasename/tablename_ibfk_<number>, where <number> is local
- to the table; look for the highest <number> for table_to_alter, so
- that we can assign to new constraints higher numbers. */
-
- /* If we are altering a temporary table, the table name after ALTER
- TABLE does not correspond to the internal table name, and
- table_to_alter is NULL. TODO: should we fix this somehow? */
-
- if (table_to_alter == NULL) {
- highest_id_so_far = 0;
- } else {
- highest_id_so_far = dict_table_get_highest_foreign_id(
- table_to_alter);
- }
-
- /* Scan for foreign key declarations in a loop */
-loop:
- /* Scan either to "CONSTRAINT" or "FOREIGN", whichever is closer */
-
- ptr1 = dict_scan_to(ptr, "CONSTRAINT");
- ptr2 = dict_scan_to(ptr, "FOREIGN");
-
- constraint_name = NULL;
-
- if (ptr1 < ptr2) {
- /* The user may have specified a constraint name. Pick it so
- that we can store 'databasename/constraintname' as the id of
- of the constraint to system tables. */
- ptr = ptr1;
-
- ptr = dict_accept(ptr, "CONSTRAINT", &success);
-
- ut_a(success);
-
- if (!isspace(*ptr) && *ptr != '"' && *ptr != '`') {
- goto loop;
- }
-
- while (isspace(*ptr)) {
- ptr++;
- }
-
- /* read constraint name unless got "CONSTRAINT FOREIGN" */
- if (ptr != ptr2) {
- ptr = dict_scan_id(ptr, heap, &constraint_name, FALSE);
- }
- } else {
- ptr = ptr2;
- }
-
- if (*ptr == '\0') {
- /**********************************************************/
- /* The following call adds the foreign key constraints
- to the data dictionary system tables on disk */
-
- error = dict_create_add_foreigns_to_dictionary(
- highest_id_so_far, table, trx);
- return(error);
- }
-
- start_of_latest_foreign = ptr;
-
- ptr = dict_accept(ptr, "FOREIGN", &success);
-
- if (!success) {
- goto loop;
- }
-
- if (!isspace(*ptr)) {
- goto loop;
- }
-
- ptr = dict_accept(ptr, "KEY", &success);
-
- if (!success) {
- goto loop;
- }
-
- ptr = dict_accept(ptr, "(", &success);
-
- if (!success) {
- /* MySQL allows also an index id before the '('; we
- skip it */
- ptr = dict_skip_word(ptr, &success);
-
- if (!success) {
- dict_foreign_report_syntax_err(name,
- start_of_latest_foreign, ptr);
-
- return(DB_CANNOT_ADD_CONSTRAINT);
- }
-
- ptr = dict_accept(ptr, "(", &success);
-
- if (!success) {
- /* We do not flag a syntax error here because in an
- ALTER TABLE we may also have DROP FOREIGN KEY abc */
-
- goto loop;
- }
- }
-
- i = 0;
-
- /* Scan the columns in the first list */
-col_loop1:
- ut_a(i < (sizeof column_names) / sizeof *column_names);
- ptr = dict_scan_col(ptr, &success, table, columns + i,
- heap, column_names + i);
- if (!success) {
- mutex_enter(&dict_foreign_err_mutex);
- dict_foreign_error_report_low(ef, name);
- fprintf(ef, "%s:\nCannot resolve column name close to:\n%s\n",
- start_of_latest_foreign, ptr);
- mutex_exit(&dict_foreign_err_mutex);
-
- return(DB_CANNOT_ADD_CONSTRAINT);
- }
-
- i++;
-
- ptr = dict_accept(ptr, ",", &success);
-
- if (success) {
- goto col_loop1;
- }
-
- ptr = dict_accept(ptr, ")", &success);
-
- if (!success) {
- dict_foreign_report_syntax_err(name, start_of_latest_foreign,
- ptr);
- return(DB_CANNOT_ADD_CONSTRAINT);
- }
-
- /* Try to find an index which contains the columns
- as the first fields and in the right order */
-
- index = dict_foreign_find_index(table, column_names, i, NULL);
-
- if (!index) {
- mutex_enter(&dict_foreign_err_mutex);
- dict_foreign_error_report_low(ef, name);
- fputs("There is no index in table ", ef);
- ut_print_name(ef, NULL, name);
- fprintf(ef, " where the columns appear\n"
-"as the first columns. Constraint:\n%s\n"
-"See http://dev.mysql.com/doc/mysql/en/InnoDB_foreign_key_constraints.html\n"
-"for correct foreign key definition.\n",
- start_of_latest_foreign);
- mutex_exit(&dict_foreign_err_mutex);
-
- return(DB_CANNOT_ADD_CONSTRAINT);
- }
- ptr = dict_accept(ptr, "REFERENCES", &success);
-
- if (!success || !isspace(*ptr)) {
- dict_foreign_report_syntax_err(name, start_of_latest_foreign,
- ptr);
- return(DB_CANNOT_ADD_CONSTRAINT);
- }
-
- /* Let us create a constraint struct */
-
- foreign = dict_mem_foreign_create();
-
- if (constraint_name) {
- ulint db_len;
-
- /* Catenate 'databasename/' to the constraint name specified
- by the user: we conceive the constraint as belonging to the
- same MySQL 'database' as the table itself. We store the name
- to foreign->id. */
-
- db_len = dict_get_db_name_len(table->name);
-
- foreign->id = mem_heap_alloc(foreign->heap,
- db_len + strlen(constraint_name) + 2);
-
- ut_memcpy(foreign->id, table->name, db_len);
- foreign->id[db_len] = '/';
- strcpy(foreign->id + db_len + 1, constraint_name);
- }
-
- foreign->foreign_table = table;
- foreign->foreign_table_name = mem_heap_strdup(foreign->heap,
- table->name);
- foreign->foreign_index = index;
- foreign->n_fields = i;
- foreign->foreign_col_names = mem_heap_alloc(foreign->heap,
- i * sizeof(void*));
- for (i = 0; i < foreign->n_fields; i++) {
- foreign->foreign_col_names[i] =
- mem_heap_strdup(foreign->heap, columns[i]->name);
- }
-
- ptr = dict_scan_table_name(ptr, &referenced_table, name,
- &success, heap, &referenced_table_name);
-
- /* Note that referenced_table can be NULL if the user has suppressed
- checking of foreign key constraints! */
-
- if (!success || (!referenced_table && trx->check_foreigns)) {
- dict_foreign_free(foreign);
-
- mutex_enter(&dict_foreign_err_mutex);
- dict_foreign_error_report_low(ef, name);
- fprintf(ef, "%s:\nCannot resolve table name close to:\n"
- "%s\n",
- start_of_latest_foreign, ptr);
- mutex_exit(&dict_foreign_err_mutex);
-
- return(DB_CANNOT_ADD_CONSTRAINT);
- }
-
- ptr = dict_accept(ptr, "(", &success);
-
- if (!success) {
- dict_foreign_free(foreign);
- dict_foreign_report_syntax_err(name, start_of_latest_foreign,
- ptr);
- return(DB_CANNOT_ADD_CONSTRAINT);
- }
-
- /* Scan the columns in the second list */
- i = 0;
-
-col_loop2:
- ptr = dict_scan_col(ptr, &success, referenced_table, columns + i,
- heap, column_names + i);
- i++;
-
- if (!success) {
- dict_foreign_free(foreign);
-
- mutex_enter(&dict_foreign_err_mutex);
- dict_foreign_error_report_low(ef, name);
- fprintf(ef, "%s:\nCannot resolve column name close to:\n"
- "%s\n",
- start_of_latest_foreign, ptr);
- mutex_exit(&dict_foreign_err_mutex);
-
- return(DB_CANNOT_ADD_CONSTRAINT);
- }
-
- ptr = dict_accept(ptr, ",", &success);
-
- if (success) {
- goto col_loop2;
- }
-
- ptr = dict_accept(ptr, ")", &success);
-
- if (!success || foreign->n_fields != i) {
- dict_foreign_free(foreign);
-
- dict_foreign_report_syntax_err(name, start_of_latest_foreign,
- ptr);
- return(DB_CANNOT_ADD_CONSTRAINT);
- }
-
- n_on_deletes = 0;
- n_on_updates = 0;
-
-scan_on_conditions:
- /* Loop here as long as we can find ON ... conditions */
-
- ptr = dict_accept(ptr, "ON", &success);
-
- if (!success) {
-
- goto try_find_index;
- }
-
- ptr = dict_accept(ptr, "DELETE", &success);
-
- if (!success) {
- ptr = dict_accept(ptr, "UPDATE", &success);
-
- if (!success) {
- dict_foreign_free(foreign);
-
- dict_foreign_report_syntax_err(name,
- start_of_latest_foreign, ptr);
- return(DB_CANNOT_ADD_CONSTRAINT);
- }
-
- is_on_delete = FALSE;
- n_on_updates++;
- } else {
- is_on_delete = TRUE;
- n_on_deletes++;
- }
-
- ptr = dict_accept(ptr, "RESTRICT", &success);
-
- if (success) {
- goto scan_on_conditions;
- }
-
- ptr = dict_accept(ptr, "CASCADE", &success);
-
- if (success) {
- if (is_on_delete) {
- foreign->type |= DICT_FOREIGN_ON_DELETE_CASCADE;
- } else {
- foreign->type |= DICT_FOREIGN_ON_UPDATE_CASCADE;
- }
-
- goto scan_on_conditions;
- }
-
- ptr = dict_accept(ptr, "NO", &success);
-
- if (success) {
- ptr = dict_accept(ptr, "ACTION", &success);
-
- if (!success) {
- dict_foreign_free(foreign);
- dict_foreign_report_syntax_err(name,
- start_of_latest_foreign, ptr);
-
- return(DB_CANNOT_ADD_CONSTRAINT);
- }
-
- if (is_on_delete) {
- foreign->type |= DICT_FOREIGN_ON_DELETE_NO_ACTION;
- } else {
- foreign->type |= DICT_FOREIGN_ON_UPDATE_NO_ACTION;
- }
-
- goto scan_on_conditions;
- }
-
- ptr = dict_accept(ptr, "SET", &success);
-
- if (!success) {
- dict_foreign_free(foreign);
- dict_foreign_report_syntax_err(name, start_of_latest_foreign,
- ptr);
- return(DB_CANNOT_ADD_CONSTRAINT);
- }
-
- ptr = dict_accept(ptr, "NULL", &success);
-
- if (!success) {
- dict_foreign_free(foreign);
- dict_foreign_report_syntax_err(name, start_of_latest_foreign,
- ptr);
- return(DB_CANNOT_ADD_CONSTRAINT);
- }
-
- for (j = 0; j < foreign->n_fields; j++) {
- if ((dict_index_get_nth_type(
- foreign->foreign_index, j)->prtype)
- & DATA_NOT_NULL) {
-
- /* It is not sensible to define SET NULL
- if the column is not allowed to be NULL! */
-
- dict_foreign_free(foreign);
-
- mutex_enter(&dict_foreign_err_mutex);
- dict_foreign_error_report_low(ef, name);
- fprintf(ef, "%s:\n"
- "You have defined a SET NULL condition though some of the\n"
- "columns are defined as NOT NULL.\n", start_of_latest_foreign);
- mutex_exit(&dict_foreign_err_mutex);
-
- return(DB_CANNOT_ADD_CONSTRAINT);
- }
- }
-
- if (is_on_delete) {
- foreign->type |= DICT_FOREIGN_ON_DELETE_SET_NULL;
- } else {
- foreign->type |= DICT_FOREIGN_ON_UPDATE_SET_NULL;
- }
-
- goto scan_on_conditions;
-
-try_find_index:
- if (n_on_deletes > 1 || n_on_updates > 1) {
- /* It is an error to define more than 1 action */
-
- dict_foreign_free(foreign);
-
- mutex_enter(&dict_foreign_err_mutex);
- dict_foreign_error_report_low(ef, name);
- fprintf(ef, "%s:\n"
-"You have twice an ON DELETE clause or twice an ON UPDATE clause.\n",
- start_of_latest_foreign);
- mutex_exit(&dict_foreign_err_mutex);
-
- return(DB_CANNOT_ADD_CONSTRAINT);
- }
-
- /* Try to find an index which contains the columns as the first fields
- and in the right order, and the types are the same as in
- foreign->foreign_index */
-
- if (referenced_table) {
- index = dict_foreign_find_index(referenced_table,
- column_names, i,
- foreign->foreign_index);
- if (!index) {
- dict_foreign_free(foreign);
- mutex_enter(&dict_foreign_err_mutex);
- dict_foreign_error_report_low(ef, name);
- fprintf(ef, "%s:\n"
-"Cannot find an index in the referenced table where the\n"
-"referenced columns appear as the first columns, or column types\n"
-"in the table and the referenced table do not match for constraint.\n"
-"See http://dev.mysql.com/doc/mysql/en/InnoDB_foreign_key_constraints.html\n"
-"for correct foreign key definition.\n",
- start_of_latest_foreign);
- mutex_exit(&dict_foreign_err_mutex);
-
- return(DB_CANNOT_ADD_CONSTRAINT);
- }
- } else {
- ut_a(trx->check_foreigns == FALSE);
- index = NULL;
- }
-
- foreign->referenced_index = index;
- foreign->referenced_table = referenced_table;
-
- foreign->referenced_table_name = mem_heap_strdup(foreign->heap,
- referenced_table_name);
-
- foreign->referenced_col_names = mem_heap_alloc(foreign->heap,
- i * sizeof(void*));
- for (i = 0; i < foreign->n_fields; i++) {
- foreign->referenced_col_names[i]
- = mem_heap_strdup(foreign->heap, column_names[i]);
- }
-
- /* We found an ok constraint definition: add to the lists */
-
- UT_LIST_ADD_LAST(foreign_list, table->foreign_list, foreign);
-
- if (referenced_table) {
- UT_LIST_ADD_LAST(referenced_list,
- referenced_table->referenced_list,
- foreign);
- }
-
- goto loop;
-}
-
-/*************************************************************************
-Scans a table create SQL string and adds to the data dictionary the foreign
-key constraints declared in the string. This function should be called after
-the indexes for a table have been created. Each foreign key constraint must
-be accompanied with indexes in both participating tables. The indexes are
-allowed to contain more fields than mentioned in the constraint. */
-
-ulint
-dict_create_foreign_constraints(
-/*============================*/
- /* out: error code or DB_SUCCESS */
- trx_t* trx, /* in: transaction */
- const char* sql_string, /* in: table create statement where
- foreign keys are declared like:
- FOREIGN KEY (a, b) REFERENCES
- table2(c, d), table2 can be written
- also with the database
- name before it: test.table2; the
- default database id the database of
- parameter name */
- const char* name) /* in: table full name in the
- normalized form
- database_name/table_name */
-{
- char* str;
- ulint err;
- mem_heap_t* heap;
-
- str = dict_strip_comments(sql_string);
- heap = mem_heap_create(10000);
-
- err = dict_create_foreign_constraints_low(trx, heap, str, name);
-
- mem_heap_free(heap);
- mem_free(str);
-
- return(err);
-}
-
-/**************************************************************************
-Parses the CONSTRAINT id's to be dropped in an ALTER TABLE statement. */
-
-ulint
-dict_foreign_parse_drop_constraints(
-/*================================*/
- /* out: DB_SUCCESS or
- DB_CANNOT_DROP_CONSTRAINT if
- syntax error or the constraint
- id does not match */
- mem_heap_t* heap, /* in: heap from which we can
- allocate memory */
- trx_t* trx, /* in: transaction */
- dict_table_t* table, /* in: table */
- ulint* n, /* out: number of constraints
- to drop */
- const char*** constraints_to_drop) /* out: id's of the
- constraints to drop */
-{
- dict_foreign_t* foreign;
- ibool success;
- char* str;
- const char* ptr;
- const char* id;
- FILE* ef = dict_foreign_err_file;
-
- *n = 0;
-
- *constraints_to_drop = mem_heap_alloc(heap, 1000 * sizeof(char*));
-
- str = dict_strip_comments(*(trx->mysql_query_str));
- ptr = str;
-
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(mutex_own(&(dict_sys->mutex)));
-#endif /* UNIV_SYNC_DEBUG */
-loop:
- ptr = dict_scan_to(ptr, "DROP");
-
- if (*ptr == '\0') {
- mem_free(str);
-
- return(DB_SUCCESS);
- }
-
- ptr = dict_accept(ptr, "DROP", &success);
-
- if (!isspace(*ptr)) {
-
- goto loop;
- }
-
- ptr = dict_accept(ptr, "FOREIGN", &success);
-
- if (!success) {
-
- goto loop;
- }
-
- ptr = dict_accept(ptr, "KEY", &success);
-
- if (!success) {
-
- goto syntax_error;
- }
-
- ptr = dict_scan_id(ptr, heap, &id, TRUE);
-
- if (id == NULL) {
-
- goto syntax_error;
- }
-
- ut_a(*n < 1000);
- (*constraints_to_drop)[*n] = id;
- (*n)++;
-
- /* Look for the given constraint id */
-
- foreign = UT_LIST_GET_FIRST(table->foreign_list);
-
- while (foreign != NULL) {
- if (0 == strcmp(foreign->id, id)
- || (strchr(foreign->id, '/')
- && 0 == strcmp(id,
- dict_remove_db_name(foreign->id)))) {
- /* Found */
- break;
- }
-
- foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
- }
-
- if (foreign == NULL) {
- mutex_enter(&dict_foreign_err_mutex);
- rewind(ef);
- ut_print_timestamp(ef);
- fputs(
- " Error in dropping of a foreign key constraint of table ", ef);
- ut_print_name(ef, NULL, table->name);
- fputs(",\n"
- "in SQL command\n", ef);
- fputs(str, ef);
- fputs("\nCannot find a constraint with the given id ", ef);
- ut_print_name(ef, NULL, id);
- fputs(".\n", ef);
- mutex_exit(&dict_foreign_err_mutex);
-
- mem_free(str);
-
- return(DB_CANNOT_DROP_CONSTRAINT);
- }
-
- goto loop;
-
-syntax_error:
- mutex_enter(&dict_foreign_err_mutex);
- rewind(ef);
- ut_print_timestamp(ef);
- fputs(
- " Syntax error in dropping of a foreign key constraint of table ", ef);
- ut_print_name(ef, NULL, table->name);
- fprintf(ef, ",\n"
- "close to:\n%s\n in SQL command\n%s\n", ptr, str);
- mutex_exit(&dict_foreign_err_mutex);
-
- mem_free(str);
-
- return(DB_CANNOT_DROP_CONSTRAINT);
-}
-
-/*==================== END OF FOREIGN KEY PROCESSING ====================*/
-
-/**************************************************************************
-Returns an index object if it is found in the dictionary cache. */
-
-dict_index_t*
-dict_index_get_if_in_cache(
-/*=======================*/
- /* out: index, NULL if not found */
- dulint index_id) /* in: index id */
-{
- dict_table_t* table;
- dict_index_t* index;
-
- if (dict_sys == NULL) {
- return(NULL);
- }
-
- mutex_enter(&(dict_sys->mutex));
-
- table = UT_LIST_GET_FIRST(dict_sys->table_LRU);
-
- while (table) {
- index = UT_LIST_GET_FIRST(table->indexes);
-
- while (index) {
- if (0 == ut_dulint_cmp(index->id, index_id)) {
-
- goto found;
- }
-
- index = UT_LIST_GET_NEXT(indexes, index);
- }
-
- table = UT_LIST_GET_NEXT(table_LRU, table);
- }
-
- index = NULL;
-found:
- mutex_exit(&(dict_sys->mutex));
-
- return(index);
-}
-
-/**************************************************************************
-Creates an index tree struct. */
-
-dict_tree_t*
-dict_tree_create(
-/*=============*/
- /* out, own: created tree */
- dict_index_t* index, /* in: the index for which to create: in the
- case of a mixed tree, this should be the
- index of the cluster object */
- ulint page_no)/* in: root page number of the index */
-{
- dict_tree_t* tree;
-
- tree = mem_alloc(sizeof(dict_tree_t));
-
- /* Inherit info from the index */
-
- tree->type = index->type;
- tree->space = index->space;
- tree->page = page_no;
-
- tree->id = index->id;
-
- UT_LIST_INIT(tree->tree_indexes);
-
- tree->magic_n = DICT_TREE_MAGIC_N;
-
- rw_lock_create(&(tree->lock));
-
- rw_lock_set_level(&(tree->lock), SYNC_INDEX_TREE);
-
- return(tree);
-}
-
-/**************************************************************************
-Frees an index tree struct. */
-
-void
-dict_tree_free(
-/*===========*/
- dict_tree_t* tree) /* in, own: index tree */
-{
- ut_a(tree);
- ut_ad(tree->magic_n == DICT_TREE_MAGIC_N);
-
- rw_lock_free(&(tree->lock));
- mem_free(tree);
-}
-
-/**************************************************************************
-In an index tree, finds the index corresponding to a record in the tree. */
-UNIV_INLINE
-dict_index_t*
-dict_tree_find_index_low(
-/*=====================*/
- /* out: index */
- dict_tree_t* tree, /* in: index tree */
- rec_t* rec) /* in: record for which to find correct
- index */
-{
- dict_index_t* index;
- dict_table_t* table;
- dulint mix_id;
- ulint len;
-
- index = UT_LIST_GET_FIRST(tree->tree_indexes);
- ut_ad(index);
- table = index->table;
-
- if ((index->type & DICT_CLUSTERED)
- && (table->type != DICT_TABLE_ORDINARY)) {
-
- /* Get the mix id of the record */
- ut_a(!table->comp);
-
- mix_id = mach_dulint_read_compressed(
- rec_get_nth_field_old(rec, table->mix_len, &len));
-
- while (ut_dulint_cmp(table->mix_id, mix_id) != 0) {
-
- index = UT_LIST_GET_NEXT(tree_indexes, index);
- table = index->table;
- ut_ad(index);
- }
- }
-
- return(index);
-}
-
-/**************************************************************************
-In an index tree, finds the index corresponding to a record in the tree. */
-
-dict_index_t*
-dict_tree_find_index(
-/*=================*/
- /* out: index */
- dict_tree_t* tree, /* in: index tree */
- rec_t* rec) /* in: record for which to find correct
- index */
-{
- dict_index_t* index;
-
- index = dict_tree_find_index_low(tree, rec);
-
- return(index);
-}
-
-/**************************************************************************
-In an index tree, finds the index corresponding to a dtuple which is used
-in a search to a tree. */
-
-dict_index_t*
-dict_tree_find_index_for_tuple(
-/*===========================*/
- /* out: index; NULL if the tuple does not
- contain the mix id field in a mixed tree */
- dict_tree_t* tree, /* in: index tree */
- dtuple_t* tuple) /* in: tuple for which to find index */
-{
- dict_index_t* index;
- dict_table_t* table;
- dulint mix_id;
-
- ut_ad(dtuple_check_typed(tuple));
-
- if (UT_LIST_GET_LEN(tree->tree_indexes) == 1) {
-
- return(UT_LIST_GET_FIRST(tree->tree_indexes));
- }
-
- index = UT_LIST_GET_FIRST(tree->tree_indexes);
- ut_ad(index);
- table = index->table;
-
- if (dtuple_get_n_fields(tuple) <= table->mix_len) {
-
- return(NULL);
- }
-
- /* Get the mix id of the record */
-
- mix_id = mach_dulint_read_compressed(
- dfield_get_data(
- dtuple_get_nth_field(tuple, table->mix_len)));
-
- while (ut_dulint_cmp(table->mix_id, mix_id) != 0) {
-
- index = UT_LIST_GET_NEXT(tree_indexes, index);
- table = index->table;
- ut_ad(index);
- }
-
- return(index);
-}
-
-/***********************************************************************
-Checks if a table which is a mixed cluster member owns a record. */
-
-ibool
-dict_is_mixed_table_rec(
-/*====================*/
- /* out: TRUE if the record belongs to this
- table */
- dict_table_t* table, /* in: table in a mixed cluster */
- rec_t* rec) /* in: user record in the clustered index */
-{
- byte* mix_id_field;
- ulint len;
-
- ut_ad(!table->comp);
-
- mix_id_field = rec_get_nth_field_old(rec,
- table->mix_len, &len);
-
- return(len == table->mix_id_len
- && !ut_memcmp(table->mix_id_buf, mix_id_field, len));
-}
-
-/**************************************************************************
-Checks that a tuple has n_fields_cmp value in a sensible range, so that
-no comparison can occur with the page number field in a node pointer. */
-
-ibool
-dict_tree_check_search_tuple(
-/*=========================*/
- /* out: TRUE if ok */
- dict_tree_t* tree, /* in: index tree */
- dtuple_t* tuple) /* in: tuple used in a search */
-{
- dict_index_t* index;
-
- index = dict_tree_find_index_for_tuple(tree, tuple);
-
- if (index == NULL) {
-
- return(TRUE);
- }
-
- ut_a(dtuple_get_n_fields_cmp(tuple)
- <= dict_index_get_n_unique_in_tree(index));
- return(TRUE);
-}
-
-/**************************************************************************
-Builds a node pointer out of a physical record and a page number. */
-
-dtuple_t*
-dict_tree_build_node_ptr(
-/*=====================*/
- /* out, own: node pointer */
- dict_tree_t* tree, /* in: index tree */
- rec_t* rec, /* in: record for which to build node
- pointer */
- ulint page_no,/* in: page number to put in node pointer */
- mem_heap_t* heap, /* in: memory heap where pointer created */
- ulint level) /* in: level of rec in tree: 0 means leaf
- level */
-{
- dtuple_t* tuple;
- dict_index_t* ind;
- dfield_t* field;
- byte* buf;
- ulint n_unique;
-
- ind = dict_tree_find_index_low(tree, rec);
-
- if (tree->type & DICT_UNIVERSAL) {
- /* In a universal index tree, we take the whole record as
- the node pointer if the reord is on the leaf level,
- on non-leaf levels we remove the last field, which
- contains the page number of the child page */
-
- ut_a(!ind->table->comp);
- n_unique = rec_get_n_fields_old(rec);
-
- if (level > 0) {
- ut_a(n_unique > 1);
- n_unique--;
- }
- } else {
- n_unique = dict_index_get_n_unique_in_tree(ind);
- }
-
- tuple = dtuple_create(heap, n_unique + 1);
-
- /* When searching in the tree for the node pointer, we must not do
- comparison on the last field, the page number field, as on upper
- levels in the tree there may be identical node pointers with a
- different page number; therefore, we set the n_fields_cmp to one
- less: */
-
- dtuple_set_n_fields_cmp(tuple, n_unique);
-
- dict_index_copy_types(tuple, ind, n_unique);
-
- buf = mem_heap_alloc(heap, 4);
-
- mach_write_to_4(buf, page_no);
-
- field = dtuple_get_nth_field(tuple, n_unique);
- dfield_set_data(field, buf, 4);
-
- dtype_set(dfield_get_type(field), DATA_SYS_CHILD, DATA_NOT_NULL, 4, 0);
-
- rec_copy_prefix_to_dtuple(tuple, rec, ind, n_unique, heap);
- dtuple_set_info_bits(tuple, dtuple_get_info_bits(tuple) |
- REC_STATUS_NODE_PTR);
-
- ut_ad(dtuple_check_typed(tuple));
-
- return(tuple);
-}
-
-/**************************************************************************
-Copies an initial segment of a physical record, long enough to specify an
-index entry uniquely. */
-
-rec_t*
-dict_tree_copy_rec_order_prefix(
-/*============================*/
- /* out: pointer to the prefix record */
- dict_tree_t* tree, /* in: index tree */
- rec_t* rec, /* in: record for which to copy prefix */
- ulint* n_fields,/* out: number of fields copied */
- byte** buf, /* in/out: memory buffer for the copied prefix,
- or NULL */
- ulint* buf_size)/* in/out: buffer size */
-{
- dict_index_t* index;
- ulint n;
-
- index = dict_tree_find_index_low(tree, rec);
-
- if (tree->type & DICT_UNIVERSAL) {
- ut_a(!index->table->comp);
- n = rec_get_n_fields_old(rec);
- } else {
- n = dict_index_get_n_unique_in_tree(index);
- }
-
- *n_fields = n;
- return(rec_copy_prefix_to_buf(rec, index, n, buf, buf_size));
-}
-
-/**************************************************************************
-Builds a typed data tuple out of a physical record. */
-
-dtuple_t*
-dict_tree_build_data_tuple(
-/*=======================*/
- /* out, own: data tuple */
- dict_tree_t* tree, /* in: index tree */
- rec_t* rec, /* in: record for which to build data tuple */
- ulint n_fields,/* in: number of data fields */
- mem_heap_t* heap) /* in: memory heap where tuple created */
-{
- dtuple_t* tuple;
- dict_index_t* ind;
-
- ind = dict_tree_find_index_low(tree, rec);
-
- ut_ad(ind->table->comp || n_fields <= rec_get_n_fields_old(rec));
-
- tuple = dtuple_create(heap, n_fields);
-
- dict_index_copy_types(tuple, ind, n_fields);
-
- rec_copy_prefix_to_dtuple(tuple, rec, ind, n_fields, heap);
-
- ut_ad(dtuple_check_typed(tuple));
-
- return(tuple);
-}
-
-/*************************************************************************
-Calculates the minimum record length in an index. */
-
-ulint
-dict_index_calc_min_rec_len(
-/*========================*/
- dict_index_t* index) /* in: index */
-{
- ulint sum = 0;
- ulint i;
-
- if (index->table->comp) {
- ulint nullable = 0;
- sum = REC_N_NEW_EXTRA_BYTES;
- for (i = 0; i < dict_index_get_n_fields(index); i++) {
- dtype_t*t = dict_index_get_nth_type(index, i);
- ulint size = dtype_get_fixed_size(t);
- sum += size;
- if (!size) {
- size = dtype_get_len(t);
- sum += size < 128 ? 1 : 2;
- }
- if (!(dtype_get_prtype(t) & DATA_NOT_NULL))
- nullable++;
- }
-
- /* round the NULL flags up to full bytes */
- sum += (nullable + 7) / 8;
-
- return(sum);
- }
-
- for (i = 0; i < dict_index_get_n_fields(index); i++) {
- sum += dtype_get_fixed_size(dict_index_get_nth_type(index, i));
- }
-
- if (sum > 127) {
- sum += 2 * dict_index_get_n_fields(index);
- } else {
- sum += dict_index_get_n_fields(index);
- }
-
- sum += REC_N_OLD_EXTRA_BYTES;
-
- return(sum);
-}
-
-/*************************************************************************
-Calculates new estimates for table and index statistics. The statistics
-are used in query optimization. */
-
-void
-dict_update_statistics_low(
-/*=======================*/
- dict_table_t* table, /* in: table */
- ibool has_dict_mutex __attribute__((unused)))
- /* in: TRUE if the caller has the
- dictionary mutex */
-{
- dict_index_t* index;
- ulint size;
- ulint sum_of_index_sizes = 0;
-
- if (table->ibd_file_missing) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: cannot calculate statistics for table %s\n"
-"InnoDB: because the .ibd file is missing. For help, please refer to\n"
-"InnoDB: "
-"http://dev.mysql.com/doc/mysql/en/InnoDB_troubleshooting_datadict.html\n",
- table->name);
-
- return;
- }
-
- /* If we have set a high innodb_force_recovery level, do not calculate
- statistics, as a badly corrupted index can cause a crash in it. */
-
- if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
-
- return;
- }
-
- /* Find out the sizes of the indexes and how many different values
- for the key they approximately have */
-
- index = dict_table_get_first_index(table);
-
- if (index == NULL) {
- /* Table definition is corrupt */
-
- return;
- }
-
- while (index) {
- size = btr_get_size(index, BTR_TOTAL_SIZE);
-
- index->stat_index_size = size;
-
- sum_of_index_sizes += size;
-
- size = btr_get_size(index, BTR_N_LEAF_PAGES);
-
- if (size == 0) {
- /* The root node of the tree is a leaf */
- size = 1;
- }
-
- index->stat_n_leaf_pages = size;
-
- btr_estimate_number_of_different_key_vals(index);
-
- index = dict_table_get_next_index(index);
- }
-
- index = dict_table_get_first_index(table);
-
- table->stat_n_rows = index->stat_n_diff_key_vals[
- dict_index_get_n_unique(index)];
-
- table->stat_clustered_index_size = index->stat_index_size;
-
- table->stat_sum_of_other_index_sizes = sum_of_index_sizes
- - index->stat_index_size;
-
- table->stat_initialized = TRUE;
-
- table->stat_modified_counter = 0;
-}
-
-/*************************************************************************
-Calculates new estimates for table and index statistics. The statistics
-are used in query optimization. */
-
-void
-dict_update_statistics(
-/*===================*/
- dict_table_t* table) /* in: table */
-{
- dict_update_statistics_low(table, FALSE);
-}
-
-/**************************************************************************
-Prints info of a foreign key constraint. */
-static
-void
-dict_foreign_print_low(
-/*===================*/
- dict_foreign_t* foreign) /* in: foreign key constraint */
-{
- ulint i;
-
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(mutex_own(&(dict_sys->mutex)));
-#endif /* UNIV_SYNC_DEBUG */
-
- fprintf(stderr, " FOREIGN KEY CONSTRAINT %s: %s (",
- foreign->id, foreign->foreign_table_name);
-
- for (i = 0; i < foreign->n_fields; i++) {
- fprintf(stderr, " %s", foreign->foreign_col_names[i]);
- }
-
- fprintf(stderr, " )\n"
- " REFERENCES %s (",
- foreign->referenced_table_name);
-
- for (i = 0; i < foreign->n_fields; i++) {
- fprintf(stderr, " %s", foreign->referenced_col_names[i]);
- }
-
- fputs(" )\n", stderr);
-}
-
-/**************************************************************************
-Prints a table data. */
-
-void
-dict_table_print(
-/*=============*/
- dict_table_t* table) /* in: table */
-{
- mutex_enter(&(dict_sys->mutex));
- dict_table_print_low(table);
- mutex_exit(&(dict_sys->mutex));
-}
-
-/**************************************************************************
-Prints a table data when we know the table name. */
-
-void
-dict_table_print_by_name(
-/*=====================*/
- const char* name)
-{
- dict_table_t* table;
-
- mutex_enter(&(dict_sys->mutex));
-
- table = dict_table_get_low(name);
-
- ut_a(table);
-
- dict_table_print_low(table);
- mutex_exit(&(dict_sys->mutex));
-}
-
-/**************************************************************************
-Prints a table data. */
-
-void
-dict_table_print_low(
-/*=================*/
- dict_table_t* table) /* in: table */
-{
- dict_index_t* index;
- dict_foreign_t* foreign;
- ulint i;
-
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(mutex_own(&(dict_sys->mutex)));
-#endif /* UNIV_SYNC_DEBUG */
-
- dict_update_statistics_low(table, TRUE);
-
- fprintf(stderr,
-"--------------------------------------\n"
-"TABLE: name %s, id %lu %lu, columns %lu, indexes %lu, appr.rows %lu\n"
-" COLUMNS: ",
- table->name,
- (ulong) ut_dulint_get_high(table->id),
- (ulong) ut_dulint_get_low(table->id),
- (ulong) table->n_cols,
- (ulong) UT_LIST_GET_LEN(table->indexes),
- (ulong) table->stat_n_rows);
-
- for (i = 0; i < table->n_cols - 1; i++) {
- dict_col_print_low(dict_table_get_nth_col(table, i));
- fputs("; ", stderr);
- }
-
- putc('\n', stderr);
-
- index = UT_LIST_GET_FIRST(table->indexes);
-
- while (index != NULL) {
- dict_index_print_low(index);
- index = UT_LIST_GET_NEXT(indexes, index);
- }
-
- foreign = UT_LIST_GET_FIRST(table->foreign_list);
-
- while (foreign != NULL) {
- dict_foreign_print_low(foreign);
- foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
- }
-
- foreign = UT_LIST_GET_FIRST(table->referenced_list);
-
- while (foreign != NULL) {
- dict_foreign_print_low(foreign);
- foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
- }
-}
-
-/**************************************************************************
-Prints a column data. */
-static
-void
-dict_col_print_low(
-/*===============*/
- dict_col_t* col) /* in: column */
-{
- dtype_t* type;
-
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(mutex_own(&(dict_sys->mutex)));
-#endif /* UNIV_SYNC_DEBUG */
-
- type = dict_col_get_type(col);
- fprintf(stderr, "%s: ", col->name);
-
- dtype_print(type);
-}
-
-/**************************************************************************
-Prints an index data. */
-static
-void
-dict_index_print_low(
-/*=================*/
- dict_index_t* index) /* in: index */
-{
- dict_tree_t* tree;
- ib_longlong n_vals;
- ulint i;
-
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(mutex_own(&(dict_sys->mutex)));
-#endif /* UNIV_SYNC_DEBUG */
-
- tree = index->tree;
-
- if (index->n_user_defined_cols > 0) {
- n_vals = index->stat_n_diff_key_vals[
- index->n_user_defined_cols];
- } else {
- n_vals = index->stat_n_diff_key_vals[1];
- }
-
- fprintf(stderr,
- " INDEX: name %s, id %lu %lu, fields %lu/%lu, type %lu\n"
- " root page %lu, appr.key vals %lu,"
- " leaf pages %lu, size pages %lu\n"
- " FIELDS: ",
- index->name,
- (ulong) ut_dulint_get_high(tree->id),
- (ulong) ut_dulint_get_low(tree->id),
- (ulong) index->n_user_defined_cols,
- (ulong) index->n_fields, (ulong) index->type,
- (ulong) tree->page,
- (ulong) n_vals,
- (ulong) index->stat_n_leaf_pages,
- (ulong) index->stat_index_size);
-
- for (i = 0; i < index->n_fields; i++) {
- dict_field_print_low(dict_index_get_nth_field(index, i));
- }
-
- putc('\n', stderr);
-
-/* btr_print_size(tree); */
-
-/* btr_print_tree(tree, 7); */
-}
-
-/**************************************************************************
-Prints a field data. */
-static
-void
-dict_field_print_low(
-/*=================*/
- dict_field_t* field) /* in: field */
-{
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(mutex_own(&(dict_sys->mutex)));
-#endif /* UNIV_SYNC_DEBUG */
- fprintf(stderr, " %s", field->name);
-
- if (field->prefix_len != 0) {
- fprintf(stderr, "(%lu)", (ulong) field->prefix_len);
- }
-}
-
-/**************************************************************************
-Outputs info on a foreign key of a table in a format suitable for
-CREATE TABLE. */
-
-void
-dict_print_info_on_foreign_key_in_create_format(
-/*============================================*/
- FILE* file, /* in: file where to print */
- trx_t* trx, /* in: transaction */
- dict_foreign_t* foreign)/* in: foreign key constraint */
-{
- const char* stripped_id;
- ulint i;
-
- if (strchr(foreign->id, '/')) {
- /* Strip the preceding database name from the constraint id */
- stripped_id = foreign->id + 1
- + dict_get_db_name_len(foreign->id);
- } else {
- stripped_id = foreign->id;
- }
-
- fputs(",\n CONSTRAINT ", file);
- ut_print_name(file, trx, stripped_id);
- fputs(" FOREIGN KEY (", file);
-
- for (i = 0;;) {
- ut_print_name(file, trx, foreign->foreign_col_names[i]);
- if (++i < foreign->n_fields) {
- fputs(", ", file);
- } else {
- break;
- }
- }
-
- fputs(") REFERENCES ", file);
-
- if (dict_tables_have_same_db(foreign->foreign_table_name,
- foreign->referenced_table_name)) {
- /* Do not print the database name of the referenced table */
- ut_print_name(file, trx, dict_remove_db_name(
- foreign->referenced_table_name));
- } else {
- /* Look for the '/' in the table name */
-
- i = 0;
- while (foreign->referenced_table_name[i] != '/') {
- i++;
- }
-
- ut_print_namel(file, trx, foreign->referenced_table_name, i);
- putc('.', file);
- ut_print_name(file, trx,
- foreign->referenced_table_name + i + 1);
- }
-
- putc(' ', file);
- putc('(', file);
-
- for (i = 0;;) {
- ut_print_name(file, trx, foreign->referenced_col_names[i]);
- if (++i < foreign->n_fields) {
- fputs(", ", file);
- } else {
- break;
- }
- }
-
- putc(')', file);
-
- if (foreign->type & DICT_FOREIGN_ON_DELETE_CASCADE) {
- fputs(" ON DELETE CASCADE", file);
- }
-
- if (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL) {
- fputs(" ON DELETE SET NULL", file);
- }
-
- if (foreign->type & DICT_FOREIGN_ON_DELETE_NO_ACTION) {
- fputs(" ON DELETE NO ACTION", file);
- }
-
- if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE) {
- fputs(" ON UPDATE CASCADE", file);
- }
-
- if (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL) {
- fputs(" ON UPDATE SET NULL", file);
- }
-
- if (foreign->type & DICT_FOREIGN_ON_UPDATE_NO_ACTION) {
- fputs(" ON UPDATE NO ACTION", file);
- }
-}
-
-/**************************************************************************
-Outputs info on foreign keys of a table. */
-
-void
-dict_print_info_on_foreign_keys(
-/*============================*/
- ibool create_table_format, /* in: if TRUE then print in
- a format suitable to be inserted into
- a CREATE TABLE, otherwise in the format
- of SHOW TABLE STATUS */
- FILE* file, /* in: file where to print */
- trx_t* trx, /* in: transaction */
- dict_table_t* table) /* in: table */
-{
- dict_foreign_t* foreign;
-
- mutex_enter(&(dict_sys->mutex));
-
- foreign = UT_LIST_GET_FIRST(table->foreign_list);
-
- if (foreign == NULL) {
- mutex_exit(&(dict_sys->mutex));
-
- return;
- }
-
- while (foreign != NULL) {
- if (create_table_format) {
- dict_print_info_on_foreign_key_in_create_format(
- file, trx, foreign);
- } else {
- ulint i;
- fputs("; (", file);
-
- for (i = 0; i < foreign->n_fields; i++) {
- if (i) {
- putc(' ', file);
- }
-
- ut_print_name(file, trx,
- foreign->foreign_col_names[i]);
- }
-
- fputs(") REFER ", file);
- ut_print_name(file, trx,
- foreign->referenced_table_name);
- putc('(', file);
-
- for (i = 0; i < foreign->n_fields; i++) {
- if (i) {
- putc(' ', file);
- }
- ut_print_name(file, trx,
- foreign->referenced_col_names[i]);
- }
-
- putc(')', file);
-
- if (foreign->type == DICT_FOREIGN_ON_DELETE_CASCADE) {
- fputs(" ON DELETE CASCADE", file);
- }
-
- if (foreign->type == DICT_FOREIGN_ON_DELETE_SET_NULL) {
- fputs(" ON DELETE SET NULL", file);
- }
-
- if (foreign->type & DICT_FOREIGN_ON_DELETE_NO_ACTION) {
- fputs(" ON DELETE NO ACTION", file);
- }
-
- if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE) {
- fputs(" ON UPDATE CASCADE", file);
- }
-
- if (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL) {
- fputs(" ON UPDATE SET NULL", file);
- }
-
- if (foreign->type & DICT_FOREIGN_ON_UPDATE_NO_ACTION) {
- fputs(" ON UPDATE NO ACTION", file);
- }
- }
-
- foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
- }
-
- mutex_exit(&(dict_sys->mutex));
-}
-
-/************************************************************************
-Displays the names of the index and the table. */
-void
-dict_index_name_print(
-/*==================*/
- FILE* file, /* in: output stream */
- trx_t* trx, /* in: transaction */
- const dict_index_t* index) /* in: index to print */
-{
- fputs("index ", file);
- ut_print_name(file, trx, index->name);
- fputs(" of table ", file);
- ut_print_name(file, trx, index->table_name);
-}
diff --git a/innobase/dict/dict0load.c b/innobase/dict/dict0load.c
deleted file mode 100644
index 289b5dab4f2..00000000000
--- a/innobase/dict/dict0load.c
+++ /dev/null
@@ -1,1355 +0,0 @@
-/******************************************************
-Loads to the memory cache database object definitions
-from dictionary tables
-
-(c) 1996 Innobase Oy
-
-Created 4/24/1996 Heikki Tuuri
-*******************************************************/
-
-#include "dict0load.h"
-#ifndef UNIV_HOTBACKUP
-#include "mysql_version.h"
-#endif /* !UNIV_HOTBACKUP */
-
-#ifdef UNIV_NONINL
-#include "dict0load.ic"
-#endif
-
-#include "btr0pcur.h"
-#include "btr0btr.h"
-#include "page0page.h"
-#include "mach0data.h"
-#include "dict0dict.h"
-#include "dict0boot.h"
-#include "rem0cmp.h"
-#include "srv0start.h"
-#include "srv0srv.h"
-
-/************************************************************************
-Finds the first table name in the given database. */
-
-char*
-dict_get_first_table_name_in_db(
-/*============================*/
- /* out, own: table name, NULL if
- does not exist; the caller must
- free the memory in the string! */
- const char* name) /* in: database name which ends in '/' */
-{
- dict_table_t* sys_tables;
- btr_pcur_t pcur;
- dict_index_t* sys_index;
- dtuple_t* tuple;
- mem_heap_t* heap;
- dfield_t* dfield;
- rec_t* rec;
- byte* field;
- ulint len;
- mtr_t mtr;
-
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(mutex_own(&(dict_sys->mutex)));
-#endif /* UNIV_SYNC_DEBUG */
-
- heap = mem_heap_create(1000);
-
- mtr_start(&mtr);
-
- sys_tables = dict_table_get_low("SYS_TABLES");
- sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
- ut_a(!sys_tables->comp);
-
- tuple = dtuple_create(heap, 1);
- dfield = dtuple_get_nth_field(tuple, 0);
-
- dfield_set_data(dfield, name, ut_strlen(name));
- dict_index_copy_types(tuple, sys_index, 1);
-
- btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
- BTR_SEARCH_LEAF, &pcur, &mtr);
-loop:
- rec = btr_pcur_get_rec(&pcur);
-
- if (!btr_pcur_is_on_user_rec(&pcur, &mtr)) {
- /* Not found */
-
- btr_pcur_close(&pcur);
- mtr_commit(&mtr);
- mem_heap_free(heap);
-
- return(NULL);
- }
-
- field = rec_get_nth_field_old(rec, 0, &len);
-
- if (len < strlen(name)
- || ut_memcmp(name, field, strlen(name)) != 0) {
- /* Not found */
-
- btr_pcur_close(&pcur);
- mtr_commit(&mtr);
- mem_heap_free(heap);
-
- return(NULL);
- }
-
- if (!rec_get_deleted_flag(rec, sys_tables->comp)) {
-
- /* We found one */
-
- char* table_name = mem_strdupl((char*) field, len);
-
- btr_pcur_close(&pcur);
- mtr_commit(&mtr);
- mem_heap_free(heap);
-
- return(table_name);
- }
-
- btr_pcur_move_to_next_user_rec(&pcur, &mtr);
-
- goto loop;
-}
-
-/************************************************************************
-Prints to the standard output information on all tables found in the data
-dictionary system table. */
-
-void
-dict_print(void)
-/*============*/
-{
- dict_table_t* sys_tables;
- dict_index_t* sys_index;
- dict_table_t* table;
- btr_pcur_t pcur;
- rec_t* rec;
- byte* field;
- ulint len;
- mtr_t mtr;
-
- /* Enlarge the fatal semaphore wait timeout during the InnoDB table
- monitor printout */
-
- mutex_enter(&kernel_mutex);
- srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */
- mutex_exit(&kernel_mutex);
-
- mutex_enter(&(dict_sys->mutex));
-
- mtr_start(&mtr);
-
- sys_tables = dict_table_get_low("SYS_TABLES");
- sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
-
- btr_pcur_open_at_index_side(TRUE, sys_index, BTR_SEARCH_LEAF, &pcur,
- TRUE, &mtr);
-loop:
- btr_pcur_move_to_next_user_rec(&pcur, &mtr);
-
- rec = btr_pcur_get_rec(&pcur);
-
- if (!btr_pcur_is_on_user_rec(&pcur, &mtr)) {
- /* end of index */
-
- btr_pcur_close(&pcur);
- mtr_commit(&mtr);
-
- mutex_exit(&(dict_sys->mutex));
-
- /* Restore the fatal semaphore wait timeout */
-
- mutex_enter(&kernel_mutex);
- srv_fatal_semaphore_wait_threshold -= 7200; /* 2 hours */
- mutex_exit(&kernel_mutex);
-
- return;
- }
-
- field = rec_get_nth_field_old(rec, 0, &len);
-
- if (!rec_get_deleted_flag(rec, sys_tables->comp)) {
-
- /* We found one */
-
- char* table_name = mem_strdupl((char*) field, len);
-
- btr_pcur_store_position(&pcur, &mtr);
-
- mtr_commit(&mtr);
-
- table = dict_table_get_low(table_name);
- mem_free(table_name);
-
- if (table == NULL) {
- fputs("InnoDB: Failed to load table ", stderr);
- ut_print_namel(stderr, NULL, (char*) field, len);
- putc('\n', stderr);
- } else {
- /* The table definition was corrupt if there
- is no index */
-
- if (dict_table_get_first_index(table)) {
- dict_update_statistics_low(table, TRUE);
- }
-
- dict_table_print_low(table);
- }
-
- mtr_start(&mtr);
-
- btr_pcur_restore_position(BTR_SEARCH_LEAF, &pcur, &mtr);
- }
-
- goto loop;
-}
-
-/************************************************************************
-In a crash recovery we already have all the tablespace objects created.
-This function compares the space id information in the InnoDB data dictionary
-to what we already read with fil_load_single_table_tablespaces().
-
-In a normal startup, we create the tablespace objects for every table in
-InnoDB's data dictionary, if the corresponding .ibd file exists.
-We also scan the biggest space id, and store it to fil_system. */
-
-void
-dict_check_tablespaces_and_store_max_id(
-/*====================================*/
- ibool in_crash_recovery) /* in: are we doing a crash recovery */
-{
- dict_table_t* sys_tables;
- dict_index_t* sys_index;
- btr_pcur_t pcur;
- rec_t* rec;
- byte* field;
- ulint len;
- ulint space_id;
- ulint max_space_id = 0;
- mtr_t mtr;
-
- mutex_enter(&(dict_sys->mutex));
-
- mtr_start(&mtr);
-
- sys_tables = dict_table_get_low("SYS_TABLES");
- sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
- ut_a(!sys_tables->comp);
-
- btr_pcur_open_at_index_side(TRUE, sys_index, BTR_SEARCH_LEAF, &pcur,
- TRUE, &mtr);
-loop:
- btr_pcur_move_to_next_user_rec(&pcur, &mtr);
-
- rec = btr_pcur_get_rec(&pcur);
-
- if (!btr_pcur_is_on_user_rec(&pcur, &mtr)) {
- /* end of index */
-
- btr_pcur_close(&pcur);
- mtr_commit(&mtr);
-
- /* We must make the tablespace cache aware of the biggest
- known space id */
-
- /* printf("Biggest space id in data dictionary %lu\n",
- max_space_id); */
- fil_set_max_space_id_if_bigger(max_space_id);
-
- mutex_exit(&(dict_sys->mutex));
-
- return;
- }
-
- field = rec_get_nth_field_old(rec, 0, &len);
-
- if (!rec_get_deleted_flag(rec, sys_tables->comp)) {
-
- /* We found one */
-
- char* name = mem_strdupl((char*) field, len);
-
- field = rec_get_nth_field_old(rec, 9, &len);
- ut_a(len == 4);
-
- space_id = mach_read_from_4(field);
-
- btr_pcur_store_position(&pcur, &mtr);
-
- mtr_commit(&mtr);
-
- if (space_id != 0 && in_crash_recovery) {
- /* Check that the tablespace (the .ibd file) really
- exists; print a warning to the .err log if not */
-
- fil_space_for_table_exists_in_mem(space_id, name,
- FALSE, TRUE, TRUE);
- }
-
- if (space_id != 0 && !in_crash_recovery) {
- /* It is a normal database startup: create the space
- object and check that the .ibd file exists. */
-
- fil_open_single_table_tablespace(FALSE, space_id,
- name);
- }
-
- mem_free(name);
-
- if (space_id > max_space_id) {
- max_space_id = space_id;
- }
-
- mtr_start(&mtr);
-
- btr_pcur_restore_position(BTR_SEARCH_LEAF, &pcur, &mtr);
- }
-
- goto loop;
-}
-
-/************************************************************************
-Loads definitions for table columns. */
-static
-void
-dict_load_columns(
-/*==============*/
- dict_table_t* table, /* in: table */
- mem_heap_t* heap) /* in: memory heap for temporary storage */
-{
- dict_table_t* sys_columns;
- dict_index_t* sys_index;
- btr_pcur_t pcur;
- dtuple_t* tuple;
- dfield_t* dfield;
- rec_t* rec;
- byte* field;
- ulint len;
- byte* buf;
- char* name;
- ulint mtype;
- ulint prtype;
- ulint col_len;
- ulint prec;
- ulint i;
- mtr_t mtr;
-
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(mutex_own(&(dict_sys->mutex)));
-#endif /* UNIV_SYNC_DEBUG */
-
- mtr_start(&mtr);
-
- sys_columns = dict_table_get_low("SYS_COLUMNS");
- sys_index = UT_LIST_GET_FIRST(sys_columns->indexes);
- ut_a(!sys_columns->comp);
-
- tuple = dtuple_create(heap, 1);
- dfield = dtuple_get_nth_field(tuple, 0);
-
- buf = mem_heap_alloc(heap, 8);
- mach_write_to_8(buf, table->id);
-
- dfield_set_data(dfield, buf, 8);
- dict_index_copy_types(tuple, sys_index, 1);
-
- btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
- BTR_SEARCH_LEAF, &pcur, &mtr);
- for (i = 0; i < table->n_cols - DATA_N_SYS_COLS; i++) {
-
- rec = btr_pcur_get_rec(&pcur);
-
- ut_a(btr_pcur_is_on_user_rec(&pcur, &mtr));
-
- ut_a(!rec_get_deleted_flag(rec, sys_columns->comp));
-
- field = rec_get_nth_field_old(rec, 0, &len);
- ut_ad(len == 8);
- ut_a(ut_dulint_cmp(table->id, mach_read_from_8(field)) == 0);
-
- field = rec_get_nth_field_old(rec, 1, &len);
- ut_ad(len == 4);
- ut_a(i == mach_read_from_4(field));
-
- ut_a(0 == ut_strcmp("NAME",
- dict_field_get_col(
- dict_index_get_nth_field(sys_index, 4))->name));
-
- field = rec_get_nth_field_old(rec, 4, &len);
- name = mem_heap_strdupl(heap, (char*) field, len);
-
- field = rec_get_nth_field_old(rec, 5, &len);
- mtype = mach_read_from_4(field);
-
- field = rec_get_nth_field_old(rec, 6, &len);
- prtype = mach_read_from_4(field);
-
- if (dtype_is_non_binary_string_type(mtype, prtype)
- && dtype_get_charset_coll(prtype) == 0) {
- /* This is a non-binary string type, and the table
- was created with < 4.1.2. Use the default charset. */
-
- prtype = dtype_form_prtype(prtype,
- data_mysql_default_charset_coll);
- }
-
- field = rec_get_nth_field_old(rec, 7, &len);
- col_len = mach_read_from_4(field);
-
- ut_a(0 == ut_strcmp("PREC",
- dict_field_get_col(
- dict_index_get_nth_field(sys_index, 8))->name));
-
- field = rec_get_nth_field_old(rec, 8, &len);
- prec = mach_read_from_4(field);
-
- dict_mem_table_add_col(table, name, mtype, prtype, col_len,
- prec);
- btr_pcur_move_to_next_user_rec(&pcur, &mtr);
- }
-
- btr_pcur_close(&pcur);
- mtr_commit(&mtr);
-}
-
-/************************************************************************
-Report that an index field or index for a table has been delete marked. */
-static
-void
-dict_load_report_deleted_index(
-/*===========================*/
- const char* name, /* in: table name */
- ulint field) /* in: index field, or ULINT_UNDEFINED */
-{
- fprintf(stderr, "InnoDB: Error: data dictionary entry"
- " for table %s is corrupt!\n", name);
- if (field != ULINT_UNDEFINED) {
- fprintf(stderr,
- "InnoDB: Index field %lu is delete marked.\n", field);
- } else {
- fputs("InnoDB: An index is delete marked.\n", stderr);
- }
-}
-
-/************************************************************************
-Loads definitions for index fields. */
-static
-void
-dict_load_fields(
-/*=============*/
- dict_table_t* table, /* in: table */
- dict_index_t* index, /* in: index whose fields to load */
- mem_heap_t* heap) /* in: memory heap for temporary storage */
-{
- dict_table_t* sys_fields;
- dict_index_t* sys_index;
- btr_pcur_t pcur;
- dtuple_t* tuple;
- dfield_t* dfield;
- ulint pos_and_prefix_len;
- ulint prefix_len;
- rec_t* rec;
- byte* field;
- ulint len;
- byte* buf;
- ulint i;
- mtr_t mtr;
-
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(mutex_own(&(dict_sys->mutex)));
-#endif /* UNIV_SYNC_DEBUG */
-
- UT_NOT_USED(table);
-
- mtr_start(&mtr);
-
- sys_fields = dict_table_get_low("SYS_FIELDS");
- sys_index = UT_LIST_GET_FIRST(sys_fields->indexes);
- ut_a(!sys_fields->comp);
-
- tuple = dtuple_create(heap, 1);
- dfield = dtuple_get_nth_field(tuple, 0);
-
- buf = mem_heap_alloc(heap, 8);
- mach_write_to_8(buf, index->id);
-
- dfield_set_data(dfield, buf, 8);
- dict_index_copy_types(tuple, sys_index, 1);
-
- btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
- BTR_SEARCH_LEAF, &pcur, &mtr);
- for (i = 0; i < index->n_fields; i++) {
-
- rec = btr_pcur_get_rec(&pcur);
-
- ut_a(btr_pcur_is_on_user_rec(&pcur, &mtr));
- if (rec_get_deleted_flag(rec, sys_fields->comp)) {
- dict_load_report_deleted_index(table->name, i);
- }
-
- field = rec_get_nth_field_old(rec, 0, &len);
- ut_ad(len == 8);
- ut_a(ut_memcmp(buf, field, len) == 0);
-
- field = rec_get_nth_field_old(rec, 1, &len);
- ut_a(len == 4);
-
- /* The next field stores the field position in the index
- and a possible column prefix length if the index field
- does not contain the whole column. The storage format is
- like this: if there is at least one prefix field in the index,
- then the HIGH 2 bytes contain the field number (== i) and the
- low 2 bytes the prefix length for the field. Otherwise the
- field number (== i) is contained in the 2 LOW bytes. */
-
- pos_and_prefix_len = mach_read_from_4(field);
-
- ut_a((pos_and_prefix_len & 0xFFFFUL) == i
- || (pos_and_prefix_len & 0xFFFF0000UL) == (i << 16));
-
- if ((i == 0 && pos_and_prefix_len > 0)
- || (pos_and_prefix_len & 0xFFFF0000UL) > 0) {
-
- prefix_len = pos_and_prefix_len & 0xFFFFUL;
- } else {
- prefix_len = 0;
- }
-
- ut_a(0 == ut_strcmp("COL_NAME",
- dict_field_get_col(
- dict_index_get_nth_field(sys_index, 4))->name));
-
- field = rec_get_nth_field_old(rec, 4, &len);
-
- dict_mem_index_add_field(index,
- mem_heap_strdupl(heap, (char*) field, len), 0, prefix_len);
-
- btr_pcur_move_to_next_user_rec(&pcur, &mtr);
- }
-
- btr_pcur_close(&pcur);
- mtr_commit(&mtr);
-}
-
-/************************************************************************
-Loads definitions for table indexes. Adds them to the data dictionary
-cache. */
-static
-ibool
-dict_load_indexes(
-/*==============*/
- /* out: TRUE if ok, FALSE if corruption
- of dictionary table */
- dict_table_t* table, /* in: table */
- mem_heap_t* heap) /* in: memory heap for temporary storage */
-{
- dict_table_t* sys_indexes;
- dict_index_t* sys_index;
- dict_index_t* index;
- btr_pcur_t pcur;
- dtuple_t* tuple;
- dfield_t* dfield;
- rec_t* rec;
- byte* field;
- ulint len;
- ulint name_len;
- char* name_buf;
- ulint type;
- ulint space;
- ulint page_no;
- ulint n_fields;
- byte* buf;
- ibool is_sys_table;
- dulint id;
- mtr_t mtr;
-
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(mutex_own(&(dict_sys->mutex)));
-#endif /* UNIV_SYNC_DEBUG */
-
- if ((ut_dulint_get_high(table->id) == 0)
- && (ut_dulint_get_low(table->id) < DICT_HDR_FIRST_ID)) {
- is_sys_table = TRUE;
- } else {
- is_sys_table = FALSE;
- }
-
- mtr_start(&mtr);
-
- sys_indexes = dict_table_get_low("SYS_INDEXES");
- sys_index = UT_LIST_GET_FIRST(sys_indexes->indexes);
- ut_a(!sys_indexes->comp);
-
- tuple = dtuple_create(heap, 1);
- dfield = dtuple_get_nth_field(tuple, 0);
-
- buf = mem_heap_alloc(heap, 8);
- mach_write_to_8(buf, table->id);
-
- dfield_set_data(dfield, buf, 8);
- dict_index_copy_types(tuple, sys_index, 1);
-
- btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
- BTR_SEARCH_LEAF, &pcur, &mtr);
- for (;;) {
- if (!btr_pcur_is_on_user_rec(&pcur, &mtr)) {
-
- break;
- }
-
- rec = btr_pcur_get_rec(&pcur);
-
- field = rec_get_nth_field_old(rec, 0, &len);
- ut_ad(len == 8);
-
- if (ut_memcmp(buf, field, len) != 0) {
- break;
- }
-
- if (rec_get_deleted_flag(rec, table->comp)) {
- dict_load_report_deleted_index(table->name,
- ULINT_UNDEFINED);
-
- btr_pcur_close(&pcur);
- mtr_commit(&mtr);
-
- return(FALSE);
- }
-
- field = rec_get_nth_field_old(rec, 1, &len);
- ut_ad(len == 8);
- id = mach_read_from_8(field);
-
- ut_a(0 == ut_strcmp("NAME",
- dict_field_get_col(
- dict_index_get_nth_field(sys_index, 4))->name));
-
- field = rec_get_nth_field_old(rec, 4, &name_len);
- name_buf = mem_heap_strdupl(heap, (char*) field, name_len);
-
- field = rec_get_nth_field_old(rec, 5, &len);
- n_fields = mach_read_from_4(field);
-
- field = rec_get_nth_field_old(rec, 6, &len);
- type = mach_read_from_4(field);
-
- field = rec_get_nth_field_old(rec, 7, &len);
- space = mach_read_from_4(field);
-
- ut_a(0 == ut_strcmp("PAGE_NO",
- dict_field_get_col(
- dict_index_get_nth_field(sys_index, 8))->name));
-
- field = rec_get_nth_field_old(rec, 8, &len);
- page_no = mach_read_from_4(field);
-
- if (page_no == FIL_NULL) {
-
- fprintf(stderr,
- "InnoDB: Error: trying to load index %s for table %s\n"
- "InnoDB: but the index tree has been freed!\n",
- name_buf, table->name);
-
- btr_pcur_close(&pcur);
- mtr_commit(&mtr);
-
- return(FALSE);
- }
-
- if ((type & DICT_CLUSTERED) == 0
- && NULL == dict_table_get_first_index(table)) {
-
- fprintf(stderr,
- "InnoDB: Error: trying to load index %s for table %s\n"
- "InnoDB: but the first index is not clustered!\n",
- name_buf, table->name);
-
- btr_pcur_close(&pcur);
- mtr_commit(&mtr);
-
- return(FALSE);
- }
-
- if (is_sys_table
- && ((type & DICT_CLUSTERED)
- || ((table == dict_sys->sys_tables)
- && (name_len == (sizeof "ID_IND") - 1)
- && (0 == ut_memcmp(name_buf, "ID_IND",
- name_len))))) {
-
- /* The index was created in memory already at booting
- of the database server */
- } else {
- index = dict_mem_index_create(table->name, name_buf,
- space, type, n_fields);
- index->id = id;
-
- dict_load_fields(table, index, heap);
- dict_index_add_to_cache(table, index, page_no);
- }
-
- btr_pcur_move_to_next_user_rec(&pcur, &mtr);
- }
-
- btr_pcur_close(&pcur);
- mtr_commit(&mtr);
-
- return(TRUE);
-}
-
-/************************************************************************
-Loads a table definition and also all its index definitions, and also
-the cluster definition if the table is a member in a cluster. Also loads
-all foreign key constraints where the foreign key is in the table or where
-a foreign key references columns in this table. Adds all these to the data
-dictionary cache. */
-
-dict_table_t*
-dict_load_table(
-/*============*/
- /* out: table, NULL if does not exist;
- if the table is stored in an .ibd file,
- but the file does not exist,
- then we set the ibd_file_missing flag TRUE
- in the table object we return */
- const char* name) /* in: table name in the
- databasename/tablename format */
-{
- ibool ibd_file_missing = FALSE;
- dict_table_t* table;
- dict_table_t* sys_tables;
- btr_pcur_t pcur;
- dict_index_t* sys_index;
- dtuple_t* tuple;
- mem_heap_t* heap;
- dfield_t* dfield;
- rec_t* rec;
- byte* field;
- ulint len;
- ulint space;
- ulint n_cols;
- ulint err;
- mtr_t mtr;
-
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(mutex_own(&(dict_sys->mutex)));
-#endif /* UNIV_SYNC_DEBUG */
-
- heap = mem_heap_create(1000);
-
- mtr_start(&mtr);
-
- sys_tables = dict_table_get_low("SYS_TABLES");
- sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
- ut_a(!sys_tables->comp);
-
- tuple = dtuple_create(heap, 1);
- dfield = dtuple_get_nth_field(tuple, 0);
-
- dfield_set_data(dfield, name, ut_strlen(name));
- dict_index_copy_types(tuple, sys_index, 1);
-
- btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
- BTR_SEARCH_LEAF, &pcur, &mtr);
- rec = btr_pcur_get_rec(&pcur);
-
- if (!btr_pcur_is_on_user_rec(&pcur, &mtr)
- || rec_get_deleted_flag(rec, sys_tables->comp)) {
- /* Not found */
-
- btr_pcur_close(&pcur);
- mtr_commit(&mtr);
- mem_heap_free(heap);
-
- return(NULL);
- }
-
- field = rec_get_nth_field_old(rec, 0, &len);
-
- /* Check if the table name in record is the searched one */
- if (len != ut_strlen(name) || ut_memcmp(name, field, len) != 0) {
- btr_pcur_close(&pcur);
- mtr_commit(&mtr);
- mem_heap_free(heap);
-
- return(NULL);
- }
-
- ut_a(0 == ut_strcmp("SPACE",
- dict_field_get_col(
- dict_index_get_nth_field(sys_index, 9))->name));
-
- field = rec_get_nth_field_old(rec, 9, &len);
- space = mach_read_from_4(field);
-
- /* Check if the tablespace exists and has the right name */
- if (space != 0) {
- if (fil_space_for_table_exists_in_mem(space, name, FALSE,
- FALSE, FALSE)) {
- /* Ok; (if we did a crash recovery then the tablespace
- can already be in the memory cache) */
- } else {
- /* In >= 4.1.9, InnoDB scans the data dictionary also
- at a normal mysqld startup. It is an error if the
- space object does not exist in memory. */
-
- ut_print_timestamp(stderr);
- fprintf(stderr,
-" InnoDB: error: space object of table %s,\n"
-"InnoDB: space id %lu did not exist in memory. Retrying an open.\n",
- name, (ulong)space);
- /* Try to open the tablespace */
- if (!fil_open_single_table_tablespace(TRUE,
- space, name)) {
- /* We failed to find a sensible tablespace
- file */
-
- ibd_file_missing = TRUE;
- }
- }
- }
-
- ut_a(0 == ut_strcmp("N_COLS",
- dict_field_get_col(
- dict_index_get_nth_field(sys_index, 4))->name));
-
- field = rec_get_nth_field_old(rec, 4, &len);
- n_cols = mach_read_from_4(field);
-
- /* The high-order bit of N_COLS is the "compact format" flag. */
- table = dict_mem_table_create(name, space,
- n_cols & ~0x80000000UL,
- !!(n_cols & 0x80000000UL));
-
- table->ibd_file_missing = ibd_file_missing;
-
- ut_a(0 == ut_strcmp("ID",
- dict_field_get_col(
- dict_index_get_nth_field(sys_index, 3))->name));
-
- field = rec_get_nth_field_old(rec, 3, &len);
- table->id = mach_read_from_8(field);
-
- field = rec_get_nth_field_old(rec, 5, &len);
- table->type = mach_read_from_4(field);
-
- if (table->type == DICT_TABLE_CLUSTER_MEMBER) {
- ut_error;
-#if 0 /* clustered tables have not been implemented yet */
- field = rec_get_nth_field_old(rec, 6, &len);
- table->mix_id = mach_read_from_8(field);
-
- field = rec_get_nth_field_old(rec, 8, &len);
- table->cluster_name = mem_heap_strdupl(heap, (char*) field, len);
-#endif
- }
-
- if ((table->type == DICT_TABLE_CLUSTER)
- || (table->type == DICT_TABLE_CLUSTER_MEMBER)) {
-
- field = rec_get_nth_field_old(rec, 7, &len);
- ut_a(len == 4);
- table->mix_len = mach_read_from_4(field);
- }
-
- btr_pcur_close(&pcur);
- mtr_commit(&mtr);
-
- if (table->type == DICT_TABLE_CLUSTER_MEMBER) {
- /* Load the cluster table definition if not yet in
- memory cache */
- dict_table_get_low(table->cluster_name);
- }
-
- dict_load_columns(table, heap);
-
- dict_table_add_to_cache(table);
-
- dict_load_indexes(table, heap);
-
- err = dict_load_foreigns(table->name);
-/*
- if (err != DB_SUCCESS) {
-
- mutex_enter(&dict_foreign_err_mutex);
-
- ut_print_timestamp(stderr);
-
- fprintf(stderr,
-" InnoDB: Error: could not make a foreign key definition to match\n"
-"InnoDB: the foreign key table or the referenced table!\n"
-"InnoDB: The data dictionary of InnoDB is corrupt. You may need to drop\n"
-"InnoDB: and recreate the foreign key table or the referenced table.\n"
-"InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n"
-"InnoDB: Latest foreign key error printout:\n%s\n", dict_foreign_err_buf);
-
- mutex_exit(&dict_foreign_err_mutex);
- }
-*/
- mem_heap_free(heap);
-
- return(table);
-}
-
-/***************************************************************************
-Loads a table object based on the table id. */
-
-dict_table_t*
-dict_load_table_on_id(
-/*==================*/
- /* out: table; NULL if table does not exist */
- dulint table_id) /* in: table id */
-{
- byte id_buf[8];
- btr_pcur_t pcur;
- mem_heap_t* heap;
- dtuple_t* tuple;
- dfield_t* dfield;
- dict_index_t* sys_table_ids;
- dict_table_t* sys_tables;
- rec_t* rec;
- byte* field;
- ulint len;
- dict_table_t* table;
- mtr_t mtr;
-
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(mutex_own(&(dict_sys->mutex)));
-#endif /* UNIV_SYNC_DEBUG */
-
- /* NOTE that the operation of this function is protected by
- the dictionary mutex, and therefore no deadlocks can occur
- with other dictionary operations. */
-
- mtr_start(&mtr);
- /*---------------------------------------------------*/
- /* Get the secondary index based on ID for table SYS_TABLES */
- sys_tables = dict_sys->sys_tables;
- sys_table_ids = dict_table_get_next_index(
- dict_table_get_first_index(sys_tables));
- ut_a(!sys_tables->comp);
- heap = mem_heap_create(256);
-
- tuple = dtuple_create(heap, 1);
- dfield = dtuple_get_nth_field(tuple, 0);
-
- /* Write the table id in byte format to id_buf */
- mach_write_to_8(id_buf, table_id);
-
- dfield_set_data(dfield, id_buf, 8);
- dict_index_copy_types(tuple, sys_table_ids, 1);
-
- btr_pcur_open_on_user_rec(sys_table_ids, tuple, PAGE_CUR_GE,
- BTR_SEARCH_LEAF, &pcur, &mtr);
- rec = btr_pcur_get_rec(&pcur);
-
- if (!btr_pcur_is_on_user_rec(&pcur, &mtr)
- || rec_get_deleted_flag(rec, sys_tables->comp)) {
- /* Not found */
-
- btr_pcur_close(&pcur);
- mtr_commit(&mtr);
- mem_heap_free(heap);
-
- return(NULL);
- }
-
- /*---------------------------------------------------*/
- /* Now we have the record in the secondary index containing the
- table ID and NAME */
-
- rec = btr_pcur_get_rec(&pcur);
- field = rec_get_nth_field_old(rec, 0, &len);
- ut_ad(len == 8);
-
- /* Check if the table id in record is the one searched for */
- if (ut_dulint_cmp(table_id, mach_read_from_8(field)) != 0) {
-
- btr_pcur_close(&pcur);
- mtr_commit(&mtr);
- mem_heap_free(heap);
-
- return(NULL);
- }
-
- /* Now we get the table name from the record */
- field = rec_get_nth_field_old(rec, 1, &len);
- /* Load the table definition to memory */
- table = dict_load_table(mem_heap_strdupl(heap, (char*) field, len));
-
- btr_pcur_close(&pcur);
- mtr_commit(&mtr);
- mem_heap_free(heap);
-
- return(table);
-}
-
-/************************************************************************
-This function is called when the database is booted. Loads system table
-index definitions except for the clustered index which is added to the
-dictionary cache at booting before calling this function. */
-
-void
-dict_load_sys_table(
-/*================*/
- dict_table_t* table) /* in: system table */
-{
- mem_heap_t* heap;
-
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(mutex_own(&(dict_sys->mutex)));
-#endif /* UNIV_SYNC_DEBUG */
-
- heap = mem_heap_create(1000);
-
- dict_load_indexes(table, heap);
-
- mem_heap_free(heap);
-}
-
-/************************************************************************
-Loads foreign key constraint col names (also for the referenced table). */
-static
-void
-dict_load_foreign_cols(
-/*===================*/
- const char* id, /* in: foreign constraint id as a null-
- terminated string */
- dict_foreign_t* foreign)/* in: foreign constraint object */
-{
- dict_table_t* sys_foreign_cols;
- dict_index_t* sys_index;
- btr_pcur_t pcur;
- dtuple_t* tuple;
- dfield_t* dfield;
- rec_t* rec;
- byte* field;
- ulint len;
- ulint i;
- mtr_t mtr;
-
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(mutex_own(&(dict_sys->mutex)));
-#endif /* UNIV_SYNC_DEBUG */
-
- foreign->foreign_col_names = mem_heap_alloc(foreign->heap,
- foreign->n_fields * sizeof(void*));
-
- foreign->referenced_col_names = mem_heap_alloc(foreign->heap,
- foreign->n_fields * sizeof(void*));
- mtr_start(&mtr);
-
- sys_foreign_cols = dict_table_get_low("SYS_FOREIGN_COLS");
- sys_index = UT_LIST_GET_FIRST(sys_foreign_cols->indexes);
- ut_a(!sys_foreign_cols->comp);
-
- tuple = dtuple_create(foreign->heap, 1);
- dfield = dtuple_get_nth_field(tuple, 0);
-
- dfield_set_data(dfield, id, ut_strlen(id));
- dict_index_copy_types(tuple, sys_index, 1);
-
- btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
- BTR_SEARCH_LEAF, &pcur, &mtr);
- for (i = 0; i < foreign->n_fields; i++) {
-
- rec = btr_pcur_get_rec(&pcur);
-
- ut_a(btr_pcur_is_on_user_rec(&pcur, &mtr));
- ut_a(!rec_get_deleted_flag(rec, sys_foreign_cols->comp));
-
- field = rec_get_nth_field_old(rec, 0, &len);
- ut_a(len == ut_strlen(id));
- ut_a(ut_memcmp(id, field, len) == 0);
-
- field = rec_get_nth_field_old(rec, 1, &len);
- ut_a(len == 4);
- ut_a(i == mach_read_from_4(field));
-
- field = rec_get_nth_field_old(rec, 4, &len);
- foreign->foreign_col_names[i] =
- mem_heap_strdupl(foreign->heap, (char*) field, len);
-
- field = rec_get_nth_field_old(rec, 5, &len);
- foreign->referenced_col_names[i] =
- mem_heap_strdupl(foreign->heap, (char*) field, len);
-
- btr_pcur_move_to_next_user_rec(&pcur, &mtr);
- }
-
- btr_pcur_close(&pcur);
- mtr_commit(&mtr);
-}
-
-/***************************************************************************
-Loads a foreign key constraint to the dictionary cache. */
-static
-ulint
-dict_load_foreign(
-/*==============*/
- /* out: DB_SUCCESS or error code */
- const char* id) /* in: foreign constraint id as a
- null-terminated string */
-{
- dict_foreign_t* foreign;
- dict_table_t* sys_foreign;
- btr_pcur_t pcur;
- dict_index_t* sys_index;
- dtuple_t* tuple;
- mem_heap_t* heap2;
- dfield_t* dfield;
- rec_t* rec;
- byte* field;
- ulint len;
- ulint err;
- mtr_t mtr;
-
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(mutex_own(&(dict_sys->mutex)));
-#endif /* UNIV_SYNC_DEBUG */
-
- heap2 = mem_heap_create(1000);
-
- mtr_start(&mtr);
-
- sys_foreign = dict_table_get_low("SYS_FOREIGN");
- sys_index = UT_LIST_GET_FIRST(sys_foreign->indexes);
- ut_a(!sys_foreign->comp);
-
- tuple = dtuple_create(heap2, 1);
- dfield = dtuple_get_nth_field(tuple, 0);
-
- dfield_set_data(dfield, id, ut_strlen(id));
- dict_index_copy_types(tuple, sys_index, 1);
-
- btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
- BTR_SEARCH_LEAF, &pcur, &mtr);
- rec = btr_pcur_get_rec(&pcur);
-
- if (!btr_pcur_is_on_user_rec(&pcur, &mtr)
- || rec_get_deleted_flag(rec, sys_foreign->comp)) {
- /* Not found */
-
- fprintf(stderr,
- "InnoDB: Error A: cannot load foreign constraint %s\n",
- id);
-
- btr_pcur_close(&pcur);
- mtr_commit(&mtr);
- mem_heap_free(heap2);
-
- return(DB_ERROR);
- }
-
- field = rec_get_nth_field_old(rec, 0, &len);
-
- /* Check if the id in record is the searched one */
- if (len != ut_strlen(id) || ut_memcmp(id, field, len) != 0) {
-
- fprintf(stderr,
- "InnoDB: Error B: cannot load foreign constraint %s\n",
- id);
-
- btr_pcur_close(&pcur);
- mtr_commit(&mtr);
- mem_heap_free(heap2);
-
- return(DB_ERROR);
- }
-
- /* Read the table names and the number of columns associated
- with the constraint */
-
- mem_heap_free(heap2);
-
- foreign = dict_mem_foreign_create();
-
- foreign->n_fields =
- mach_read_from_4(rec_get_nth_field_old(rec, 5, &len));
-
- ut_a(len == 4);
-
- /* We store the type to the bits 24-31 of n_fields */
-
- foreign->type = foreign->n_fields >> 24;
- foreign->n_fields = foreign->n_fields & 0xFFFFFFUL;
-
- foreign->id = mem_heap_strdup(foreign->heap, id);
-
- field = rec_get_nth_field_old(rec, 3, &len);
- foreign->foreign_table_name =
- mem_heap_strdupl(foreign->heap, (char*) field, len);
-
- field = rec_get_nth_field_old(rec, 4, &len);
- foreign->referenced_table_name =
- mem_heap_strdupl(foreign->heap, (char*) field, len);
-
- btr_pcur_close(&pcur);
- mtr_commit(&mtr);
-
- dict_load_foreign_cols(id, foreign);
-
- /* If the foreign table is not yet in the dictionary cache, we
- have to load it so that we are able to make type comparisons
- in the next function call. */
-
- dict_table_get_low(foreign->foreign_table_name);
-
- /* Note that there may already be a foreign constraint object in
- the dictionary cache for this constraint: then the following
- call only sets the pointers in it to point to the appropriate table
- and index objects and frees the newly created object foreign.
- Adding to the cache should always succeed since we are not creating
- a new foreign key constraint but loading one from the data
- dictionary. */
-
- err = dict_foreign_add_to_cache(foreign);
-
- return(err);
-}
-
-/***************************************************************************
-Loads foreign key constraints where the table is either the foreign key
-holder or where the table is referenced by a foreign key. Adds these
-constraints to the data dictionary. Note that we know that the dictionary
-cache already contains all constraints where the other relevant table is
-already in the dictionary cache. */
-
-ulint
-dict_load_foreigns(
-/*===============*/
- /* out: DB_SUCCESS or error code */
- const char* table_name) /* in: table name */
-{
- btr_pcur_t pcur;
- mem_heap_t* heap;
- dtuple_t* tuple;
- dfield_t* dfield;
- dict_index_t* sec_index;
- dict_table_t* sys_foreign;
- rec_t* rec;
- byte* field;
- ulint len;
- char* id ;
- ulint err;
- mtr_t mtr;
-
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(mutex_own(&(dict_sys->mutex)));
-#endif /* UNIV_SYNC_DEBUG */
-
- sys_foreign = dict_table_get_low("SYS_FOREIGN");
-
- if (sys_foreign == NULL) {
- /* No foreign keys defined yet in this database */
-
- fprintf(stderr,
- "InnoDB: Error: no foreign key system tables in the database\n");
-
- return(DB_ERROR);
- }
-
- ut_a(!sys_foreign->comp);
- mtr_start(&mtr);
-
- /* Get the secondary index based on FOR_NAME from table
- SYS_FOREIGN */
-
- sec_index = dict_table_get_next_index(
- dict_table_get_first_index(sys_foreign));
-start_load:
- heap = mem_heap_create(256);
-
- tuple = dtuple_create(heap, 1);
- dfield = dtuple_get_nth_field(tuple, 0);
-
- dfield_set_data(dfield, table_name, ut_strlen(table_name));
- dict_index_copy_types(tuple, sec_index, 1);
-
- btr_pcur_open_on_user_rec(sec_index, tuple, PAGE_CUR_GE,
- BTR_SEARCH_LEAF, &pcur, &mtr);
-loop:
- rec = btr_pcur_get_rec(&pcur);
-
- if (!btr_pcur_is_on_user_rec(&pcur, &mtr)) {
- /* End of index */
-
- goto load_next_index;
- }
-
- /* Now we have the record in the secondary index containing a table
- name and a foreign constraint ID */
-
- rec = btr_pcur_get_rec(&pcur);
- field = rec_get_nth_field_old(rec, 0, &len);
-
- /* Check if the table name in the record is the one searched for; the
- following call does the comparison in the latin1_swedish_ci
- charset-collation, in a case-insensitive way. */
-
- if (0 != cmp_data_data(dfield_get_type(dfield),
- dfield_get_data(dfield), dfield_get_len(dfield),
- field, len)) {
-
- goto load_next_index;
- }
-
- /* Since table names in SYS_FOREIGN are stored in a case-insensitive
- order, we have to check that the table name matches also in a binary
- string comparison. On Unix, MySQL allows table names that only differ
- in character case. */
-
- if (0 != ut_memcmp(field, table_name, len)) {
-
- goto next_rec;
- }
-
- if (rec_get_deleted_flag(rec, sys_foreign->comp)) {
-
- goto next_rec;
- }
-
- /* Now we get a foreign key constraint id */
- field = rec_get_nth_field_old(rec, 1, &len);
- id = mem_heap_strdupl(heap, (char*) field, len);
-
- btr_pcur_store_position(&pcur, &mtr);
-
- mtr_commit(&mtr);
-
- /* Load the foreign constraint definition to the dictionary cache */
-
- err = dict_load_foreign(id);
-
- if (err != DB_SUCCESS) {
- btr_pcur_close(&pcur);
- mem_heap_free(heap);
-
- return(err);
- }
-
- mtr_start(&mtr);
-
- btr_pcur_restore_position(BTR_SEARCH_LEAF, &pcur, &mtr);
-next_rec:
- btr_pcur_move_to_next_user_rec(&pcur, &mtr);
-
- goto loop;
-
-load_next_index:
- btr_pcur_close(&pcur);
- mtr_commit(&mtr);
- mem_heap_free(heap);
-
- sec_index = dict_table_get_next_index(sec_index);
-
- if (sec_index != NULL) {
-
- mtr_start(&mtr);
-
- goto start_load;
- }
-
- return(DB_SUCCESS);
-}
diff --git a/innobase/dict/dict0mem.c b/innobase/dict/dict0mem.c
deleted file mode 100644
index 48b9f28d292..00000000000
--- a/innobase/dict/dict0mem.c
+++ /dev/null
@@ -1,293 +0,0 @@
-/**********************************************************************
-Data dictionary memory object creation
-
-(c) 1996 Innobase Oy
-
-Created 1/8/1996 Heikki Tuuri
-***********************************************************************/
-
-#include "dict0mem.h"
-
-#ifdef UNIV_NONINL
-#include "dict0mem.ic"
-#endif
-
-#include "rem0rec.h"
-#include "data0type.h"
-#include "mach0data.h"
-#include "dict0dict.h"
-#include "que0que.h"
-#include "pars0pars.h"
-#include "lock0lock.h"
-
-#define DICT_HEAP_SIZE 100 /* initial memory heap size when
- creating a table or index object */
-
-/**************************************************************************
-Creates a table memory object. */
-
-dict_table_t*
-dict_mem_table_create(
-/*==================*/
- /* out, own: table object */
- const char* name, /* in: table name */
- ulint space, /* in: space where the clustered index of
- the table is placed; this parameter is
- ignored if the table is made a member of
- a cluster */
- ulint n_cols, /* in: number of columns */
- ibool comp) /* in: TRUE=compact page format */
-{
- dict_table_t* table;
- mem_heap_t* heap;
-
- ut_ad(name);
-
- heap = mem_heap_create(DICT_HEAP_SIZE);
-
- table = mem_heap_alloc(heap, sizeof(dict_table_t));
-
- table->heap = heap;
-
- table->type = DICT_TABLE_ORDINARY;
- table->name = mem_heap_strdup(heap, name);
- table->dir_path_of_temp_table = NULL;
- table->space = space;
- table->ibd_file_missing = FALSE;
- table->tablespace_discarded = FALSE;
- table->comp = comp;
- table->n_def = 0;
- table->n_cols = n_cols + DATA_N_SYS_COLS;
- table->mem_fix = 0;
-
- table->n_mysql_handles_opened = 0;
- table->n_foreign_key_checks_running = 0;
-
- table->cached = FALSE;
-
- table->mix_id = ut_dulint_zero;
- table->mix_len = 0;
-
- table->cols = mem_heap_alloc(heap, (n_cols + DATA_N_SYS_COLS)
- * sizeof(dict_col_t));
- UT_LIST_INIT(table->indexes);
-
- table->auto_inc_lock = mem_heap_alloc(heap, lock_get_size());
-
- table->query_cache_inv_trx_id = ut_dulint_zero;
-
- UT_LIST_INIT(table->locks);
- UT_LIST_INIT(table->foreign_list);
- UT_LIST_INIT(table->referenced_list);
-
- table->does_not_fit_in_memory = FALSE;
-
- table->stat_initialized = FALSE;
-
- table->stat_modified_counter = 0;
-
- mutex_create(&(table->autoinc_mutex));
- mutex_set_level(&(table->autoinc_mutex), SYNC_DICT_AUTOINC_MUTEX);
-
- table->autoinc_inited = FALSE;
-
- table->magic_n = DICT_TABLE_MAGIC_N;
-
- return(table);
-}
-
-/**************************************************************************
-Creates a cluster memory object. */
-
-dict_table_t*
-dict_mem_cluster_create(
-/*====================*/
- /* out, own: cluster object */
- const char* name, /* in: cluster name */
- ulint space, /* in: space where the clustered indexes
- of the member tables are placed */
- ulint n_cols, /* in: number of columns */
- ulint mix_len)/* in: length of the common key prefix in the
- cluster */
-{
- dict_table_t* cluster;
-
- /* Clustered tables cannot work with the compact record format. */
- cluster = dict_mem_table_create(name, space, n_cols, FALSE);
-
- cluster->type = DICT_TABLE_CLUSTER;
- cluster->mix_len = mix_len;
-
- return(cluster);
-}
-
-/**************************************************************************
-Declares a non-published table as a member in a cluster. */
-
-void
-dict_mem_table_make_cluster_member(
-/*===============================*/
- dict_table_t* table, /* in: non-published table */
- const char* cluster_name) /* in: cluster name */
-{
- table->type = DICT_TABLE_CLUSTER_MEMBER;
- table->cluster_name = cluster_name;
-}
-
-/**************************************************************************
-Adds a column definition to a table. */
-
-void
-dict_mem_table_add_col(
-/*===================*/
- dict_table_t* table, /* in: table */
- const char* name, /* in: column name */
- ulint mtype, /* in: main datatype */
- ulint prtype, /* in: precise type */
- ulint len, /* in: length */
- ulint prec) /* in: precision */
-{
- dict_col_t* col;
- dtype_t* type;
-
- ut_ad(table && name);
- ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
-
- table->n_def++;
-
- col = dict_table_get_nth_col(table, table->n_def - 1);
-
- col->ind = table->n_def - 1;
- col->name = mem_heap_strdup(table->heap, name);
- col->table = table;
- col->ord_part = 0;
-
- col->clust_pos = ULINT_UNDEFINED;
-
- type = dict_col_get_type(col);
-
- dtype_set(type, mtype, prtype, len, prec);
-}
-
-/**************************************************************************
-Creates an index memory object. */
-
-dict_index_t*
-dict_mem_index_create(
-/*==================*/
- /* out, own: index object */
- const char* table_name, /* in: table name */
- const char* index_name, /* in: index name */
- ulint space, /* in: space where the index tree is
- placed, ignored if the index is of
- the clustered type */
- ulint type, /* in: DICT_UNIQUE,
- DICT_CLUSTERED, ... ORed */
- ulint n_fields) /* in: number of fields */
-{
- dict_index_t* index;
- mem_heap_t* heap;
-
- ut_ad(table_name && index_name);
-
- heap = mem_heap_create(DICT_HEAP_SIZE);
- index = mem_heap_alloc(heap, sizeof(dict_index_t));
-
- index->heap = heap;
-
- index->type = type;
- index->space = space;
- index->name = mem_heap_strdup(heap, index_name);
- index->table_name = table_name;
- index->table = NULL;
- index->n_def = index->n_nullable = 0;
- index->n_fields = n_fields;
- index->fields = mem_heap_alloc(heap, 1 + n_fields
- * sizeof(dict_field_t));
- /* The '1 +' above prevents allocation
- of an empty mem block */
- index->stat_n_diff_key_vals = NULL;
-
- index->cached = FALSE;
- index->magic_n = DICT_INDEX_MAGIC_N;
-
- return(index);
-}
-
-/**************************************************************************
-Creates and initializes a foreign constraint memory object. */
-
-dict_foreign_t*
-dict_mem_foreign_create(void)
-/*=========================*/
- /* out, own: foreign constraint struct */
-{
- dict_foreign_t* foreign;
- mem_heap_t* heap;
-
- heap = mem_heap_create(100);
-
- foreign = mem_heap_alloc(heap, sizeof(dict_foreign_t));
-
- foreign->heap = heap;
-
- foreign->id = NULL;
-
- foreign->type = 0;
- foreign->foreign_table_name = NULL;
- foreign->foreign_table = NULL;
- foreign->foreign_col_names = NULL;
-
- foreign->referenced_table_name = NULL;
- foreign->referenced_table = NULL;
- foreign->referenced_col_names = NULL;
-
- foreign->n_fields = 0;
-
- foreign->foreign_index = NULL;
- foreign->referenced_index = NULL;
-
- return(foreign);
-}
-
-/**************************************************************************
-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. */
-
-void
-dict_mem_index_add_field(
-/*=====================*/
- dict_index_t* index, /* in: index */
- const char* name, /* in: column name */
- ulint order, /* in: order criterion; 0 means an
- ascending order */
- ulint prefix_len) /* in: 0 or the column prefix length
- in a MySQL index like
- INDEX (textcol(25)) */
-{
- dict_field_t* field;
-
- ut_ad(index && name);
- ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
-
- index->n_def++;
-
- field = dict_index_get_nth_field(index, index->n_def - 1);
-
- field->name = name;
- field->order = order;
-
- field->prefix_len = prefix_len;
-}
-
-/**************************************************************************
-Frees an index memory object. */
-
-void
-dict_mem_index_free(
-/*================*/
- dict_index_t* index) /* in: index */
-{
- mem_heap_free(index->heap);
-}
diff --git a/innobase/dict/makefilewin b/innobase/dict/makefilewin
deleted file mode 100644
index e828d06943c..00000000000
--- a/innobase/dict/makefilewin
+++ /dev/null
@@ -1,21 +0,0 @@
-include ..\include\makefile.i
-
-dict.lib: dict0dict.obj dict0boot.obj dict0load.obj dict0mem.obj dict0crea.obj
- lib -out:..\libs\dict.lib dict0dict.obj dict0boot.obj dict0load.obj dict0mem.obj dict0crea.obj
-
-dict0dict.obj: dict0dict.c
- $(CCOM) $(CFL) -c dict0dict.c
-
-dict0boot.obj: dict0boot.c
- $(CCOM) $(CFL) -c dict0boot.c
-
-dict0mem.obj: dict0mem.c
- $(CCOM) $(CFL) -c dict0mem.c
-
-dict0crea.obj: dict0crea.c
- $(CCOM) $(CFL) -c dict0crea.c
-
-dict0load.obj: dict0load.c
- $(CCOM) $(CFL) -c dict0load.c
-
-