mirror of
https://github.com/MariaDB/server.git
synced 2025-01-19 05:22:25 +01:00
611 lines
14 KiB
C
611 lines
14 KiB
C
/******************************************************
|
|
Loads to the memory cache database object definitions
|
|
from dictionary tables
|
|
|
|
(c) 1996 Innobase Oy
|
|
|
|
Created 4/24/1996 Heikki Tuuri
|
|
*******************************************************/
|
|
|
|
#include "dict0load.h"
|
|
|
|
#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"
|
|
|
|
/************************************************************************
|
|
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 */
|
|
/************************************************************************
|
|
Loads definitions for table indexes. */
|
|
static
|
|
void
|
|
dict_load_indexes(
|
|
/*==============*/
|
|
dict_table_t* table, /* in: table */
|
|
mem_heap_t* heap); /* in: memory heap for temporary storage */
|
|
/************************************************************************
|
|
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 */
|
|
|
|
|
|
/************************************************************************
|
|
Loads a table definition and also all its index definitions, and also
|
|
the cluster definition if the table is a member in a cluster. */
|
|
|
|
dict_table_t*
|
|
dict_load_table(
|
|
/*============*/
|
|
/* out: table, NULL if does not exist */
|
|
char* name) /* in: table name */
|
|
{
|
|
dict_table_t* table;
|
|
dict_table_t* sys_tables;
|
|
mtr_t mtr;
|
|
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* buf;
|
|
ulint space;
|
|
ulint n_cols;
|
|
|
|
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);
|
|
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);
|
|
}
|
|
|
|
field = rec_get_nth_field(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(
|
|
dict_table_get_first_index(sys_tables), 9))->name));
|
|
|
|
field = rec_get_nth_field(rec, 9, &len);
|
|
space = mach_read_from_4(field);
|
|
|
|
ut_a(0 == ut_strcmp("N_COLS",
|
|
dict_field_get_col(
|
|
dict_index_get_nth_field(
|
|
dict_table_get_first_index(sys_tables), 4))->name));
|
|
|
|
field = rec_get_nth_field(rec, 4, &len);
|
|
n_cols = mach_read_from_4(field);
|
|
|
|
table = dict_mem_table_create(name, space, n_cols);
|
|
|
|
ut_a(0 == ut_strcmp("ID",
|
|
dict_field_get_col(
|
|
dict_index_get_nth_field(
|
|
dict_table_get_first_index(sys_tables), 3))->name));
|
|
|
|
field = rec_get_nth_field(rec, 3, &len);
|
|
table->id = mach_read_from_8(field);
|
|
|
|
field = rec_get_nth_field(rec, 5, &len);
|
|
table->type = mach_read_from_4(field);
|
|
|
|
if (table->type == DICT_TABLE_CLUSTER_MEMBER) {
|
|
ut_a(0);
|
|
|
|
field = rec_get_nth_field(rec, 6, &len);
|
|
table->mix_id = mach_read_from_8(field);
|
|
|
|
field = rec_get_nth_field(rec, 8, &len);
|
|
buf = mem_heap_alloc(heap, len);
|
|
ut_memcpy(buf, field, len);
|
|
|
|
table->cluster_name = buf;
|
|
}
|
|
|
|
if ((table->type == DICT_TABLE_CLUSTER)
|
|
|| (table->type == DICT_TABLE_CLUSTER_MEMBER)) {
|
|
|
|
field = rec_get_nth_field(rec, 7, &len);
|
|
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);
|
|
|
|
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;
|
|
|
|
ut_ad(mutex_own(&(dict_sys->mutex)));
|
|
|
|
heap = mem_heap_create(1000);
|
|
|
|
dict_load_indexes(table, heap);
|
|
|
|
mem_heap_free(heap);
|
|
}
|
|
|
|
/************************************************************************
|
|
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_buf;
|
|
char* name;
|
|
ulint mtype;
|
|
ulint prtype;
|
|
ulint col_len;
|
|
ulint prec;
|
|
ulint i;
|
|
mtr_t mtr;
|
|
|
|
ut_ad(mutex_own(&(dict_sys->mutex)));
|
|
|
|
mtr_start(&mtr);
|
|
|
|
sys_columns = dict_table_get_low("SYS_COLUMNS");
|
|
sys_index = UT_LIST_GET_FIRST(sys_columns->indexes);
|
|
|
|
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));
|
|
|
|
field = rec_get_nth_field(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(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(
|
|
dict_table_get_first_index(sys_columns), 4))->name));
|
|
|
|
field = rec_get_nth_field(rec, 4, &len);
|
|
|
|
name_buf = mem_heap_alloc(heap, len + 1);
|
|
ut_memcpy(name_buf, field, len);
|
|
name_buf[len] = '\0';
|
|
|
|
name = name_buf;
|
|
|
|
field = rec_get_nth_field(rec, 5, &len);
|
|
mtype = mach_read_from_4(field);
|
|
|
|
field = rec_get_nth_field(rec, 6, &len);
|
|
prtype = mach_read_from_4(field);
|
|
|
|
field = rec_get_nth_field(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(
|
|
dict_table_get_first_index(sys_columns), 8))->name));
|
|
|
|
field = rec_get_nth_field(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);
|
|
}
|
|
|
|
/************************************************************************
|
|
Loads definitions for table indexes. */
|
|
static
|
|
void
|
|
dict_load_indexes(
|
|
/*==============*/
|
|
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;
|
|
|
|
ut_ad(mutex_own(&(dict_sys->mutex)));
|
|
|
|
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);
|
|
|
|
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(rec, 0, &len);
|
|
ut_ad(len == 8);
|
|
|
|
if (ut_memcmp(buf, field, len) != 0) {
|
|
break;
|
|
}
|
|
|
|
ut_a(!rec_get_deleted_flag(rec));
|
|
|
|
field = rec_get_nth_field(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(
|
|
dict_table_get_first_index(sys_indexes), 4))->name));
|
|
|
|
field = rec_get_nth_field(rec, 4, &name_len);
|
|
|
|
name_buf = mem_heap_alloc(heap, name_len + 1);
|
|
ut_memcpy(name_buf, field, name_len);
|
|
name_buf[name_len] = '\0';
|
|
|
|
field = rec_get_nth_field(rec, 5, &len);
|
|
n_fields = mach_read_from_4(field);
|
|
|
|
field = rec_get_nth_field(rec, 6, &len);
|
|
type = mach_read_from_4(field);
|
|
|
|
field = rec_get_nth_field(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(
|
|
dict_table_get_first_index(sys_indexes), 8))->name));
|
|
|
|
field = rec_get_nth_field(rec, 8, &len);
|
|
page_no = mach_read_from_4(field);
|
|
|
|
if (is_sys_table
|
|
&& ((type & DICT_CLUSTERED)
|
|
|| ((table == dict_sys->sys_tables)
|
|
&& (name_len == ut_strlen("ID_IND"))
|
|
&& (0 == ut_memcmp(name_buf, "ID_IND",
|
|
name_len))))) {
|
|
|
|
/* The index was created in memory already in
|
|
booting */
|
|
} else {
|
|
index = dict_mem_index_create(table->name, name_buf,
|
|
space, type, n_fields);
|
|
index->page_no = page_no;
|
|
index->id = id;
|
|
|
|
dict_load_fields(table, index, heap);
|
|
|
|
dict_index_add_to_cache(table, index);
|
|
}
|
|
|
|
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
|
|
}
|
|
|
|
btr_pcur_close(&pcur);
|
|
mtr_commit(&mtr);
|
|
}
|
|
|
|
/************************************************************************
|
|
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;
|
|
mtr_t mtr;
|
|
btr_pcur_t pcur;
|
|
dtuple_t* tuple;
|
|
dfield_t* dfield;
|
|
char* col_name;
|
|
rec_t* rec;
|
|
byte* field;
|
|
ulint len;
|
|
byte* buf;
|
|
ulint i;
|
|
|
|
ut_ad(mutex_own(&(dict_sys->mutex)));
|
|
|
|
UT_NOT_USED(table);
|
|
|
|
mtr_start(&mtr);
|
|
|
|
sys_fields = dict_table_get_low("SYS_FIELDS");
|
|
sys_index = UT_LIST_GET_FIRST(sys_fields->indexes);
|
|
|
|
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));
|
|
ut_a(!rec_get_deleted_flag(rec));
|
|
|
|
field = rec_get_nth_field(rec, 0, &len);
|
|
ut_ad(len == 8);
|
|
ut_a(ut_memcmp(buf, field, len) == 0);
|
|
|
|
field = rec_get_nth_field(rec, 1, &len);
|
|
ut_ad(len == 4);
|
|
ut_a(i == mach_read_from_4(field));
|
|
|
|
ut_a(0 == ut_strcmp("COL_NAME",
|
|
dict_field_get_col(
|
|
dict_index_get_nth_field(
|
|
dict_table_get_first_index(sys_fields), 4))->name));
|
|
|
|
field = rec_get_nth_field(rec, 4, &len);
|
|
|
|
col_name = mem_heap_alloc(heap, len + 1);
|
|
ut_memcpy(col_name, field, len);
|
|
col_name[len] = '\0';
|
|
|
|
dict_mem_index_add_field(index, col_name, 0);
|
|
|
|
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. */
|
|
|
|
dict_table_t*
|
|
dict_load_table_on_id(
|
|
/*==================*/
|
|
/* out: table; NULL if table does not exist */
|
|
dulint table_id) /* in: table id */
|
|
{
|
|
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;
|
|
rec_t* rec;
|
|
byte* field;
|
|
ulint len;
|
|
dict_table_t* table;
|
|
char* name;
|
|
|
|
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);
|
|
}
|