summaryrefslogtreecommitdiff
path: root/innobase/dict
diff options
context:
space:
mode:
authorheikki@hundin.mysql.fi <>2003-06-15 01:04:28 +0300
committerheikki@hundin.mysql.fi <>2003-06-15 01:04:28 +0300
commit4da7f485b75867dbc2ed02054459d1e8050144f3 (patch)
tree20d5e35fb0abb5c95cf3a833e58bcd4bf0a1c585 /innobase/dict
parent8a52c2d20bdb23ef154aa5c6a5980a2d763c9c4e (diff)
downloadmariadb-git-4da7f485b75867dbc2ed02054459d1e8050144f3.tar.gz
Many files:
Merge InnoDB-4.0.14: SAVEPOINT now implemented; InnoDB now accepts also column prefix keys; crashing bug in ON UPDATE CASCADE fixed; page checksum formula fixed
Diffstat (limited to 'innobase/dict')
-rw-r--r--innobase/dict/dict0boot.c16
-rw-r--r--innobase/dict/dict0crea.c28
-rw-r--r--innobase/dict/dict0dict.c162
-rw-r--r--innobase/dict/dict0load.c28
-rw-r--r--innobase/dict/dict0mem.c13
5 files changed, 169 insertions, 78 deletions
diff --git a/innobase/dict/dict0boot.c b/innobase/dict/dict0boot.c
index 374c567c3ca..0bf2ace3324 100644
--- a/innobase/dict/dict0boot.c
+++ b/innobase/dict/dict0boot.c
@@ -276,7 +276,7 @@ dict_boot(void)
DICT_HDR_SPACE,
DICT_UNIQUE | DICT_CLUSTERED, 1);
- dict_mem_index_add_field(index, (char *) "NAME", 0);
+ dict_mem_index_add_field(index, (char *) "NAME", 0, 0);
index->page_no = mtr_read_ulint(dict_hdr + DICT_HDR_TABLES,
MLOG_4BYTES, &mtr);
@@ -287,7 +287,7 @@ dict_boot(void)
index = dict_mem_index_create((char *) "SYS_TABLES",
(char *) "ID_IND", DICT_HDR_SPACE,
DICT_UNIQUE, 1);
- dict_mem_index_add_field(index, (char *) "ID", 0);
+ dict_mem_index_add_field(index, (char *) "ID", 0, 0);
index->page_no = mtr_read_ulint(dict_hdr + DICT_HDR_TABLE_IDS,
MLOG_4BYTES, &mtr);
@@ -313,8 +313,8 @@ dict_boot(void)
(char *) "CLUST_IND", DICT_HDR_SPACE,
DICT_UNIQUE | DICT_CLUSTERED, 2);
- dict_mem_index_add_field(index, (char *) "TABLE_ID", 0);
- dict_mem_index_add_field(index, (char *) "POS", 0);
+ dict_mem_index_add_field(index, (char *) "TABLE_ID", 0, 0);
+ dict_mem_index_add_field(index, (char *) "POS", 0, 0);
index->page_no = mtr_read_ulint(dict_hdr + DICT_HDR_COLUMNS,
MLOG_4BYTES, &mtr);
@@ -343,8 +343,8 @@ dict_boot(void)
(char *) "CLUST_IND", DICT_HDR_SPACE,
DICT_UNIQUE | DICT_CLUSTERED, 2);
- dict_mem_index_add_field(index, (char *) "TABLE_ID", 0);
- dict_mem_index_add_field(index, (char *) "ID", 0);
+ dict_mem_index_add_field(index, (char *) "TABLE_ID", 0, 0);
+ dict_mem_index_add_field(index, (char *) "ID", 0, 0);
index->page_no = mtr_read_ulint(dict_hdr + DICT_HDR_INDEXES,
MLOG_4BYTES, &mtr);
@@ -365,8 +365,8 @@ dict_boot(void)
(char *) "CLUST_IND", DICT_HDR_SPACE,
DICT_UNIQUE | DICT_CLUSTERED, 2);
- dict_mem_index_add_field(index, (char *) "INDEX_ID", 0);
- dict_mem_index_add_field(index, (char *) "POS", 0);
+ dict_mem_index_add_field(index, (char *) "INDEX_ID", 0, 0);
+ dict_mem_index_add_field(index, (char *) "POS", 0, 0);
index->page_no = mtr_read_ulint(dict_hdr + DICT_HDR_FIELDS,
MLOG_4BYTES, &mtr);
diff --git a/innobase/dict/dict0crea.c b/innobase/dict/dict0crea.c
index 3619ac02f4d..9139e589a0a 100644
--- a/innobase/dict/dict0crea.c
+++ b/innobase/dict/dict0crea.c
@@ -337,7 +337,7 @@ dict_create_index_for_cluster_step(
for (i = 0; i < table->n_cols; i++) {
col = dict_table_get_nth_col(table, i);
- dict_mem_index_add_field(index, col->name, 0);
+ dict_mem_index_add_field(index, col->name, 0, 0);
}
(node->cluster)->index = index;
@@ -450,9 +450,17 @@ dict_create_sys_fields_tuple(
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;
@@ -466,11 +474,25 @@ dict_create_sys_fields_tuple(
mach_write_to_8(ptr, index->id);
dfield_set_data(dfield, ptr, 8);
- /* 1: POS ----------------------------*/
+ /* 1: POS + PREFIX LENGTH ----------------------------*/
+
dfield = dtuple_get_nth_field(entry, 1);
ptr = mem_heap_alloc(heap, 4);
- mach_write_to_4(ptr, i);
+
+ 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 -------------------------*/
diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c
index c11a5f76d94..2fc05b1923f 100644
--- a/innobase/dict/dict0dict.c
+++ b/innobase/dict/dict0dict.c
@@ -88,15 +88,6 @@ dict_index_remove_from_cache(
dict_table_t* table, /* in: table */
dict_index_t* index); /* in, own: index */
/***********************************************************************
-Adds a column to index. */
-UNIV_INLINE
-void
-dict_index_add_col(
-/*===============*/
- dict_index_t* index, /* in: index */
- dict_col_t* col, /* in: column */
- ulint order); /* in: order criterion */
-/***********************************************************************
Copies fields contained in index2 to index1. */
static
void
@@ -482,8 +473,9 @@ dict_index_get_nth_col_pos(
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) {
- col = dict_table_get_nth_col(index->table, n);
return(col->clust_pos);
}
@@ -492,9 +484,8 @@ dict_index_get_nth_col_pos(
for (pos = 0; pos < n_fields; pos++) {
field = dict_index_get_nth_field(index, pos);
- col = field->col;
- if (dict_col_get_no(col) == n) {
+ if (col == field->col && field->prefix_len == 0) {
return(pos);
}
@@ -502,7 +493,46 @@ dict_index_get_nth_col_pos(
return(ULINT_UNDEFINED);
}
+
+/************************************************************************
+Looks for a matching field in an index. The column and the prefix len have
+to be the same. */
+
+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 == field2->prefix_len) {
+
+ return(pos);
+ }
+ }
+
+ return(ULINT_UNDEFINED);
+}
+
/**************************************************************************
Returns a table object, based on table id, and memoryfixes it. */
@@ -622,8 +652,7 @@ dict_table_get(
}
/**************************************************************************
-Returns a table object and increments MySQL open handle count on the table.
-*/
+Returns a table object and increments MySQL open handle count on the table. */
dict_table_t*
dict_table_get_and_increment_handle_count(
@@ -732,11 +761,12 @@ dict_table_add_to_cache(
}
/* Add table to hash table of tables */
- HASH_INSERT(dict_table_t, name_hash, dict_sys->table_hash, fold, table);
+ 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);
+ table);
/* Add table to LRU list of tables */
UT_LIST_ADD_FIRST(table_LRU, dict_sys->table_LRU, table);
@@ -828,7 +858,7 @@ dict_table_rename_in_cache(
/* 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);
+ ut_fold_string(table->name), table);
name_buf = mem_heap_alloc(table->heap, ut_strlen(new_name) + 1);
@@ -837,7 +867,8 @@ dict_table_rename_in_cache(
table->name = name_buf;
/* Add table to hash table of tables */
- HASH_INSERT(dict_table_t, name_hash, dict_sys->table_hash, fold, table);
+ HASH_INSERT(dict_table_t, name_hash, dict_sys->table_hash, fold,
+ table);
dict_sys->size += (mem_heap_get_size(table->heap) - old_size);
@@ -1128,7 +1159,6 @@ dict_index_add_to_cache(
ulint n_ord;
ibool success;
ulint i;
- ulint j;
ut_ad(index);
ut_ad(mutex_own(&(dict_sys->mutex)));
@@ -1158,28 +1188,6 @@ dict_index_add_to_cache(
return(FALSE);
}
-
- /* Check that the same column does not appear twice in the index.
- InnoDB assumes this in its algorithms, e.g., update of an index
- entry */
-
- for (i = 0; i < dict_index_get_n_fields(index); i++) {
-
- for (j = 0; j < i; j++) {
- if (dict_index_get_nth_field(index, j)->col
- == dict_index_get_nth_field(index, i)->col) {
-
- ut_print_timestamp(stderr);
-
- fprintf(stderr,
-" InnoDB: Error: column %s appears twice in index %s of table %s\n"
-"InnoDB: This is not allowed in InnoDB.\n"
-"InnoDB: UPDATE can cause such an index to become corrupt in InnoDB.\n",
- dict_index_get_nth_field(index, i)->col->name,
- index->name, table->name);
- }
- }
- }
/* Build the cache internal representation of the index,
containing also the added system fields */
@@ -1223,8 +1231,8 @@ dict_index_add_to_cache(
cluster = dict_table_get_low(table->cluster_name);
- tree = dict_index_get_tree(UT_LIST_GET_FIRST(cluster->indexes));
-
+ tree = dict_index_get_tree(
+ UT_LIST_GET_FIRST(cluster->indexes));
new_index->tree = tree;
new_index->page_no = tree->page;
} else {
@@ -1352,13 +1360,14 @@ UNIV_INLINE
void
dict_index_add_col(
/*===============*/
- dict_index_t* index, /* in: index */
- dict_col_t* col, /* in: column */
- ulint order) /* in: order criterion */
+ 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);
+ dict_mem_index_add_field(index, col->name, order, prefix_len);
field = dict_index_get_nth_field(index, index->n_def - 1);
@@ -1384,7 +1393,8 @@ dict_index_copy(
for (i = start; i < end; i++) {
field = dict_index_get_nth_field(index2, i);
- dict_index_add_col(index1, field->col, field->order);
+ dict_index_add_col(index1, field->col, field->order,
+ field->prefix_len);
}
}
@@ -1487,7 +1497,7 @@ dict_index_build_internal_clust(
/* Add the mix id column */
dict_index_add_col(new_index,
- dict_table_get_sys_col(table, DATA_MIX_ID), 0);
+ 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,
@@ -1525,14 +1535,15 @@ dict_index_build_internal_clust(
if (!(index->type & DICT_UNIQUE)) {
dict_index_add_col(new_index,
- dict_table_get_sys_col(table, DATA_ROW_ID), 0);
+ 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);
+ 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);
+ dict_table_get_sys_col(table, DATA_ROLL_PTR), 0, 0);
for (i = 0; i < trx_id_pos; i++) {
@@ -1561,7 +1572,14 @@ dict_index_build_internal_clust(
for (i = 0; i < new_index->n_def; i++) {
field = dict_index_get_nth_field(new_index, i);
- (field->col)->aux = 0;
+
+ /* 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
@@ -1572,7 +1590,7 @@ dict_index_build_internal_clust(
ut_ad(col->type.mtype != DATA_SYS);
if (col->aux == ULINT_UNDEFINED) {
- dict_index_add_col(new_index, col, 0);
+ dict_index_add_col(new_index, col, 0, 0);
}
}
@@ -1584,7 +1602,11 @@ dict_index_build_internal_clust(
for (i = 0; i < new_index->n_def; i++) {
field = dict_index_get_nth_field(new_index, i);
- (field->col)->clust_pos = i;
+
+ if (field->prefix_len == 0) {
+
+ field->col->clust_pos = i;
+ }
}
new_index->cached = TRUE;
@@ -1646,25 +1668,33 @@ dict_index_build_internal_non_clust(
for (i = 0; i < clust_index->n_uniq; i++) {
field = dict_index_get_nth_field(clust_index, i);
- (field->col)->aux = ULINT_UNDEFINED;
+ 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);
- (field->col)->aux = 0;
+
+ /* 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 columns necessary to determine the clustered
+ /* 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);
+ if (field->col->aux == ULINT_UNDEFINED) {
+ dict_index_add_col(new_index, field->col, 0,
+ field->prefix_len);
}
}
@@ -1787,6 +1817,14 @@ dict_foreign_find_index(
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 (ut_strlen(columns[i]) !=
ut_strlen(col_name)
|| 0 != ut_cmp_in_lower_case(columns[i],
@@ -3776,6 +3814,10 @@ dict_field_print_low(
ut_ad(mutex_own(&(dict_sys->mutex)));
printf(" %s", field->name);
+
+ if (field->prefix_len != 0) {
+ printf("(%lu)", field->prefix_len);
+ }
}
/**************************************************************************
diff --git a/innobase/dict/dict0load.c b/innobase/dict/dict0load.c
index 8f39605e493..48c445fa0c9 100644
--- a/innobase/dict/dict0load.c
+++ b/innobase/dict/dict0load.c
@@ -301,6 +301,8 @@ dict_load_fields(
dtuple_t* tuple;
dfield_t* dfield;
char* col_name;
+ ulint pos_and_prefix_len;
+ ulint prefix_len;
rec_t* rec;
byte* field;
ulint len;
@@ -345,8 +347,28 @@ dict_load_fields(
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(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 & 0xFFFF) == i
+ || (pos_and_prefix_len & 0xFFFF0000) == (i << 16));
+
+ if ((i == 0 && pos_and_prefix_len > 0)
+ || (pos_and_prefix_len & 0xFFFF0000) > 0) {
+
+ prefix_len = pos_and_prefix_len & 0xFFFF;
+ } else {
+ prefix_len = 0;
+ }
ut_a(0 == ut_strcmp((char*) "COL_NAME",
dict_field_get_col(
@@ -359,7 +381,7 @@ dict_load_fields(
ut_memcpy(col_name, field, len);
col_name[len] = '\0';
- dict_mem_index_add_field(index, col_name, 0);
+ dict_mem_index_add_field(index, col_name, 0, prefix_len);
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
}
diff --git a/innobase/dict/dict0mem.c b/innobase/dict/dict0mem.c
index e5918c6aeb6..56efc0a0117 100644
--- a/innobase/dict/dict0mem.c
+++ b/innobase/dict/dict0mem.c
@@ -266,10 +266,13 @@ by the column name may be released only after publishing the index. */
void
dict_mem_index_add_field(
/*=====================*/
- dict_index_t* index, /* in: index */
- char* name, /* in: column name */
- ulint order) /* in: order criterion; 0 means an ascending
- order */
+ dict_index_t* index, /* in: index */
+ 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;
@@ -282,6 +285,8 @@ dict_mem_index_add_field(
field->name = name;
field->order = order;
+
+ field->prefix_len = prefix_len;
}
/**************************************************************************