26
26
#include "pars0sym.h"
27
27
#include "que0que.h"
28
28
#include "rem0cmp.h"
29
#include "row0merge.h"
29
30
#ifndef UNIV_HOTBACKUP
30
# include <mystrings/m_ctype.h> /* my_isspace() */
31
# if defined(BUILD_DRIZZLE)
32
# include <mystrings/m_ctype.h>
34
# include "m_ctype.h" /* my_isspace() */
36
# include "ha_prototypes.h" /* innobase_strcasecmp() */
31
37
#endif /* !UNIV_HOTBACKUP */
35
dict_sys_t* dict_sys = NULL; /* the dictionary system */
37
rw_lock_t dict_operation_lock; /* table create, drop, etc. reserve
38
this in X-mode; implicit or backround
39
operations purge, rollback, foreign
40
key checks reserve this in S-mode; we
41
cannot trust that MySQL protects
42
implicit or background operations
43
a table drop since MySQL does not
44
know of them; therefore we need this;
45
NOTE: a transaction which reserves
46
this must keep book on the mode in
47
trx->dict_operation_lock_mode */
49
#define DICT_HEAP_SIZE 100 /* initial memory heap size when
50
creating a table or index object */
41
/* the dictionary system */
42
UNIV_INTERN dict_sys_t* dict_sys = NULL;
44
/* table create, drop, etc. reserve this in X-mode; implicit or
45
backround operations purge, rollback, foreign key checks reserve this
46
in S-mode; we cannot trust that MySQL protects implicit or background
47
operations a table drop since MySQL does not know of them; therefore
48
we need this; NOTE: a transaction which reserves this must keep book
49
on the mode in trx->dict_operation_lock_mode */
50
UNIV_INTERN rw_lock_t dict_operation_lock;
51
52
#define DICT_POOL_PER_TABLE_HASH 512 /* buffer pool max size per table
52
53
hash table fixed size in bytes */
53
#define DICT_POOL_PER_VARYING 4 /* buffer pool max size per data
54
dictionary varying size in bytes */
56
55
/* Identifies generated InnoDB foreign key names */
57
56
static char dict_ibfk[] = "_ibfk_";
84
83
ulint len); /* in: length of 'to', in bytes;
85
84
should be at least 3 * strlen(to) + 1 */
86
85
/**********************************************************************
87
Compares NUL-terminated UTF-8 strings case insensitively.
89
NOTE: the prototype of this function is copied from ha_innodb.cc! If you change
90
this function, you MUST change also the prototype here! */
95
/* out: 0 if a=b, <0 if a<b, >1 if a>b */
96
const char* a, /* in: first string to compare */
97
const char* b); /* in: second string to compare */
99
/**********************************************************************
100
86
Makes all characters in a NUL-terminated UTF-8 string lower case.
102
88
NOTE: the prototype of this function is copied from ha_innodb.cc! If you change
103
89
this function, you MUST change also the prototype here! */
106
92
innobase_casedn_str(
107
93
/*================*/
119
105
void* mysql_thd); /* in: MySQL thread handle */
120
106
#endif /* !UNIV_HOTBACKUP */
122
/**************************************************************************
123
Removes an index from the dictionary cache. */
126
dict_index_remove_from_cache(
127
/*=========================*/
128
dict_table_t* table, /* in: table */
129
dict_index_t* index); /* in, own: index */
130
/***********************************************************************
131
Copies fields contained in index2 to index1. */
136
dict_index_t* index1, /* in: index to copy to */
137
dict_index_t* index2, /* in: index to copy from */
138
dict_table_t* table, /* in: table */
139
ulint start, /* in: first position to copy */
140
ulint end); /* in: last position to copy */
141
108
/***********************************************************************
142
109
Tries to find column names for the index and sets the col field of the
155
122
dict_index_build_internal_clust(
156
123
/*============================*/
157
/* out, own: the internal representation
158
of the clustered index */
159
dict_table_t* table, /* in: table */
160
dict_index_t* index); /* in: user representation of a clustered
124
/* out, own: the internal
125
representation of the clustered
127
const dict_table_t* table, /* in: table */
128
dict_index_t* index); /* in: user representation of
162
130
/***********************************************************************
163
131
Builds the internal dictionary cache representation for a non-clustered
164
132
index, containing also system fields not defined by the user. */
167
135
dict_index_build_internal_non_clust(
168
136
/*================================*/
169
/* out, own: the internal representation
170
of the non-clustered index */
171
dict_table_t* table, /* in: table */
172
dict_index_t* index); /* in: user representation of a non-clustered
137
/* out, own: the internal
138
representation of the non-clustered
140
const dict_table_t* table, /* in: table */
141
dict_index_t* index); /* in: user representation of
142
a non-clustered index */
174
143
/**************************************************************************
175
144
Removes a foreign constraint struct from the dictionary cache. */
303
272
/************************************************************************
304
273
Decrements the count of open MySQL handles to a table. */
307
276
dict_table_decrement_handle_count(
308
277
/*==============================*/
309
dict_table_t* table) /* in: table */
278
dict_table_t* table, /* in/out: table */
279
ibool dict_locked) /* in: TRUE=data dictionary locked */
311
mutex_enter(&(dict_sys->mutex));
282
mutex_enter(&dict_sys->mutex);
285
ut_ad(mutex_own(&dict_sys->mutex));
313
286
ut_a(table->n_mysql_handles_opened > 0);
315
288
table->n_mysql_handles_opened--;
317
mutex_exit(&(dict_sys->mutex));
320
/*************************************************************************
321
Gets the column data type. */
324
dict_col_copy_type_noninline(
325
/*=========================*/
326
const dict_col_t* col, /* in: column */
327
dtype_t* type) /* out: data type */
329
dict_col_copy_type(col, type);
332
/************************************************************************
333
Gets the nth column of a table. */
336
dict_table_get_nth_col_noninline(
337
/*=============================*/
338
/* out: pointer to column object */
339
const dict_table_t* table, /* in: table */
340
ulint pos) /* in: position of column */
342
return(dict_table_get_nth_col(table, pos));
345
/************************************************************************
346
Gets the first index on the table (the clustered index). */
349
dict_table_get_first_index_noninline(
350
/*=================================*/
351
/* out: index, NULL if none exists */
352
dict_table_t* table) /* in: table */
354
return(dict_table_get_first_index(table));
357
/************************************************************************
358
Gets the next index on the table. */
361
dict_table_get_next_index_noninline(
362
/*================================*/
363
/* out: index, NULL if none left */
364
dict_index_t* index) /* in: index */
366
return(dict_table_get_next_index(index));
369
/**************************************************************************
370
Returns an index object. */
373
dict_table_get_index_noninline(
374
/*===========================*/
375
/* out: index, NULL if does not exist */
376
dict_table_t* table, /* in: table */
377
const char* name) /* in: index name */
379
return(dict_table_get_index(table, name));
291
mutex_exit(&dict_sys->mutex);
382
295
/**************************************************************************
383
296
Returns a column's name. */
386
299
dict_table_get_col_name(
387
300
/*====================*/
481
394
/************************************************************************
482
395
Release the autoinc lock.*/
485
398
dict_table_autoinc_unlock(
486
399
/*======================*/
487
dict_table_t* table) /* in: release autoinc lock for this table */
400
dict_table_t* table) /* in/out: table */
489
402
mutex_exit(&table->autoinc_mutex);
405
/**************************************************************************
406
Looks for an index with the given table and index id.
407
NOTE that we do not reserve the dictionary mutex. */
410
dict_index_get_on_id_low(
411
/*=====================*/
412
/* out: index or NULL if not found
414
dict_table_t* table, /* in: table */
415
dulint id) /* in: index id */
419
index = dict_table_get_first_index(table);
422
if (0 == ut_dulint_cmp(id, index->id)) {
428
index = dict_table_get_next_index(index);
492
434
/************************************************************************
493
435
Looks for column n in an index. */
496
438
dict_index_get_nth_col_pos(
497
439
/*=======================*/
498
/* out: position in internal representation
499
of the index; if not contained, returns
501
dict_index_t* index, /* in: index */
502
ulint n) /* in: column number */
440
/* out: position in internal
441
representation of the index;
442
if not contained, returns
444
const dict_index_t* index, /* in: index */
445
ulint n) /* in: column number */
504
447
const dict_field_t* field;
505
448
const dict_col_t* col;
575
518
column in index must be complete, or must contain a prefix longer than the
576
519
column in index2. That is, we must be able to construct the prefix in index2
577
520
from the prefix in index. */
580
523
dict_index_get_nth_field_pos(
581
524
/*=========================*/
582
/* out: position in internal representation
583
of the index; if not contained, returns
585
dict_index_t* index, /* in: index from which to search */
586
dict_index_t* index2, /* in: index */
587
ulint n) /* in: field number in index2 */
525
/* out: position in internal
526
representation of the index;
527
if not contained, returns
529
const dict_index_t* index, /* in: index from which to search */
530
const dict_index_t* index2, /* in: index */
531
ulint n) /* in: field number in index2 */
590
dict_field_t* field2;
533
const dict_field_t* field;
534
const dict_field_t* field2;
595
539
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
650
594
/************************************************************************
651
595
Looks for column n position in the clustered index. */
654
598
dict_table_get_nth_col_pos(
655
599
/*=======================*/
656
/* out: position in internal representation
657
of the clustered index */
658
dict_table_t* table, /* in: table */
659
ulint n) /* in: column number */
600
/* out: position in internal
602
the clustered index */
603
const dict_table_t* table, /* in: table */
604
ulint n) /* in: column number */
661
606
return(dict_index_get_nth_col_pos(dict_table_get_first_index(table),
665
610
/************************************************************************
666
Check whether the table uses the compact page format. */
669
dict_table_is_comp_noninline(
670
/*=========================*/
671
/* out: TRUE if table uses the
672
compact page format */
673
const dict_table_t* table) /* in: table */
675
return(dict_table_is_comp(table));
678
/************************************************************************
679
611
Checks if a column is in the ordering columns of the clustered index of a
680
612
table. Column prefixes are treated like whole columns. */
683
615
dict_table_col_in_clustered_key(
684
616
/*============================*/
685
/* out: TRUE if the column, or its prefix, is
686
in the clustered key */
687
dict_table_t* table, /* in: table */
688
ulint n) /* in: column number */
617
/* out: TRUE if the column, or its
618
prefix, is in the clustered key */
619
const dict_table_t* table, /* in: table */
620
ulint n) /* in: column number */
622
const dict_index_t* index;
691
623
const dict_field_t* field;
692
624
const dict_col_t* col;
953
887
dict_index_t* index;
890
const char* old_name;
960
893
ut_ad(mutex_own(&(dict_sys->mutex)));
962
895
old_size = mem_heap_get_size(table->heap);
896
old_name = table->name;
964
898
fold = ut_fold_string(new_name);
966
900
/* Look for a table with the same name: error if such exists */
968
902
dict_table_t* table2;
969
HASH_SEARCH(name_hash, dict_sys->table_hash, fold, table2,
903
HASH_SEARCH(name_hash, dict_sys->table_hash, fold,
904
dict_table_t*, table2,
970
905
(ut_strcmp(table2->name, new_name) == 0));
973
"InnoDB: Error: dictionary cache"
974
" already contains a table of name %s\n",
906
if (UNIV_LIKELY_NULL(table2)) {
907
ut_print_timestamp(stderr);
908
fputs(" InnoDB: Error: dictionary cache"
909
" already contains a table ", stderr);
910
ut_print_name(stderr, NULL, TRUE, new_name);
912
"InnoDB: cannot rename table ", stderr);
913
ut_print_name(stderr, NULL, TRUE, old_name);
983
922
if (table->space != 0) {
984
923
if (table->dir_path_of_temp_table != NULL) {
986
"InnoDB: Error: trying to rename a table"
987
" %s (%s) created with CREATE\n"
988
"InnoDB: TEMPORARY TABLE\n",
989
table->name, table->dir_path_of_temp_table);
992
success = fil_rename_tablespace(
993
table->name, table->space, new_name);
924
ut_print_timestamp(stderr);
925
fputs(" InnoDB: Error: trying to rename a"
926
" TEMPORARY TABLE ", stderr);
927
ut_print_name(stderr, NULL, TRUE, old_name);
929
ut_print_filename(stderr,
930
table->dir_path_of_temp_table);
931
fputs(" )\n", stderr);
933
} else if (!fil_rename_tablespace(old_name, table->space,
1002
939
/* Remove table from the hash tables of tables */
1003
940
HASH_DELETE(dict_table_t, name_hash, dict_sys->table_hash,
1004
ut_fold_string(table->name), table);
1005
old_name = mem_heap_strdup(table->heap, table->name);
941
ut_fold_string(old_name), table);
1006
942
table->name = mem_heap_strdup(table->heap, new_name);
1008
944
/* Add table to hash table of tables */
1242
1178
dict_mem_table_free(table);
1245
/*************************************************************************
1246
Gets the column position in the clustered index. */
1249
dict_col_get_clust_pos_noninline(
1250
/*=============================*/
1251
const dict_col_t* col, /* in: table column */
1252
const dict_index_t* clust_index) /* in: clustered index */
1254
return(dict_col_get_clust_pos(col, clust_index));
1257
1181
/********************************************************************
1258
1182
If the given column name is reserved for InnoDB system columns, return
1262
1186
dict_col_name_is_reserved(
1263
1187
/*======================*/
1213
/********************************************************************
1214
If an undo log record for this table might not fit on a single page,
1218
dict_index_too_big_for_undo(
1219
/*========================*/
1220
/* out: TRUE if the undo log
1221
record could become too big */
1222
const dict_table_t* table, /* in: table */
1223
const dict_index_t* new_index) /* in: index */
1225
/* Make sure that all column prefixes will fit in the undo log record
1226
in trx_undo_page_report_modify() right after trx_undo_page_init(). */
1229
const dict_index_t* clust_index
1230
= dict_table_get_first_index(table);
1232
= TRX_UNDO_PAGE_HDR - TRX_UNDO_PAGE_HDR_SIZE
1233
+ 2 /* next record pointer */
1235
+ 11 /* trx->undo_no */ - 11 /* table->id */
1236
+ 1 /* rec_get_info_bits() */
1237
+ 11 /* DB_TRX_ID */
1238
+ 11 /* DB_ROLL_PTR */
1239
+ 10 + FIL_PAGE_DATA_END /* trx_undo_left() */
1240
+ 2/* pointer to previous undo log record */;
1242
if (UNIV_UNLIKELY(!clust_index)) {
1243
ut_a(dict_index_is_clust(new_index));
1244
clust_index = new_index;
1247
/* Add the size of the ordering columns in the
1249
for (i = 0; i < clust_index->n_uniq; i++) {
1250
const dict_col_t* col
1251
= dict_index_get_nth_col(clust_index, i);
1253
/* Use the maximum output size of
1254
mach_write_compressed(), although the encoded
1255
length should always fit in 2 bytes. */
1256
undo_page_len += 5 + dict_col_get_max_size(col);
1259
/* Add the old values of the columns to be updated.
1260
First, the amount and the numbers of the columns.
1261
These are written by mach_write_compressed() whose
1262
maximum output length is 5 bytes. However, given that
1263
the quantities are below REC_MAX_N_FIELDS (10 bits),
1264
the maximum length is 2 bytes per item. */
1265
undo_page_len += 2 * (dict_table_get_n_cols(table) + 1);
1267
for (i = 0; i < clust_index->n_def; i++) {
1268
const dict_col_t* col
1269
= dict_index_get_nth_col(clust_index, i);
1271
= dict_col_get_max_size(col);
1273
= dict_col_get_fixed_size(col);
1276
/* Fixed-size columns are stored locally. */
1277
max_size = fixed_size;
1278
} else if (max_size <= BTR_EXTERN_FIELD_REF_SIZE * 2) {
1279
/* Short columns are stored locally. */
1280
} else if (!col->ord_part) {
1281
/* See if col->ord_part would be set
1282
because of new_index. */
1285
for (j = 0; j < new_index->n_uniq; j++) {
1286
if (dict_index_get_nth_col(
1287
new_index, j) == col) {
1293
/* This is not an ordering column in any index.
1294
Thus, it can be stored completely externally. */
1295
max_size = BTR_EXTERN_FIELD_REF_SIZE;
1298
/* This is an ordering column in some index.
1299
A long enough prefix must be written to the
1300
undo log. See trx_undo_page_fetch_ext(). */
1302
if (max_size > REC_MAX_INDEX_COL_LEN) {
1303
max_size = REC_MAX_INDEX_COL_LEN;
1306
max_size += BTR_EXTERN_FIELD_REF_SIZE;
1309
undo_page_len += 5 + max_size;
1312
return(undo_page_len >= UNIV_PAGE_SIZE);
1289
1315
/**************************************************************************
1290
1316
Adds an index to the dictionary cache. */
1293
1319
dict_index_add_to_cache(
1294
1320
/*====================*/
1321
/* out: DB_SUCCESS or DB_TOO_BIG_RECORD */
1295
1322
dict_table_t* table, /* in: table on which the index is */
1296
1323
dict_index_t* index, /* in, own: index; NOTE! The index memory
1297
1324
object is freed in this function! */
1329
1342
/* Build the cache internal representation of the index,
1330
1343
containing also the added system fields */
1332
if (index->type & DICT_CLUSTERED) {
1345
if (dict_index_is_clust(index)) {
1333
1346
new_index = dict_index_build_internal_clust(table, index);
1335
1348
new_index = dict_index_build_internal_non_clust(table, index);
1338
new_index->search_info = btr_search_info_create(new_index->heap);
1340
1351
/* Set the n_fields value in new_index to the actual defined
1341
1352
number of fields in the cache internal representation */
1343
1354
new_index->n_fields = new_index->n_def;
1356
if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) {
1357
n_ord = new_index->n_fields;
1359
n_ord = new_index->n_uniq;
1362
for (i = 0; i < n_ord; i++) {
1363
const dict_field_t* field
1364
= dict_index_get_nth_field(new_index, i);
1365
const dict_col_t* col
1366
= dict_field_get_col(field);
1368
/* In dtuple_convert_big_rec(), variable-length columns
1369
that are longer than BTR_EXTERN_FIELD_REF_SIZE * 2
1370
may be chosen for external storage. If the column appears
1371
in an ordering column of an index, a longer prefix of
1372
REC_MAX_INDEX_COL_LEN will be copied to the undo log
1373
by trx_undo_page_report_modify() and
1374
trx_undo_page_fetch_ext(). It suffices to check the
1375
capacity of the undo log whenever new_index includes
1376
a column prefix on a column that may be stored externally. */
1378
if (field->prefix_len /* prefix index */
1379
&& !col->ord_part /* not yet ordering column */
1380
&& !dict_col_get_fixed_size(col) /* variable-length */
1381
&& dict_col_get_max_size(col)
1382
> BTR_EXTERN_FIELD_REF_SIZE * 2 /* long enough */) {
1384
if (dict_index_too_big_for_undo(table, new_index)) {
1385
/* An undo log record might not fit in
1386
a single page. Refuse to create this index. */
1387
dict_mem_index_free(new_index);
1388
dict_mem_index_free(index);
1389
return(DB_TOO_BIG_RECORD);
1396
/* Flag the ordering columns */
1398
for (i = 0; i < n_ord; i++) {
1400
dict_index_get_nth_field(new_index, i)->col->ord_part = 1;
1345
1403
/* Add the new index as the last index for the table */
1347
1405
UT_LIST_ADD_LAST(indexes, table->indexes, new_index);
1348
1406
new_index->table = table;
1349
1407
new_index->table_name = table->name;
1351
/* Increment the ord_part counts in columns which are ordering */
1353
if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) {
1354
n_ord = new_index->n_fields;
1356
n_ord = dict_index_get_n_unique(new_index);
1359
for (i = 0; i < n_ord; i++) {
1361
dict_index_get_nth_field(new_index, i)->col->ord_part = 1;
1364
new_index->page = (unsigned int) page_no;
1409
new_index->search_info = btr_search_info_create(new_index->heap);
1411
new_index->stat_index_size = 1;
1412
new_index->stat_n_leaf_pages = 1;
1414
new_index->page = page_no;
1365
1415
rw_lock_create(&new_index->lock, SYNC_INDEX_TREE);
1367
1417
if (!UNIV_UNLIKELY(new_index->type & DICT_UNIVERSAL)) {
1447
1498
/* It is an error not to find a matching column. */
1455
1506
/***********************************************************************
1456
1507
Adds a column to index. */
1459
1510
dict_index_add_col(
1460
1511
/*===============*/
1461
dict_index_t* index, /* in: index */
1462
dict_table_t* table, /* in: table */
1463
dict_col_t* col, /* in: column */
1464
ulint prefix_len) /* in: column prefix length */
1512
dict_index_t* index, /* in/out: index */
1513
const dict_table_t* table, /* in: table */
1514
dict_col_t* col, /* in: column */
1515
ulint prefix_len) /* in: column prefix length */
1466
1517
dict_field_t* field;
1467
1518
const char* col_name;
1505
1556
dict_index_copy(
1506
1557
/*============*/
1507
dict_index_t* index1, /* in: index to copy to */
1508
dict_index_t* index2, /* in: index to copy from */
1509
dict_table_t* table, /* in: table */
1510
ulint start, /* in: first position to copy */
1511
ulint end) /* in: last position to copy */
1558
dict_index_t* index1, /* in: index to copy to */
1559
dict_index_t* index2, /* in: index to copy from */
1560
const dict_table_t* table, /* in: table */
1561
ulint start, /* in: first position to copy */
1562
ulint end) /* in: last position to copy */
1513
1564
dict_field_t* field;
1554
1606
/***********************************************************************
1555
Copies types of columns contained in table to tuple. */
1607
Copies types of columns contained in table to tuple and sets all
1608
fields of the tuple to the SQL NULL value. This function should
1609
be called right after dtuple_create(). */
1558
1612
dict_table_copy_types(
1559
1613
/*==================*/
1560
dtuple_t* tuple, /* in: data tuple */
1561
dict_table_t* table) /* in: index */
1614
dtuple_t* tuple, /* in/out: data tuple */
1615
const dict_table_t* table) /* in: table */
1563
dtype_t* dfield_type;
1566
1619
for (i = 0; i < dtuple_get_n_fields(tuple); i++) {
1568
dfield_type = dfield_get_type(dtuple_get_nth_field(tuple, i));
1569
dict_col_copy_type(dict_table_get_nth_col(table, i),
1621
dfield_t* dfield = dtuple_get_nth_field(tuple, i);
1622
dtype_t* dtype = dfield_get_type(dfield);
1624
dfield_set_null(dfield);
1625
dict_col_copy_type(dict_table_get_nth_col(table, i), dtype);
1644
1700
# error "DATA_ROLL_PTR != 2"
1647
if (!(index->type & DICT_UNIQUE)) {
1648
dict_index_add_col(new_index, table, (dict_col_t*)
1703
if (!dict_index_is_unique(index)) {
1704
dict_index_add_col(new_index, table,
1649
1705
dict_table_get_sys_col(
1650
1706
table, DATA_ROW_ID),
1655
dict_index_add_col(new_index, table, (dict_col_t*)
1711
dict_index_add_col(new_index, table,
1656
1712
dict_table_get_sys_col(table, DATA_TRX_ID),
1659
dict_index_add_col(new_index, table, (dict_col_t*)
1715
dict_index_add_col(new_index, table,
1660
1716
dict_table_get_sys_col(table,
1661
1717
DATA_ROLL_PTR),
1825
1879
/*************************************************************************
1826
1880
Checks if a table is referenced by foreign keys. */
1829
dict_table_referenced_by_foreign_key(
1883
dict_table_is_referenced_by_foreign_key(
1884
/*====================================*/
1885
/* out: TRUE if table is referenced
1887
const dict_table_t* table) /* in: InnoDB table */
1889
return(UT_LIST_GET_LEN(table->referenced_list) > 0);
1892
/*************************************************************************
1893
Check if the index is referenced by a foreign key, if TRUE return foreign
1897
dict_table_get_referenced_constraint(
1830
1898
/*=================================*/
1831
/* out: TRUE if table is referenced by a
1833
dict_table_t* table) /* in: InnoDB table */
1835
if (UT_LIST_GET_LEN(table->referenced_list) > 0) {
1899
/* out: pointer to foreign key struct if index
1900
is defined for foreign key, otherwise NULL */
1901
dict_table_t* table, /* in: InnoDB table */
1902
dict_index_t* index) /* in: InnoDB index */
1904
dict_foreign_t* foreign = NULL;
1906
ut_ad(index && table);
1908
/* If the referenced list is empty, nothing to do */
1910
if (UT_LIST_GET_LEN(table->referenced_list) == 0) {
1915
foreign = UT_LIST_GET_FIRST(table->referenced_list);
1918
if (foreign->referenced_index == index
1919
|| foreign->referenced_index == index) {
1924
foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
1930
/*************************************************************************
1931
Checks if a index is defined for a foreign key constraint. Index is a part
1932
of a foreign key constraint if the index is referenced by foreign key
1933
or index is a foreign key index. */
1936
dict_table_get_foreign_constraint(
1937
/*==============================*/
1938
/* out: pointer to foreign key struct if index
1939
is defined for foreign key, otherwise NULL */
1940
dict_table_t* table, /* in: InnoDB table */
1941
dict_index_t* index) /* in: InnoDB index */
1943
dict_foreign_t* foreign = NULL;
1945
ut_ad(index && table);
1947
/* If list empty then nothgin to do */
1949
if (UT_LIST_GET_LEN(table->foreign_list) == 0) {
1954
/* Check whether this index is defined for a foreign key */
1956
foreign = UT_LIST_GET_FIRST(table->foreign_list);
1959
if (foreign->foreign_index == index
1960
|| foreign->referenced_index == index) {
1965
foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
1843
1971
/*************************************************************************
1998
2135
/**************************************************************************
2136
Returns an index object by matching on the name and column names and
2137
if more than one index matches return the index with the max id */
2140
dict_table_get_index_by_max_id(
2141
/*===========================*/
2142
/* out: matching index, NULL if not found */
2143
dict_table_t* table, /* in: table */
2144
const char* name, /* in: the index name to find */
2145
const char** columns,/* in: array of column names */
2146
ulint n_cols) /* in: number of columns */
2148
dict_index_t* index;
2149
dict_index_t* found;
2152
index = dict_table_get_first_index(table);
2154
while (index != NULL) {
2155
if (ut_strcmp(index->name, name) == 0
2156
&& dict_index_get_n_ordering_defined_by_user(index)
2161
for (i = 0; i < n_cols; i++) {
2162
dict_field_t* field;
2163
const char* col_name;
2165
field = dict_index_get_nth_field(index, i);
2167
col_name = dict_table_get_col_name(
2168
table, dict_col_get_no(field->col));
2170
if (0 != innobase_strcasecmp(
2171
columns[i], col_name)) {
2178
/* We found a matching index, select
2179
the index with the higher id*/
2182
|| ut_dulint_cmp(index->id, found->id) > 0) {
2189
index = dict_table_get_next_index(index);
2195
/**************************************************************************
1999
2196
Report an error in a foreign key definition. */
3476
3673
/*==================== END OF FOREIGN KEY PROCESSING ====================*/
3675
/**************************************************************************
3676
Returns an index object if it is found in the dictionary cache.
3677
Assumes that dict_sys->mutex is already being held. */
3680
dict_index_get_if_in_cache_low(
3681
/*===========================*/
3682
/* out: index, NULL if not found */
3683
dulint index_id) /* in: index id */
3685
ut_ad(mutex_own(&(dict_sys->mutex)));
3687
return(dict_index_find_on_id_low(index_id));
3690
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
3479
3691
/**************************************************************************
3480
3692
Returns an index object if it is found in the dictionary cache. */
3483
3695
dict_index_get_if_in_cache(
3484
3696
/*=======================*/
3494
3706
mutex_enter(&(dict_sys->mutex));
3496
index = dict_index_find_on_id_low(index_id);
3708
index = dict_index_get_if_in_cache_low(index_id);
3498
3710
mutex_exit(&(dict_sys->mutex));
3502
#endif /* UNIV_DEBUG */
3714
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
3504
3716
#ifdef UNIV_DEBUG
3505
3717
/**************************************************************************
3506
3718
Checks that a tuple has n_fields_cmp value in a sensible range, so that
3507
3719
no comparison can occur with the page number field in a node pointer. */
3510
3722
dict_index_check_search_tuple(
3511
3723
/*==========================*/
3512
/* out: TRUE if ok */
3513
dict_index_t* index, /* in: index tree */
3514
dtuple_t* tuple) /* in: tuple used in a search */
3724
/* out: TRUE if ok */
3725
const dict_index_t* index, /* in: index tree */
3726
const dtuple_t* tuple) /* in: tuple used in a search */
3517
3729
ut_a(dtuple_get_n_fields_cmp(tuple)
3523
3735
/**************************************************************************
3524
3736
Builds a node pointer out of a physical record and a page number. */
3527
3739
dict_index_build_node_ptr(
3528
3740
/*======================*/
3529
/* out, own: node pointer */
3530
dict_index_t* index, /* in: index tree */
3531
rec_t* rec, /* in: record for which to build node
3533
ulint page_no,/* in: page number to put in node pointer */
3534
mem_heap_t* heap, /* in: memory heap where pointer created */
3535
ulint level) /* in: level of rec in tree: 0 means leaf
3741
/* out, own: node pointer */
3742
const dict_index_t* index, /* in: index */
3743
const rec_t* rec, /* in: record for which to build node
3745
ulint page_no,/* in: page number to put in node
3747
mem_heap_t* heap, /* in: memory heap where pointer
3749
ulint level) /* in: level of rec in tree:
3750
0 means leaf level */
3538
3752
dtuple_t* tuple;
3539
3753
dfield_t* field;
3590
3804
/**************************************************************************
3591
3805
Copies an initial segment of a physical record, long enough to specify an
3592
3806
index entry uniquely. */
3595
3809
dict_index_copy_rec_order_prefix(
3596
3810
/*=============================*/
3597
/* out: pointer to the prefix record */
3598
dict_index_t* index, /* in: index tree */
3599
rec_t* rec, /* in: record for which to copy prefix */
3600
ulint* n_fields,/* out: number of fields copied */
3601
byte** buf, /* in/out: memory buffer for the copied prefix,
3603
ulint* buf_size)/* in/out: buffer size */
3811
/* out: pointer to the prefix record */
3812
const dict_index_t* index, /* in: index */
3813
const rec_t* rec, /* in: record for which to
3815
ulint* n_fields,/* out: number of fields copied */
3816
byte** buf, /* in/out: memory buffer for the
3817
copied prefix, or NULL */
3818
ulint* buf_size)/* in/out: buffer size */
3782
3997
/*************************************************************************
3783
3998
Calculates new estimates for table and index statistics. The statistics
3784
3999
are used in query optimization. */
3787
4002
dict_update_statistics(
3788
4003
/*===================*/
3789
dict_table_t* table) /* in: table */
4004
dict_table_t* table) /* in/out: table */
3791
4006
dict_update_statistics_low(table, FALSE);
3794
4009
/**************************************************************************
3795
A noninlined version of dict_table_get_low. */
3798
dict_table_get_low_noninlined(
3799
/*==========================*/
3800
/* out: table, NULL if not found */
3801
const char* table_name) /* in: table name */
3803
return(dict_table_get_low(table_name));
3806
/**************************************************************************
3807
4010
Prints info of a foreign key constraint. */
4213
4427
fputs(" of table ", file);
4214
4428
ut_print_name(file, trx, TRUE, index->table_name);
4431
/**************************************************************************
4432
Get index by name */
4435
dict_table_get_index_on_name(
4436
/*=========================*/
4437
/* out: index, NULL if does not exist */
4438
dict_table_t* table, /* in: table */
4439
const char* name) /* in: name of the index to find */
4441
dict_index_t* index;
4443
index = dict_table_get_first_index(table);
4445
while (index != NULL) {
4446
if (ut_strcmp(index->name, name) == 0) {
4451
index = dict_table_get_next_index(index);
4458
/**************************************************************************
4459
Find and index that is equivalent to the one passed in. */
4462
dict_table_find_equivalent_index(
4463
/*=============================*/
4464
dict_table_t* table, /* in/out: table */
4465
dict_index_t* index) /* in: index to match */
4468
const char** column_names;
4469
dict_index_t* equiv_index;
4471
if (UT_LIST_GET_LEN(table->foreign_list) == 0) {
4476
column_names = mem_alloc(index->n_fields * sizeof *column_names);
4478
/* Convert the column names to the format & type accepted by the find
4480
for (i = 0; i < index->n_fields; i++) {
4481
column_names[i] = index->fields[i].name;
4484
equiv_index = dict_foreign_find_index(
4485
table, column_names, index->n_fields,
4486
index, TRUE, FALSE);
4488
mem_free((void*) column_names);
4490
return(equiv_index);
4493
/**************************************************************************
4494
Replace the index passed in with another equivalent index in the tables
4495
foreign key list. */
4498
dict_table_replace_index_in_foreign_list(
4499
/*=====================================*/
4500
dict_table_t* table, /* in/out: table */
4501
dict_index_t* index) /* in: index to be replaced */
4503
dict_index_t* new_index;
4505
new_index = dict_table_find_equivalent_index(table, index);
4507
/* If match found */
4509
dict_foreign_t* foreign;
4511
ut_a(new_index != index);
4513
foreign = UT_LIST_GET_FIRST(table->foreign_list);
4515
/* If the list is not empty then this should hold */
4518
/* Iterate over the foreign index list and replace the index
4519
passed in with the new index */
4522
if (foreign->foreign_index == index) {
4523
foreign->foreign_index = new_index;
4526
foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
4531
/**************************************************************************
4532
In case there is more than one index with the same name return the index
4533
with the min(id). */
4536
dict_table_get_index_on_name_and_min_id(
4537
/*=====================================*/
4538
/* out: index, NULL if does not exist */
4539
dict_table_t* table, /* in: table */
4540
const char* name) /* in: name of the index to find */
4542
dict_index_t* index;
4543
dict_index_t* min_index; /* Index with matching name and min(id) */
4546
index = dict_table_get_first_index(table);
4548
while (index != NULL) {
4549
if (ut_strcmp(index->name, name) == 0) {
4551
|| ut_dulint_cmp(index->id, min_index->id) < 0) {
4557
index = dict_table_get_next_index(index);
4565
/**************************************************************************
4566
Check for duplicate index entries in a table [using the index name] */
4569
dict_table_check_for_dup_indexes(
4570
/*=============================*/
4571
const dict_table_t* table) /* in: Check for dup indexes
4574
/* Check for duplicates, ignoring indexes that are marked
4577
const dict_index_t* index1;
4578
const dict_index_t* index2;
4580
/* The primary index _must_ exist */
4581
ut_a(UT_LIST_GET_LEN(table->indexes) > 0);
4583
index1 = UT_LIST_GET_FIRST(table->indexes);
4584
index2 = UT_LIST_GET_NEXT(indexes, index1);
4586
while (index1 && index2) {
4590
if (!index2->to_be_dropped) {
4591
ut_ad(ut_strcmp(index1->name, index2->name));
4594
index2 = UT_LIST_GET_NEXT(indexes, index2);
4597
index1 = UT_LIST_GET_NEXT(indexes, index1);
4598
index2 = UT_LIST_GET_NEXT(indexes, index1);
4601
#endif /* UNIV_DEBUG */