diff options
author | unknown <heikki@donna.mysql.fi> | 2001-10-10 22:47:08 +0300 |
---|---|---|
committer | unknown <heikki@donna.mysql.fi> | 2001-10-10 22:47:08 +0300 |
commit | 1904897be71cba7e6f2cf1192ba0cc2e8d907e00 (patch) | |
tree | fc361924d14a3d1727a8b88f61352ed039054720 /innobase/dict/dict0load.c | |
parent | 151ffe886b4b21499471658fdf01ea8347287092 (diff) | |
download | mariadb-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.c | 606 |
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); } |