1
/*****************************************************************************
3
Copyright (C) 1996, 2010, Innobase Oy. All Rights Reserved.
5
This program is free software; you can redistribute it and/or modify it under
6
the terms of the GNU General Public License as published by the Free Software
7
Foundation; version 2 of the License.
9
This program is distributed in the hope that it will be useful, but WITHOUT
10
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
You should have received a copy of the GNU General Public License along with
14
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
15
St, Fifth Floor, Boston, MA 02110-1301 USA
17
*****************************************************************************/
19
/******************************************************************//**
20
@file dict/dict0dict.c
21
Data dictionary system
23
Created 1/8/1996 Heikki Tuuri
24
***********************************************************************/
26
#include "dict0dict.h"
29
#include "dict0dict.ic"
32
/** dummy index for ROW_FORMAT=REDUNDANT supremum and infimum records */
33
UNIV_INTERN dict_index_t* dict_ind_redundant;
34
/** dummy index for ROW_FORMAT=COMPACT supremum and infimum records */
35
UNIV_INTERN dict_index_t* dict_ind_compact;
37
#ifndef UNIV_HOTBACKUP
39
#include "data0type.h"
40
#include "mach0data.h"
41
#include "dict0boot.h"
43
#include "dict0crea.h"
49
#include "page0page.h"
50
#include "pars0pars.h"
54
#include "row0merge.h"
55
#include "ha_prototypes.h" /* innobase_strcasecmp() */
59
/** the dictionary system */
60
UNIV_INTERN dict_sys_t* dict_sys = NULL;
62
/** @brief the data dictionary rw-latch protecting dict_sys
64
table create, drop, etc. reserve this in X-mode; implicit or
65
backround operations purge, rollback, foreign key checks reserve this
66
in S-mode; we cannot trust that MySQL protects implicit or background
67
operations a table drop since MySQL does not know of them; therefore
68
we need this; NOTE: a transaction which reserves this must keep book
69
on the mode in trx_struct::dict_operation_lock_mode */
70
UNIV_INTERN rw_lock_t dict_operation_lock;
72
/* Keys to register rwlocks and mutexes with performance schema */
73
#ifdef UNIV_PFS_RWLOCK
74
UNIV_INTERN mysql_pfs_key_t dict_operation_lock_key;
75
UNIV_INTERN mysql_pfs_key_t index_tree_rw_lock_key;
76
#endif /* UNIV_PFS_RWLOCK */
79
UNIV_INTERN mysql_pfs_key_t dict_sys_mutex_key;
80
UNIV_INTERN mysql_pfs_key_t dict_foreign_err_mutex_key;
81
#endif /* UNIV_PFS_MUTEX */
83
#define DICT_HEAP_SIZE 100 /*!< initial memory heap size when
84
creating a table or index object */
85
#define DICT_POOL_PER_TABLE_HASH 512 /*!< buffer pool max size per table
86
hash table fixed size in bytes */
87
#define DICT_POOL_PER_VARYING 4 /*!< buffer pool max size per data
88
dictionary varying size in bytes */
90
/** Identifies generated InnoDB foreign key names */
91
static char dict_ibfk[] = "_ibfk_";
93
/** array of mutexes protecting dict_index_t::stat_n_diff_key_vals[] */
94
#define DICT_INDEX_STAT_MUTEX_SIZE 32
95
static mutex_t dict_index_stat_mutex[DICT_INDEX_STAT_MUTEX_SIZE];
97
/*******************************************************************//**
98
Tries to find column names for the index and sets the col field of the
100
@return TRUE if the column names were found */
103
dict_index_find_cols(
104
/*=================*/
105
dict_table_t* table, /*!< in: table */
106
dict_index_t* index); /*!< in: index */
107
/*******************************************************************//**
108
Builds the internal dictionary cache representation for a clustered
109
index, containing also system fields not defined by the user.
110
@return own: the internal representation of the clustered index */
113
dict_index_build_internal_clust(
114
/*============================*/
115
const dict_table_t* table, /*!< in: table */
116
dict_index_t* index); /*!< in: user representation of
118
/*******************************************************************//**
119
Builds the internal dictionary cache representation for a non-clustered
120
index, containing also system fields not defined by the user.
121
@return own: the internal representation of the non-clustered index */
124
dict_index_build_internal_non_clust(
125
/*================================*/
126
const dict_table_t* table, /*!< in: table */
127
dict_index_t* index); /*!< in: user representation of
128
a non-clustered index */
129
/**********************************************************************//**
130
Removes a foreign constraint struct from the dictionary cache. */
133
dict_foreign_remove_from_cache(
134
/*===========================*/
135
dict_foreign_t* foreign); /*!< in, own: foreign constraint */
136
/**********************************************************************//**
137
Prints a column data. */
142
const dict_table_t* table, /*!< in: table */
143
const dict_col_t* col); /*!< in: column */
144
/**********************************************************************//**
145
Prints an index data. */
148
dict_index_print_low(
149
/*=================*/
150
dict_index_t* index); /*!< in: index */
151
/**********************************************************************//**
152
Prints a field data. */
155
dict_field_print_low(
156
/*=================*/
157
const dict_field_t* field); /*!< in: field */
158
/*********************************************************************//**
159
Frees a foreign key struct. */
164
dict_foreign_t* foreign); /*!< in, own: foreign key struct */
166
/* Stream for storing detailed information about the latest foreign key
167
and unique key errors */
168
UNIV_INTERN FILE* dict_foreign_err_file = NULL;
169
/* mutex protecting the foreign and unique error buffers */
170
UNIV_INTERN mutex_t dict_foreign_err_mutex;
172
/******************************************************************//**
173
Makes all characters in a NUL-terminated UTF-8 string lower case. */
178
char* a) /*!< in/out: string to put in lower case */
180
innobase_casedn_str(a);
183
/********************************************************************//**
184
Checks if the database name in two table names is the same.
185
@return TRUE if same db name */
188
dict_tables_have_same_db(
189
/*=====================*/
190
const char* name1, /*!< in: table name in the form
191
dbname '/' tablename */
192
const char* name2) /*!< in: table name in the form
193
dbname '/' tablename */
195
for (; *name1 == *name2; name1++, name2++) {
199
ut_a(*name1); /* the names must contain '/' */
204
/********************************************************************//**
205
Return the end of table name where we have removed dbname and '/'.
206
@return table name */
211
const char* name) /*!< in: table name in the form
212
dbname '/' tablename */
214
const char* s = strchr(name, '/');
220
/********************************************************************//**
221
Get the database name length in a table name.
222
@return database name length */
225
dict_get_db_name_len(
226
/*=================*/
227
const char* name) /*!< in: table name in the form
228
dbname '/' tablename */
231
s = strchr(name, '/');
236
/********************************************************************//**
237
Reserves the dictionary system mutex for MySQL. */
240
dict_mutex_enter_for_mysql(void)
241
/*============================*/
243
mutex_enter(&(dict_sys->mutex));
246
/********************************************************************//**
247
Releases the dictionary system mutex for MySQL. */
250
dict_mutex_exit_for_mysql(void)
251
/*===========================*/
253
mutex_exit(&(dict_sys->mutex));
256
/** Get the mutex that protects index->stat_n_diff_key_vals[] */
257
#define GET_INDEX_STAT_MUTEX(index) \
258
(&dict_index_stat_mutex[ut_fold_ull(index->id) \
259
% DICT_INDEX_STAT_MUTEX_SIZE])
261
/**********************************************************************//**
262
Lock the appropriate mutex to protect index->stat_n_diff_key_vals[].
263
index->id is used to pick the right mutex and it should not change
264
before dict_index_stat_mutex_exit() is called on this index. */
267
dict_index_stat_mutex_enter(
268
/*========================*/
269
const dict_index_t* index) /*!< in: index */
271
ut_ad(index != NULL);
272
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
273
ut_ad(index->cached);
274
ut_ad(!index->to_be_dropped);
276
mutex_enter(GET_INDEX_STAT_MUTEX(index));
279
/**********************************************************************//**
280
Unlock the appropriate mutex that protects index->stat_n_diff_key_vals[]. */
283
dict_index_stat_mutex_exit(
284
/*=======================*/
285
const dict_index_t* index) /*!< in: index */
287
ut_ad(index != NULL);
288
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
289
ut_ad(index->cached);
290
ut_ad(!index->to_be_dropped);
292
mutex_exit(GET_INDEX_STAT_MUTEX(index));
295
/********************************************************************//**
296
Decrements the count of open MySQL handles to a table. */
299
dict_table_decrement_handle_count(
300
/*==============================*/
301
dict_table_t* table, /*!< in/out: table */
302
ibool dict_locked) /*!< in: TRUE=data dictionary locked */
305
mutex_enter(&dict_sys->mutex);
308
ut_ad(mutex_own(&dict_sys->mutex));
309
ut_a(table->n_mysql_handles_opened > 0);
311
table->n_mysql_handles_opened--;
314
mutex_exit(&dict_sys->mutex);
317
#endif /* !UNIV_HOTBACKUP */
319
/**********************************************************************//**
320
Returns a column's name.
321
@return column name. NOTE: not guaranteed to stay valid if table is
322
modified in any way (columns added, etc.). */
325
dict_table_get_col_name(
326
/*====================*/
327
const dict_table_t* table, /*!< in: table */
328
ulint col_nr) /*!< in: column number */
334
ut_ad(col_nr < table->n_def);
335
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
337
s = table->col_names;
339
for (i = 0; i < col_nr; i++) {
347
#ifndef UNIV_HOTBACKUP
348
/********************************************************************//**
349
Acquire the autoinc lock. */
352
dict_table_autoinc_lock(
353
/*====================*/
354
dict_table_t* table) /*!< in/out: table */
356
mutex_enter(&table->autoinc_mutex);
359
/********************************************************************//**
360
Unconditionally set the autoinc counter. */
363
dict_table_autoinc_initialize(
364
/*==========================*/
365
dict_table_t* table, /*!< in/out: table */
366
ib_uint64_t value) /*!< in: next value to assign to a row */
368
ut_ad(mutex_own(&table->autoinc_mutex));
370
table->autoinc = value;
373
/********************************************************************//**
374
Reads the next autoinc value (== autoinc counter value), 0 if not yet
376
@return value for a new row, or 0 */
379
dict_table_autoinc_read(
380
/*====================*/
381
const dict_table_t* table) /*!< in: table */
383
ut_ad(mutex_own(&table->autoinc_mutex));
385
return(table->autoinc);
388
/********************************************************************//**
389
Updates the autoinc counter if the value supplied is greater than the
393
dict_table_autoinc_update_if_greater(
394
/*=================================*/
396
dict_table_t* table, /*!< in/out: table */
397
ib_uint64_t value) /*!< in: value which was assigned to a row */
399
ut_ad(mutex_own(&table->autoinc_mutex));
401
if (value > table->autoinc) {
403
table->autoinc = value;
407
/********************************************************************//**
408
Release the autoinc lock. */
411
dict_table_autoinc_unlock(
412
/*======================*/
413
dict_table_t* table) /*!< in/out: table */
415
mutex_exit(&table->autoinc_mutex);
418
/**********************************************************************//**
419
Looks for an index with the given table and index id.
420
NOTE that we do not reserve the dictionary mutex.
421
@return index or NULL if not found from cache */
424
dict_index_get_on_id_low(
425
/*=====================*/
426
dict_table_t* table, /*!< in: table */
427
index_id_t id) /*!< in: index id */
431
index = dict_table_get_first_index(table);
434
if (id == index->id) {
440
index = dict_table_get_next_index(index);
445
#endif /* !UNIV_HOTBACKUP */
447
/********************************************************************//**
448
Looks for column n in an index.
449
@return position in internal representation of the index;
450
ULINT_UNDEFINED if not contained */
453
dict_index_get_nth_col_pos(
454
/*=======================*/
455
const dict_index_t* index, /*!< in: index */
456
ulint n) /*!< in: column number */
458
const dict_field_t* field;
459
const dict_col_t* col;
464
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
466
col = dict_table_get_nth_col(index->table, n);
468
if (dict_index_is_clust(index)) {
470
return(dict_col_get_clust_pos(col, index));
473
n_fields = dict_index_get_n_fields(index);
475
for (pos = 0; pos < n_fields; pos++) {
476
field = dict_index_get_nth_field(index, pos);
478
if (col == field->col && field->prefix_len == 0) {
484
return(ULINT_UNDEFINED);
487
#ifndef UNIV_HOTBACKUP
488
/********************************************************************//**
489
Returns TRUE if the index contains a column or a prefix of that column.
490
@return TRUE if contains the column or its prefix */
493
dict_index_contains_col_or_prefix(
494
/*==============================*/
495
const dict_index_t* index, /*!< in: index */
496
ulint n) /*!< in: column number */
498
const dict_field_t* field;
499
const dict_col_t* col;
504
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
506
if (dict_index_is_clust(index)) {
511
col = dict_table_get_nth_col(index->table, n);
513
n_fields = dict_index_get_n_fields(index);
515
for (pos = 0; pos < n_fields; pos++) {
516
field = dict_index_get_nth_field(index, pos);
518
if (col == field->col) {
527
/********************************************************************//**
528
Looks for a matching field in an index. The column has to be the same. The
529
column in index must be complete, or must contain a prefix longer than the
530
column in index2. That is, we must be able to construct the prefix in index2
531
from the prefix in index.
532
@return position in internal representation of the index;
533
ULINT_UNDEFINED if not contained */
536
dict_index_get_nth_field_pos(
537
/*=========================*/
538
const dict_index_t* index, /*!< in: index from which to search */
539
const dict_index_t* index2, /*!< in: index */
540
ulint n) /*!< in: field number in index2 */
542
const dict_field_t* field;
543
const dict_field_t* field2;
548
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
550
field2 = dict_index_get_nth_field(index2, n);
552
n_fields = dict_index_get_n_fields(index);
554
for (pos = 0; pos < n_fields; pos++) {
555
field = dict_index_get_nth_field(index, pos);
557
if (field->col == field2->col
558
&& (field->prefix_len == 0
559
|| (field->prefix_len >= field2->prefix_len
560
&& field2->prefix_len != 0))) {
566
return(ULINT_UNDEFINED);
569
/**********************************************************************//**
570
Returns a table object based on table id.
571
@return table, NULL if does not exist */
574
dict_table_get_on_id(
575
/*=================*/
576
table_id_t table_id, /*!< in: table id */
577
trx_t* trx) /*!< in: transaction handle */
581
if (trx->dict_operation_lock_mode == RW_X_LATCH) {
583
/* Note: An X latch implies that the transaction
584
already owns the dictionary mutex. */
586
ut_ad(mutex_own(&dict_sys->mutex));
588
return(dict_table_get_on_id_low(table_id));
591
mutex_enter(&(dict_sys->mutex));
593
table = dict_table_get_on_id_low(table_id);
595
mutex_exit(&(dict_sys->mutex));
600
/********************************************************************//**
601
Looks for column n position in the clustered index.
602
@return position in internal representation of the clustered index */
605
dict_table_get_nth_col_pos(
606
/*=======================*/
607
const dict_table_t* table, /*!< in: table */
608
ulint n) /*!< in: column number */
610
return(dict_index_get_nth_col_pos(dict_table_get_first_index(table),
614
/********************************************************************//**
615
Checks if a column is in the ordering columns of the clustered index of a
616
table. Column prefixes are treated like whole columns.
617
@return TRUE if the column, or its prefix, is in the clustered key */
620
dict_table_col_in_clustered_key(
621
/*============================*/
622
const dict_table_t* table, /*!< in: table */
623
ulint n) /*!< in: column number */
625
const dict_index_t* index;
626
const dict_field_t* field;
627
const dict_col_t* col;
633
col = dict_table_get_nth_col(table, n);
635
index = dict_table_get_first_index(table);
637
n_fields = dict_index_get_n_unique(index);
639
for (pos = 0; pos < n_fields; pos++) {
640
field = dict_index_get_nth_field(index, pos);
642
if (col == field->col) {
651
/**********************************************************************//**
652
Inits the data dictionary module. */
660
dict_sys = mem_alloc(sizeof(dict_sys_t));
662
mutex_create(dict_sys_mutex_key, &dict_sys->mutex, SYNC_DICT);
664
dict_sys->table_hash = hash_create(buf_pool_get_curr_size()
665
/ (DICT_POOL_PER_TABLE_HASH
667
dict_sys->table_id_hash = hash_create(buf_pool_get_curr_size()
668
/ (DICT_POOL_PER_TABLE_HASH
672
UT_LIST_INIT(dict_sys->table_LRU);
674
rw_lock_create(dict_operation_lock_key,
675
&dict_operation_lock, SYNC_DICT_OPERATION);
677
dict_foreign_err_file = os_file_create_tmpfile();
678
ut_a(dict_foreign_err_file);
680
mutex_create(dict_foreign_err_mutex_key,
681
&dict_foreign_err_mutex, SYNC_ANY_LATCH);
683
for (i = 0; i < DICT_INDEX_STAT_MUTEX_SIZE; i++) {
684
mutex_create(PFS_NOT_INSTRUMENTED,
685
&dict_index_stat_mutex[i], SYNC_INDEX_TREE);
689
/**********************************************************************//**
690
Returns a table object and optionally increment its MySQL open handle count.
691
NOTE! This is a high-level function to be used mainly from outside the
692
'dict' directory. Inside this directory dict_table_get_low is usually the
693
appropriate function.
694
@return table, NULL if does not exist */
699
const char* table_name, /*!< in: table name */
700
ibool inc_mysql_count)/*!< in: whether to increment the open
701
handle count on the table */
705
mutex_enter(&(dict_sys->mutex));
707
table = dict_table_get_low(table_name);
709
if (inc_mysql_count && table) {
710
table->n_mysql_handles_opened++;
713
mutex_exit(&(dict_sys->mutex));
716
if (!table->stat_initialized) {
717
/* If table->ibd_file_missing == TRUE, this will
718
print an error message and return without doing
720
dict_update_statistics(table);
726
#endif /* !UNIV_HOTBACKUP */
728
/**********************************************************************//**
729
Adds system columns to a table object. */
732
dict_table_add_system_columns(
733
/*==========================*/
734
dict_table_t* table, /*!< in/out: table */
735
mem_heap_t* heap) /*!< in: temporary heap */
738
ut_ad(table->n_def == table->n_cols - DATA_N_SYS_COLS);
739
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
740
ut_ad(!table->cached);
742
/* NOTE: the system columns MUST be added in the following order
743
(so that they can be indexed by the numerical value of DATA_ROW_ID,
744
etc.) and as the last columns of the table memory object.
745
The clustered index will not always physically contain all
748
dict_mem_table_add_col(table, heap, "DB_ROW_ID", DATA_SYS,
749
DATA_ROW_ID | DATA_NOT_NULL,
752
#error "DATA_ROW_ID != 0"
754
dict_mem_table_add_col(table, heap, "DB_TRX_ID", DATA_SYS,
755
DATA_TRX_ID | DATA_NOT_NULL,
758
#error "DATA_TRX_ID != 1"
760
dict_mem_table_add_col(table, heap, "DB_ROLL_PTR", DATA_SYS,
761
DATA_ROLL_PTR | DATA_NOT_NULL,
763
#if DATA_ROLL_PTR != 2
764
#error "DATA_ROLL_PTR != 2"
767
/* This check reminds that if a new system column is added to
768
the program, it should be dealt with here */
769
#if DATA_N_SYS_COLS != 3
770
#error "DATA_N_SYS_COLS != 3"
774
#ifndef UNIV_HOTBACKUP
775
/**********************************************************************//**
776
Adds a table object to the dictionary cache. */
779
dict_table_add_to_cache(
780
/*====================*/
781
dict_table_t* table, /*!< in: table */
782
mem_heap_t* heap) /*!< in: temporary heap */
789
/* The lower limit for what we consider a "big" row */
790
#define BIG_ROW_SIZE 1024
792
ut_ad(mutex_own(&(dict_sys->mutex)));
794
dict_table_add_system_columns(table, heap);
796
table->cached = TRUE;
798
fold = ut_fold_string(table->name);
799
id_fold = ut_fold_ull(table->id);
802
for (i = 0; i < table->n_def; i++) {
803
ulint col_len = dict_col_get_max_size(
804
dict_table_get_nth_col(table, i));
808
/* If we have a single unbounded field, or several gigantic
809
fields, mark the maximum row size as BIG_ROW_SIZE. */
810
if (row_len >= BIG_ROW_SIZE || col_len >= BIG_ROW_SIZE) {
811
row_len = BIG_ROW_SIZE;
817
table->big_rows = row_len >= BIG_ROW_SIZE;
819
/* Look for a table with the same name: error if such exists */
821
dict_table_t* table2;
822
HASH_SEARCH(name_hash, dict_sys->table_hash, fold,
823
dict_table_t*, table2, ut_ad(table2->cached),
824
ut_strcmp(table2->name, table->name) == 0);
825
ut_a(table2 == NULL);
828
/* Look for the same table pointer with a different name */
829
HASH_SEARCH_ALL(name_hash, dict_sys->table_hash,
830
dict_table_t*, table2, ut_ad(table2->cached),
832
ut_ad(table2 == NULL);
833
#endif /* UNIV_DEBUG */
836
/* Look for a table with the same id: error if such exists */
838
dict_table_t* table2;
839
HASH_SEARCH(id_hash, dict_sys->table_id_hash, id_fold,
840
dict_table_t*, table2, ut_ad(table2->cached),
841
table2->id == table->id);
842
ut_a(table2 == NULL);
845
/* Look for the same table pointer with a different id */
846
HASH_SEARCH_ALL(id_hash, dict_sys->table_id_hash,
847
dict_table_t*, table2, ut_ad(table2->cached),
849
ut_ad(table2 == NULL);
850
#endif /* UNIV_DEBUG */
853
/* Add table to hash table of tables */
854
HASH_INSERT(dict_table_t, name_hash, dict_sys->table_hash, fold,
857
/* Add table to hash table of tables based on table id */
858
HASH_INSERT(dict_table_t, id_hash, dict_sys->table_id_hash, id_fold,
860
/* Add table to LRU list of tables */
861
UT_LIST_ADD_FIRST(table_LRU, dict_sys->table_LRU, table);
863
dict_sys->size += mem_heap_get_size(table->heap)
864
+ strlen(table->name) + 1;
867
/**********************************************************************//**
868
Looks for an index with the given id. NOTE that we do not reserve
869
the dictionary mutex: this function is for emergency purposes like
870
printing info of a corrupt database page!
871
@return index or NULL if not found from cache */
874
dict_index_find_on_id_low(
875
/*======================*/
876
index_id_t id) /*!< in: index id */
881
table = UT_LIST_GET_FIRST(dict_sys->table_LRU);
884
index = dict_table_get_first_index(table);
887
if (id == index->id) {
893
index = dict_table_get_next_index(index);
896
table = UT_LIST_GET_NEXT(table_LRU, table);
902
/**********************************************************************//**
903
Renames a table object.
904
@return TRUE if success */
907
dict_table_rename_in_cache(
908
/*=======================*/
909
dict_table_t* table, /*!< in/out: table */
910
const char* new_name, /*!< in: new name */
911
ibool rename_also_foreigns)/*!< in: in ALTER TABLE we want
912
to preserve the original table name
913
in constraints which reference it */
915
dict_foreign_t* foreign;
918
char old_name[MAX_TABLE_NAME_LEN + 1];
921
ut_ad(mutex_own(&(dict_sys->mutex)));
923
/* store the old/current name to an automatic variable */
924
if (strlen(table->name) + 1 <= sizeof(old_name)) {
925
memcpy(old_name, table->name, strlen(table->name) + 1);
927
ut_print_timestamp(stderr);
928
fprintf(stderr, "InnoDB: too long table name: '%s', "
929
"max length is %d\n", table->name,
934
fold = ut_fold_string(new_name);
936
/* Look for a table with the same name: error if such exists */
938
dict_table_t* table2;
939
HASH_SEARCH(name_hash, dict_sys->table_hash, fold,
940
dict_table_t*, table2, ut_ad(table2->cached),
941
(ut_strcmp(table2->name, new_name) == 0));
942
if (UNIV_LIKELY_NULL(table2)) {
943
ut_print_timestamp(stderr);
944
fputs(" InnoDB: Error: dictionary cache"
945
" already contains a table ", stderr);
946
ut_print_name(stderr, NULL, TRUE, new_name);
948
"InnoDB: cannot rename table ", stderr);
949
ut_print_name(stderr, NULL, TRUE, old_name);
955
/* If the table is stored in a single-table tablespace, rename the
958
if (table->space != 0) {
959
if (table->dir_path_of_temp_table != NULL) {
960
ut_print_timestamp(stderr);
961
fputs(" InnoDB: Error: trying to rename a"
962
" TEMPORARY TABLE ", stderr);
963
ut_print_name(stderr, NULL, TRUE, old_name);
965
ut_print_filename(stderr,
966
table->dir_path_of_temp_table);
967
fputs(" )\n", stderr);
969
} else if (!fil_rename_tablespace(old_name, table->space,
975
/* Remove table from the hash tables of tables */
976
HASH_DELETE(dict_table_t, name_hash, dict_sys->table_hash,
977
ut_fold_string(old_name), table);
979
if (strlen(new_name) > strlen(table->name)) {
980
/* We allocate MAX_TABLE_NAME_LEN+1 bytes here to avoid
981
memory fragmentation, we assume a repeated calls of
982
ut_realloc() with the same size do not cause fragmentation */
983
ut_a(strlen(new_name) <= MAX_TABLE_NAME_LEN);
984
table->name = ut_realloc(table->name, MAX_TABLE_NAME_LEN + 1);
986
memcpy(table->name, new_name, strlen(new_name) + 1);
988
/* Add table to hash table of tables */
989
HASH_INSERT(dict_table_t, name_hash, dict_sys->table_hash, fold,
992
dict_sys->size += strlen(new_name) - strlen(old_name);
993
ut_a(dict_sys->size > 0);
995
/* Update the table_name field in indexes */
996
index = dict_table_get_first_index(table);
998
while (index != NULL) {
999
index->table_name = table->name;
1001
index = dict_table_get_next_index(index);
1004
if (!rename_also_foreigns) {
1005
/* In ALTER TABLE we think of the rename table operation
1006
in the direction table -> temporary table (#sql...)
1007
as dropping the table with the old name and creating
1008
a new with the new name. Thus we kind of drop the
1009
constraints from the dictionary cache here. The foreign key
1010
constraints will be inherited to the new table from the
1011
system tables through a call of dict_load_foreigns. */
1013
/* Remove the foreign constraints from the cache */
1014
foreign = UT_LIST_GET_LAST(table->foreign_list);
1016
while (foreign != NULL) {
1017
dict_foreign_remove_from_cache(foreign);
1018
foreign = UT_LIST_GET_LAST(table->foreign_list);
1021
/* Reset table field in referencing constraints */
1023
foreign = UT_LIST_GET_FIRST(table->referenced_list);
1025
while (foreign != NULL) {
1026
foreign->referenced_table = NULL;
1027
foreign->referenced_index = NULL;
1029
foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
1032
/* Make the list of referencing constraints empty */
1034
UT_LIST_INIT(table->referenced_list);
1039
/* Update the table name fields in foreign constraints, and update also
1040
the constraint id of new format >= 4.0.18 constraints. Note that at
1041
this point we have already changed table->name to the new name. */
1043
foreign = UT_LIST_GET_FIRST(table->foreign_list);
1045
while (foreign != NULL) {
1046
if (ut_strlen(foreign->foreign_table_name)
1047
< ut_strlen(table->name)) {
1048
/* Allocate a longer name buffer;
1049
TODO: store buf len to save memory */
1051
foreign->foreign_table_name
1052
= mem_heap_alloc(foreign->heap,
1053
ut_strlen(table->name) + 1);
1056
strcpy(foreign->foreign_table_name, table->name);
1058
if (strchr(foreign->id, '/')) {
1062
/* This is a >= 4.0.18 format id */
1064
old_id = mem_strdup(foreign->id);
1066
if (ut_strlen(foreign->id) > ut_strlen(old_name)
1067
+ ((sizeof dict_ibfk) - 1)
1068
&& !memcmp(foreign->id, old_name,
1069
ut_strlen(old_name))
1070
&& !memcmp(foreign->id + ut_strlen(old_name),
1071
dict_ibfk, (sizeof dict_ibfk) - 1)) {
1073
/* This is a generated >= 4.0.18 format id */
1075
if (strlen(table->name) > strlen(old_name)) {
1076
foreign->id = mem_heap_alloc(
1079
+ strlen(old_id) + 1);
1082
/* Replace the prefix 'databasename/tablename'
1083
with the new names */
1084
strcpy(foreign->id, table->name);
1086
old_id + ut_strlen(old_name));
1088
/* This is a >= 4.0.18 format id where the user
1090
db_len = dict_get_db_name_len(table->name) + 1;
1092
if (dict_get_db_name_len(table->name)
1093
> dict_get_db_name_len(foreign->id)) {
1095
foreign->id = mem_heap_alloc(
1097
db_len + strlen(old_id) + 1);
1100
/* Replace the database prefix in id with the
1101
one from table->name */
1103
ut_memcpy(foreign->id, table->name, db_len);
1105
strcpy(foreign->id + db_len,
1106
dict_remove_db_name(old_id));
1112
foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
1115
foreign = UT_LIST_GET_FIRST(table->referenced_list);
1117
while (foreign != NULL) {
1118
if (ut_strlen(foreign->referenced_table_name)
1119
< ut_strlen(table->name)) {
1120
/* Allocate a longer name buffer;
1121
TODO: store buf len to save memory */
1123
foreign->referenced_table_name = mem_heap_alloc(
1124
foreign->heap, strlen(table->name) + 1);
1127
strcpy(foreign->referenced_table_name, table->name);
1129
foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
1135
/**********************************************************************//**
1136
Change the id of a table object in the dictionary cache. This is used in
1137
DISCARD TABLESPACE. */
1140
dict_table_change_id_in_cache(
1141
/*==========================*/
1142
dict_table_t* table, /*!< in/out: table object already in cache */
1143
table_id_t new_id) /*!< in: new id to set */
1146
ut_ad(mutex_own(&(dict_sys->mutex)));
1147
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
1149
/* Remove the table from the hash table of id's */
1151
HASH_DELETE(dict_table_t, id_hash, dict_sys->table_id_hash,
1152
ut_fold_ull(table->id), table);
1155
/* Add the table back to the hash table */
1156
HASH_INSERT(dict_table_t, id_hash, dict_sys->table_id_hash,
1157
ut_fold_ull(table->id), table);
1160
/**********************************************************************//**
1161
Removes a table object from the dictionary cache. */
1164
dict_table_remove_from_cache(
1165
/*=========================*/
1166
dict_table_t* table) /*!< in, own: table */
1168
dict_foreign_t* foreign;
1169
dict_index_t* index;
1173
ut_ad(mutex_own(&(dict_sys->mutex)));
1174
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
1177
fputs("Removing table ", stderr);
1178
ut_print_name(stderr, table->name, ULINT_UNDEFINED);
1179
fputs(" from dictionary cache\n", stderr);
1182
/* Remove the foreign constraints from the cache */
1183
foreign = UT_LIST_GET_LAST(table->foreign_list);
1185
while (foreign != NULL) {
1186
dict_foreign_remove_from_cache(foreign);
1187
foreign = UT_LIST_GET_LAST(table->foreign_list);
1190
/* Reset table field in referencing constraints */
1192
foreign = UT_LIST_GET_FIRST(table->referenced_list);
1194
while (foreign != NULL) {
1195
foreign->referenced_table = NULL;
1196
foreign->referenced_index = NULL;
1198
foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
1201
/* Remove the indexes from the cache */
1202
index = UT_LIST_GET_LAST(table->indexes);
1204
while (index != NULL) {
1205
dict_index_remove_from_cache(table, index);
1206
index = UT_LIST_GET_LAST(table->indexes);
1209
/* Remove table from the hash tables of tables */
1210
HASH_DELETE(dict_table_t, name_hash, dict_sys->table_hash,
1211
ut_fold_string(table->name), table);
1212
HASH_DELETE(dict_table_t, id_hash, dict_sys->table_id_hash,
1213
ut_fold_ull(table->id), table);
1215
/* Remove table from LRU list of tables */
1216
UT_LIST_REMOVE(table_LRU, dict_sys->table_LRU, table);
1218
size = mem_heap_get_size(table->heap) + strlen(table->name) + 1;
1220
ut_ad(dict_sys->size >= size);
1222
dict_sys->size -= size;
1224
dict_mem_table_free(table);
1227
/****************************************************************//**
1228
If the given column name is reserved for InnoDB system columns, return
1230
@return TRUE if name is reserved */
1233
dict_col_name_is_reserved(
1234
/*======================*/
1235
const char* name) /*!< in: column name */
1237
/* This check reminds that if a new system column is added to
1238
the program, it should be dealt with here. */
1239
#if DATA_N_SYS_COLS != 3
1240
#error "DATA_N_SYS_COLS != 3"
1243
static const char* reserved_names[] = {
1244
"DB_ROW_ID", "DB_TRX_ID", "DB_ROLL_PTR"
1249
for (i = 0; i < UT_ARR_SIZE(reserved_names); i++) {
1250
if (innobase_strcasecmp(name, reserved_names[i]) == 0) {
1259
/****************************************************************//**
1260
If an undo log record for this table might not fit on a single page,
1262
@return TRUE if the undo log record could become too big */
1265
dict_index_too_big_for_undo(
1266
/*========================*/
1267
const dict_table_t* table, /*!< in: table */
1268
const dict_index_t* new_index) /*!< in: index */
1270
/* Make sure that all column prefixes will fit in the undo log record
1271
in trx_undo_page_report_modify() right after trx_undo_page_init(). */
1274
const dict_index_t* clust_index
1275
= dict_table_get_first_index(table);
1277
= TRX_UNDO_PAGE_HDR - TRX_UNDO_PAGE_HDR_SIZE
1278
+ 2 /* next record pointer */
1280
+ 11 /* trx->undo_no */ + 11 /* table->id */
1281
+ 1 /* rec_get_info_bits() */
1282
+ 11 /* DB_TRX_ID */
1283
+ 11 /* DB_ROLL_PTR */
1284
+ 10 + FIL_PAGE_DATA_END /* trx_undo_left() */
1285
+ 2/* pointer to previous undo log record */;
1287
if (UNIV_UNLIKELY(!clust_index)) {
1288
ut_a(dict_index_is_clust(new_index));
1289
clust_index = new_index;
1292
/* Add the size of the ordering columns in the
1294
for (i = 0; i < clust_index->n_uniq; i++) {
1295
const dict_col_t* col
1296
= dict_index_get_nth_col(clust_index, i);
1298
/* Use the maximum output size of
1299
mach_write_compressed(), although the encoded
1300
length should always fit in 2 bytes. */
1301
undo_page_len += 5 + dict_col_get_max_size(col);
1304
/* Add the old values of the columns to be updated.
1305
First, the amount and the numbers of the columns.
1306
These are written by mach_write_compressed() whose
1307
maximum output length is 5 bytes. However, given that
1308
the quantities are below REC_MAX_N_FIELDS (10 bits),
1309
the maximum length is 2 bytes per item. */
1310
undo_page_len += 2 * (dict_table_get_n_cols(table) + 1);
1312
for (i = 0; i < clust_index->n_def; i++) {
1313
const dict_col_t* col
1314
= dict_index_get_nth_col(clust_index, i);
1316
= dict_col_get_max_size(col);
1318
= dict_col_get_fixed_size(col,
1319
dict_table_is_comp(table));
1322
/* Fixed-size columns are stored locally. */
1323
max_size = fixed_size;
1324
} else if (max_size <= BTR_EXTERN_FIELD_REF_SIZE * 2) {
1325
/* Short columns are stored locally. */
1326
} else if (!col->ord_part) {
1327
/* See if col->ord_part would be set
1328
because of new_index. */
1331
for (j = 0; j < new_index->n_uniq; j++) {
1332
if (dict_index_get_nth_col(
1333
new_index, j) == col) {
1339
/* This is not an ordering column in any index.
1340
Thus, it can be stored completely externally. */
1341
max_size = BTR_EXTERN_FIELD_REF_SIZE;
1344
/* This is an ordering column in some index.
1345
A long enough prefix must be written to the
1346
undo log. See trx_undo_page_fetch_ext(). */
1348
if (max_size > REC_MAX_INDEX_COL_LEN) {
1349
max_size = REC_MAX_INDEX_COL_LEN;
1352
max_size += BTR_EXTERN_FIELD_REF_SIZE;
1355
undo_page_len += 5 + max_size;
1358
return(undo_page_len >= UNIV_PAGE_SIZE);
1361
/****************************************************************//**
1362
If a record of this index might not fit on a single B-tree page,
1364
@return TRUE if the index record could become too big */
1367
dict_index_too_big_for_tree(
1368
/*========================*/
1369
const dict_table_t* table, /*!< in: table */
1370
const dict_index_t* new_index) /*!< in: index */
1375
/* maximum possible storage size of a record */
1377
/* maximum allowed size of a record on a leaf page */
1379
/* maximum allowed size of a node pointer record */
1382
comp = dict_table_is_comp(table);
1383
zip_size = dict_table_zip_size(table);
1385
if (zip_size && zip_size < UNIV_PAGE_SIZE) {
1386
/* On a compressed page, two records must fit in the
1387
uncompressed page modification log. On compressed
1388
pages with zip_size == UNIV_PAGE_SIZE, this limit will
1389
never be reached. */
1391
/* The maximum allowed record size is the size of
1392
an empty page, minus a byte for recoding the heap
1393
number in the page modification log. The maximum
1394
allowed node pointer size is half that. */
1395
page_rec_max = page_zip_empty_size(new_index->n_fields,
1397
page_ptr_max = page_rec_max / 2;
1398
/* On a compressed page, there is a two-byte entry in
1399
the dense page directory for every record. But there
1400
is no record header. */
1403
/* The maximum allowed record size is half a B-tree
1404
page. No additional sparse page directory entry will
1405
be generated for the first few user records. */
1406
page_rec_max = page_get_free_space_of_empty(comp) / 2;
1407
page_ptr_max = page_rec_max;
1408
/* Each record has a header. */
1410
? REC_N_NEW_EXTRA_BYTES
1411
: REC_N_OLD_EXTRA_BYTES;
1415
/* Include the "null" flags in the
1416
maximum possible record size. */
1417
rec_max_size += UT_BITS_IN_BYTES(new_index->n_nullable);
1419
/* For each column, include a 2-byte offset and a
1420
"null" flag. The 1-byte format is only used in short
1421
records that do not contain externally stored columns.
1422
Such records could never exceed the page limit, even
1423
when using the 2-byte format. */
1424
rec_max_size += 2 * new_index->n_fields;
1427
/* Compute the maximum possible record size. */
1428
for (i = 0; i < new_index->n_fields; i++) {
1429
const dict_field_t* field
1430
= dict_index_get_nth_field(new_index, i);
1431
const dict_col_t* col
1432
= dict_field_get_col(field);
1433
ulint field_max_size;
1434
ulint field_ext_max_size;
1436
/* In dtuple_convert_big_rec(), variable-length columns
1437
that are longer than BTR_EXTERN_FIELD_REF_SIZE * 2
1438
may be chosen for external storage.
1440
Fixed-length columns, and all columns of secondary
1441
index records are always stored inline. */
1443
/* Determine the maximum length of the index field.
1444
The field_ext_max_size should be computed as the worst
1445
case in rec_get_converted_size_comp() for
1446
REC_STATUS_ORDINARY records. */
1448
field_max_size = dict_col_get_fixed_size(col, comp);
1449
if (field_max_size) {
1450
/* dict_index_add_col() should guarantee this */
1451
ut_ad(!field->prefix_len
1452
|| field->fixed_len == field->prefix_len);
1453
/* Fixed lengths are not encoded
1454
in ROW_FORMAT=COMPACT. */
1455
field_ext_max_size = 0;
1456
goto add_field_size;
1459
field_max_size = dict_col_get_max_size(col);
1460
field_ext_max_size = field_max_size < 256 ? 1 : 2;
1462
if (field->prefix_len) {
1463
if (field->prefix_len < field_max_size) {
1464
field_max_size = field->prefix_len;
1466
} else if (field_max_size > BTR_EXTERN_FIELD_REF_SIZE * 2
1467
&& dict_index_is_clust(new_index)) {
1469
/* In the worst case, we have a locally stored
1470
column of BTR_EXTERN_FIELD_REF_SIZE * 2 bytes.
1471
The length can be stored in one byte. If the
1472
column were stored externally, the lengths in
1473
the clustered index page would be
1474
BTR_EXTERN_FIELD_REF_SIZE and 2. */
1475
field_max_size = BTR_EXTERN_FIELD_REF_SIZE * 2;
1476
field_ext_max_size = 1;
1480
/* Add the extra size for ROW_FORMAT=COMPACT.
1481
For ROW_FORMAT=REDUNDANT, these bytes were
1482
added to rec_max_size before this loop. */
1483
rec_max_size += field_ext_max_size;
1486
rec_max_size += field_max_size;
1488
/* Check the size limit on leaf pages. */
1489
if (UNIV_UNLIKELY(rec_max_size >= page_rec_max)) {
1494
/* Check the size limit on non-leaf pages. Records
1495
stored in non-leaf B-tree pages consist of the unique
1496
columns of the record (the key columns of the B-tree)
1497
and a node pointer field. When we have processed the
1498
unique columns, rec_max_size equals the size of the
1499
node pointer record minus the node pointer column. */
1500
if (i + 1 == dict_index_get_n_unique_in_tree(new_index)
1501
&& rec_max_size + REC_NODE_PTR_SIZE >= page_ptr_max) {
1510
/**********************************************************************//**
1511
Adds an index to the dictionary cache.
1512
@return DB_SUCCESS, DB_TOO_BIG_RECORD, or DB_CORRUPTION */
1515
dict_index_add_to_cache(
1516
/*====================*/
1517
dict_table_t* table, /*!< in: table on which the index is */
1518
dict_index_t* index, /*!< in, own: index; NOTE! The index memory
1519
object is freed in this function! */
1520
ulint page_no,/*!< in: root page number of the index */
1521
ibool strict) /*!< in: TRUE=refuse to create the index
1522
if records could be too big to fit in
1525
dict_index_t* new_index;
1530
ut_ad(mutex_own(&(dict_sys->mutex)));
1531
ut_ad(index->n_def == index->n_fields);
1532
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
1534
ut_ad(mem_heap_validate(index->heap));
1535
ut_a(!dict_index_is_clust(index)
1536
|| UT_LIST_GET_LEN(table->indexes) == 0);
1538
if (!dict_index_find_cols(table, index)) {
1540
dict_mem_index_free(index);
1541
return(DB_CORRUPTION);
1544
/* Build the cache internal representation of the index,
1545
containing also the added system fields */
1547
if (dict_index_is_clust(index)) {
1548
new_index = dict_index_build_internal_clust(table, index);
1550
new_index = dict_index_build_internal_non_clust(table, index);
1553
/* Set the n_fields value in new_index to the actual defined
1554
number of fields in the cache internal representation */
1556
new_index->n_fields = new_index->n_def;
1558
if (strict && dict_index_too_big_for_tree(table, new_index)) {
1560
dict_mem_index_free(new_index);
1561
dict_mem_index_free(index);
1562
return(DB_TOO_BIG_RECORD);
1565
if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) {
1566
n_ord = new_index->n_fields;
1568
n_ord = new_index->n_uniq;
1571
switch (dict_table_get_format(table)) {
1572
case DICT_TF_FORMAT_51:
1573
/* ROW_FORMAT=REDUNDANT and ROW_FORMAT=COMPACT store
1574
prefixes of externally stored columns locally within
1575
the record. There are no special considerations for
1576
the undo log record size. */
1579
case DICT_TF_FORMAT_ZIP:
1580
/* In ROW_FORMAT=DYNAMIC and ROW_FORMAT=COMPRESSED,
1581
column prefix indexes require that prefixes of
1582
externally stored columns are written to the undo log.
1583
This may make the undo log record bigger than the
1584
record on the B-tree page. The maximum size of an
1585
undo log record is the page size. That must be
1586
checked for below. */
1589
#if DICT_TF_FORMAT_ZIP != DICT_TF_FORMAT_MAX
1590
# error "DICT_TF_FORMAT_ZIP != DICT_TF_FORMAT_MAX"
1594
for (i = 0; i < n_ord; i++) {
1595
const dict_field_t* field
1596
= dict_index_get_nth_field(new_index, i);
1597
const dict_col_t* col
1598
= dict_field_get_col(field);
1600
/* In dtuple_convert_big_rec(), variable-length columns
1601
that are longer than BTR_EXTERN_FIELD_REF_SIZE * 2
1602
may be chosen for external storage. If the column appears
1603
in an ordering column of an index, a longer prefix of
1604
REC_MAX_INDEX_COL_LEN will be copied to the undo log
1605
by trx_undo_page_report_modify() and
1606
trx_undo_page_fetch_ext(). It suffices to check the
1607
capacity of the undo log whenever new_index includes
1608
a column prefix on a column that may be stored externally. */
1610
if (field->prefix_len /* prefix index */
1611
&& !col->ord_part /* not yet ordering column */
1612
&& !dict_col_get_fixed_size(col, TRUE) /* variable-length */
1613
&& dict_col_get_max_size(col)
1614
> BTR_EXTERN_FIELD_REF_SIZE * 2 /* long enough */) {
1616
if (dict_index_too_big_for_undo(table, new_index)) {
1617
/* An undo log record might not fit in
1618
a single page. Refuse to create this index. */
1628
/* Flag the ordering columns */
1630
for (i = 0; i < n_ord; i++) {
1632
dict_index_get_nth_field(new_index, i)->col->ord_part = 1;
1635
/* Add the new index as the last index for the table */
1637
UT_LIST_ADD_LAST(indexes, table->indexes, new_index);
1638
new_index->table = table;
1639
new_index->table_name = table->name;
1641
new_index->search_info = btr_search_info_create(new_index->heap);
1643
new_index->stat_index_size = 1;
1644
new_index->stat_n_leaf_pages = 1;
1646
new_index->page = page_no;
1647
rw_lock_create(index_tree_rw_lock_key, &new_index->lock,
1650
if (!UNIV_UNLIKELY(new_index->type & DICT_UNIVERSAL)) {
1652
new_index->stat_n_diff_key_vals = mem_heap_alloc(
1654
(1 + dict_index_get_n_unique(new_index))
1655
* sizeof(ib_int64_t));
1656
/* Give some sensible values to stat_n_... in case we do
1657
not calculate statistics quickly enough */
1659
for (i = 0; i <= dict_index_get_n_unique(new_index); i++) {
1661
new_index->stat_n_diff_key_vals[i] = 100;
1665
dict_sys->size += mem_heap_get_size(new_index->heap);
1667
dict_mem_index_free(index);
1672
/**********************************************************************//**
1673
Removes an index from the dictionary cache. */
1676
dict_index_remove_from_cache(
1677
/*=========================*/
1678
dict_table_t* table, /*!< in/out: table */
1679
dict_index_t* index) /*!< in, own: index */
1685
ut_ad(table && index);
1686
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
1687
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
1688
ut_ad(mutex_own(&(dict_sys->mutex)));
1690
/* We always create search info whether or not adaptive
1691
hash index is enabled or not. */
1692
info = index->search_info;
1695
/* We are not allowed to free the in-memory index struct
1696
dict_index_t until all entries in the adaptive hash index
1697
that point to any of the page belonging to his b-tree index
1698
are dropped. This is so because dropping of these entries
1699
require access to dict_index_t struct. To avoid such scenario
1700
We keep a count of number of such pages in the search_info and
1701
only free the dict_index_t struct when this count drops to
1705
ulint ref_count = btr_search_info_get_ref_count(info);
1706
if (ref_count == 0) {
1710
/* Sleep for 10ms before trying again. */
1711
os_thread_sleep(10000);
1714
if (retries % 500 == 0) {
1715
/* No luck after 5 seconds of wait. */
1716
fprintf(stderr, "InnoDB: Error: Waited for"
1717
" %lu secs for hash index"
1718
" ref_count (%lu) to drop"
1728
/* To avoid a hang here we commit suicide if the
1729
ref_count doesn't drop to zero in 600 seconds. */
1730
if (retries >= 60000) {
1735
rw_lock_free(&index->lock);
1737
/* Remove the index from the list of indexes of the table */
1738
UT_LIST_REMOVE(indexes, table->indexes, index);
1740
size = mem_heap_get_size(index->heap);
1742
ut_ad(dict_sys->size >= size);
1744
dict_sys->size -= size;
1746
dict_mem_index_free(index);
1749
/*******************************************************************//**
1750
Tries to find column names for the index and sets the col field of the
1752
@return TRUE if the column names were found */
1755
dict_index_find_cols(
1756
/*=================*/
1757
dict_table_t* table, /*!< in: table */
1758
dict_index_t* index) /*!< in: index */
1762
ut_ad(table && index);
1763
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
1764
ut_ad(mutex_own(&(dict_sys->mutex)));
1766
for (i = 0; i < index->n_fields; i++) {
1768
dict_field_t* field = dict_index_get_nth_field(index, i);
1770
for (j = 0; j < table->n_cols; j++) {
1771
if (!strcmp(dict_table_get_col_name(table, j),
1773
field->col = dict_table_get_nth_col(table, j);
1780
/* It is an error not to find a matching column. */
1781
fputs("InnoDB: Error: no matching column for ", stderr);
1782
ut_print_name(stderr, NULL, FALSE, field->name);
1783
fputs(" in ", stderr);
1784
dict_index_name_print(stderr, NULL, index);
1785
fputs("!\n", stderr);
1786
#endif /* UNIV_DEBUG */
1795
#endif /* !UNIV_HOTBACKUP */
1797
/*******************************************************************//**
1798
Adds a column to index. */
1803
dict_index_t* index, /*!< in/out: index */
1804
const dict_table_t* table, /*!< in: table */
1805
dict_col_t* col, /*!< in: column */
1806
ulint prefix_len) /*!< in: column prefix length */
1808
dict_field_t* field;
1809
const char* col_name;
1811
col_name = dict_table_get_col_name(table, dict_col_get_no(col));
1813
dict_mem_index_add_field(index, col_name, prefix_len);
1815
field = dict_index_get_nth_field(index, index->n_def - 1);
1818
field->fixed_len = (unsigned int) dict_col_get_fixed_size(
1819
col, dict_table_is_comp(table));
1821
if (prefix_len && field->fixed_len > prefix_len) {
1822
field->fixed_len = (unsigned int) prefix_len;
1825
/* Long fixed-length fields that need external storage are treated as
1826
variable-length fields, so that the extern flag can be embedded in
1829
if (field->fixed_len > DICT_MAX_INDEX_COL_LEN) {
1830
field->fixed_len = 0;
1832
#if DICT_MAX_INDEX_COL_LEN != 1024
1833
/* The comparison limit above must be constant. If it were
1834
changed, the disk format of some fixed-length columns would
1835
change, which would be a disaster. */
1836
# error "DICT_MAX_INDEX_COL_LEN != 1024"
1839
if (!(col->prtype & DATA_NOT_NULL)) {
1840
index->n_nullable++;
1844
#ifndef UNIV_HOTBACKUP
1845
/*******************************************************************//**
1846
Copies fields contained in index2 to index1. */
1851
dict_index_t* index1, /*!< in: index to copy to */
1852
dict_index_t* index2, /*!< in: index to copy from */
1853
const dict_table_t* table, /*!< in: table */
1854
ulint start, /*!< in: first position to copy */
1855
ulint end) /*!< in: last position to copy */
1857
dict_field_t* field;
1860
/* Copy fields contained in index2 */
1862
for (i = start; i < end; i++) {
1864
field = dict_index_get_nth_field(index2, i);
1865
dict_index_add_col(index1, table, field->col,
1870
/*******************************************************************//**
1871
Copies types of fields contained in index to tuple. */
1874
dict_index_copy_types(
1875
/*==================*/
1876
dtuple_t* tuple, /*!< in/out: data tuple */
1877
const dict_index_t* index, /*!< in: index */
1878
ulint n_fields) /*!< in: number of
1879
field types to copy */
1883
if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) {
1884
dtuple_set_types_binary(tuple, n_fields);
1889
for (i = 0; i < n_fields; i++) {
1890
const dict_field_t* ifield;
1891
dtype_t* dfield_type;
1893
ifield = dict_index_get_nth_field(index, i);
1894
dfield_type = dfield_get_type(dtuple_get_nth_field(tuple, i));
1895
dict_col_copy_type(dict_field_get_col(ifield), dfield_type);
1899
/*******************************************************************//**
1900
Copies types of columns contained in table to tuple and sets all
1901
fields of the tuple to the SQL NULL value. This function should
1902
be called right after dtuple_create(). */
1905
dict_table_copy_types(
1906
/*==================*/
1907
dtuple_t* tuple, /*!< in/out: data tuple */
1908
const dict_table_t* table) /*!< in: table */
1912
for (i = 0; i < dtuple_get_n_fields(tuple); i++) {
1914
dfield_t* dfield = dtuple_get_nth_field(tuple, i);
1915
dtype_t* dtype = dfield_get_type(dfield);
1917
dfield_set_null(dfield);
1918
dict_col_copy_type(dict_table_get_nth_col(table, i), dtype);
1922
/*******************************************************************//**
1923
Builds the internal dictionary cache representation for a clustered
1924
index, containing also system fields not defined by the user.
1925
@return own: the internal representation of the clustered index */
1928
dict_index_build_internal_clust(
1929
/*============================*/
1930
const dict_table_t* table, /*!< in: table */
1931
dict_index_t* index) /*!< in: user representation of
1932
a clustered index */
1934
dict_index_t* new_index;
1935
dict_field_t* field;
1941
ut_ad(table && index);
1942
ut_ad(dict_index_is_clust(index));
1943
ut_ad(mutex_own(&(dict_sys->mutex)));
1944
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
1946
/* Create a new index object with certainly enough fields */
1947
new_index = dict_mem_index_create(table->name,
1948
index->name, table->space,
1950
index->n_fields + table->n_cols);
1952
/* Copy other relevant data from the old index struct to the new
1953
struct: it inherits the values */
1955
new_index->n_user_defined_cols = index->n_fields;
1957
new_index->id = index->id;
1959
/* Copy the fields of index */
1960
dict_index_copy(new_index, index, table, 0, index->n_fields);
1962
if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) {
1963
/* No fixed number of fields determines an entry uniquely */
1965
new_index->n_uniq = REC_MAX_N_FIELDS;
1967
} else if (dict_index_is_unique(index)) {
1968
/* Only the fields defined so far are needed to identify
1969
the index entry uniquely */
1971
new_index->n_uniq = new_index->n_def;
1973
/* Also the row id is needed to identify the entry */
1974
new_index->n_uniq = 1 + new_index->n_def;
1977
new_index->trx_id_offset = 0;
1979
if (!dict_index_is_ibuf(index)) {
1980
/* Add system columns, trx id first */
1982
trx_id_pos = new_index->n_def;
1984
#if DATA_ROW_ID != 0
1985
# error "DATA_ROW_ID != 0"
1987
#if DATA_TRX_ID != 1
1988
# error "DATA_TRX_ID != 1"
1990
#if DATA_ROLL_PTR != 2
1991
# error "DATA_ROLL_PTR != 2"
1994
if (!dict_index_is_unique(index)) {
1995
dict_index_add_col(new_index, table,
1996
dict_table_get_sys_col(
1997
table, DATA_ROW_ID),
2002
dict_index_add_col(new_index, table,
2003
dict_table_get_sys_col(table, DATA_TRX_ID),
2006
dict_index_add_col(new_index, table,
2007
dict_table_get_sys_col(table,
2011
for (i = 0; i < trx_id_pos; i++) {
2013
fixed_size = dict_col_get_fixed_size(
2014
dict_index_get_nth_col(new_index, i),
2015
dict_table_is_comp(table));
2017
if (fixed_size == 0) {
2018
new_index->trx_id_offset = 0;
2023
if (dict_index_get_nth_field(new_index, i)->prefix_len
2025
new_index->trx_id_offset = 0;
2030
new_index->trx_id_offset += (unsigned int) fixed_size;
2035
/* Remember the table columns already contained in new_index */
2036
indexed = mem_zalloc(table->n_cols * sizeof *indexed);
2038
/* Mark the table columns already contained in new_index */
2039
for (i = 0; i < new_index->n_def; i++) {
2041
field = dict_index_get_nth_field(new_index, i);
2043
/* If there is only a prefix of the column in the index
2044
field, do not mark the column as contained in the index */
2046
if (field->prefix_len == 0) {
2048
indexed[field->col->ind] = TRUE;
2052
/* Add to new_index non-system columns of table not yet included
2054
for (i = 0; i + DATA_N_SYS_COLS < (ulint) table->n_cols; i++) {
2056
dict_col_t* col = dict_table_get_nth_col(table, i);
2057
ut_ad(col->mtype != DATA_SYS);
2059
if (!indexed[col->ind]) {
2060
dict_index_add_col(new_index, table, col, 0);
2066
ut_ad(dict_index_is_ibuf(index)
2067
|| (UT_LIST_GET_LEN(table->indexes) == 0));
2069
new_index->cached = TRUE;
2074
/*******************************************************************//**
2075
Builds the internal dictionary cache representation for a non-clustered
2076
index, containing also system fields not defined by the user.
2077
@return own: the internal representation of the non-clustered index */
2080
dict_index_build_internal_non_clust(
2081
/*================================*/
2082
const dict_table_t* table, /*!< in: table */
2083
dict_index_t* index) /*!< in: user representation of
2084
a non-clustered index */
2086
dict_field_t* field;
2087
dict_index_t* new_index;
2088
dict_index_t* clust_index;
2092
ut_ad(table && index);
2093
ut_ad(!dict_index_is_clust(index));
2094
ut_ad(mutex_own(&(dict_sys->mutex)));
2095
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
2097
/* The clustered index should be the first in the list of indexes */
2098
clust_index = UT_LIST_GET_FIRST(table->indexes);
2101
ut_ad(dict_index_is_clust(clust_index));
2102
ut_ad(!(clust_index->type & DICT_UNIVERSAL));
2104
/* Create a new index */
2105
new_index = dict_mem_index_create(
2106
table->name, index->name, index->space, index->type,
2107
index->n_fields + 1 + clust_index->n_uniq);
2109
/* Copy other relevant data from the old index
2110
struct to the new struct: it inherits the values */
2112
new_index->n_user_defined_cols = index->n_fields;
2114
new_index->id = index->id;
2116
/* Copy fields from index to new_index */
2117
dict_index_copy(new_index, index, table, 0, index->n_fields);
2119
/* Remember the table columns already contained in new_index */
2120
indexed = mem_zalloc(table->n_cols * sizeof *indexed);
2122
/* Mark the table columns already contained in new_index */
2123
for (i = 0; i < new_index->n_def; i++) {
2125
field = dict_index_get_nth_field(new_index, i);
2127
/* If there is only a prefix of the column in the index
2128
field, do not mark the column as contained in the index */
2130
if (field->prefix_len == 0) {
2132
indexed[field->col->ind] = TRUE;
2136
/* Add to new_index the columns necessary to determine the clustered
2137
index entry uniquely */
2139
for (i = 0; i < clust_index->n_uniq; i++) {
2141
field = dict_index_get_nth_field(clust_index, i);
2143
if (!indexed[field->col->ind]) {
2144
dict_index_add_col(new_index, table, field->col,
2151
if (dict_index_is_unique(index)) {
2152
new_index->n_uniq = index->n_fields;
2154
new_index->n_uniq = new_index->n_def;
2157
/* Set the n_fields value in new_index to the actual defined
2160
new_index->n_fields = new_index->n_def;
2162
new_index->cached = TRUE;
2167
/*====================== FOREIGN KEY PROCESSING ========================*/
2169
/*********************************************************************//**
2170
Checks if a table is referenced by foreign keys.
2171
@return TRUE if table is referenced by a foreign key */
2174
dict_table_is_referenced_by_foreign_key(
2175
/*====================================*/
2176
const dict_table_t* table) /*!< in: InnoDB table */
2178
return(UT_LIST_GET_LEN(table->referenced_list) > 0);
2181
/*********************************************************************//**
2182
Check if the index is referenced by a foreign key, if TRUE return foreign
2184
@return pointer to foreign key struct if index is defined for foreign
2185
key, otherwise NULL */
2188
dict_table_get_referenced_constraint(
2189
/*=================================*/
2190
dict_table_t* table, /*!< in: InnoDB table */
2191
dict_index_t* index) /*!< in: InnoDB index */
2193
dict_foreign_t* foreign;
2195
ut_ad(index != NULL);
2196
ut_ad(table != NULL);
2198
for (foreign = UT_LIST_GET_FIRST(table->referenced_list);
2200
foreign = UT_LIST_GET_NEXT(referenced_list, foreign)) {
2202
if (foreign->referenced_index == index) {
2211
/*********************************************************************//**
2212
Checks if a index is defined for a foreign key constraint. Index is a part
2213
of a foreign key constraint if the index is referenced by foreign key
2214
or index is a foreign key index.
2215
@return pointer to foreign key struct if index is defined for foreign
2216
key, otherwise NULL */
2219
dict_table_get_foreign_constraint(
2220
/*==============================*/
2221
dict_table_t* table, /*!< in: InnoDB table */
2222
dict_index_t* index) /*!< in: InnoDB index */
2224
dict_foreign_t* foreign;
2226
ut_ad(index != NULL);
2227
ut_ad(table != NULL);
2229
for (foreign = UT_LIST_GET_FIRST(table->foreign_list);
2231
foreign = UT_LIST_GET_NEXT(foreign_list, foreign)) {
2233
if (foreign->foreign_index == index
2234
|| foreign->referenced_index == index) {
2243
/*********************************************************************//**
2244
Frees a foreign key struct. */
2249
dict_foreign_t* foreign) /*!< in, own: foreign key struct */
2251
mem_heap_free(foreign->heap);
2254
/**********************************************************************//**
2255
Removes a foreign constraint struct from the dictionary cache. */
2258
dict_foreign_remove_from_cache(
2259
/*===========================*/
2260
dict_foreign_t* foreign) /*!< in, own: foreign constraint */
2262
ut_ad(mutex_own(&(dict_sys->mutex)));
2265
if (foreign->referenced_table) {
2266
UT_LIST_REMOVE(referenced_list,
2267
foreign->referenced_table->referenced_list,
2271
if (foreign->foreign_table) {
2272
UT_LIST_REMOVE(foreign_list,
2273
foreign->foreign_table->foreign_list,
2277
dict_foreign_free(foreign);
2280
/**********************************************************************//**
2281
Looks for the foreign constraint from the foreign and referenced lists
2283
@return foreign constraint */
2288
dict_table_t* table, /*!< in: table object */
2289
const char* id) /*!< in: foreign constraint id */
2291
dict_foreign_t* foreign;
2293
ut_ad(mutex_own(&(dict_sys->mutex)));
2295
foreign = UT_LIST_GET_FIRST(table->foreign_list);
2298
if (ut_strcmp(id, foreign->id) == 0) {
2303
foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
2306
foreign = UT_LIST_GET_FIRST(table->referenced_list);
2309
if (ut_strcmp(id, foreign->id) == 0) {
2314
foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
2320
/*********************************************************************//**
2321
Tries to find an index whose first fields are the columns in the array,
2322
in the same order and is not marked for deletion and is not the same
2324
@return matching index, NULL if not found */
2327
dict_foreign_find_index(
2328
/*====================*/
2329
dict_table_t* table, /*!< in: table */
2330
const char** columns,/*!< in: array of column names */
2331
ulint n_cols, /*!< in: number of columns */
2332
dict_index_t* types_idx, /*!< in: NULL or an index to whose types the
2333
column types must match */
2334
ibool check_charsets,
2335
/*!< in: whether to check charsets.
2336
only has an effect if types_idx != NULL */
2338
/*!< in: nonzero if none of the columns must
2339
be declared NOT NULL */
2341
dict_index_t* index;
2343
index = dict_table_get_first_index(table);
2345
while (index != NULL) {
2346
/* Ignore matches that refer to the same instance
2347
or the index is to be dropped */
2348
if (index->to_be_dropped || types_idx == index) {
2352
} else if (dict_index_get_n_fields(index) >= n_cols) {
2355
for (i = 0; i < n_cols; i++) {
2356
dict_field_t* field;
2357
const char* col_name;
2359
field = dict_index_get_nth_field(index, i);
2361
col_name = dict_table_get_col_name(
2362
table, dict_col_get_no(field->col));
2364
if (field->prefix_len != 0) {
2365
/* We do not accept column prefix
2371
if (0 != innobase_strcasecmp(columns[i],
2377
&& (field->col->prtype & DATA_NOT_NULL)) {
2382
if (types_idx && !cmp_cols_are_equal(
2383
dict_index_get_nth_col(index, i),
2384
dict_index_get_nth_col(types_idx,
2393
/* We found a matching index */
2400
index = dict_table_get_next_index(index);
2406
/**********************************************************************//**
2407
Find an index that is equivalent to the one passed in and is not marked
2409
@return index equivalent to foreign->foreign_index, or NULL */
2412
dict_foreign_find_equiv_index(
2413
/*==========================*/
2414
dict_foreign_t* foreign)/*!< in: foreign key */
2416
ut_a(foreign != NULL);
2418
/* Try to find an index which contains the columns as the
2419
first fields and in the right order, and the types are the
2420
same as in foreign->foreign_index */
2422
return(dict_foreign_find_index(
2423
foreign->foreign_table,
2424
foreign->foreign_col_names, foreign->n_fields,
2425
foreign->foreign_index, TRUE, /* check types */
2426
FALSE/* allow columns to be NULL */));
2429
/**********************************************************************//**
2430
Returns an index object by matching on the name and column names and
2431
if more than one index matches return the index with the max id
2432
@return matching index, NULL if not found */
2435
dict_table_get_index_by_max_id(
2436
/*===========================*/
2437
dict_table_t* table, /*!< in: table */
2438
const char* name, /*!< in: the index name to find */
2439
const char** columns,/*!< in: array of column names */
2440
ulint n_cols) /*!< in: number of columns */
2442
dict_index_t* index;
2443
dict_index_t* found;
2446
index = dict_table_get_first_index(table);
2448
while (index != NULL) {
2449
if (ut_strcmp(index->name, name) == 0
2450
&& dict_index_get_n_ordering_defined_by_user(index)
2455
for (i = 0; i < n_cols; i++) {
2456
dict_field_t* field;
2457
const char* col_name;
2459
field = dict_index_get_nth_field(index, i);
2461
col_name = dict_table_get_col_name(
2462
table, dict_col_get_no(field->col));
2464
if (0 != innobase_strcasecmp(
2465
columns[i], col_name)) {
2472
/* We found a matching index, select
2473
the index with the higher id*/
2475
if (!found || index->id > found->id) {
2482
index = dict_table_get_next_index(index);
2488
/**********************************************************************//**
2489
Report an error in a foreign key definition. */
2492
dict_foreign_error_report_low(
2493
/*==========================*/
2494
FILE* file, /*!< in: output stream */
2495
const char* name) /*!< in: table name */
2498
ut_print_timestamp(file);
2499
fprintf(file, " Error in foreign key constraint of table %s:\n",
2503
/**********************************************************************//**
2504
Report an error in a foreign key definition. */
2507
dict_foreign_error_report(
2508
/*======================*/
2509
FILE* file, /*!< in: output stream */
2510
dict_foreign_t* fk, /*!< in: foreign key constraint */
2511
const char* msg) /*!< in: the error message */
2513
mutex_enter(&dict_foreign_err_mutex);
2514
dict_foreign_error_report_low(file, fk->foreign_table_name);
2516
fputs(" Constraint:\n", file);
2517
dict_print_info_on_foreign_key_in_create_format(file, NULL, fk, TRUE);
2519
if (fk->foreign_index) {
2520
fputs("The index in the foreign key in table is ", file);
2521
ut_print_name(file, NULL, FALSE, fk->foreign_index->name);
2523
"See " REFMAN "innodb-foreign-key-constraints.html\n"
2524
"for correct foreign key definition.\n",
2527
mutex_exit(&dict_foreign_err_mutex);
2530
/**********************************************************************//**
2531
Adds a foreign key constraint object to the dictionary cache. May free
2532
the object if there already is an object with the same identifier in.
2533
At least one of the foreign table and the referenced table must already
2534
be in the dictionary cache!
2535
@return DB_SUCCESS or error code */
2538
dict_foreign_add_to_cache(
2539
/*======================*/
2540
dict_foreign_t* foreign, /*!< in, own: foreign key constraint */
2541
ibool check_charsets) /*!< in: TRUE=check charset
2544
dict_table_t* for_table;
2545
dict_table_t* ref_table;
2546
dict_foreign_t* for_in_cache = NULL;
2547
dict_index_t* index;
2548
ibool added_to_referenced_list= FALSE;
2549
FILE* ef = dict_foreign_err_file;
2551
ut_ad(mutex_own(&(dict_sys->mutex)));
2553
for_table = dict_table_check_if_in_cache_low(
2554
foreign->foreign_table_name);
2556
ref_table = dict_table_check_if_in_cache_low(
2557
foreign->referenced_table_name);
2558
ut_a(for_table || ref_table);
2561
for_in_cache = dict_foreign_find(for_table, foreign->id);
2564
if (!for_in_cache && ref_table) {
2565
for_in_cache = dict_foreign_find(ref_table, foreign->id);
2569
/* Free the foreign object */
2570
mem_heap_free(foreign->heap);
2572
for_in_cache = foreign;
2575
if (for_in_cache->referenced_table == NULL && ref_table) {
2576
index = dict_foreign_find_index(
2578
for_in_cache->referenced_col_names,
2579
for_in_cache->n_fields, for_in_cache->foreign_index,
2580
check_charsets, FALSE);
2582
if (index == NULL) {
2583
dict_foreign_error_report(
2585
"there is no index in referenced table"
2586
" which would contain\n"
2587
"the columns as the first columns,"
2588
" or the data types in the\n"
2589
"referenced table do not match"
2590
" the ones in table.");
2592
if (for_in_cache == foreign) {
2593
mem_heap_free(foreign->heap);
2596
return(DB_CANNOT_ADD_CONSTRAINT);
2599
for_in_cache->referenced_table = ref_table;
2600
for_in_cache->referenced_index = index;
2601
UT_LIST_ADD_LAST(referenced_list,
2602
ref_table->referenced_list,
2604
added_to_referenced_list = TRUE;
2607
if (for_in_cache->foreign_table == NULL && for_table) {
2608
index = dict_foreign_find_index(
2610
for_in_cache->foreign_col_names,
2611
for_in_cache->n_fields,
2612
for_in_cache->referenced_index, check_charsets,
2614
& (DICT_FOREIGN_ON_DELETE_SET_NULL
2615
| DICT_FOREIGN_ON_UPDATE_SET_NULL));
2617
if (index == NULL) {
2618
dict_foreign_error_report(
2620
"there is no index in the table"
2621
" which would contain\n"
2622
"the columns as the first columns,"
2623
" or the data types in the\n"
2624
"table do not match"
2625
" the ones in the referenced table\n"
2626
"or one of the ON ... SET NULL columns"
2627
" is declared NOT NULL.");
2629
if (for_in_cache == foreign) {
2630
if (added_to_referenced_list) {
2633
ref_table->referenced_list,
2637
mem_heap_free(foreign->heap);
2640
return(DB_CANNOT_ADD_CONSTRAINT);
2643
for_in_cache->foreign_table = for_table;
2644
for_in_cache->foreign_index = index;
2645
UT_LIST_ADD_LAST(foreign_list,
2646
for_table->foreign_list,
2653
/*********************************************************************//**
2654
Scans from pointer onwards. Stops if is at the start of a copy of
2655
'string' where characters are compared without case sensitivity, and
2656
only outside `` or "" quotes. Stops also at NUL.
2657
@return scanned up to this */
2662
const char* ptr, /*!< in: scan from */
2663
const char* string) /*!< in: look for this */
2667
for (; *ptr; ptr++) {
2668
if (*ptr == quote) {
2669
/* Closing quote character: do not look for
2670
starting quote or the keyword. */
2673
/* Within quotes: do nothing. */
2674
} else if (*ptr == '`' || *ptr == '"') {
2675
/* Starting quote: remember the quote character. */
2678
/* Outside quotes: look for the keyword. */
2680
for (i = 0; string[i]; i++) {
2681
if (toupper((int)(unsigned char)(ptr[i]))
2682
!= toupper((int)(unsigned char)
2696
/*********************************************************************//**
2697
Accepts a specified string. Comparisons are case-insensitive.
2698
@return if string was accepted, the pointer is moved after that, else
2704
const void* cs,/*!< in: the character set of ptr */
2705
const char* ptr, /*!< in: scan from this */
2706
const char* string, /*!< in: accept only this string as the next
2707
non-whitespace string */
2708
ibool* success)/*!< out: TRUE if accepted */
2710
const char* old_ptr = ptr;
2711
const char* old_ptr2;
2715
while (innobase_isspace(cs, *ptr)) {
2721
ptr = dict_scan_to(ptr, string);
2723
if (*ptr == '\0' || old_ptr2 != ptr) {
2729
return(ptr + ut_strlen(string));
2732
/*********************************************************************//**
2733
Scans an id. For the lexical definition of an 'id', see the code below.
2734
Strips backquotes or double quotes from around the id.
2735
@return scanned to */
2740
const void* cs,/*!< in: the character set of ptr */
2741
const char* ptr, /*!< in: scanned to */
2742
mem_heap_t* heap, /*!< in: heap where to allocate the id
2743
(NULL=id will not be allocated, but it
2744
will point to string near ptr) */
2745
const char** id, /*!< out,own: the id; NULL if no id was
2747
ibool table_id,/*!< in: TRUE=convert the allocated id
2748
as a table name; FALSE=convert to UTF-8 */
2749
ibool accept_also_dot)
2750
/*!< in: TRUE if also a dot can appear in a
2751
non-quoted id; in a quoted id it can appear
2762
while (innobase_isspace(cs, *ptr)) {
2771
if (*ptr == '`' || *ptr == '"') {
2783
if (*ptr == quote) {
2785
if (*ptr != quote) {
2793
while (!innobase_isspace(cs, *ptr) && *ptr != '(' && *ptr != ')'
2794
&& (accept_also_dot || *ptr != '.')
2795
&& *ptr != ',' && *ptr != '\0') {
2803
if (UNIV_UNLIKELY(!heap)) {
2804
/* no heap given: id will point to source string */
2811
str = d = mem_heap_alloc(heap, len + 1);
2813
if ((*d++ = *s++) == quote) {
2820
ut_ad(s + 1 == ptr);
2822
str = mem_heap_strdupl(heap, s, len);
2827
/* Convert the identifier from connection character set
2830
*id = dst = mem_heap_alloc(heap, len);
2832
innobase_convert_from_id(cs, dst, str, len);
2833
} else if (!strncmp(str, srv_mysql50_table_name_prefix,
2834
sizeof srv_mysql50_table_name_prefix)) {
2835
/* This is a pre-5.1 table name
2836
containing chars other than [A-Za-z0-9].
2837
Discard the prefix and use raw UTF-8 encoding. */
2838
str += sizeof srv_mysql50_table_name_prefix;
2839
len -= sizeof srv_mysql50_table_name_prefix;
2842
/* Encode using filename-safe characters. */
2844
*id = dst = mem_heap_alloc(heap, len);
2846
innobase_convert_from_table_id(cs, dst, str, len);
2852
/*********************************************************************//**
2853
Tries to scan a column name.
2854
@return scanned to */
2859
const void* cs, /*!< in: the character set of ptr */
2860
const char* ptr, /*!< in: scanned to */
2861
ibool* success,/*!< out: TRUE if success */
2862
dict_table_t* table, /*!< in: table in which the column is */
2863
const dict_col_t** column, /*!< out: pointer to column if success */
2864
mem_heap_t* heap, /*!< in: heap where to allocate */
2865
const char** name) /*!< out,own: the column name;
2866
NULL if no name was scannable */
2872
ptr = dict_scan_id(cs, ptr, heap, name, FALSE, TRUE);
2874
if (*name == NULL) {
2876
return(ptr); /* Syntax error */
2879
if (table == NULL) {
2883
for (i = 0; i < dict_table_get_n_cols(table); i++) {
2885
const char* col_name = dict_table_get_col_name(
2888
if (0 == innobase_strcasecmp(col_name, *name)) {
2892
*column = dict_table_get_nth_col(table, i);
2893
strcpy((char*) *name, col_name);
2903
/*********************************************************************//**
2904
Scans a table name from an SQL string.
2905
@return scanned to */
2908
dict_scan_table_name(
2909
/*=================*/
2910
const void* cs,/*!< in: the character set of ptr */
2911
const char* ptr, /*!< in: scanned to */
2912
dict_table_t** table, /*!< out: table object or NULL */
2913
const char* name, /*!< in: foreign key table name */
2914
ibool* success,/*!< out: TRUE if ok name found */
2915
mem_heap_t* heap, /*!< in: heap where to allocate the id */
2916
const char** ref_name)/*!< out,own: the table name;
2917
NULL if no name was scannable */
2919
const char* database_name = NULL;
2920
ulint database_name_len = 0;
2921
const char* table_name = NULL;
2922
ulint table_name_len;
2923
const char* scan_name;
2929
ptr = dict_scan_id(cs, ptr, heap, &scan_name, TRUE, FALSE);
2931
if (scan_name == NULL) {
2933
return(ptr); /* Syntax error */
2937
/* We scanned the database name; scan also the table name */
2941
database_name = scan_name;
2942
database_name_len = strlen(database_name);
2944
ptr = dict_scan_id(cs, ptr, heap, &table_name, TRUE, FALSE);
2946
if (table_name == NULL) {
2948
return(ptr); /* Syntax error */
2951
/* To be able to read table dumps made with InnoDB-4.0.17 or
2952
earlier, we must allow the dot separator between the database
2953
name and the table name also to appear within a quoted
2954
identifier! InnoDB used to print a constraint as:
2955
... REFERENCES `databasename.tablename` ...
2956
starting from 4.0.18 it is
2957
... REFERENCES `databasename`.`tablename` ... */
2960
for (s = scan_name; *s; s++) {
2962
database_name = scan_name;
2963
database_name_len = s - scan_name;
2965
break;/* to do: multiple dots? */
2969
table_name = scan_name;
2972
if (database_name == NULL) {
2973
/* Use the database name of the foreign key table */
2975
database_name = name;
2976
database_name_len = dict_get_db_name_len(name);
2979
table_name_len = strlen(table_name);
2981
/* Copy database_name, '/', table_name, '\0' */
2982
ref = mem_heap_alloc(heap, database_name_len + table_name_len + 2);
2983
memcpy(ref, database_name, database_name_len);
2984
ref[database_name_len] = '/';
2985
memcpy(ref + database_name_len + 1, table_name, table_name_len + 1);
2987
if (srv_lower_case_table_names) {
2988
#endif /* !__WIN__ */
2989
/* The table name is always put to lower case on Windows. */
2990
innobase_casedn_str(ref);
2993
#endif /* !__WIN__ */
2997
*table = dict_table_get_low(ref);
3002
/*********************************************************************//**
3003
Skips one id. The id is allowed to contain also '.'.
3004
@return scanned to */
3009
const void* cs,/*!< in: the character set of ptr */
3010
const char* ptr, /*!< in: scanned to */
3011
ibool* success)/*!< out: TRUE if success, FALSE if just spaces
3012
left in string or a syntax error */
3018
ptr = dict_scan_id(cs, ptr, NULL, &start, FALSE, TRUE);
3027
/*********************************************************************//**
3028
Removes MySQL comments from an SQL string. A comment is either
3029
(a) '#' to the end of the line,
3030
(b) '--[space]' to the end of the line, or
3031
(c) '[slash][asterisk]' till the next '[asterisk][slash]' (like the familiar
3033
@return own: SQL string stripped from comments; the caller must free
3034
this with mem_free()! */
3037
dict_strip_comments(
3038
/*================*/
3039
const char* sql_string, /*!< in: SQL string */
3040
size_t sql_length) /*!< in: length of sql_string */
3044
const char* eptr = sql_string + sql_length;
3046
/* unclosed quote character (0 if none) */
3049
str = mem_alloc(sql_length + 1);
3056
if (sptr >= eptr || *sptr == '\0') {
3060
ut_a(ptr <= str + sql_length);
3065
if (*sptr == quote) {
3066
/* Closing quote character: do not look for
3067
starting quote or comments. */
3070
/* Within quotes: do not look for
3071
starting quotes or comments. */
3072
} else if (*sptr == '"' || *sptr == '`' || *sptr == '\'') {
3073
/* Starting quote: remember the quote character. */
3075
} else if (*sptr == '#'
3076
|| (sptr[0] == '-' && sptr[1] == '-'
3077
&& sptr[2] == ' ')) {
3079
if (++sptr >= eptr) {
3083
/* In Unix a newline is 0x0A while in Windows
3084
it is 0x0D followed by 0x0A */
3093
} else if (!quote && *sptr == '/' && *(sptr + 1) == '*') {
3104
if (sptr[1] == '/') {
3121
/*********************************************************************//**
3122
Finds the highest [number] for foreign key constraints of the table. Looks
3123
only at the >= 4.0.18-format id's, which are of the form
3124
databasename/tablename_ibfk_[number].
3125
@return highest number, 0 if table has no new format foreign key constraints */
3128
dict_table_get_highest_foreign_id(
3129
/*==============================*/
3130
dict_table_t* table) /*!< in: table in the dictionary memory cache */
3132
dict_foreign_t* foreign;
3134
ulint biggest_id = 0;
3140
len = ut_strlen(table->name);
3141
foreign = UT_LIST_GET_FIRST(table->foreign_list);
3144
if (ut_strlen(foreign->id) > ((sizeof dict_ibfk) - 1) + len
3145
&& 0 == ut_memcmp(foreign->id, table->name, len)
3146
&& 0 == ut_memcmp(foreign->id + len,
3147
dict_ibfk, (sizeof dict_ibfk) - 1)
3148
&& foreign->id[len + ((sizeof dict_ibfk) - 1)] != '0') {
3149
/* It is of the >= 4.0.18 format */
3151
id = strtoul(foreign->id + len
3152
+ ((sizeof dict_ibfk) - 1),
3154
if (*endp == '\0') {
3155
ut_a(id != biggest_id);
3157
if (id > biggest_id) {
3163
foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
3169
/*********************************************************************//**
3170
Reports a simple foreign key create clause syntax error. */
3173
dict_foreign_report_syntax_err(
3174
/*===========================*/
3175
const char* name, /*!< in: table name */
3176
const char* start_of_latest_foreign,
3177
/*!< in: start of the foreign key clause
3178
in the SQL string */
3179
const char* ptr) /*!< in: place of the syntax error */
3181
FILE* ef = dict_foreign_err_file;
3183
mutex_enter(&dict_foreign_err_mutex);
3184
dict_foreign_error_report_low(ef, name);
3185
fprintf(ef, "%s:\nSyntax error close to:\n%s\n",
3186
start_of_latest_foreign, ptr);
3187
mutex_exit(&dict_foreign_err_mutex);
3190
/*********************************************************************//**
3191
Scans a table create SQL string and adds to the data dictionary the foreign
3192
key constraints declared in the string. This function should be called after
3193
the indexes for a table have been created. Each foreign key constraint must
3194
be accompanied with indexes in both participating tables. The indexes are
3195
allowed to contain more fields than mentioned in the constraint.
3196
@return error code or DB_SUCCESS */
3199
dict_create_foreign_constraints_low(
3200
/*================================*/
3201
trx_t* trx, /*!< in: transaction */
3202
mem_heap_t* heap, /*!< in: memory heap */
3203
const void* cs,/*!< in: the character set of sql_string */
3204
const char* sql_string,
3205
/*!< in: CREATE TABLE or ALTER TABLE statement
3206
where foreign keys are declared like:
3207
FOREIGN KEY (a, b) REFERENCES table2(c, d),
3208
table2 can be written also with the database
3209
name before it: test.table2; the default
3210
database is the database of parameter name */
3211
const char* name, /*!< in: table full name in the normalized form
3212
database_name/table_name */
3214
/*!< in: if TRUE, fail with error code
3215
DB_CANNOT_ADD_CONSTRAINT if any foreign
3218
dict_table_t* table;
3219
dict_table_t* referenced_table;
3220
dict_table_t* table_to_alter;
3221
ulint highest_id_so_far = 0;
3222
dict_index_t* index;
3223
dict_foreign_t* foreign;
3224
const char* ptr = sql_string;
3225
const char* start_of_latest_foreign = sql_string;
3226
FILE* ef = dict_foreign_err_file;
3227
const char* constraint_name;
3237
const dict_col_t*columns[500];
3238
const char* column_names[500];
3239
const char* referenced_table_name;
3241
ut_ad(mutex_own(&(dict_sys->mutex)));
3243
table = dict_table_get_low(name);
3245
if (table == NULL) {
3246
mutex_enter(&dict_foreign_err_mutex);
3247
dict_foreign_error_report_low(ef, name);
3249
"Cannot find the table in the internal"
3250
" data dictionary of InnoDB.\n"
3251
"Create table statement:\n%s\n", sql_string);
3252
mutex_exit(&dict_foreign_err_mutex);
3257
/* First check if we are actually doing an ALTER TABLE, and in that
3258
case look for the table being altered */
3260
ptr = dict_accept(cs, ptr, "ALTER", &success);
3267
ptr = dict_accept(cs, ptr, "TABLE", &success);
3274
/* We are doing an ALTER TABLE: scan the table name we are altering */
3276
ptr = dict_scan_table_name(cs, ptr, &table_to_alter, name,
3277
&success, heap, &referenced_table_name);
3280
"InnoDB: Error: could not find"
3281
" the table being ALTERED in:\n%s\n",
3287
/* Starting from 4.0.18 and 4.1.2, we generate foreign key id's in the
3288
format databasename/tablename_ibfk_[number], where [number] is local
3289
to the table; look for the highest [number] for table_to_alter, so
3290
that we can assign to new constraints higher numbers. */
3292
/* If we are altering a temporary table, the table name after ALTER
3293
TABLE does not correspond to the internal table name, and
3294
table_to_alter is NULL. TODO: should we fix this somehow? */
3296
if (table_to_alter == NULL) {
3297
highest_id_so_far = 0;
3299
highest_id_so_far = dict_table_get_highest_foreign_id(
3303
/* Scan for foreign key declarations in a loop */
3305
/* Scan either to "CONSTRAINT" or "FOREIGN", whichever is closer */
3307
ptr1 = dict_scan_to(ptr, "CONSTRAINT");
3308
ptr2 = dict_scan_to(ptr, "FOREIGN");
3310
constraint_name = NULL;
3313
/* The user may have specified a constraint name. Pick it so
3314
that we can store 'databasename/constraintname' as the id of
3315
of the constraint to system tables. */
3318
ptr = dict_accept(cs, ptr, "CONSTRAINT", &success);
3322
if (!innobase_isspace(cs, *ptr) && *ptr != '"' && *ptr != '`') {
3326
while (innobase_isspace(cs, *ptr)) {
3330
/* read constraint name unless got "CONSTRAINT FOREIGN" */
3332
ptr = dict_scan_id(cs, ptr, heap,
3333
&constraint_name, FALSE, FALSE);
3340
/* The proper way to reject foreign keys for temporary
3341
tables would be to split the lexing and syntactical
3342
analysis of foreign key clauses from the actual adding
3343
of them, so that ha_innodb.cc could first parse the SQL
3344
command, determine if there are any foreign keys, and
3345
if so, immediately reject the command if the table is a
3346
temporary one. For now, this kludge will work. */
3347
if (reject_fks && (UT_LIST_GET_LEN(table->foreign_list) > 0)) {
3349
return(DB_CANNOT_ADD_CONSTRAINT);
3352
/**********************************************************/
3353
/* The following call adds the foreign key constraints
3354
to the data dictionary system tables on disk */
3356
error = dict_create_add_foreigns_to_dictionary(
3357
highest_id_so_far, table, trx);
3361
start_of_latest_foreign = ptr;
3363
ptr = dict_accept(cs, ptr, "FOREIGN", &success);
3369
if (!innobase_isspace(cs, *ptr)) {
3373
ptr = dict_accept(cs, ptr, "KEY", &success);
3379
ptr = dict_accept(cs, ptr, "(", &success);
3382
/* MySQL allows also an index id before the '('; we
3384
ptr = dict_skip_word(cs, ptr, &success);
3387
dict_foreign_report_syntax_err(
3388
name, start_of_latest_foreign, ptr);
3390
return(DB_CANNOT_ADD_CONSTRAINT);
3393
ptr = dict_accept(cs, ptr, "(", &success);
3396
/* We do not flag a syntax error here because in an
3397
ALTER TABLE we may also have DROP FOREIGN KEY abc */
3405
/* Scan the columns in the first list */
3407
ut_a(i < (sizeof column_names) / sizeof *column_names);
3408
ptr = dict_scan_col(cs, ptr, &success, table, columns + i,
3409
heap, column_names + i);
3411
mutex_enter(&dict_foreign_err_mutex);
3412
dict_foreign_error_report_low(ef, name);
3413
fprintf(ef, "%s:\nCannot resolve column name close to:\n%s\n",
3414
start_of_latest_foreign, ptr);
3415
mutex_exit(&dict_foreign_err_mutex);
3417
return(DB_CANNOT_ADD_CONSTRAINT);
3422
ptr = dict_accept(cs, ptr, ",", &success);
3428
ptr = dict_accept(cs, ptr, ")", &success);
3431
dict_foreign_report_syntax_err(
3432
name, start_of_latest_foreign, ptr);
3433
return(DB_CANNOT_ADD_CONSTRAINT);
3436
/* Try to find an index which contains the columns
3437
as the first fields and in the right order */
3439
index = dict_foreign_find_index(table, column_names, i,
3443
mutex_enter(&dict_foreign_err_mutex);
3444
dict_foreign_error_report_low(ef, name);
3445
fputs("There is no index in table ", ef);
3446
ut_print_name(ef, NULL, TRUE, name);
3447
fprintf(ef, " where the columns appear\n"
3448
"as the first columns. Constraint:\n%s\n"
3449
"See " REFMAN "innodb-foreign-key-constraints.html\n"
3450
"for correct foreign key definition.\n",
3451
start_of_latest_foreign);
3452
mutex_exit(&dict_foreign_err_mutex);
3454
return(DB_CANNOT_ADD_CONSTRAINT);
3456
ptr = dict_accept(cs, ptr, "REFERENCES", &success);
3458
if (!success || !innobase_isspace(cs, *ptr)) {
3459
dict_foreign_report_syntax_err(
3460
name, start_of_latest_foreign, ptr);
3461
return(DB_CANNOT_ADD_CONSTRAINT);
3464
/* Let us create a constraint struct */
3466
foreign = dict_mem_foreign_create();
3468
if (constraint_name) {
3471
/* Catenate 'databasename/' to the constraint name specified
3472
by the user: we conceive the constraint as belonging to the
3473
same MySQL 'database' as the table itself. We store the name
3476
db_len = dict_get_db_name_len(table->name);
3478
foreign->id = mem_heap_alloc(
3479
foreign->heap, db_len + strlen(constraint_name) + 2);
3481
ut_memcpy(foreign->id, table->name, db_len);
3482
foreign->id[db_len] = '/';
3483
strcpy(foreign->id + db_len + 1, constraint_name);
3486
foreign->foreign_table = table;
3487
foreign->foreign_table_name = mem_heap_strdup(foreign->heap,
3489
foreign->foreign_index = index;
3490
foreign->n_fields = (unsigned int) i;
3491
foreign->foreign_col_names = mem_heap_alloc(foreign->heap,
3493
for (i = 0; i < foreign->n_fields; i++) {
3494
foreign->foreign_col_names[i] = mem_heap_strdup(
3496
dict_table_get_col_name(table,
3497
dict_col_get_no(columns[i])));
3500
ptr = dict_scan_table_name(cs, ptr, &referenced_table, name,
3501
&success, heap, &referenced_table_name);
3503
/* Note that referenced_table can be NULL if the user has suppressed
3504
checking of foreign key constraints! */
3506
if (!success || (!referenced_table && trx->check_foreigns)) {
3507
dict_foreign_free(foreign);
3509
mutex_enter(&dict_foreign_err_mutex);
3510
dict_foreign_error_report_low(ef, name);
3511
fprintf(ef, "%s:\nCannot resolve table name close to:\n"
3513
start_of_latest_foreign, ptr);
3514
mutex_exit(&dict_foreign_err_mutex);
3516
return(DB_CANNOT_ADD_CONSTRAINT);
3519
ptr = dict_accept(cs, ptr, "(", &success);
3522
dict_foreign_free(foreign);
3523
dict_foreign_report_syntax_err(name, start_of_latest_foreign,
3525
return(DB_CANNOT_ADD_CONSTRAINT);
3528
/* Scan the columns in the second list */
3532
ptr = dict_scan_col(cs, ptr, &success, referenced_table, columns + i,
3533
heap, column_names + i);
3537
dict_foreign_free(foreign);
3539
mutex_enter(&dict_foreign_err_mutex);
3540
dict_foreign_error_report_low(ef, name);
3541
fprintf(ef, "%s:\nCannot resolve column name close to:\n"
3543
start_of_latest_foreign, ptr);
3544
mutex_exit(&dict_foreign_err_mutex);
3546
return(DB_CANNOT_ADD_CONSTRAINT);
3549
ptr = dict_accept(cs, ptr, ",", &success);
3555
ptr = dict_accept(cs, ptr, ")", &success);
3557
if (!success || foreign->n_fields != i) {
3558
dict_foreign_free(foreign);
3560
dict_foreign_report_syntax_err(name, start_of_latest_foreign,
3562
return(DB_CANNOT_ADD_CONSTRAINT);
3569
/* Loop here as long as we can find ON ... conditions */
3571
ptr = dict_accept(cs, ptr, "ON", &success);
3575
goto try_find_index;
3578
ptr = dict_accept(cs, ptr, "DELETE", &success);
3581
ptr = dict_accept(cs, ptr, "UPDATE", &success);
3584
dict_foreign_free(foreign);
3586
dict_foreign_report_syntax_err(
3587
name, start_of_latest_foreign, ptr);
3588
return(DB_CANNOT_ADD_CONSTRAINT);
3591
is_on_delete = FALSE;
3594
is_on_delete = TRUE;
3598
ptr = dict_accept(cs, ptr, "RESTRICT", &success);
3601
goto scan_on_conditions;
3604
ptr = dict_accept(cs, ptr, "CASCADE", &success);
3608
foreign->type |= DICT_FOREIGN_ON_DELETE_CASCADE;
3610
foreign->type |= DICT_FOREIGN_ON_UPDATE_CASCADE;
3613
goto scan_on_conditions;
3616
ptr = dict_accept(cs, ptr, "NO", &success);
3619
ptr = dict_accept(cs, ptr, "ACTION", &success);
3622
dict_foreign_free(foreign);
3623
dict_foreign_report_syntax_err(
3624
name, start_of_latest_foreign, ptr);
3626
return(DB_CANNOT_ADD_CONSTRAINT);
3630
foreign->type |= DICT_FOREIGN_ON_DELETE_NO_ACTION;
3632
foreign->type |= DICT_FOREIGN_ON_UPDATE_NO_ACTION;
3635
goto scan_on_conditions;
3638
ptr = dict_accept(cs, ptr, "SET", &success);
3641
dict_foreign_free(foreign);
3642
dict_foreign_report_syntax_err(name, start_of_latest_foreign,
3644
return(DB_CANNOT_ADD_CONSTRAINT);
3647
ptr = dict_accept(cs, ptr, "NULL", &success);
3650
dict_foreign_free(foreign);
3651
dict_foreign_report_syntax_err(name, start_of_latest_foreign,
3653
return(DB_CANNOT_ADD_CONSTRAINT);
3656
for (j = 0; j < foreign->n_fields; j++) {
3657
if ((dict_index_get_nth_col(foreign->foreign_index, j)->prtype)
3660
/* It is not sensible to define SET NULL
3661
if the column is not allowed to be NULL! */
3663
dict_foreign_free(foreign);
3665
mutex_enter(&dict_foreign_err_mutex);
3666
dict_foreign_error_report_low(ef, name);
3668
"You have defined a SET NULL condition"
3669
" though some of the\n"
3670
"columns are defined as NOT NULL.\n",
3671
start_of_latest_foreign);
3672
mutex_exit(&dict_foreign_err_mutex);
3674
return(DB_CANNOT_ADD_CONSTRAINT);
3679
foreign->type |= DICT_FOREIGN_ON_DELETE_SET_NULL;
3681
foreign->type |= DICT_FOREIGN_ON_UPDATE_SET_NULL;
3684
goto scan_on_conditions;
3687
if (n_on_deletes > 1 || n_on_updates > 1) {
3688
/* It is an error to define more than 1 action */
3690
dict_foreign_free(foreign);
3692
mutex_enter(&dict_foreign_err_mutex);
3693
dict_foreign_error_report_low(ef, name);
3695
"You have twice an ON DELETE clause"
3696
" or twice an ON UPDATE clause.\n",
3697
start_of_latest_foreign);
3698
mutex_exit(&dict_foreign_err_mutex);
3700
return(DB_CANNOT_ADD_CONSTRAINT);
3703
/* Try to find an index which contains the columns as the first fields
3704
and in the right order, and the types are the same as in
3705
foreign->foreign_index */
3707
if (referenced_table) {
3708
index = dict_foreign_find_index(referenced_table,
3710
foreign->foreign_index,
3713
dict_foreign_free(foreign);
3714
mutex_enter(&dict_foreign_err_mutex);
3715
dict_foreign_error_report_low(ef, name);
3717
"Cannot find an index in the"
3718
" referenced table where the\n"
3719
"referenced columns appear as the"
3720
" first columns, or column types\n"
3721
"in the table and the referenced table"
3722
" do not match for constraint.\n"
3723
"Note that the internal storage type of"
3724
" ENUM and SET changed in\n"
3725
"tables created with >= InnoDB-4.1.12,"
3726
" and such columns in old tables\n"
3727
"cannot be referenced by such columns"
3730
"innodb-foreign-key-constraints.html\n"
3731
"for correct foreign key definition.\n",
3732
start_of_latest_foreign);
3733
mutex_exit(&dict_foreign_err_mutex);
3735
return(DB_CANNOT_ADD_CONSTRAINT);
3738
ut_a(trx->check_foreigns == FALSE);
3742
foreign->referenced_index = index;
3743
foreign->referenced_table = referenced_table;
3745
foreign->referenced_table_name
3746
= mem_heap_strdup(foreign->heap, referenced_table_name);
3748
foreign->referenced_col_names = mem_heap_alloc(foreign->heap,
3750
for (i = 0; i < foreign->n_fields; i++) {
3751
foreign->referenced_col_names[i]
3752
= mem_heap_strdup(foreign->heap, column_names[i]);
3755
/* We found an ok constraint definition: add to the lists */
3757
UT_LIST_ADD_LAST(foreign_list, table->foreign_list, foreign);
3759
if (referenced_table) {
3760
UT_LIST_ADD_LAST(referenced_list,
3761
referenced_table->referenced_list,
3768
/*********************************************************************//**
3769
Scans a table create SQL string and adds to the data dictionary the foreign
3770
key constraints declared in the string. This function should be called after
3771
the indexes for a table have been created. Each foreign key constraint must
3772
be accompanied with indexes in both participating tables. The indexes are
3773
allowed to contain more fields than mentioned in the constraint.
3774
@return error code or DB_SUCCESS */
3777
dict_create_foreign_constraints(
3778
/*============================*/
3779
trx_t* trx, /*!< in: transaction */
3780
const char* sql_string, /*!< in: table create statement where
3781
foreign keys are declared like:
3782
FOREIGN KEY (a, b) REFERENCES
3783
table2(c, d), table2 can be written
3784
also with the database
3785
name before it: test.table2; the
3786
default database id the database of
3788
size_t sql_length, /*!< in: length of sql_string */
3789
const char* name, /*!< in: table full name in the
3791
database_name/table_name */
3792
ibool reject_fks) /*!< in: if TRUE, fail with error
3793
code DB_CANNOT_ADD_CONSTRAINT if
3794
any foreign keys are found. */
3801
ut_a(trx->mysql_thd);
3803
str = dict_strip_comments(sql_string, sql_length);
3804
heap = mem_heap_create(10000);
3806
err = dict_create_foreign_constraints_low(
3807
trx, heap, innobase_get_charset(trx->mysql_thd), str, name,
3810
mem_heap_free(heap);
3816
/**********************************************************************//**
3817
Parses the CONSTRAINT id's to be dropped in an ALTER TABLE statement.
3818
@return DB_SUCCESS or DB_CANNOT_DROP_CONSTRAINT if syntax error or the
3819
constraint id does not match */
3822
dict_foreign_parse_drop_constraints(
3823
/*================================*/
3824
mem_heap_t* heap, /*!< in: heap from which we can
3826
trx_t* trx, /*!< in: transaction */
3827
dict_table_t* table, /*!< in: table */
3828
ulint* n, /*!< out: number of constraints
3830
const char*** constraints_to_drop) /*!< out: id's of the
3831
constraints to drop */
3833
dict_foreign_t* foreign;
3839
FILE* ef = dict_foreign_err_file;
3843
ut_a(trx->mysql_thd);
3845
cs = innobase_get_charset(trx->mysql_thd);
3849
*constraints_to_drop = mem_heap_alloc(heap, 1000 * sizeof(char*));
3851
ptr = innobase_get_stmt(trx->mysql_thd, &len);
3853
str = dict_strip_comments(ptr, len);
3857
ut_ad(mutex_own(&(dict_sys->mutex)));
3859
ptr = dict_scan_to(ptr, "DROP");
3867
ptr = dict_accept(cs, ptr, "DROP", &success);
3869
if (!innobase_isspace(cs, *ptr)) {
3874
ptr = dict_accept(cs, ptr, "FOREIGN", &success);
3876
if (!success || !innobase_isspace(cs, *ptr)) {
3881
ptr = dict_accept(cs, ptr, "KEY", &success);
3888
ptr = dict_scan_id(cs, ptr, heap, &id, FALSE, TRUE);
3896
(*constraints_to_drop)[*n] = id;
3899
/* Look for the given constraint id */
3901
foreign = UT_LIST_GET_FIRST(table->foreign_list);
3903
while (foreign != NULL) {
3904
if (0 == strcmp(foreign->id, id)
3905
|| (strchr(foreign->id, '/')
3907
dict_remove_db_name(foreign->id)))) {
3912
foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
3915
if (foreign == NULL) {
3916
mutex_enter(&dict_foreign_err_mutex);
3918
ut_print_timestamp(ef);
3919
fputs(" Error in dropping of a foreign key constraint"
3921
ut_print_name(ef, NULL, TRUE, table->name);
3923
"in SQL command\n", ef);
3925
fputs("\nCannot find a constraint with the given id ", ef);
3926
ut_print_name(ef, NULL, FALSE, id);
3928
mutex_exit(&dict_foreign_err_mutex);
3932
return(DB_CANNOT_DROP_CONSTRAINT);
3938
mutex_enter(&dict_foreign_err_mutex);
3940
ut_print_timestamp(ef);
3941
fputs(" Syntax error in dropping of a"
3942
" foreign key constraint of table ", ef);
3943
ut_print_name(ef, NULL, TRUE, table->name);
3945
"close to:\n%s\n in SQL command\n%s\n", ptr, str);
3946
mutex_exit(&dict_foreign_err_mutex);
3950
return(DB_CANNOT_DROP_CONSTRAINT);
3953
/*==================== END OF FOREIGN KEY PROCESSING ====================*/
3955
/**********************************************************************//**
3956
Returns an index object if it is found in the dictionary cache.
3957
Assumes that dict_sys->mutex is already being held.
3958
@return index, NULL if not found */
3961
dict_index_get_if_in_cache_low(
3962
/*===========================*/
3963
index_id_t index_id) /*!< in: index id */
3965
ut_ad(mutex_own(&(dict_sys->mutex)));
3967
return(dict_index_find_on_id_low(index_id));
3970
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
3971
/**********************************************************************//**
3972
Returns an index object if it is found in the dictionary cache.
3973
@return index, NULL if not found */
3976
dict_index_get_if_in_cache(
3977
/*=======================*/
3978
index_id_t index_id) /*!< in: index id */
3980
dict_index_t* index;
3982
if (dict_sys == NULL) {
3986
mutex_enter(&(dict_sys->mutex));
3988
index = dict_index_get_if_in_cache_low(index_id);
3990
mutex_exit(&(dict_sys->mutex));
3994
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
3997
/**********************************************************************//**
3998
Checks that a tuple has n_fields_cmp value in a sensible range, so that
3999
no comparison can occur with the page number field in a node pointer.
4000
@return TRUE if ok */
4003
dict_index_check_search_tuple(
4004
/*==========================*/
4005
const dict_index_t* index, /*!< in: index tree */
4006
const dtuple_t* tuple) /*!< in: tuple used in a search */
4009
ut_a(dtuple_get_n_fields_cmp(tuple)
4010
<= dict_index_get_n_unique_in_tree(index));
4013
#endif /* UNIV_DEBUG */
4015
/**********************************************************************//**
4016
Builds a node pointer out of a physical record and a page number.
4017
@return own: node pointer */
4020
dict_index_build_node_ptr(
4021
/*======================*/
4022
const dict_index_t* index, /*!< in: index */
4023
const rec_t* rec, /*!< in: record for which to build node
4025
ulint page_no,/*!< in: page number to put in node
4027
mem_heap_t* heap, /*!< in: memory heap where pointer
4029
ulint level) /*!< in: level of rec in tree:
4030
0 means leaf level */
4037
if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) {
4038
/* In a universal index tree, we take the whole record as
4039
the node pointer if the record is on the leaf level,
4040
on non-leaf levels we remove the last field, which
4041
contains the page number of the child page */
4043
ut_a(!dict_table_is_comp(index->table));
4044
n_unique = rec_get_n_fields_old(rec);
4051
n_unique = dict_index_get_n_unique_in_tree(index);
4054
tuple = dtuple_create(heap, n_unique + 1);
4056
/* When searching in the tree for the node pointer, we must not do
4057
comparison on the last field, the page number field, as on upper
4058
levels in the tree there may be identical node pointers with a
4059
different page number; therefore, we set the n_fields_cmp to one
4062
dtuple_set_n_fields_cmp(tuple, n_unique);
4064
dict_index_copy_types(tuple, index, n_unique);
4066
buf = mem_heap_alloc(heap, 4);
4068
mach_write_to_4(buf, page_no);
4070
field = dtuple_get_nth_field(tuple, n_unique);
4071
dfield_set_data(field, buf, 4);
4073
dtype_set(dfield_get_type(field), DATA_SYS_CHILD, DATA_NOT_NULL, 4);
4075
rec_copy_prefix_to_dtuple(tuple, rec, index, n_unique, heap);
4076
dtuple_set_info_bits(tuple, dtuple_get_info_bits(tuple)
4077
| REC_STATUS_NODE_PTR);
4079
ut_ad(dtuple_check_typed(tuple));
4084
/**********************************************************************//**
4085
Copies an initial segment of a physical record, long enough to specify an
4086
index entry uniquely.
4087
@return pointer to the prefix record */
4090
dict_index_copy_rec_order_prefix(
4091
/*=============================*/
4092
const dict_index_t* index, /*!< in: index */
4093
const rec_t* rec, /*!< in: record for which to
4095
ulint* n_fields,/*!< out: number of fields copied */
4096
byte** buf, /*!< in/out: memory buffer for the
4097
copied prefix, or NULL */
4098
ulint* buf_size)/*!< in/out: buffer size */
4102
UNIV_PREFETCH_R(rec);
4104
if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) {
4105
ut_a(!dict_table_is_comp(index->table));
4106
n = rec_get_n_fields_old(rec);
4108
n = dict_index_get_n_unique_in_tree(index);
4112
return(rec_copy_prefix_to_buf(rec, index, n, buf, buf_size));
4115
/**********************************************************************//**
4116
Builds a typed data tuple out of a physical record.
4117
@return own: data tuple */
4120
dict_index_build_data_tuple(
4121
/*========================*/
4122
dict_index_t* index, /*!< in: index tree */
4123
rec_t* rec, /*!< in: record for which to build data tuple */
4124
ulint n_fields,/*!< in: number of data fields */
4125
mem_heap_t* heap) /*!< in: memory heap where tuple created */
4129
ut_ad(dict_table_is_comp(index->table)
4130
|| n_fields <= rec_get_n_fields_old(rec));
4132
tuple = dtuple_create(heap, n_fields);
4134
dict_index_copy_types(tuple, index, n_fields);
4136
rec_copy_prefix_to_dtuple(tuple, rec, index, n_fields, heap);
4138
ut_ad(dtuple_check_typed(tuple));
4143
/*********************************************************************//**
4144
Calculates the minimum record length in an index. */
4147
dict_index_calc_min_rec_len(
4148
/*========================*/
4149
const dict_index_t* index) /*!< in: index */
4153
ulint comp = dict_table_is_comp(index->table);
4157
sum = REC_N_NEW_EXTRA_BYTES;
4158
for (i = 0; i < dict_index_get_n_fields(index); i++) {
4159
const dict_col_t* col
4160
= dict_index_get_nth_col(index, i);
4161
ulint size = dict_col_get_fixed_size(col, comp);
4165
sum += size < 128 ? 1 : 2;
4167
if (!(col->prtype & DATA_NOT_NULL)) {
4172
/* round the NULL flags up to full bytes */
4173
sum += UT_BITS_IN_BYTES(nullable);
4178
for (i = 0; i < dict_index_get_n_fields(index); i++) {
4179
sum += dict_col_get_fixed_size(
4180
dict_index_get_nth_col(index, i), comp);
4184
sum += 2 * dict_index_get_n_fields(index);
4186
sum += dict_index_get_n_fields(index);
4189
sum += REC_N_OLD_EXTRA_BYTES;
4194
/*********************************************************************//**
4195
Calculates new estimates for table and index statistics. The statistics
4196
are used in query optimization. */
4199
dict_update_statistics_low(
4200
/*=======================*/
4201
dict_table_t* table, /*!< in/out: table */
4202
ibool has_dict_mutex __attribute__((unused)))
4203
/*!< in: TRUE if the caller has the
4206
dict_index_t* index;
4207
ulint sum_of_index_sizes = 0;
4209
if (table->ibd_file_missing) {
4210
ut_print_timestamp(stderr);
4212
" InnoDB: cannot calculate statistics for table %s\n"
4213
"InnoDB: because the .ibd file is missing. For help,"
4214
" please refer to\n"
4215
"InnoDB: " REFMAN "innodb-troubleshooting.html\n",
4221
/* Find out the sizes of the indexes and how many different values
4222
for the key they approximately have */
4224
index = dict_table_get_first_index(table);
4226
if (index == NULL) {
4227
/* Table definition is corrupt */
4235
(srv_force_recovery < SRV_FORCE_NO_IBUF_MERGE
4236
|| (srv_force_recovery < SRV_FORCE_NO_LOG_REDO
4237
&& dict_index_is_clust(index)))) {
4239
size = btr_get_size(index, BTR_TOTAL_SIZE);
4241
index->stat_index_size = size;
4243
sum_of_index_sizes += size;
4245
size = btr_get_size(index, BTR_N_LEAF_PAGES);
4248
/* The root node of the tree is a leaf */
4252
index->stat_n_leaf_pages = size;
4254
btr_estimate_number_of_different_key_vals(index);
4256
/* If we have set a high innodb_force_recovery
4257
level, do not calculate statistics, as a badly
4258
corrupted index can cause a crash in it.
4259
Initialize some bogus index cardinality
4260
statistics, so that the data can be queried in
4261
various means, also via secondary indexes. */
4264
sum_of_index_sizes++;
4265
index->stat_index_size = index->stat_n_leaf_pages = 1;
4267
for (i = dict_index_get_n_unique(index); i; ) {
4268
index->stat_n_diff_key_vals[i--] = 1;
4272
index = dict_table_get_next_index(index);
4275
index = dict_table_get_first_index(table);
4277
dict_index_stat_mutex_enter(index);
4279
table->stat_n_rows = index->stat_n_diff_key_vals[
4280
dict_index_get_n_unique(index)];
4282
dict_index_stat_mutex_exit(index);
4284
table->stat_clustered_index_size = index->stat_index_size;
4286
table->stat_sum_of_other_index_sizes = sum_of_index_sizes
4287
- index->stat_index_size;
4289
table->stat_initialized = TRUE;
4291
table->stat_modified_counter = 0;
4294
/*********************************************************************//**
4295
Calculates new estimates for table and index statistics. The statistics
4296
are used in query optimization. */
4299
dict_update_statistics(
4300
/*===================*/
4301
dict_table_t* table) /*!< in/out: table */
4303
dict_update_statistics_low(table, FALSE);
4306
/**********************************************************************//**
4307
Prints info of a foreign key constraint. */
4310
dict_foreign_print_low(
4311
/*===================*/
4312
dict_foreign_t* foreign) /*!< in: foreign key constraint */
4316
ut_ad(mutex_own(&(dict_sys->mutex)));
4318
fprintf(stderr, " FOREIGN KEY CONSTRAINT %s: %s (",
4319
foreign->id, foreign->foreign_table_name);
4321
for (i = 0; i < foreign->n_fields; i++) {
4322
fprintf(stderr, " %s", foreign->foreign_col_names[i]);
4325
fprintf(stderr, " )\n"
4327
foreign->referenced_table_name);
4329
for (i = 0; i < foreign->n_fields; i++) {
4330
fprintf(stderr, " %s", foreign->referenced_col_names[i]);
4333
fputs(" )\n", stderr);
4336
/**********************************************************************//**
4337
Prints a table data. */
4342
dict_table_t* table) /*!< in: table */
4344
mutex_enter(&(dict_sys->mutex));
4345
dict_table_print_low(table);
4346
mutex_exit(&(dict_sys->mutex));
4349
/**********************************************************************//**
4350
Prints a table data when we know the table name. */
4353
dict_table_print_by_name(
4354
/*=====================*/
4355
const char* name) /*!< in: table name */
4357
dict_table_t* table;
4359
mutex_enter(&(dict_sys->mutex));
4361
table = dict_table_get_low(name);
4365
dict_table_print_low(table);
4366
mutex_exit(&(dict_sys->mutex));
4369
/**********************************************************************//**
4370
Prints a table data. */
4373
dict_table_print_low(
4374
/*=================*/
4375
dict_table_t* table) /*!< in: table */
4377
dict_index_t* index;
4378
dict_foreign_t* foreign;
4381
ut_ad(mutex_own(&(dict_sys->mutex)));
4383
dict_update_statistics_low(table, TRUE);
4386
"--------------------------------------\n"
4387
"TABLE: name %s, id %llu, flags %lx, columns %lu,"
4388
" indexes %lu, appr.rows %lu\n"
4392
(ulong) table->flags,
4393
(ulong) table->n_cols,
4394
(ulong) UT_LIST_GET_LEN(table->indexes),
4395
(ulong) table->stat_n_rows);
4397
for (i = 0; i < (ulint) table->n_cols; i++) {
4398
dict_col_print_low(table, dict_table_get_nth_col(table, i));
4399
fputs("; ", stderr);
4404
index = UT_LIST_GET_FIRST(table->indexes);
4406
while (index != NULL) {
4407
dict_index_print_low(index);
4408
index = UT_LIST_GET_NEXT(indexes, index);
4411
foreign = UT_LIST_GET_FIRST(table->foreign_list);
4413
while (foreign != NULL) {
4414
dict_foreign_print_low(foreign);
4415
foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
4418
foreign = UT_LIST_GET_FIRST(table->referenced_list);
4420
while (foreign != NULL) {
4421
dict_foreign_print_low(foreign);
4422
foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
4426
/**********************************************************************//**
4427
Prints a column data. */
4432
const dict_table_t* table, /*!< in: table */
4433
const dict_col_t* col) /*!< in: column */
4437
ut_ad(mutex_own(&(dict_sys->mutex)));
4439
dict_col_copy_type(col, &type);
4440
fprintf(stderr, "%s: ", dict_table_get_col_name(table,
4441
dict_col_get_no(col)));
4446
/**********************************************************************//**
4447
Prints an index data. */
4450
dict_index_print_low(
4451
/*=================*/
4452
dict_index_t* index) /*!< in: index */
4457
ut_ad(mutex_own(&(dict_sys->mutex)));
4459
dict_index_stat_mutex_enter(index);
4461
if (index->n_user_defined_cols > 0) {
4462
n_vals = index->stat_n_diff_key_vals[
4463
index->n_user_defined_cols];
4465
n_vals = index->stat_n_diff_key_vals[1];
4468
dict_index_stat_mutex_exit(index);
4471
" INDEX: name %s, id %llu, fields %lu/%lu,"
4472
" uniq %lu, type %lu\n"
4473
" root page %lu, appr.key vals %lu,"
4474
" leaf pages %lu, size pages %lu\n"
4478
(ulong) index->n_user_defined_cols,
4479
(ulong) index->n_fields,
4480
(ulong) index->n_uniq,
4481
(ulong) index->type,
4482
(ulong) index->page,
4484
(ulong) index->stat_n_leaf_pages,
4485
(ulong) index->stat_index_size);
4487
for (i = 0; i < index->n_fields; i++) {
4488
dict_field_print_low(dict_index_get_nth_field(index, i));
4493
#ifdef UNIV_BTR_PRINT
4494
btr_print_size(index);
4496
btr_print_index(index, 7);
4497
#endif /* UNIV_BTR_PRINT */
4500
/**********************************************************************//**
4501
Prints a field data. */
4504
dict_field_print_low(
4505
/*=================*/
4506
const dict_field_t* field) /*!< in: field */
4508
ut_ad(mutex_own(&(dict_sys->mutex)));
4510
fprintf(stderr, " %s", field->name);
4512
if (field->prefix_len != 0) {
4513
fprintf(stderr, "(%lu)", (ulong) field->prefix_len);
4517
/**********************************************************************//**
4518
Outputs info on a foreign key of a table in a format suitable for
4522
dict_print_info_on_foreign_key_in_create_format(
4523
/*============================================*/
4524
FILE* file, /*!< in: file where to print */
4525
trx_t* trx, /*!< in: transaction */
4526
dict_foreign_t* foreign, /*!< in: foreign key constraint */
4527
ibool add_newline) /*!< in: whether to add a newline */
4529
const char* stripped_id;
4532
if (strchr(foreign->id, '/')) {
4533
/* Strip the preceding database name from the constraint id */
4534
stripped_id = foreign->id + 1
4535
+ dict_get_db_name_len(foreign->id);
4537
stripped_id = foreign->id;
4543
/* SHOW CREATE TABLE wants constraints each printed nicely
4544
on its own line, while error messages want no newlines
4549
fputs(" CONSTRAINT ", file);
4550
ut_print_name(file, trx, FALSE, stripped_id);
4551
fputs(" FOREIGN KEY (", file);
4554
ut_print_name(file, trx, FALSE, foreign->foreign_col_names[i]);
4555
if (++i < foreign->n_fields) {
4562
fputs(") REFERENCES ", file);
4564
if (dict_tables_have_same_db(foreign->foreign_table_name,
4565
foreign->referenced_table_name)) {
4566
/* Do not print the database name of the referenced table */
4567
ut_print_name(file, trx, TRUE,
4568
dict_remove_db_name(
4569
foreign->referenced_table_name));
4571
ut_print_name(file, trx, TRUE,
4572
foreign->referenced_table_name);
4579
ut_print_name(file, trx, FALSE,
4580
foreign->referenced_col_names[i]);
4581
if (++i < foreign->n_fields) {
4590
if (foreign->type & DICT_FOREIGN_ON_DELETE_CASCADE) {
4591
fputs(" ON DELETE CASCADE", file);
4594
if (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL) {
4595
fputs(" ON DELETE SET NULL", file);
4598
if (foreign->type & DICT_FOREIGN_ON_DELETE_NO_ACTION) {
4599
fputs(" ON DELETE NO ACTION", file);
4602
if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE) {
4603
fputs(" ON UPDATE CASCADE", file);
4606
if (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL) {
4607
fputs(" ON UPDATE SET NULL", file);
4610
if (foreign->type & DICT_FOREIGN_ON_UPDATE_NO_ACTION) {
4611
fputs(" ON UPDATE NO ACTION", file);
4615
/**********************************************************************//**
4616
Outputs info on foreign keys of a table. */
4619
dict_print_info_on_foreign_keys(
4620
/*============================*/
4621
ibool create_table_format, /*!< in: if TRUE then print in
4622
a format suitable to be inserted into
4623
a CREATE TABLE, otherwise in the format
4624
of SHOW TABLE STATUS */
4625
FILE* file, /*!< in: file where to print */
4626
trx_t* trx, /*!< in: transaction */
4627
dict_table_t* table) /*!< in: table */
4629
dict_foreign_t* foreign;
4631
mutex_enter(&(dict_sys->mutex));
4633
foreign = UT_LIST_GET_FIRST(table->foreign_list);
4635
if (foreign == NULL) {
4636
mutex_exit(&(dict_sys->mutex));
4641
while (foreign != NULL) {
4642
if (create_table_format) {
4643
dict_print_info_on_foreign_key_in_create_format(
4644
file, trx, foreign, TRUE);
4649
for (i = 0; i < foreign->n_fields; i++) {
4654
ut_print_name(file, trx, FALSE,
4655
foreign->foreign_col_names[i]);
4658
fputs(") REFER ", file);
4659
ut_print_name(file, trx, TRUE,
4660
foreign->referenced_table_name);
4663
for (i = 0; i < foreign->n_fields; i++) {
4669
foreign->referenced_col_names[i]);
4674
if (foreign->type == DICT_FOREIGN_ON_DELETE_CASCADE) {
4675
fputs(" ON DELETE CASCADE", file);
4678
if (foreign->type == DICT_FOREIGN_ON_DELETE_SET_NULL) {
4679
fputs(" ON DELETE SET NULL", file);
4682
if (foreign->type & DICT_FOREIGN_ON_DELETE_NO_ACTION) {
4683
fputs(" ON DELETE NO ACTION", file);
4686
if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE) {
4687
fputs(" ON UPDATE CASCADE", file);
4690
if (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL) {
4691
fputs(" ON UPDATE SET NULL", file);
4694
if (foreign->type & DICT_FOREIGN_ON_UPDATE_NO_ACTION) {
4695
fputs(" ON UPDATE NO ACTION", file);
4699
foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
4702
mutex_exit(&(dict_sys->mutex));
4705
/********************************************************************//**
4706
Displays the names of the index and the table. */
4709
dict_index_name_print(
4710
/*==================*/
4711
FILE* file, /*!< in: output stream */
4712
trx_t* trx, /*!< in: transaction */
4713
const dict_index_t* index) /*!< in: index to print */
4715
fputs("index ", file);
4716
ut_print_name(file, trx, FALSE, index->name);
4717
fputs(" of table ", file);
4718
ut_print_name(file, trx, TRUE, index->table_name);
4720
#endif /* !UNIV_HOTBACKUP */
4722
/**********************************************************************//**
4723
Inits dict_ind_redundant and dict_ind_compact. */
4729
dict_table_t* table;
4731
/* create dummy table and index for REDUNDANT infimum and supremum */
4732
table = dict_mem_table_create("SYS_DUMMY1", DICT_HDR_SPACE, 1, 0);
4733
dict_mem_table_add_col(table, NULL, NULL, DATA_CHAR,
4734
DATA_ENGLISH | DATA_NOT_NULL, 8);
4736
dict_ind_redundant = dict_mem_index_create("SYS_DUMMY1", "SYS_DUMMY1",
4737
DICT_HDR_SPACE, 0, 1);
4738
dict_index_add_col(dict_ind_redundant, table,
4739
dict_table_get_nth_col(table, 0), 0);
4740
dict_ind_redundant->table = table;
4741
/* create dummy table and index for COMPACT infimum and supremum */
4742
table = dict_mem_table_create("SYS_DUMMY2",
4743
DICT_HDR_SPACE, 1, DICT_TF_COMPACT);
4744
dict_mem_table_add_col(table, NULL, NULL, DATA_CHAR,
4745
DATA_ENGLISH | DATA_NOT_NULL, 8);
4746
dict_ind_compact = dict_mem_index_create("SYS_DUMMY2", "SYS_DUMMY2",
4747
DICT_HDR_SPACE, 0, 1);
4748
dict_index_add_col(dict_ind_compact, table,
4749
dict_table_get_nth_col(table, 0), 0);
4750
dict_ind_compact->table = table;
4752
/* avoid ut_ad(index->cached) in dict_index_get_n_unique_in_tree */
4753
dict_ind_redundant->cached = dict_ind_compact->cached = TRUE;
4756
/**********************************************************************//**
4757
Frees dict_ind_redundant and dict_ind_compact. */
4763
dict_table_t* table;
4765
table = dict_ind_compact->table;
4766
dict_mem_index_free(dict_ind_compact);
4767
dict_ind_compact = NULL;
4768
dict_mem_table_free(table);
4770
table = dict_ind_redundant->table;
4771
dict_mem_index_free(dict_ind_redundant);
4772
dict_ind_redundant = NULL;
4773
dict_mem_table_free(table);
4776
#ifndef UNIV_HOTBACKUP
4777
/**********************************************************************//**
4779
@return index, NULL if does not exist */
4782
dict_table_get_index_on_name(
4783
/*=========================*/
4784
dict_table_t* table, /*!< in: table */
4785
const char* name) /*!< in: name of the index to find */
4787
dict_index_t* index;
4789
index = dict_table_get_first_index(table);
4791
while (index != NULL) {
4792
if (ut_strcmp(index->name, name) == 0) {
4797
index = dict_table_get_next_index(index);
4804
/**********************************************************************//**
4805
Replace the index passed in with another equivalent index in the tables
4806
foreign key list. */
4809
dict_table_replace_index_in_foreign_list(
4810
/*=====================================*/
4811
dict_table_t* table, /*!< in/out: table */
4812
dict_index_t* index) /*!< in: index to be replaced */
4814
dict_foreign_t* foreign;
4816
for (foreign = UT_LIST_GET_FIRST(table->foreign_list);
4818
foreign = UT_LIST_GET_NEXT(foreign_list, foreign)) {
4820
if (foreign->foreign_index == index) {
4821
dict_index_t* new_index
4822
= dict_foreign_find_equiv_index(foreign);
4825
foreign->foreign_index = new_index;
4830
/**********************************************************************//**
4831
In case there is more than one index with the same name return the index
4833
@return index, NULL if does not exist */
4836
dict_table_get_index_on_name_and_min_id(
4837
/*=====================================*/
4838
dict_table_t* table, /*!< in: table */
4839
const char* name) /*!< in: name of the index to find */
4841
dict_index_t* index;
4842
dict_index_t* min_index; /* Index with matching name and min(id) */
4845
index = dict_table_get_first_index(table);
4847
while (index != NULL) {
4848
if (ut_strcmp(index->name, name) == 0) {
4849
if (!min_index || index->id < min_index->id) {
4855
index = dict_table_get_next_index(index);
4863
/**********************************************************************//**
4864
Check for duplicate index entries in a table [using the index name] */
4867
dict_table_check_for_dup_indexes(
4868
/*=============================*/
4869
const dict_table_t* table, /*!< in: Check for dup indexes
4871
ibool tmp_ok) /*!< in: TRUE=allow temporary
4874
/* Check for duplicates, ignoring indexes that are marked
4877
const dict_index_t* index1;
4878
const dict_index_t* index2;
4880
ut_ad(mutex_own(&dict_sys->mutex));
4882
/* The primary index _must_ exist */
4883
ut_a(UT_LIST_GET_LEN(table->indexes) > 0);
4885
index1 = UT_LIST_GET_FIRST(table->indexes);
4888
ut_ad(tmp_ok || *index1->name != TEMP_INDEX_PREFIX);
4890
index2 = UT_LIST_GET_NEXT(indexes, index1);
4894
if (!index2->to_be_dropped) {
4895
ut_ad(ut_strcmp(index1->name, index2->name));
4898
index2 = UT_LIST_GET_NEXT(indexes, index2);
4901
index1 = UT_LIST_GET_NEXT(indexes, index1);
4904
#endif /* UNIV_DEBUG */
4906
/**************************************************************************
4907
Closes the data dictionary module. */
4915
/* Free the hash elements. We don't remove them from the table
4916
because we are going to destroy the table anyway. */
4917
for (i = 0; i < hash_get_n_cells(dict_sys->table_hash); i++) {
4918
dict_table_t* table;
4920
table = HASH_GET_FIRST(dict_sys->table_hash, i);
4923
dict_table_t* prev_table = table;
4925
table = HASH_GET_NEXT(name_hash, prev_table);
4927
ut_a(prev_table->magic_n == DICT_TABLE_MAGIC_N);
4929
/* Acquire only because it's a pre-condition. */
4930
mutex_enter(&dict_sys->mutex);
4932
dict_table_remove_from_cache(prev_table);
4934
mutex_exit(&dict_sys->mutex);
4938
hash_table_free(dict_sys->table_hash);
4940
/* The elements are the same instance as in dict_sys->table_hash,
4941
therefore we don't delete the individual elements. */
4942
hash_table_free(dict_sys->table_id_hash);
4946
mutex_free(&dict_sys->mutex);
4948
rw_lock_free(&dict_operation_lock);
4949
memset(&dict_operation_lock, 0x0, sizeof(dict_operation_lock));
4951
mutex_free(&dict_foreign_err_mutex);
4956
for (i = 0; i < DICT_INDEX_STAT_MUTEX_SIZE; i++) {
4957
mutex_free(&dict_index_stat_mutex[i]);
4960
#endif /* !UNIV_HOTBACKUP */