summaryrefslogtreecommitdiff
path: root/innobase/dict/dict0load.c
diff options
context:
space:
mode:
authorunknown <heikki@donna.mysql.fi>2001-10-10 22:47:08 +0300
committerunknown <heikki@donna.mysql.fi>2001-10-10 22:47:08 +0300
commit1904897be71cba7e6f2cf1192ba0cc2e8d907e00 (patch)
treefc361924d14a3d1727a8b88f61352ed039054720 /innobase/dict/dict0load.c
parent151ffe886b4b21499471658fdf01ea8347287092 (diff)
downloadmariadb-git-1904897be71cba7e6f2cf1192ba0cc2e8d907e00.tar.gz
ut0mem.c Merge changes in InnoDB-3.23.43b
ut0ut.c Merge changes in InnoDB-3.23.43b trx0purge.c Merge changes in InnoDB-3.23.43b trx0rec.c Merge changes in InnoDB-3.23.43b trx0trx.c Merge changes in InnoDB-3.23.43b trx0undo.c Merge changes in InnoDB-3.23.43b thr0loc.c Merge changes in InnoDB-3.23.43b sync0arr.c Merge changes in InnoDB-3.23.43b sync0rw.c Merge changes in InnoDB-3.23.43b sync0sync.c Merge changes in InnoDB-3.23.43b srv0srv.c Merge changes in InnoDB-3.23.43b srv0start.c Merge changes in InnoDB-3.23.43b row0ins.c Merge changes in InnoDB-3.23.43b row0mysql.c Merge changes in InnoDB-3.23.43b row0purge.c Merge changes in InnoDB-3.23.43b row0sel.c Merge changes in InnoDB-3.23.43b row0umod.c Merge changes in InnoDB-3.23.43b row0upd.c Merge changes in InnoDB-3.23.43b row0vers.c Merge changes in InnoDB-3.23.43b rem0cmp.c Merge changes in InnoDB-3.23.43b que0que.c Merge changes in InnoDB-3.23.43b pars0opt.c Merge changes in InnoDB-3.23.43b pars0pars.c Merge changes in InnoDB-3.23.43b lexyy.c Merge changes in InnoDB-3.23.43b pars0grm.c Merge changes in InnoDB-3.23.43b page0page.c Merge changes in InnoDB-3.23.43b os0file.c Merge changes in InnoDB-3.23.43b mtr0log.c Merge changes in InnoDB-3.23.43b mem0pool.c Merge changes in InnoDB-3.23.43b log0log.c Merge changes in InnoDB-3.23.43b log0recv.c Merge changes in InnoDB-3.23.43b lock0lock.c Merge changes in InnoDB-3.23.43b ibuf0ibuf.c Merge changes in InnoDB-3.23.43b fil0fil.c Merge changes in InnoDB-3.23.43b dict0crea.c Merge changes in InnoDB-3.23.43b dict0dict.c Merge changes in InnoDB-3.23.43b dict0load.c Merge changes in InnoDB-3.23.43b dict0mem.c Merge changes in InnoDB-3.23.43b data0data.c Merge changes in InnoDB-3.23.43b data0type.c Merge changes in InnoDB-3.23.43b buf0buf.c Merge changes in InnoDB-3.23.43b buf0lru.c Merge changes in InnoDB-3.23.43b btr0btr.c Merge changes in InnoDB-3.23.43b btr0cur.c Merge changes in InnoDB-3.23.43b btr0pcur.c Merge changes in InnoDB-3.23.43b btr0sea.c Merge changes in InnoDB-3.23.43b data0type.ic Merge changes in InnoDB-3.23.43b dict0dict.ic Merge changes in InnoDB-3.23.43b mtr0mtr.ic Merge changes in InnoDB-3.23.43b row0upd.ic Merge changes in InnoDB-3.23.43b sync0ipm.ic Merge changes in InnoDB-3.23.43b sync0rw.ic Merge changes in InnoDB-3.23.43b sync0sync.ic Merge changes in InnoDB-3.23.43b trx0rseg.ic Merge changes in InnoDB-3.23.43b btr0pcur.ic Merge changes in InnoDB-3.23.43b buf0buf.ic Merge changes in InnoDB-3.23.43b data0data.ic Merge changes in InnoDB-3.23.43b row0upd.h Merge changes in InnoDB-3.23.43b srv0srv.h Merge changes in InnoDB-3.23.43b sync0arr.h Merge changes in InnoDB-3.23.43b sync0rw.h Merge changes in InnoDB-3.23.43b sync0sync.h Merge changes in InnoDB-3.23.43b trx0trx.h Merge changes in InnoDB-3.23.43b ut0mem.h Merge changes in InnoDB-3.23.43b data0data.h Merge changes in InnoDB-3.23.43b data0type.h Merge changes in InnoDB-3.23.43b db0err.h Merge changes in InnoDB-3.23.43b dict0crea.h Merge changes in InnoDB-3.23.43b dict0dict.h Merge changes in InnoDB-3.23.43b dict0load.h Merge changes in InnoDB-3.23.43b dict0mem.h Merge changes in InnoDB-3.23.43b dict0types.h Merge changes in InnoDB-3.23.43b fil0fil.h Merge changes in InnoDB-3.23.43b ibuf0ibuf.h Merge changes in InnoDB-3.23.43b lock0lock.h Merge changes in InnoDB-3.23.43b log0log.h Merge changes in InnoDB-3.23.43b mtr0mtr.h Merge changes in InnoDB-3.23.43b rem0cmp.h Merge changes in InnoDB-3.23.43b row0ins.h Merge changes in InnoDB-3.23.43b row0mysql.h Merge changes in InnoDB-3.23.43b btr0cur.h Merge changes in InnoDB-3.23.43b btr0pcur.h Merge changes in InnoDB-3.23.43b btr0sea.h Merge changes in InnoDB-3.23.43b buf0buf.h Merge changes in InnoDB-3.23.43b sql_table.cc Merge changes in InnoDB-3.23.43b sql_db.cc Merge changes in InnoDB-3.23.43b ha_innobase.cc Merge changes in InnoDB-3.23.43b handler.cc Merge changes in InnoDB-3.23.43b ha_innobase.h Merge changes in InnoDB-3.23.43b handler.h Merge changes in InnoDB-3.23.43b sql/ha_innobase.h: Merge changes in InnoDB-3.23.43b sql/handler.h: Merge changes in InnoDB-3.23.43b sql/ha_innobase.cc: Merge changes in InnoDB-3.23.43b sql/handler.cc: Merge changes in InnoDB-3.23.43b sql/sql_db.cc: Merge changes in InnoDB-3.23.43b sql/sql_table.cc: Merge changes in InnoDB-3.23.43b innobase/include/btr0cur.h: Merge changes in InnoDB-3.23.43b innobase/include/btr0pcur.h: Merge changes in InnoDB-3.23.43b innobase/include/btr0sea.h: Merge changes in InnoDB-3.23.43b innobase/include/buf0buf.h: Merge changes in InnoDB-3.23.43b innobase/include/data0data.h: Merge changes in InnoDB-3.23.43b innobase/include/data0type.h: Merge changes in InnoDB-3.23.43b innobase/include/db0err.h: Merge changes in InnoDB-3.23.43b innobase/include/dict0crea.h: Merge changes in InnoDB-3.23.43b innobase/include/dict0dict.h: Merge changes in InnoDB-3.23.43b innobase/include/dict0load.h: Merge changes in InnoDB-3.23.43b innobase/include/dict0mem.h: Merge changes in InnoDB-3.23.43b innobase/include/dict0types.h: Merge changes in InnoDB-3.23.43b innobase/include/fil0fil.h: Merge changes in InnoDB-3.23.43b innobase/include/ibuf0ibuf.h: Merge changes in InnoDB-3.23.43b innobase/include/lock0lock.h: Merge changes in InnoDB-3.23.43b innobase/include/log0log.h: Merge changes in InnoDB-3.23.43b innobase/include/mtr0mtr.h: Merge changes in InnoDB-3.23.43b innobase/include/rem0cmp.h: Merge changes in InnoDB-3.23.43b innobase/include/row0ins.h: Merge changes in InnoDB-3.23.43b innobase/include/row0mysql.h: Merge changes in InnoDB-3.23.43b innobase/include/row0upd.h: Merge changes in InnoDB-3.23.43b innobase/include/srv0srv.h: Merge changes in InnoDB-3.23.43b innobase/include/sync0arr.h: Merge changes in InnoDB-3.23.43b innobase/include/sync0rw.h: Merge changes in InnoDB-3.23.43b innobase/include/sync0sync.h: Merge changes in InnoDB-3.23.43b innobase/include/trx0trx.h: Merge changes in InnoDB-3.23.43b innobase/include/ut0mem.h: Merge changes in InnoDB-3.23.43b innobase/include/btr0pcur.ic: Merge changes in InnoDB-3.23.43b innobase/include/buf0buf.ic: Merge changes in InnoDB-3.23.43b innobase/include/data0data.ic: Merge changes in InnoDB-3.23.43b innobase/include/data0type.ic: Merge changes in InnoDB-3.23.43b innobase/include/dict0dict.ic: Merge changes in InnoDB-3.23.43b innobase/include/mtr0mtr.ic: Merge changes in InnoDB-3.23.43b innobase/include/row0upd.ic: Merge changes in InnoDB-3.23.43b innobase/include/sync0ipm.ic: Merge changes in InnoDB-3.23.43b innobase/include/sync0rw.ic: Merge changes in InnoDB-3.23.43b innobase/include/sync0sync.ic: Merge changes in InnoDB-3.23.43b innobase/include/trx0rseg.ic: Merge changes in InnoDB-3.23.43b innobase/btr/btr0btr.c: Merge changes in InnoDB-3.23.43b innobase/btr/btr0cur.c: Merge changes in InnoDB-3.23.43b innobase/btr/btr0pcur.c: Merge changes in InnoDB-3.23.43b innobase/btr/btr0sea.c: Merge changes in InnoDB-3.23.43b innobase/buf/buf0buf.c: Merge changes in InnoDB-3.23.43b innobase/buf/buf0lru.c: Merge changes in InnoDB-3.23.43b innobase/data/data0data.c: Merge changes in InnoDB-3.23.43b innobase/data/data0type.c: Merge changes in InnoDB-3.23.43b innobase/dict/dict0crea.c: Merge changes in InnoDB-3.23.43b innobase/dict/dict0dict.c: Merge changes in InnoDB-3.23.43b innobase/dict/dict0load.c: Merge changes in InnoDB-3.23.43b innobase/dict/dict0mem.c: Merge changes in InnoDB-3.23.43b innobase/fil/fil0fil.c: Merge changes in InnoDB-3.23.43b innobase/ibuf/ibuf0ibuf.c: Merge changes in InnoDB-3.23.43b innobase/lock/lock0lock.c: Merge changes in InnoDB-3.23.43b innobase/log/log0log.c: Merge changes in InnoDB-3.23.43b innobase/log/log0recv.c: Merge changes in InnoDB-3.23.43b innobase/mem/mem0pool.c: Merge changes in InnoDB-3.23.43b innobase/mtr/mtr0log.c: Merge changes in InnoDB-3.23.43b innobase/os/os0file.c: Merge changes in InnoDB-3.23.43b innobase/page/page0page.c: Merge changes in InnoDB-3.23.43b innobase/pars/lexyy.c: Merge changes in InnoDB-3.23.43b innobase/pars/pars0grm.c: Merge changes in InnoDB-3.23.43b innobase/pars/pars0opt.c: Merge changes in InnoDB-3.23.43b innobase/pars/pars0pars.c: Merge changes in InnoDB-3.23.43b innobase/que/que0que.c: Merge changes in InnoDB-3.23.43b innobase/rem/rem0cmp.c: Merge changes in InnoDB-3.23.43b innobase/row/row0ins.c: Merge changes in InnoDB-3.23.43b innobase/row/row0mysql.c: Merge changes in InnoDB-3.23.43b innobase/row/row0purge.c: Merge changes in InnoDB-3.23.43b innobase/row/row0sel.c: Merge changes in InnoDB-3.23.43b innobase/row/row0umod.c: Merge changes in InnoDB-3.23.43b innobase/row/row0upd.c: Merge changes in InnoDB-3.23.43b innobase/row/row0vers.c: Merge changes in InnoDB-3.23.43b innobase/srv/srv0srv.c: Merge changes in InnoDB-3.23.43b innobase/srv/srv0start.c: Merge changes in InnoDB-3.23.43b innobase/sync/sync0arr.c: Merge changes in InnoDB-3.23.43b innobase/sync/sync0rw.c: Merge changes in InnoDB-3.23.43b innobase/sync/sync0sync.c: Merge changes in InnoDB-3.23.43b innobase/thr/thr0loc.c: Merge changes in InnoDB-3.23.43b innobase/trx/trx0purge.c: Merge changes in InnoDB-3.23.43b innobase/trx/trx0rec.c: Merge changes in InnoDB-3.23.43b innobase/trx/trx0trx.c: Merge changes in InnoDB-3.23.43b innobase/trx/trx0undo.c: Merge changes in InnoDB-3.23.43b innobase/ut/ut0mem.c: Merge changes in InnoDB-3.23.43b innobase/ut/ut0ut.c: Merge changes in InnoDB-3.23.43b BitKeeper/etc/logging_ok: Logging to logging@openlogging.org accepted
Diffstat (limited to 'innobase/dict/dict0load.c')
-rw-r--r--innobase/dict/dict0load.c606
1 files changed, 549 insertions, 57 deletions
diff --git a/innobase/dict/dict0load.c b/innobase/dict/dict0load.c
index be16988086a..dcdc9ee01cd 100644
--- a/innobase/dict/dict0load.c
+++ b/innobase/dict/dict0load.c
@@ -48,8 +48,171 @@ dict_load_fields(
/************************************************************************
+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! */
+ char* name) /* in: database name which ends to '/' */
+{
+ 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;
+ char* table_name;
+ mtr_t mtr;
+
+ ut_ad(mutex_own(&(dict_sys->mutex)));
+
+ 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);
+
+ 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(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)) {
+
+ /* We found one */
+
+ table_name = mem_alloc(len + 1);
+ ut_memcpy(table_name, field, len);
+ table_name[len] = '\0';
+
+ 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;
+ char table_name[10000];
+ 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);
+
+ 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));
+
+ return;
+ }
+
+ field = rec_get_nth_field(rec, 0, &len);
+
+ if (!rec_get_deleted_flag(rec)) {
+
+ /* We found one */
+
+ ut_memcpy(table_name, field, len);
+ table_name[len] = '\0';
+
+ btr_pcur_store_position(&pcur, &mtr);
+
+ mtr_commit(&mtr);
+
+ table = dict_table_get_low(table_name);
+
+ if (table == NULL) {
+ fprintf(stderr, "InnoDB: Failed to load table %s\n",
+ table_name);
+ } else {
+ 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;
+}
+
+/************************************************************************
Loads a table definition and also all its index definitions, and also
-the cluster definition if the table is a member in a cluster. */
+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(
@@ -59,7 +222,6 @@ dict_load_table(
{
dict_table_t* table;
dict_table_t* sys_tables;
- mtr_t mtr;
btr_pcur_t pcur;
dict_index_t* sys_index;
dtuple_t* tuple;
@@ -71,6 +233,7 @@ dict_load_table(
char* buf;
ulint space;
ulint n_cols;
+ mtr_t mtr;
ut_ad(mutex_own(&(dict_sys->mutex)));
@@ -178,6 +341,106 @@ dict_load_table(
dict_load_indexes(table, heap);
+ ut_a(DB_SUCCESS == dict_load_foreigns(table->name));
+
+ 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;
+ char* name;
+ mtr_t mtr;
+
+ ut_ad(mutex_own(&(dict_sys->mutex)));
+
+ /* 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));
+ 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)) {
+ /* 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(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(rec, 1, &len);
+
+ name = mem_heap_alloc(heap, len + 1);
+ ut_memcpy(name, field, len);
+ name[len] = '\0';
+
+ /* Load the table definition to memory */
+ table = dict_load_table(name);
+
+ ut_a(table);
+
+ btr_pcur_close(&pcur);
+ mtr_commit(&mtr);
mem_heap_free(heap);
return(table);
@@ -305,7 +568,8 @@ dict_load_columns(
}
/************************************************************************
-Loads definitions for table indexes. */
+Loads definitions for table indexes. Adds them to the data dictionary cache.
+*/
static
void
dict_load_indexes(
@@ -446,7 +710,6 @@ dict_load_fields(
{
dict_table_t* sys_fields;
dict_index_t* sys_index;
- mtr_t mtr;
btr_pcur_t pcur;
dtuple_t* tuple;
dfield_t* dfield;
@@ -456,6 +719,7 @@ dict_load_fields(
ulint len;
byte* buf;
ulint i;
+ mtr_t mtr;
ut_ad(mutex_own(&(dict_sys->mutex)));
@@ -512,100 +776,328 @@ dict_load_fields(
mtr_commit(&mtr);
}
+/************************************************************************
+Loads foreign key constraint col names (also for the referenced table). */
+static
+void
+dict_load_foreign_cols(
+/*===================*/
+ 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;
+ char* col_name;
+ rec_t* rec;
+ byte* field;
+ ulint len;
+ ulint i;
+ mtr_t mtr;
+
+ ut_ad(mutex_own(&(dict_sys->mutex)));
+
+ 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);
+
+ 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));
+
+ field = rec_get_nth_field(rec, 0, &len);
+ ut_a(len == ut_strlen(id));
+ ut_a(ut_memcmp(id, field, len) == 0);
+
+ field = rec_get_nth_field(rec, 1, &len);
+ ut_a(len == 4);
+ ut_a(i == mach_read_from_4(field));
+
+ field = rec_get_nth_field(rec, 4, &len);
+
+ col_name = mem_heap_alloc(foreign->heap, len + 1);
+ ut_memcpy(col_name, field, len);
+ col_name[len] = '\0';
+
+ foreign->foreign_col_names[i] = col_name;
+
+ field = rec_get_nth_field(rec, 5, &len);
+
+ col_name = mem_heap_alloc(foreign->heap, len + 1);
+ ut_memcpy(col_name, field, len);
+ col_name[len] = '\0';
+
+ foreign->referenced_col_names[i] = col_name;
+
+ btr_pcur_move_to_next_user_rec(&pcur, &mtr);
+ }
+
+ btr_pcur_close(&pcur);
+ mtr_commit(&mtr);
+}
+
/***************************************************************************
-Loads a table object based on the table id. */
+Loads a foreign key constraint to the dictionary cache. */
+static
+ulint
+dict_load_foreign(
+/*==============*/
+ /* out: DB_SUCCESS or error code */
+ 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;
+
+ ut_ad(mutex_own(&(dict_sys->mutex)));
-dict_table_t*
-dict_load_table_on_id(
-/*==================*/
- /* out: table; NULL if table does not exist */
- dulint table_id) /* in: table id */
+ 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);
+
+ 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)) {
+ /* 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(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(rec, 5, &len));
+
+ ut_a(len == 4);
+
+ foreign->id = mem_heap_alloc(foreign->heap, ut_strlen(id) + 1);
+
+ ut_memcpy(foreign->id, id, ut_strlen(id) + 1);
+
+ field = rec_get_nth_field(rec, 3, &len);
+
+ foreign->foreign_table_name = mem_heap_alloc(foreign->heap, 1 + len);
+
+ ut_memcpy(foreign->foreign_table_name, field, len);
+ foreign->foreign_table_name[len] = '\0';
+
+ field = rec_get_nth_field(rec, 4, &len);
+
+ foreign->referenced_table_name = mem_heap_alloc(foreign->heap, 1 + len);
+
+ ut_memcpy(foreign->referenced_table_name, field, len);
+ foreign->referenced_table_name[len] = '\0';
+
+ btr_pcur_close(&pcur);
+ mtr_commit(&mtr);
+
+ dict_load_foreign_cols(id, foreign);
+
+ /* 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. */
+
+ 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 */
+ char* table_name) /* in: table name */
{
- mtr_t mtr;
- 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;
+ dict_index_t* sec_index;
+ dict_table_t* sys_foreign;
rec_t* rec;
byte* field;
ulint len;
- dict_table_t* table;
- char* name;
+ char* id ;
+ ulint err;
+ mtr_t mtr;
ut_ad(mutex_own(&(dict_sys->mutex)));
- /* NOTE that the operation of this function is protected by
- the dictionary mutex, and therefore no deadlocks can occur
- with other dictionary operations. */
+ 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);
+ }
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));
+
+ /* 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);
- /* 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);
+ dfield_set_data(dfield, table_name, ut_strlen(table_name));
+ dict_index_copy_types(tuple, sec_index, 1);
- btr_pcur_open_on_user_rec(sys_table_ids, tuple, PAGE_CUR_GE,
+ 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)
- || rec_get_deleted_flag(rec)) {
- /* Not found */
+ if (!btr_pcur_is_on_user_rec(&pcur, &mtr)) {
+ /* End of index */
- btr_pcur_close(&pcur);
- mtr_commit(&mtr);
- mem_heap_free(heap);
-
- return(NULL);
+ goto load_next_index;
}
- /*---------------------------------------------------*/
- /* Now we have the record in the secondary index containing the
- table ID and NAME */
+ /* 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(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) {
+ /* Check if the table name in record is the one searched for */
+ if (len != ut_strlen(table_name)
+ || 0 != ut_memcmp(field, table_name, len)) {
- btr_pcur_close(&pcur);
- mtr_commit(&mtr);
- mem_heap_free(heap);
-
- return(NULL);
+ goto load_next_index;
}
- /* Now we get the table name from the record */
+ if (rec_get_deleted_flag(rec)) {
+
+ goto next_rec;
+ }
+
+ /* Now we get a foreign key constraint id */
field = rec_get_nth_field(rec, 1, &len);
- name = mem_heap_alloc(heap, len + 1);
- ut_memcpy(name, field, len);
- name[len] = '\0';
+ id = mem_heap_alloc(heap, len + 1);
+ ut_memcpy(id, field, len);
+ id[len] = '\0';
- /* Load the table definition to memory */
- table = dict_load_table(name);
+ btr_pcur_store_position(&pcur, &mtr);
- ut_a(table);
+ 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);
- return(table);
+ if (sec_index != NULL) {
+
+ mtr_start(&mtr);
+
+ goto start_load;
+ }
+
+ return(DB_SUCCESS);
}