1
/*****************************************************************************
3
Copyright (c) 1996, 2009, 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., 59 Temple
15
Place, Suite 330, Boston, MA 02111-1307 USA
17
*****************************************************************************/
19
/**********************************************************************
20
Data dictionary system
22
Created 1/8/1996 Heikki Tuuri
23
***********************************************************************/
25
#include "dict0dict.h"
28
#include "dict0dict.ic"
32
#include "data0type.h"
33
#include "mach0data.h"
34
#include "dict0boot.h"
36
#include "dict0crea.h"
42
#include "page0page.h"
43
#include "pars0pars.h"
47
#include "row0merge.h"
48
#ifndef UNIV_HOTBACKUP
49
# if defined(BUILD_DRIZZLE)
50
# include <mystrings/m_ctype.h>
52
# include "m_ctype.h" /* my_isspace() */
54
# include "ha_prototypes.h" /* innobase_strcasecmp() */
55
#endif /* !UNIV_HOTBACKUP */
59
/* the dictionary system */
60
UNIV_INTERN dict_sys_t* dict_sys = NULL;
62
/* table create, drop, etc. reserve this in X-mode; implicit or
63
backround operations purge, rollback, foreign key checks reserve this
64
in S-mode; we cannot trust that MySQL protects implicit or background
65
operations a table drop since MySQL does not know of them; therefore
66
we need this; NOTE: a transaction which reserves this must keep book
67
on the mode in trx->dict_operation_lock_mode */
68
UNIV_INTERN rw_lock_t dict_operation_lock;
70
#define DICT_POOL_PER_TABLE_HASH 512 /* buffer pool max size per table
71
hash table fixed size in bytes */
73
/* Identifies generated InnoDB foreign key names */
74
static char dict_ibfk[] = "_ibfk_";
76
/***********************************************************************
77
Tries to find column names for the index and sets the col field of the
83
dict_table_t* table, /* in: table */
84
dict_index_t* index); /* in: index */
85
/***********************************************************************
86
Builds the internal dictionary cache representation for a clustered
87
index, containing also system fields not defined by the user. */
90
dict_index_build_internal_clust(
91
/*============================*/
92
/* out, own: the internal
93
representation of the clustered
95
const dict_table_t* table, /* in: table */
96
dict_index_t* index); /* in: user representation of
98
/***********************************************************************
99
Builds the internal dictionary cache representation for a non-clustered
100
index, containing also system fields not defined by the user. */
103
dict_index_build_internal_non_clust(
104
/*================================*/
105
/* out, own: the internal
106
representation of the non-clustered
108
const dict_table_t* table, /* in: table */
109
dict_index_t* index); /* in: user representation of
110
a non-clustered index */
111
/**************************************************************************
112
Removes a foreign constraint struct from the dictionary cache. */
115
dict_foreign_remove_from_cache(
116
/*===========================*/
117
dict_foreign_t* foreign); /* in, own: foreign constraint */
118
/**************************************************************************
119
Prints a column data. */
124
const dict_table_t* table, /* in: table */
125
const dict_col_t* col); /* in: column */
126
/**************************************************************************
127
Prints an index data. */
130
dict_index_print_low(
131
/*=================*/
132
dict_index_t* index); /* in: index */
133
/**************************************************************************
134
Prints a field data. */
137
dict_field_print_low(
138
/*=================*/
139
dict_field_t* field); /* in: field */
140
/*************************************************************************
141
Frees a foreign key struct. */
146
dict_foreign_t* foreign); /* in, own: foreign key struct */
148
/* Stream for storing detailed information about the latest foreign key
149
and unique key errors */
150
UNIV_INTERN FILE* dict_foreign_err_file = NULL;
151
/* mutex protecting the foreign and unique error buffers */
152
UNIV_INTERN mutex_t dict_foreign_err_mutex;
154
#ifndef UNIV_HOTBACKUP
155
/**********************************************************************
156
Makes all characters in a NUL-terminated UTF-8 string lower case. */
161
char* a) /* in/out: string to put in lower case */
163
innobase_casedn_str(a);
165
#endif /* !UNIV_HOTBACKUP */
167
/************************************************************************
168
Checks if the database name in two table names is the same. */
171
dict_tables_have_same_db(
172
/*=====================*/
173
/* out: TRUE if same db name */
174
const char* name1, /* in: table name in the form
175
dbname '/' tablename */
176
const char* name2) /* in: table name in the form
177
dbname '/' tablename */
179
for (; *name1 == *name2; name1++, name2++) {
183
ut_a(*name1); /* the names must contain '/' */
188
/************************************************************************
189
Return the end of table name where we have removed dbname and '/'. */
194
/* out: table name */
195
const char* name) /* in: table name in the form
196
dbname '/' tablename */
198
const char* s = strchr(name, '/');
204
/************************************************************************
205
Get the database name length in a table name. */
208
dict_get_db_name_len(
209
/*=================*/
210
/* out: database name length */
211
const char* name) /* in: table name in the form
212
dbname '/' tablename */
215
s = strchr(name, '/');
220
/************************************************************************
221
Reserves the dictionary system mutex for MySQL. */
224
dict_mutex_enter_for_mysql(void)
225
/*============================*/
227
mutex_enter(&(dict_sys->mutex));
230
/************************************************************************
231
Releases the dictionary system mutex for MySQL. */
234
dict_mutex_exit_for_mysql(void)
235
/*===========================*/
237
mutex_exit(&(dict_sys->mutex));
240
/************************************************************************
241
Decrements the count of open MySQL handles to a table. */
244
dict_table_decrement_handle_count(
245
/*==============================*/
246
dict_table_t* table, /* in/out: table */
247
ibool dict_locked) /* in: TRUE=data dictionary locked */
250
mutex_enter(&dict_sys->mutex);
253
ut_ad(mutex_own(&dict_sys->mutex));
254
ut_a(table->n_mysql_handles_opened > 0);
256
table->n_mysql_handles_opened--;
259
mutex_exit(&dict_sys->mutex);
263
/**************************************************************************
264
Returns a column's name. */
267
dict_table_get_col_name(
268
/*====================*/
269
/* out: column name. NOTE: not
270
guaranteed to stay valid if table is
271
modified in any way (columns added,
273
const dict_table_t* table, /* in: table */
274
ulint col_nr) /* in: column number */
280
ut_ad(col_nr < table->n_def);
281
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
283
s = table->col_names;
285
for (i = 0; i < col_nr; i++) {
294
/************************************************************************
295
Acquire the autoinc lock.*/
298
dict_table_autoinc_lock(
299
/*====================*/
300
dict_table_t* table) /* in/out: table */
302
mutex_enter(&table->autoinc_mutex);
305
/************************************************************************
306
Unconditionally set the autoinc counter. */
309
dict_table_autoinc_initialize(
310
/*==========================*/
311
dict_table_t* table, /* in/out: table */
312
ib_uint64_t value) /* in: next value to assign to a row */
314
ut_ad(mutex_own(&table->autoinc_mutex));
316
table->autoinc = value;
319
/************************************************************************
320
Reads the next autoinc value (== autoinc counter value), 0 if not yet
324
dict_table_autoinc_read(
325
/*====================*/
326
/* out: value for a new row, or 0 */
327
const dict_table_t* table) /* in: table */
329
ut_ad(mutex_own(&table->autoinc_mutex));
331
return(table->autoinc);
334
/************************************************************************
335
Updates the autoinc counter if the value supplied is greater than the
339
dict_table_autoinc_update_if_greater(
340
/*=================================*/
342
dict_table_t* table, /* in/out: table */
343
ib_uint64_t value) /* in: value which was assigned to a row */
345
ut_ad(mutex_own(&table->autoinc_mutex));
347
if (value > table->autoinc) {
349
table->autoinc = value;
353
/************************************************************************
354
Release the autoinc lock.*/
357
dict_table_autoinc_unlock(
358
/*======================*/
359
dict_table_t* table) /* in/out: table */
361
mutex_exit(&table->autoinc_mutex);
364
/**************************************************************************
365
Looks for an index with the given table and index id.
366
NOTE that we do not reserve the dictionary mutex. */
369
dict_index_get_on_id_low(
370
/*=====================*/
371
/* out: index or NULL if not found
373
dict_table_t* table, /* in: table */
374
dulint id) /* in: index id */
378
index = dict_table_get_first_index(table);
381
if (0 == ut_dulint_cmp(id, index->id)) {
387
index = dict_table_get_next_index(index);
393
/************************************************************************
394
Looks for column n in an index. */
397
dict_index_get_nth_col_pos(
398
/*=======================*/
399
/* out: position in internal
400
representation of the index;
401
if not contained, returns
403
const dict_index_t* index, /* in: index */
404
ulint n) /* in: column number */
406
const dict_field_t* field;
407
const dict_col_t* col;
412
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
414
col = dict_table_get_nth_col(index->table, n);
416
if (dict_index_is_clust(index)) {
418
return(dict_col_get_clust_pos(col, index));
421
n_fields = dict_index_get_n_fields(index);
423
for (pos = 0; pos < n_fields; pos++) {
424
field = dict_index_get_nth_field(index, pos);
426
if (col == field->col && field->prefix_len == 0) {
432
return(ULINT_UNDEFINED);
435
/************************************************************************
436
Returns TRUE if the index contains a column or a prefix of that column. */
439
dict_index_contains_col_or_prefix(
440
/*==============================*/
441
/* out: TRUE if contains the column
443
const dict_index_t* index, /* in: index */
444
ulint n) /* in: column number */
446
const dict_field_t* field;
447
const dict_col_t* col;
452
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
454
if (dict_index_is_clust(index)) {
459
col = dict_table_get_nth_col(index->table, n);
461
n_fields = dict_index_get_n_fields(index);
463
for (pos = 0; pos < n_fields; pos++) {
464
field = dict_index_get_nth_field(index, pos);
466
if (col == field->col) {
475
/************************************************************************
476
Looks for a matching field in an index. The column has to be the same. The
477
column in index must be complete, or must contain a prefix longer than the
478
column in index2. That is, we must be able to construct the prefix in index2
479
from the prefix in index. */
482
dict_index_get_nth_field_pos(
483
/*=========================*/
484
/* out: position in internal
485
representation of the index;
486
if not contained, returns
488
const dict_index_t* index, /* in: index from which to search */
489
const dict_index_t* index2, /* in: index */
490
ulint n) /* in: field number in index2 */
492
const dict_field_t* field;
493
const dict_field_t* field2;
498
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
500
field2 = dict_index_get_nth_field(index2, n);
502
n_fields = dict_index_get_n_fields(index);
504
for (pos = 0; pos < n_fields; pos++) {
505
field = dict_index_get_nth_field(index, pos);
507
if (field->col == field2->col
508
&& (field->prefix_len == 0
509
|| (field->prefix_len >= field2->prefix_len
510
&& field2->prefix_len != 0))) {
516
return(ULINT_UNDEFINED);
519
/**************************************************************************
520
Returns a table object based on table id. */
523
dict_table_get_on_id(
524
/*=================*/
525
/* out: table, NULL if does not exist */
526
dulint table_id, /* in: table id */
527
trx_t* trx) /* in: transaction handle */
531
if (ut_dulint_cmp(table_id, DICT_FIELDS_ID) <= 0
532
|| trx->dict_operation_lock_mode == RW_X_LATCH) {
533
/* It is a system table which will always exist in the table
534
cache: we avoid acquiring the dictionary mutex, because
535
if we are doing a rollback to handle an error in TABLE
536
CREATE, for example, we already have the mutex! */
538
ut_ad(mutex_own(&(dict_sys->mutex))
539
|| trx->dict_operation_lock_mode == RW_X_LATCH);
541
return(dict_table_get_on_id_low(table_id));
544
mutex_enter(&(dict_sys->mutex));
546
table = dict_table_get_on_id_low(table_id);
548
mutex_exit(&(dict_sys->mutex));
553
/************************************************************************
554
Looks for column n position in the clustered index. */
557
dict_table_get_nth_col_pos(
558
/*=======================*/
559
/* out: position in internal
561
the clustered index */
562
const dict_table_t* table, /* in: table */
563
ulint n) /* in: column number */
565
return(dict_index_get_nth_col_pos(dict_table_get_first_index(table),
569
/************************************************************************
570
Checks if a column is in the ordering columns of the clustered index of a
571
table. Column prefixes are treated like whole columns. */
574
dict_table_col_in_clustered_key(
575
/*============================*/
576
/* out: TRUE if the column, or its
577
prefix, is in the clustered key */
578
const dict_table_t* table, /* in: table */
579
ulint n) /* in: column number */
581
const dict_index_t* index;
582
const dict_field_t* field;
583
const dict_col_t* col;
589
col = dict_table_get_nth_col(table, n);
591
index = dict_table_get_first_index(table);
593
n_fields = dict_index_get_n_unique(index);
595
for (pos = 0; pos < n_fields; pos++) {
596
field = dict_index_get_nth_field(index, pos);
598
if (col == field->col) {
607
/**************************************************************************
608
Inits the data dictionary module. */
614
dict_sys = mem_alloc(sizeof(dict_sys_t));
616
mutex_create(&dict_sys->mutex, SYNC_DICT);
618
dict_sys->table_hash = hash_create(buf_pool_get_curr_size()
619
/ (DICT_POOL_PER_TABLE_HASH
621
dict_sys->table_id_hash = hash_create(buf_pool_get_curr_size()
622
/ (DICT_POOL_PER_TABLE_HASH
626
UT_LIST_INIT(dict_sys->table_LRU);
628
rw_lock_create(&dict_operation_lock, SYNC_DICT_OPERATION);
630
dict_foreign_err_file = os_file_create_tmpfile();
631
ut_a(dict_foreign_err_file);
633
mutex_create(&dict_foreign_err_mutex, SYNC_ANY_LATCH);
636
/**************************************************************************
637
Returns a table object and optionally increment its MySQL open handle count.
638
NOTE! This is a high-level function to be used mainly from outside the
639
'dict' directory. Inside this directory dict_table_get_low is usually the
640
appropriate function. */
645
/* out: table, NULL if
647
const char* table_name, /* in: table name */
648
ibool inc_mysql_count)
649
/* in: whether to increment the open
650
handle count on the table */
654
mutex_enter(&(dict_sys->mutex));
656
table = dict_table_get_low(table_name);
658
if (inc_mysql_count && table) {
659
table->n_mysql_handles_opened++;
662
mutex_exit(&(dict_sys->mutex));
665
if (!table->stat_initialized) {
666
/* If table->ibd_file_missing == TRUE, this will
667
print an error message and return without doing
669
dict_update_statistics(table);
676
/**************************************************************************
677
Adds system columns to a table object. */
680
dict_table_add_system_columns(
681
/*==========================*/
682
dict_table_t* table, /* in/out: table */
683
mem_heap_t* heap) /* in: temporary heap */
686
ut_ad(table->n_def == table->n_cols - DATA_N_SYS_COLS);
687
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
688
ut_ad(!table->cached);
690
/* NOTE: the system columns MUST be added in the following order
691
(so that they can be indexed by the numerical value of DATA_ROW_ID,
692
etc.) and as the last columns of the table memory object.
693
The clustered index will not always physically contain all
696
dict_mem_table_add_col(table, heap, "DB_ROW_ID", DATA_SYS,
697
DATA_ROW_ID | DATA_NOT_NULL,
700
#error "DATA_ROW_ID != 0"
702
dict_mem_table_add_col(table, heap, "DB_TRX_ID", DATA_SYS,
703
DATA_TRX_ID | DATA_NOT_NULL,
706
#error "DATA_TRX_ID != 1"
708
dict_mem_table_add_col(table, heap, "DB_ROLL_PTR", DATA_SYS,
709
DATA_ROLL_PTR | DATA_NOT_NULL,
711
#if DATA_ROLL_PTR != 2
712
#error "DATA_ROLL_PTR != 2"
715
/* This check reminds that if a new system column is added to
716
the program, it should be dealt with here */
717
#if DATA_N_SYS_COLS != 3
718
#error "DATA_N_SYS_COLS != 3"
722
/**************************************************************************
723
Adds a table object to the dictionary cache. */
726
dict_table_add_to_cache(
727
/*====================*/
728
dict_table_t* table, /* in: table */
729
mem_heap_t* heap) /* in: temporary heap */
736
/* The lower limit for what we consider a "big" row */
737
#define BIG_ROW_SIZE 1024
739
ut_ad(mutex_own(&(dict_sys->mutex)));
741
dict_table_add_system_columns(table, heap);
743
table->cached = TRUE;
745
fold = ut_fold_string(table->name);
746
id_fold = ut_fold_dulint(table->id);
749
for (i = 0; i < table->n_def; i++) {
750
ulint col_len = dict_col_get_max_size(
751
dict_table_get_nth_col(table, i));
755
/* If we have a single unbounded field, or several gigantic
756
fields, mark the maximum row size as BIG_ROW_SIZE. */
757
if (row_len >= BIG_ROW_SIZE || col_len >= BIG_ROW_SIZE) {
758
row_len = BIG_ROW_SIZE;
764
table->big_rows = row_len >= BIG_ROW_SIZE;
766
/* Look for a table with the same name: error if such exists */
768
dict_table_t* table2;
769
HASH_SEARCH(name_hash, dict_sys->table_hash, fold,
770
dict_table_t*, table2, ut_ad(table2->cached),
771
ut_strcmp(table2->name, table->name) == 0);
772
ut_a(table2 == NULL);
775
/* Look for the same table pointer with a different name */
776
HASH_SEARCH_ALL(name_hash, dict_sys->table_hash,
777
dict_table_t*, table2, ut_ad(table2->cached),
779
ut_ad(table2 == NULL);
780
#endif /* UNIV_DEBUG */
783
/* Look for a table with the same id: error if such exists */
785
dict_table_t* table2;
786
HASH_SEARCH(id_hash, dict_sys->table_id_hash, id_fold,
787
dict_table_t*, table2, ut_ad(table2->cached),
788
ut_dulint_cmp(table2->id, table->id) == 0);
789
ut_a(table2 == NULL);
792
/* Look for the same table pointer with a different id */
793
HASH_SEARCH_ALL(id_hash, dict_sys->table_id_hash,
794
dict_table_t*, table2, ut_ad(table2->cached),
796
ut_ad(table2 == NULL);
797
#endif /* UNIV_DEBUG */
800
/* Add table to hash table of tables */
801
HASH_INSERT(dict_table_t, name_hash, dict_sys->table_hash, fold,
804
/* Add table to hash table of tables based on table id */
805
HASH_INSERT(dict_table_t, id_hash, dict_sys->table_id_hash, id_fold,
807
/* Add table to LRU list of tables */
808
UT_LIST_ADD_FIRST(table_LRU, dict_sys->table_LRU, table);
810
dict_sys->size += mem_heap_get_size(table->heap);
813
/**************************************************************************
814
Looks for an index with the given id. NOTE that we do not reserve
815
the dictionary mutex: this function is for emergency purposes like
816
printing info of a corrupt database page! */
819
dict_index_find_on_id_low(
820
/*======================*/
821
/* out: index or NULL if not found from cache */
822
dulint id) /* in: index id */
827
table = UT_LIST_GET_FIRST(dict_sys->table_LRU);
830
index = dict_table_get_first_index(table);
833
if (0 == ut_dulint_cmp(id, index->id)) {
839
index = dict_table_get_next_index(index);
842
table = UT_LIST_GET_NEXT(table_LRU, table);
848
/**************************************************************************
849
Renames a table object. */
852
dict_table_rename_in_cache(
853
/*=======================*/
854
/* out: TRUE if success */
855
dict_table_t* table, /* in/out: table */
856
const char* new_name, /* in: new name */
857
ibool rename_also_foreigns)/* in: in ALTER TABLE we want
858
to preserve the original table name
859
in constraints which reference it */
861
dict_foreign_t* foreign;
865
const char* old_name;
868
ut_ad(mutex_own(&(dict_sys->mutex)));
870
old_size = mem_heap_get_size(table->heap);
871
old_name = table->name;
873
fold = ut_fold_string(new_name);
875
/* Look for a table with the same name: error if such exists */
877
dict_table_t* table2;
878
HASH_SEARCH(name_hash, dict_sys->table_hash, fold,
879
dict_table_t*, table2, ut_ad(table2->cached),
880
(ut_strcmp(table2->name, new_name) == 0));
881
if (UNIV_LIKELY_NULL(table2)) {
882
ut_print_timestamp(stderr);
883
fputs(" InnoDB: Error: dictionary cache"
884
" already contains a table ", stderr);
885
ut_print_name(stderr, NULL, TRUE, new_name);
887
"InnoDB: cannot rename table ", stderr);
888
ut_print_name(stderr, NULL, TRUE, old_name);
894
/* If the table is stored in a single-table tablespace, rename the
897
if (table->space != 0) {
898
if (table->dir_path_of_temp_table != NULL) {
899
ut_print_timestamp(stderr);
900
fputs(" InnoDB: Error: trying to rename a"
901
" TEMPORARY TABLE ", stderr);
902
ut_print_name(stderr, NULL, TRUE, old_name);
904
ut_print_filename(stderr,
905
table->dir_path_of_temp_table);
906
fputs(" )\n", stderr);
908
} else if (!fil_rename_tablespace(old_name, table->space,
914
/* Remove table from the hash tables of tables */
915
HASH_DELETE(dict_table_t, name_hash, dict_sys->table_hash,
916
ut_fold_string(old_name), table);
917
table->name = mem_heap_strdup(table->heap, new_name);
919
/* Add table to hash table of tables */
920
HASH_INSERT(dict_table_t, name_hash, dict_sys->table_hash, fold,
922
dict_sys->size += (mem_heap_get_size(table->heap) - old_size);
924
/* Update the table_name field in indexes */
925
index = dict_table_get_first_index(table);
927
while (index != NULL) {
928
index->table_name = table->name;
930
index = dict_table_get_next_index(index);
933
if (!rename_also_foreigns) {
934
/* In ALTER TABLE we think of the rename table operation
935
in the direction table -> temporary table (#sql...)
936
as dropping the table with the old name and creating
937
a new with the new name. Thus we kind of drop the
938
constraints from the dictionary cache here. The foreign key
939
constraints will be inherited to the new table from the
940
system tables through a call of dict_load_foreigns. */
942
/* Remove the foreign constraints from the cache */
943
foreign = UT_LIST_GET_LAST(table->foreign_list);
945
while (foreign != NULL) {
946
dict_foreign_remove_from_cache(foreign);
947
foreign = UT_LIST_GET_LAST(table->foreign_list);
950
/* Reset table field in referencing constraints */
952
foreign = UT_LIST_GET_FIRST(table->referenced_list);
954
while (foreign != NULL) {
955
foreign->referenced_table = NULL;
956
foreign->referenced_index = NULL;
958
foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
961
/* Make the list of referencing constraints empty */
963
UT_LIST_INIT(table->referenced_list);
968
/* Update the table name fields in foreign constraints, and update also
969
the constraint id of new format >= 4.0.18 constraints. Note that at
970
this point we have already changed table->name to the new name. */
972
foreign = UT_LIST_GET_FIRST(table->foreign_list);
974
while (foreign != NULL) {
975
if (ut_strlen(foreign->foreign_table_name)
976
< ut_strlen(table->name)) {
977
/* Allocate a longer name buffer;
978
TODO: store buf len to save memory */
980
foreign->foreign_table_name
981
= mem_heap_alloc(foreign->heap,
982
ut_strlen(table->name) + 1);
985
strcpy(foreign->foreign_table_name, table->name);
987
if (strchr(foreign->id, '/')) {
991
/* This is a >= 4.0.18 format id */
993
old_id = mem_strdup(foreign->id);
995
if (ut_strlen(foreign->id) > ut_strlen(old_name)
996
+ ((sizeof dict_ibfk) - 1)
997
&& !memcmp(foreign->id, old_name,
999
&& !memcmp(foreign->id + ut_strlen(old_name),
1000
dict_ibfk, (sizeof dict_ibfk) - 1)) {
1002
/* This is a generated >= 4.0.18 format id */
1004
if (strlen(table->name) > strlen(old_name)) {
1005
foreign->id = mem_heap_alloc(
1008
+ strlen(old_id) + 1);
1011
/* Replace the prefix 'databasename/tablename'
1012
with the new names */
1013
strcpy(foreign->id, table->name);
1015
old_id + ut_strlen(old_name));
1017
/* This is a >= 4.0.18 format id where the user
1019
db_len = dict_get_db_name_len(table->name) + 1;
1021
if (dict_get_db_name_len(table->name)
1022
> dict_get_db_name_len(foreign->id)) {
1024
foreign->id = mem_heap_alloc(
1026
db_len + strlen(old_id) + 1);
1029
/* Replace the database prefix in id with the
1030
one from table->name */
1032
ut_memcpy(foreign->id, table->name, db_len);
1034
strcpy(foreign->id + db_len,
1035
dict_remove_db_name(old_id));
1041
foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
1044
foreign = UT_LIST_GET_FIRST(table->referenced_list);
1046
while (foreign != NULL) {
1047
if (ut_strlen(foreign->referenced_table_name)
1048
< ut_strlen(table->name)) {
1049
/* Allocate a longer name buffer;
1050
TODO: store buf len to save memory */
1052
foreign->referenced_table_name = mem_heap_alloc(
1053
foreign->heap, strlen(table->name) + 1);
1056
strcpy(foreign->referenced_table_name, table->name);
1058
foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
1064
/**************************************************************************
1065
Change the id of a table object in the dictionary cache. This is used in
1066
DISCARD TABLESPACE. */
1069
dict_table_change_id_in_cache(
1070
/*==========================*/
1071
dict_table_t* table, /* in/out: table object already in cache */
1072
dulint new_id) /* in: new id to set */
1075
ut_ad(mutex_own(&(dict_sys->mutex)));
1076
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
1078
/* Remove the table from the hash table of id's */
1080
HASH_DELETE(dict_table_t, id_hash, dict_sys->table_id_hash,
1081
ut_fold_dulint(table->id), table);
1084
/* Add the table back to the hash table */
1085
HASH_INSERT(dict_table_t, id_hash, dict_sys->table_id_hash,
1086
ut_fold_dulint(table->id), table);
1089
/**************************************************************************
1090
Removes a table object from the dictionary cache. */
1093
dict_table_remove_from_cache(
1094
/*=========================*/
1095
dict_table_t* table) /* in, own: table */
1097
dict_foreign_t* foreign;
1098
dict_index_t* index;
1102
ut_ad(mutex_own(&(dict_sys->mutex)));
1103
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
1106
fputs("Removing table ", stderr);
1107
ut_print_name(stderr, table->name, ULINT_UNDEFINED);
1108
fputs(" from dictionary cache\n", stderr);
1111
/* Remove the foreign constraints from the cache */
1112
foreign = UT_LIST_GET_LAST(table->foreign_list);
1114
while (foreign != NULL) {
1115
dict_foreign_remove_from_cache(foreign);
1116
foreign = UT_LIST_GET_LAST(table->foreign_list);
1119
/* Reset table field in referencing constraints */
1121
foreign = UT_LIST_GET_FIRST(table->referenced_list);
1123
while (foreign != NULL) {
1124
foreign->referenced_table = NULL;
1125
foreign->referenced_index = NULL;
1127
foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
1130
/* Remove the indexes from the cache */
1131
index = UT_LIST_GET_LAST(table->indexes);
1133
while (index != NULL) {
1134
dict_index_remove_from_cache(table, index);
1135
index = UT_LIST_GET_LAST(table->indexes);
1138
/* Remove table from the hash tables of tables */
1139
HASH_DELETE(dict_table_t, name_hash, dict_sys->table_hash,
1140
ut_fold_string(table->name), table);
1141
HASH_DELETE(dict_table_t, id_hash, dict_sys->table_id_hash,
1142
ut_fold_dulint(table->id), table);
1144
/* Remove table from LRU list of tables */
1145
UT_LIST_REMOVE(table_LRU, dict_sys->table_LRU, table);
1147
size = mem_heap_get_size(table->heap);
1149
ut_ad(dict_sys->size >= size);
1151
dict_sys->size -= size;
1153
dict_mem_table_free(table);
1156
/********************************************************************
1157
If the given column name is reserved for InnoDB system columns, return
1161
dict_col_name_is_reserved(
1162
/*======================*/
1163
/* out: TRUE if name is reserved */
1164
const char* name) /* in: column name */
1166
/* This check reminds that if a new system column is added to
1167
the program, it should be dealt with here. */
1168
#if DATA_N_SYS_COLS != 3
1169
#error "DATA_N_SYS_COLS != 3"
1172
static const char* reserved_names[] = {
1173
"DB_ROW_ID", "DB_TRX_ID", "DB_ROLL_PTR"
1178
for (i = 0; i < UT_ARR_SIZE(reserved_names); i++) {
1179
if (strcmp(name, reserved_names[i]) == 0) {
1188
/********************************************************************
1189
If an undo log record for this table might not fit on a single page,
1193
dict_index_too_big_for_undo(
1194
/*========================*/
1195
/* out: TRUE if the undo log
1196
record could become too big */
1197
const dict_table_t* table, /* in: table */
1198
const dict_index_t* new_index) /* in: index */
1200
/* Make sure that all column prefixes will fit in the undo log record
1201
in trx_undo_page_report_modify() right after trx_undo_page_init(). */
1204
const dict_index_t* clust_index
1205
= dict_table_get_first_index(table);
1207
= TRX_UNDO_PAGE_HDR - TRX_UNDO_PAGE_HDR_SIZE
1208
+ 2 /* next record pointer */
1210
+ 11 /* trx->undo_no */ - 11 /* table->id */
1211
+ 1 /* rec_get_info_bits() */
1212
+ 11 /* DB_TRX_ID */
1213
+ 11 /* DB_ROLL_PTR */
1214
+ 10 + FIL_PAGE_DATA_END /* trx_undo_left() */
1215
+ 2/* pointer to previous undo log record */;
1217
if (UNIV_UNLIKELY(!clust_index)) {
1218
ut_a(dict_index_is_clust(new_index));
1219
clust_index = new_index;
1222
/* Add the size of the ordering columns in the
1224
for (i = 0; i < clust_index->n_uniq; i++) {
1225
const dict_col_t* col
1226
= dict_index_get_nth_col(clust_index, i);
1228
/* Use the maximum output size of
1229
mach_write_compressed(), although the encoded
1230
length should always fit in 2 bytes. */
1231
undo_page_len += 5 + dict_col_get_max_size(col);
1234
/* Add the old values of the columns to be updated.
1235
First, the amount and the numbers of the columns.
1236
These are written by mach_write_compressed() whose
1237
maximum output length is 5 bytes. However, given that
1238
the quantities are below REC_MAX_N_FIELDS (10 bits),
1239
the maximum length is 2 bytes per item. */
1240
undo_page_len += 2 * (dict_table_get_n_cols(table) + 1);
1242
for (i = 0; i < clust_index->n_def; i++) {
1243
const dict_col_t* col
1244
= dict_index_get_nth_col(clust_index, i);
1246
= dict_col_get_max_size(col);
1248
= dict_col_get_fixed_size(col);
1251
/* Fixed-size columns are stored locally. */
1252
max_size = fixed_size;
1253
} else if (max_size <= BTR_EXTERN_FIELD_REF_SIZE * 2) {
1254
/* Short columns are stored locally. */
1255
} else if (!col->ord_part) {
1256
/* See if col->ord_part would be set
1257
because of new_index. */
1260
for (j = 0; j < new_index->n_uniq; j++) {
1261
if (dict_index_get_nth_col(
1262
new_index, j) == col) {
1268
/* This is not an ordering column in any index.
1269
Thus, it can be stored completely externally. */
1270
max_size = BTR_EXTERN_FIELD_REF_SIZE;
1273
/* This is an ordering column in some index.
1274
A long enough prefix must be written to the
1275
undo log. See trx_undo_page_fetch_ext(). */
1277
if (max_size > REC_MAX_INDEX_COL_LEN) {
1278
max_size = REC_MAX_INDEX_COL_LEN;
1281
max_size += BTR_EXTERN_FIELD_REF_SIZE;
1284
undo_page_len += 5 + max_size;
1287
return(undo_page_len >= UNIV_PAGE_SIZE);
1290
/********************************************************************
1291
If a record of this index might not fit on a single B-tree page,
1295
dict_index_too_big_for_tree(
1296
/*========================*/
1297
/* out: TRUE if the index
1298
record could become too big */
1299
const dict_table_t* table, /* in: table */
1300
const dict_index_t* new_index) /* in: index */
1305
/* maximum possible storage size of a record */
1307
/* maximum allowed size of a record on a leaf page */
1309
/* maximum allowed size of a node pointer record */
1312
comp = dict_table_is_comp(table);
1313
zip_size = dict_table_zip_size(table);
1315
if (zip_size && zip_size < UNIV_PAGE_SIZE) {
1316
/* On a compressed page, two records must fit in the
1317
uncompressed page modification log. On compressed
1318
pages with zip_size == UNIV_PAGE_SIZE, this limit will
1319
never be reached. */
1321
/* The maximum allowed record size is the size of
1322
an empty page, minus a byte for recoding the heap
1323
number in the page modification log. The maximum
1324
allowed node pointer size is half that. */
1325
page_rec_max = page_zip_empty_size(new_index->n_fields,
1327
page_ptr_max = page_rec_max / 2;
1328
/* On a compressed page, there is a two-byte entry in
1329
the dense page directory for every record. But there
1330
is no record header. */
1333
/* The maximum allowed record size is half a B-tree
1334
page. No additional sparse page directory entry will
1335
be generated for the first few user records. */
1336
page_rec_max = page_get_free_space_of_empty(comp) / 2;
1337
page_ptr_max = page_rec_max;
1338
/* Each record has a header. */
1340
? REC_N_NEW_EXTRA_BYTES
1341
: REC_N_OLD_EXTRA_BYTES;
1345
/* Include the "null" flags in the
1346
maximum possible record size. */
1347
rec_max_size += UT_BITS_IN_BYTES(new_index->n_nullable);
1349
/* For each column, include a 2-byte offset and a
1350
"null" flag. The 1-byte format is only used in short
1351
records that do not contain externally stored columns.
1352
Such records could never exceed the page limit, even
1353
when using the 2-byte format. */
1354
rec_max_size += 2 * new_index->n_fields;
1357
/* Compute the maximum possible record size. */
1358
for (i = 0; i < new_index->n_fields; i++) {
1359
const dict_field_t* field
1360
= dict_index_get_nth_field(new_index, i);
1361
const dict_col_t* col
1362
= dict_field_get_col(field);
1363
ulint field_max_size;
1364
ulint field_ext_max_size;
1366
/* In dtuple_convert_big_rec(), variable-length columns
1367
that are longer than BTR_EXTERN_FIELD_REF_SIZE * 2
1368
may be chosen for external storage.
1370
Fixed-length columns, and all columns of secondary
1371
index records are always stored inline. */
1373
/* Determine the maximum length of the index field.
1374
The field_ext_max_size should be computed as the worst
1375
case in rec_get_converted_size_comp() for
1376
REC_STATUS_ORDINARY records. */
1378
field_max_size = dict_col_get_fixed_size(col);
1379
if (field_max_size) {
1380
/* dict_index_add_col() should guarantee this */
1381
ut_ad(!field->prefix_len
1382
|| field->fixed_len == field->prefix_len);
1383
/* Fixed lengths are not encoded
1384
in ROW_FORMAT=COMPACT. */
1385
field_ext_max_size = 0;
1386
goto add_field_size;
1389
field_max_size = dict_col_get_max_size(col);
1390
field_ext_max_size = field_max_size < 256 ? 1 : 2;
1392
if (field->prefix_len) {
1393
if (field->prefix_len < field_max_size) {
1394
field_max_size = field->prefix_len;
1396
} else if (field_max_size > BTR_EXTERN_FIELD_REF_SIZE * 2
1397
&& dict_index_is_clust(new_index)) {
1399
/* In the worst case, we have a locally stored
1400
column of BTR_EXTERN_FIELD_REF_SIZE * 2 bytes.
1401
The length can be stored in one byte. If the
1402
column were stored externally, the lengths in
1403
the clustered index page would be
1404
BTR_EXTERN_FIELD_REF_SIZE and 2. */
1405
field_max_size = BTR_EXTERN_FIELD_REF_SIZE * 2;
1406
field_ext_max_size = 1;
1410
/* Add the extra size for ROW_FORMAT=COMPACT.
1411
For ROW_FORMAT=REDUNDANT, these bytes were
1412
added to rec_max_size before this loop. */
1413
rec_max_size += field_ext_max_size;
1416
rec_max_size += field_max_size;
1418
/* Check the size limit on leaf pages. */
1419
if (UNIV_UNLIKELY(rec_max_size >= page_rec_max)) {
1424
/* Check the size limit on non-leaf pages. Records
1425
stored in non-leaf B-tree pages consist of the unique
1426
columns of the record (the key columns of the B-tree)
1427
and a node pointer field. When we have processed the
1428
unique columns, rec_max_size equals the size of the
1429
node pointer record minus the node pointer column. */
1430
if (i + 1 == dict_index_get_n_unique_in_tree(new_index)
1431
&& rec_max_size + REC_NODE_PTR_SIZE >= page_ptr_max) {
1440
/**************************************************************************
1441
Adds an index to the dictionary cache. */
1444
dict_index_add_to_cache(
1445
/*====================*/
1446
/* out: DB_SUCCESS or DB_TOO_BIG_RECORD */
1447
dict_table_t* table, /* in: table on which the index is */
1448
dict_index_t* index, /* in, own: index; NOTE! The index memory
1449
object is freed in this function! */
1450
ulint page_no,/* in: root page number of the index */
1451
ibool strict) /* in: TRUE=refuse to create the index
1452
if records could be too big to fit in
1455
dict_index_t* new_index;
1460
ut_ad(mutex_own(&(dict_sys->mutex)));
1461
ut_ad(index->n_def == index->n_fields);
1462
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
1464
ut_ad(mem_heap_validate(index->heap));
1465
ut_a(!dict_index_is_clust(index)
1466
|| UT_LIST_GET_LEN(table->indexes) == 0);
1468
dict_index_find_cols(table, index);
1470
/* Build the cache internal representation of the index,
1471
containing also the added system fields */
1473
if (dict_index_is_clust(index)) {
1474
new_index = dict_index_build_internal_clust(table, index);
1476
new_index = dict_index_build_internal_non_clust(table, index);
1479
/* Set the n_fields value in new_index to the actual defined
1480
number of fields in the cache internal representation */
1482
new_index->n_fields = new_index->n_def;
1484
if (strict && dict_index_too_big_for_tree(table, new_index)) {
1486
dict_mem_index_free(new_index);
1487
dict_mem_index_free(index);
1488
return(DB_TOO_BIG_RECORD);
1491
if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) {
1492
n_ord = new_index->n_fields;
1494
n_ord = new_index->n_uniq;
1497
switch (dict_table_get_format(table)) {
1498
case DICT_TF_FORMAT_51:
1499
/* ROW_FORMAT=REDUNDANT and ROW_FORMAT=COMPACT store
1500
prefixes of externally stored columns locally within
1501
the record. There are no special considerations for
1502
the undo log record size. */
1505
case DICT_TF_FORMAT_ZIP:
1506
/* In ROW_FORMAT=DYNAMIC and ROW_FORMAT=COMPRESSED,
1507
column prefix indexes require that prefixes of
1508
externally stored columns are written to the undo log.
1509
This may make the undo log record bigger than the
1510
record on the B-tree page. The maximum size of an
1511
undo log record is the page size. That must be
1512
checked for below. */
1515
#if DICT_TF_FORMAT_ZIP != DICT_TF_FORMAT_MAX
1516
# error "DICT_TF_FORMAT_ZIP != DICT_TF_FORMAT_MAX"
1520
for (i = 0; i < n_ord; i++) {
1521
const dict_field_t* field
1522
= dict_index_get_nth_field(new_index, i);
1523
const dict_col_t* col
1524
= dict_field_get_col(field);
1526
/* In dtuple_convert_big_rec(), variable-length columns
1527
that are longer than BTR_EXTERN_FIELD_REF_SIZE * 2
1528
may be chosen for external storage. If the column appears
1529
in an ordering column of an index, a longer prefix of
1530
REC_MAX_INDEX_COL_LEN will be copied to the undo log
1531
by trx_undo_page_report_modify() and
1532
trx_undo_page_fetch_ext(). It suffices to check the
1533
capacity of the undo log whenever new_index includes
1534
a column prefix on a column that may be stored externally. */
1536
if (field->prefix_len /* prefix index */
1537
&& !col->ord_part /* not yet ordering column */
1538
&& !dict_col_get_fixed_size(col) /* variable-length */
1539
&& dict_col_get_max_size(col)
1540
> BTR_EXTERN_FIELD_REF_SIZE * 2 /* long enough */) {
1542
if (dict_index_too_big_for_undo(table, new_index)) {
1543
/* An undo log record might not fit in
1544
a single page. Refuse to create this index. */
1554
/* Flag the ordering columns */
1556
for (i = 0; i < n_ord; i++) {
1558
dict_index_get_nth_field(new_index, i)->col->ord_part = 1;
1561
/* Add the new index as the last index for the table */
1563
UT_LIST_ADD_LAST(indexes, table->indexes, new_index);
1564
new_index->table = table;
1565
new_index->table_name = table->name;
1567
new_index->search_info = btr_search_info_create(new_index->heap);
1569
new_index->stat_index_size = 1;
1570
new_index->stat_n_leaf_pages = 1;
1572
new_index->page = page_no;
1573
rw_lock_create(&new_index->lock, SYNC_INDEX_TREE);
1575
if (!UNIV_UNLIKELY(new_index->type & DICT_UNIVERSAL)) {
1577
new_index->stat_n_diff_key_vals = mem_heap_alloc(
1579
(1 + dict_index_get_n_unique(new_index))
1580
* sizeof(ib_int64_t));
1581
/* Give some sensible values to stat_n_... in case we do
1582
not calculate statistics quickly enough */
1584
for (i = 0; i <= dict_index_get_n_unique(new_index); i++) {
1586
new_index->stat_n_diff_key_vals[i] = 100;
1590
dict_sys->size += mem_heap_get_size(new_index->heap);
1592
dict_mem_index_free(index);
1597
/**************************************************************************
1598
Removes an index from the dictionary cache. */
1601
dict_index_remove_from_cache(
1602
/*=========================*/
1603
dict_table_t* table, /* in/out: table */
1604
dict_index_t* index) /* in, own: index */
1610
ut_ad(table && index);
1611
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
1612
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
1613
ut_ad(mutex_own(&(dict_sys->mutex)));
1615
/* We always create search info whether or not adaptive
1616
hash index is enabled or not. */
1617
info = index->search_info;
1620
/* We are not allowed to free the in-memory index struct
1621
dict_index_t until all entries in the adaptive hash index
1622
that point to any of the page belonging to his b-tree index
1623
are dropped. This is so because dropping of these entries
1624
require access to dict_index_t struct. To avoid such scenario
1625
We keep a count of number of such pages in the search_info and
1626
only free the dict_index_t struct when this count drops to
1630
ulint ref_count = btr_search_info_get_ref_count(info);
1631
if (ref_count == 0) {
1635
/* Sleep for 10ms before trying again. */
1636
os_thread_sleep(10000);
1639
if (retries % 500 == 0) {
1640
/* No luck after 5 seconds of wait. */
1641
fprintf(stderr, "InnoDB: Error: Waited for"
1642
" %lu secs for hash index"
1643
" ref_count (%lu) to drop"
1653
/* To avoid a hang here we commit suicide if the
1654
ref_count doesn't drop to zero in 600 seconds. */
1655
if (retries >= 60000) {
1660
rw_lock_free(&index->lock);
1662
/* Remove the index from the list of indexes of the table */
1663
UT_LIST_REMOVE(indexes, table->indexes, index);
1665
size = mem_heap_get_size(index->heap);
1667
ut_ad(dict_sys->size >= size);
1669
dict_sys->size -= size;
1671
dict_mem_index_free(index);
1674
/***********************************************************************
1675
Tries to find column names for the index and sets the col field of the
1679
dict_index_find_cols(
1680
/*=================*/
1681
dict_table_t* table, /* in: table */
1682
dict_index_t* index) /* in: index */
1686
ut_ad(table && index);
1687
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
1688
ut_ad(mutex_own(&(dict_sys->mutex)));
1690
for (i = 0; i < index->n_fields; i++) {
1692
dict_field_t* field = dict_index_get_nth_field(index, i);
1694
for (j = 0; j < table->n_cols; j++) {
1695
if (!strcmp(dict_table_get_col_name(table, j),
1697
field->col = dict_table_get_nth_col(table, j);
1703
/* It is an error not to find a matching column. */
1711
/***********************************************************************
1712
Adds a column to index. */
1717
dict_index_t* index, /* in/out: index */
1718
const dict_table_t* table, /* in: table */
1719
dict_col_t* col, /* in: column */
1720
ulint prefix_len) /* in: column prefix length */
1722
dict_field_t* field;
1723
const char* col_name;
1725
col_name = dict_table_get_col_name(table, dict_col_get_no(col));
1727
dict_mem_index_add_field(index, col_name, prefix_len);
1729
field = dict_index_get_nth_field(index, index->n_def - 1);
1732
field->fixed_len = (unsigned int) dict_col_get_fixed_size(col);
1734
if (prefix_len && field->fixed_len > prefix_len) {
1735
field->fixed_len = (unsigned int) prefix_len;
1738
/* Long fixed-length fields that need external storage are treated as
1739
variable-length fields, so that the extern flag can be embedded in
1742
if (field->fixed_len > DICT_MAX_INDEX_COL_LEN) {
1743
field->fixed_len = 0;
1745
#if DICT_MAX_INDEX_COL_LEN != 768
1746
/* The comparison limit above must be constant. If it were
1747
changed, the disk format of some fixed-length columns would
1748
change, which would be a disaster. */
1749
# error "DICT_MAX_INDEX_COL_LEN != 768"
1752
if (!(col->prtype & DATA_NOT_NULL)) {
1753
index->n_nullable++;
1757
/***********************************************************************
1758
Copies fields contained in index2 to index1. */
1763
dict_index_t* index1, /* in: index to copy to */
1764
dict_index_t* index2, /* in: index to copy from */
1765
const dict_table_t* table, /* in: table */
1766
ulint start, /* in: first position to copy */
1767
ulint end) /* in: last position to copy */
1769
dict_field_t* field;
1772
/* Copy fields contained in index2 */
1774
for (i = start; i < end; i++) {
1776
field = dict_index_get_nth_field(index2, i);
1777
dict_index_add_col(index1, table, field->col,
1782
/***********************************************************************
1783
Copies types of fields contained in index to tuple. */
1786
dict_index_copy_types(
1787
/*==================*/
1788
dtuple_t* tuple, /* in/out: data tuple */
1789
const dict_index_t* index, /* in: index */
1790
ulint n_fields) /* in: number of
1791
field types to copy */
1795
if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) {
1796
dtuple_set_types_binary(tuple, n_fields);
1801
for (i = 0; i < n_fields; i++) {
1802
const dict_field_t* ifield;
1803
dtype_t* dfield_type;
1805
ifield = dict_index_get_nth_field(index, i);
1806
dfield_type = dfield_get_type(dtuple_get_nth_field(tuple, i));
1807
dict_col_copy_type(dict_field_get_col(ifield), dfield_type);
1811
/***********************************************************************
1812
Copies types of columns contained in table to tuple and sets all
1813
fields of the tuple to the SQL NULL value. This function should
1814
be called right after dtuple_create(). */
1817
dict_table_copy_types(
1818
/*==================*/
1819
dtuple_t* tuple, /* in/out: data tuple */
1820
const dict_table_t* table) /* in: table */
1824
for (i = 0; i < dtuple_get_n_fields(tuple); i++) {
1826
dfield_t* dfield = dtuple_get_nth_field(tuple, i);
1827
dtype_t* dtype = dfield_get_type(dfield);
1829
dfield_set_null(dfield);
1830
dict_col_copy_type(dict_table_get_nth_col(table, i), dtype);
1834
/***********************************************************************
1835
Builds the internal dictionary cache representation for a clustered
1836
index, containing also system fields not defined by the user. */
1839
dict_index_build_internal_clust(
1840
/*============================*/
1841
/* out, own: the internal
1842
representation of the clustered
1844
const dict_table_t* table, /* in: table */
1845
dict_index_t* index) /* in: user representation of
1846
a clustered index */
1848
dict_index_t* new_index;
1849
dict_field_t* field;
1855
ut_ad(table && index);
1856
ut_ad(dict_index_is_clust(index));
1857
ut_ad(mutex_own(&(dict_sys->mutex)));
1858
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
1860
/* Create a new index object with certainly enough fields */
1861
new_index = dict_mem_index_create(table->name,
1862
index->name, table->space,
1864
index->n_fields + table->n_cols);
1866
/* Copy other relevant data from the old index struct to the new
1867
struct: it inherits the values */
1869
new_index->n_user_defined_cols = index->n_fields;
1871
new_index->id = index->id;
1873
/* Copy the fields of index */
1874
dict_index_copy(new_index, index, table, 0, index->n_fields);
1876
if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) {
1877
/* No fixed number of fields determines an entry uniquely */
1879
new_index->n_uniq = REC_MAX_N_FIELDS;
1881
} else if (dict_index_is_unique(index)) {
1882
/* Only the fields defined so far are needed to identify
1883
the index entry uniquely */
1885
new_index->n_uniq = new_index->n_def;
1887
/* Also the row id is needed to identify the entry */
1888
new_index->n_uniq = 1 + new_index->n_def;
1891
new_index->trx_id_offset = 0;
1893
if (!dict_index_is_ibuf(index)) {
1894
/* Add system columns, trx id first */
1896
trx_id_pos = new_index->n_def;
1898
#if DATA_ROW_ID != 0
1899
# error "DATA_ROW_ID != 0"
1901
#if DATA_TRX_ID != 1
1902
# error "DATA_TRX_ID != 1"
1904
#if DATA_ROLL_PTR != 2
1905
# error "DATA_ROLL_PTR != 2"
1908
if (!dict_index_is_unique(index)) {
1909
dict_index_add_col(new_index, table,
1910
dict_table_get_sys_col(
1911
table, DATA_ROW_ID),
1916
dict_index_add_col(new_index, table,
1917
dict_table_get_sys_col(table, DATA_TRX_ID),
1920
dict_index_add_col(new_index, table,
1921
dict_table_get_sys_col(table,
1925
for (i = 0; i < trx_id_pos; i++) {
1927
fixed_size = dict_col_get_fixed_size(
1928
dict_index_get_nth_col(new_index, i));
1930
if (fixed_size == 0) {
1931
new_index->trx_id_offset = 0;
1936
if (dict_index_get_nth_field(new_index, i)->prefix_len
1938
new_index->trx_id_offset = 0;
1943
new_index->trx_id_offset += (unsigned int) fixed_size;
1948
/* Remember the table columns already contained in new_index */
1949
indexed = mem_zalloc(table->n_cols * sizeof *indexed);
1951
/* Mark the table columns already contained in new_index */
1952
for (i = 0; i < new_index->n_def; i++) {
1954
field = dict_index_get_nth_field(new_index, i);
1956
/* If there is only a prefix of the column in the index
1957
field, do not mark the column as contained in the index */
1959
if (field->prefix_len == 0) {
1961
indexed[field->col->ind] = TRUE;
1965
/* Add to new_index non-system columns of table not yet included
1967
for (i = 0; i + DATA_N_SYS_COLS < (ulint) table->n_cols; i++) {
1969
dict_col_t* col = dict_table_get_nth_col(table, i);
1970
ut_ad(col->mtype != DATA_SYS);
1972
if (!indexed[col->ind]) {
1973
dict_index_add_col(new_index, table, col, 0);
1979
ut_ad(dict_index_is_ibuf(index)
1980
|| (UT_LIST_GET_LEN(table->indexes) == 0));
1982
new_index->cached = TRUE;
1987
/***********************************************************************
1988
Builds the internal dictionary cache representation for a non-clustered
1989
index, containing also system fields not defined by the user. */
1992
dict_index_build_internal_non_clust(
1993
/*================================*/
1994
/* out, own: the internal
1995
representation of the non-clustered
1997
const dict_table_t* table, /* in: table */
1998
dict_index_t* index) /* in: user representation of
1999
a non-clustered index */
2001
dict_field_t* field;
2002
dict_index_t* new_index;
2003
dict_index_t* clust_index;
2007
ut_ad(table && index);
2008
ut_ad(!dict_index_is_clust(index));
2009
ut_ad(mutex_own(&(dict_sys->mutex)));
2010
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
2012
/* The clustered index should be the first in the list of indexes */
2013
clust_index = UT_LIST_GET_FIRST(table->indexes);
2016
ut_ad(dict_index_is_clust(clust_index));
2017
ut_ad(!(clust_index->type & DICT_UNIVERSAL));
2019
/* Create a new index */
2020
new_index = dict_mem_index_create(
2021
table->name, index->name, index->space, index->type,
2022
index->n_fields + 1 + clust_index->n_uniq);
2024
/* Copy other relevant data from the old index
2025
struct to the new struct: it inherits the values */
2027
new_index->n_user_defined_cols = index->n_fields;
2029
new_index->id = index->id;
2031
/* Copy fields from index to new_index */
2032
dict_index_copy(new_index, index, table, 0, index->n_fields);
2034
/* Remember the table columns already contained in new_index */
2035
indexed = mem_zalloc(table->n_cols * sizeof *indexed);
2037
/* Mark the table columns already contained in new_index */
2038
for (i = 0; i < new_index->n_def; i++) {
2040
field = dict_index_get_nth_field(new_index, i);
2042
/* If there is only a prefix of the column in the index
2043
field, do not mark the column as contained in the index */
2045
if (field->prefix_len == 0) {
2047
indexed[field->col->ind] = TRUE;
2051
/* Add to new_index the columns necessary to determine the clustered
2052
index entry uniquely */
2054
for (i = 0; i < clust_index->n_uniq; i++) {
2056
field = dict_index_get_nth_field(clust_index, i);
2058
if (!indexed[field->col->ind]) {
2059
dict_index_add_col(new_index, table, field->col,
2066
if (dict_index_is_unique(index)) {
2067
new_index->n_uniq = index->n_fields;
2069
new_index->n_uniq = new_index->n_def;
2072
/* Set the n_fields value in new_index to the actual defined
2075
new_index->n_fields = new_index->n_def;
2077
new_index->cached = TRUE;
2082
/*====================== FOREIGN KEY PROCESSING ========================*/
2084
/*************************************************************************
2085
Checks if a table is referenced by foreign keys. */
2088
dict_table_is_referenced_by_foreign_key(
2089
/*====================================*/
2090
/* out: TRUE if table is referenced
2092
const dict_table_t* table) /* in: InnoDB table */
2094
return(UT_LIST_GET_LEN(table->referenced_list) > 0);
2097
/*************************************************************************
2098
Check if the index is referenced by a foreign key, if TRUE return foreign
2102
dict_table_get_referenced_constraint(
2103
/*=================================*/
2104
/* out: pointer to foreign key struct if index
2105
is defined for foreign key, otherwise NULL */
2106
dict_table_t* table, /* in: InnoDB table */
2107
dict_index_t* index) /* in: InnoDB index */
2109
dict_foreign_t* foreign;
2111
ut_ad(index != NULL);
2112
ut_ad(table != NULL);
2114
for (foreign = UT_LIST_GET_FIRST(table->referenced_list);
2116
foreign = UT_LIST_GET_NEXT(referenced_list, foreign)) {
2118
if (foreign->referenced_index == index) {
2127
/*************************************************************************
2128
Checks if a index is defined for a foreign key constraint. Index is a part
2129
of a foreign key constraint if the index is referenced by foreign key
2130
or index is a foreign key index. */
2133
dict_table_get_foreign_constraint(
2134
/*==============================*/
2135
/* out: pointer to foreign key struct if index
2136
is defined for foreign key, otherwise NULL */
2137
dict_table_t* table, /* in: InnoDB table */
2138
dict_index_t* index) /* in: InnoDB index */
2140
dict_foreign_t* foreign;
2142
ut_ad(index != NULL);
2143
ut_ad(table != NULL);
2145
for (foreign = UT_LIST_GET_FIRST(table->foreign_list);
2147
foreign = UT_LIST_GET_NEXT(foreign_list, foreign)) {
2149
if (foreign->foreign_index == index
2150
|| foreign->referenced_index == index) {
2159
/*************************************************************************
2160
Frees a foreign key struct. */
2165
dict_foreign_t* foreign) /* in, own: foreign key struct */
2167
mem_heap_free(foreign->heap);
2170
/**************************************************************************
2171
Removes a foreign constraint struct from the dictionary cache. */
2174
dict_foreign_remove_from_cache(
2175
/*===========================*/
2176
dict_foreign_t* foreign) /* in, own: foreign constraint */
2178
ut_ad(mutex_own(&(dict_sys->mutex)));
2181
if (foreign->referenced_table) {
2182
UT_LIST_REMOVE(referenced_list,
2183
foreign->referenced_table->referenced_list,
2187
if (foreign->foreign_table) {
2188
UT_LIST_REMOVE(foreign_list,
2189
foreign->foreign_table->foreign_list,
2193
dict_foreign_free(foreign);
2196
#ifndef UNIV_HOTBACKUP
2197
/**************************************************************************
2198
Looks for the foreign constraint from the foreign and referenced lists
2204
/* out: foreign constraint */
2205
dict_table_t* table, /* in: table object */
2206
const char* id) /* in: foreign constraint id */
2208
dict_foreign_t* foreign;
2210
ut_ad(mutex_own(&(dict_sys->mutex)));
2212
foreign = UT_LIST_GET_FIRST(table->foreign_list);
2215
if (ut_strcmp(id, foreign->id) == 0) {
2220
foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
2223
foreign = UT_LIST_GET_FIRST(table->referenced_list);
2226
if (ut_strcmp(id, foreign->id) == 0) {
2231
foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
2237
/*************************************************************************
2238
Tries to find an index whose first fields are the columns in the array,
2239
in the same order and is not marked for deletion and is not the same
2243
dict_foreign_find_index(
2244
/*====================*/
2245
/* out: matching index, NULL if not found */
2246
dict_table_t* table, /* in: table */
2247
const char** columns,/* in: array of column names */
2248
ulint n_cols, /* in: number of columns */
2249
dict_index_t* types_idx, /* in: NULL or an index to whose types the
2250
column types must match */
2251
ibool check_charsets,
2252
/* in: whether to check charsets.
2253
only has an effect if types_idx != NULL */
2255
/* in: nonzero if none of the columns must
2256
be declared NOT NULL */
2258
dict_index_t* index;
2260
index = dict_table_get_first_index(table);
2262
while (index != NULL) {
2263
/* Ignore matches that refer to the same instance
2264
or the index is to be dropped */
2265
if (index->to_be_dropped || types_idx == index) {
2269
} else if (dict_index_get_n_fields(index) >= n_cols) {
2272
for (i = 0; i < n_cols; i++) {
2273
dict_field_t* field;
2274
const char* col_name;
2276
field = dict_index_get_nth_field(index, i);
2278
col_name = dict_table_get_col_name(
2279
table, dict_col_get_no(field->col));
2281
if (field->prefix_len != 0) {
2282
/* We do not accept column prefix
2288
if (0 != innobase_strcasecmp(columns[i],
2294
&& (field->col->prtype & DATA_NOT_NULL)) {
2299
if (types_idx && !cmp_cols_are_equal(
2300
dict_index_get_nth_col(index, i),
2301
dict_index_get_nth_col(types_idx,
2310
/* We found a matching index */
2317
index = dict_table_get_next_index(index);
2323
/**************************************************************************
2324
Find an index that is equivalent to the one passed in and is not marked
2328
dict_foreign_find_equiv_index(
2329
/*==========================*/
2330
/* out: index equivalent to
2331
foreign->foreign_index, or NULL */
2332
dict_foreign_t* foreign)/* in: foreign key */
2334
ut_a(foreign != NULL);
2336
/* Try to find an index which contains the columns as the
2337
first fields and in the right order, and the types are the
2338
same as in foreign->foreign_index */
2340
return(dict_foreign_find_index(
2341
foreign->foreign_table,
2342
foreign->foreign_col_names, foreign->n_fields,
2343
foreign->foreign_index, TRUE, /* check types */
2344
FALSE/* allow columns to be NULL */));
2347
/**************************************************************************
2348
Returns an index object by matching on the name and column names and
2349
if more than one index matches return the index with the max id */
2352
dict_table_get_index_by_max_id(
2353
/*===========================*/
2354
/* out: matching index, NULL if not found */
2355
dict_table_t* table, /* in: table */
2356
const char* name, /* in: the index name to find */
2357
const char** columns,/* in: array of column names */
2358
ulint n_cols) /* in: number of columns */
2360
dict_index_t* index;
2361
dict_index_t* found;
2364
index = dict_table_get_first_index(table);
2366
while (index != NULL) {
2367
if (ut_strcmp(index->name, name) == 0
2368
&& dict_index_get_n_ordering_defined_by_user(index)
2373
for (i = 0; i < n_cols; i++) {
2374
dict_field_t* field;
2375
const char* col_name;
2377
field = dict_index_get_nth_field(index, i);
2379
col_name = dict_table_get_col_name(
2380
table, dict_col_get_no(field->col));
2382
if (0 != innobase_strcasecmp(
2383
columns[i], col_name)) {
2390
/* We found a matching index, select
2391
the index with the higher id*/
2394
|| ut_dulint_cmp(index->id, found->id) > 0) {
2401
index = dict_table_get_next_index(index);
2407
/**************************************************************************
2408
Report an error in a foreign key definition. */
2411
dict_foreign_error_report_low(
2412
/*==========================*/
2413
FILE* file, /* in: output stream */
2414
const char* name) /* in: table name */
2417
ut_print_timestamp(file);
2418
fprintf(file, " Error in foreign key constraint of table %s:\n",
2422
/**************************************************************************
2423
Report an error in a foreign key definition. */
2426
dict_foreign_error_report(
2427
/*======================*/
2428
FILE* file, /* in: output stream */
2429
dict_foreign_t* fk, /* in: foreign key constraint */
2430
const char* msg) /* in: the error message */
2432
mutex_enter(&dict_foreign_err_mutex);
2433
dict_foreign_error_report_low(file, fk->foreign_table_name);
2435
fputs(" Constraint:\n", file);
2436
dict_print_info_on_foreign_key_in_create_format(file, NULL, fk, TRUE);
2438
if (fk->foreign_index) {
2439
fputs("The index in the foreign key in table is ", file);
2440
ut_print_name(file, NULL, FALSE, fk->foreign_index->name);
2442
"See http://dev.mysql.com/doc/refman/5.1/en/"
2443
"innodb-foreign-key-constraints.html\n"
2444
"for correct foreign key definition.\n",
2447
mutex_exit(&dict_foreign_err_mutex);
2450
/**************************************************************************
2451
Adds a foreign key constraint object to the dictionary cache. May free
2452
the object if there already is an object with the same identifier in.
2453
At least one of the foreign table and the referenced table must already
2454
be in the dictionary cache! */
2457
dict_foreign_add_to_cache(
2458
/*======================*/
2459
/* out: DB_SUCCESS or error code */
2460
dict_foreign_t* foreign, /* in, own: foreign key constraint */
2461
ibool check_charsets) /* in: TRUE=check charset
2464
dict_table_t* for_table;
2465
dict_table_t* ref_table;
2466
dict_foreign_t* for_in_cache = NULL;
2467
dict_index_t* index;
2468
ibool added_to_referenced_list= FALSE;
2469
FILE* ef = dict_foreign_err_file;
2471
ut_ad(mutex_own(&(dict_sys->mutex)));
2473
for_table = dict_table_check_if_in_cache_low(
2474
foreign->foreign_table_name);
2476
ref_table = dict_table_check_if_in_cache_low(
2477
foreign->referenced_table_name);
2478
ut_a(for_table || ref_table);
2481
for_in_cache = dict_foreign_find(for_table, foreign->id);
2484
if (!for_in_cache && ref_table) {
2485
for_in_cache = dict_foreign_find(ref_table, foreign->id);
2489
/* Free the foreign object */
2490
mem_heap_free(foreign->heap);
2492
for_in_cache = foreign;
2495
if (for_in_cache->referenced_table == NULL && ref_table) {
2496
index = dict_foreign_find_index(
2498
for_in_cache->referenced_col_names,
2499
for_in_cache->n_fields, for_in_cache->foreign_index,
2500
check_charsets, FALSE);
2502
if (index == NULL) {
2503
dict_foreign_error_report(
2505
"there is no index in referenced table"
2506
" which would contain\n"
2507
"the columns as the first columns,"
2508
" or the data types in the\n"
2509
"referenced table do not match"
2510
" the ones in table.");
2512
if (for_in_cache == foreign) {
2513
mem_heap_free(foreign->heap);
2516
return(DB_CANNOT_ADD_CONSTRAINT);
2519
for_in_cache->referenced_table = ref_table;
2520
for_in_cache->referenced_index = index;
2521
UT_LIST_ADD_LAST(referenced_list,
2522
ref_table->referenced_list,
2524
added_to_referenced_list = TRUE;
2527
if (for_in_cache->foreign_table == NULL && for_table) {
2528
index = dict_foreign_find_index(
2530
for_in_cache->foreign_col_names,
2531
for_in_cache->n_fields,
2532
for_in_cache->referenced_index, check_charsets,
2534
& (DICT_FOREIGN_ON_DELETE_SET_NULL
2535
| DICT_FOREIGN_ON_UPDATE_SET_NULL));
2537
if (index == NULL) {
2538
dict_foreign_error_report(
2540
"there is no index in the table"
2541
" which would contain\n"
2542
"the columns as the first columns,"
2543
" or the data types in the\n"
2544
"table do not match"
2545
" the ones in the referenced table\n"
2546
"or one of the ON ... SET NULL columns"
2547
" is declared NOT NULL.");
2549
if (for_in_cache == foreign) {
2550
if (added_to_referenced_list) {
2553
ref_table->referenced_list,
2557
mem_heap_free(foreign->heap);
2560
return(DB_CANNOT_ADD_CONSTRAINT);
2563
for_in_cache->foreign_table = for_table;
2564
for_in_cache->foreign_index = index;
2565
UT_LIST_ADD_LAST(foreign_list,
2566
for_table->foreign_list,
2573
/*************************************************************************
2574
Scans from pointer onwards. Stops if is at the start of a copy of
2575
'string' where characters are compared without case sensitivity, and
2576
only outside `` or "" quotes. Stops also at '\0'. */
2581
/* out: scanned up to this */
2582
const char* ptr, /* in: scan from */
2583
const char* string) /* in: look for this */
2587
for (; *ptr; ptr++) {
2588
if (*ptr == quote) {
2589
/* Closing quote character: do not look for
2590
starting quote or the keyword. */
2593
/* Within quotes: do nothing. */
2594
} else if (*ptr == '`' || *ptr == '"') {
2595
/* Starting quote: remember the quote character. */
2598
/* Outside quotes: look for the keyword. */
2600
for (i = 0; string[i]; i++) {
2601
if (toupper((int)(unsigned char)(ptr[i]))
2602
!= toupper((int)(unsigned char)
2616
/*************************************************************************
2617
Accepts a specified string. Comparisons are case-insensitive. */
2622
/* out: if string was accepted, the pointer
2623
is moved after that, else ptr is returned */
2624
const struct charset_info_st* cs,/* in: the character set of ptr */
2625
const char* ptr, /* in: scan from this */
2626
const char* string, /* in: accept only this string as the next
2627
non-whitespace string */
2628
ibool* success)/* out: TRUE if accepted */
2630
const char* old_ptr = ptr;
2631
const char* old_ptr2;
2635
while (my_isspace(cs, *ptr)) {
2641
ptr = dict_scan_to(ptr, string);
2643
if (*ptr == '\0' || old_ptr2 != ptr) {
2649
return(ptr + ut_strlen(string));
2652
/*************************************************************************
2653
Scans an id. For the lexical definition of an 'id', see the code below.
2654
Strips backquotes or double quotes from around the id. */
2659
/* out: scanned to */
2660
const struct charset_info_st* cs,/* in: the character set of ptr */
2661
const char* ptr, /* in: scanned to */
2662
mem_heap_t* heap, /* in: heap where to allocate the id
2663
(NULL=id will not be allocated, but it
2664
will point to string near ptr) */
2665
const char** id, /* out,own: the id; NULL if no id was
2667
ibool table_id,/* in: TRUE=convert the allocated id
2668
as a table name; FALSE=convert to UTF-8 */
2669
ibool accept_also_dot)
2670
/* in: TRUE if also a dot can appear in a
2671
non-quoted id; in a quoted id it can appear
2682
while (my_isspace(cs, *ptr)) {
2691
if (*ptr == '`' || *ptr == '"') {
2703
if (*ptr == quote) {
2705
if (*ptr != quote) {
2713
while (!my_isspace(cs, *ptr) && *ptr != '(' && *ptr != ')'
2714
&& (accept_also_dot || *ptr != '.')
2715
&& *ptr != ',' && *ptr != '\0') {
2723
if (UNIV_UNLIKELY(!heap)) {
2724
/* no heap given: id will point to source string */
2731
str = d = mem_heap_alloc(heap, len + 1);
2733
if ((*d++ = *s++) == quote) {
2740
ut_ad(s + 1 == ptr);
2742
str = mem_heap_strdupl(heap, s, len);
2747
/* Convert the identifier from connection character set
2750
*id = dst = mem_heap_alloc(heap, len);
2752
innobase_convert_from_id(cs, dst, str, len);
2753
} else if (!strncmp(str, srv_mysql50_table_name_prefix,
2754
sizeof srv_mysql50_table_name_prefix)) {
2755
/* This is a pre-5.1 table name
2756
containing chars other than [A-Za-z0-9].
2757
Discard the prefix and use raw UTF-8 encoding. */
2758
str += sizeof srv_mysql50_table_name_prefix;
2759
len -= sizeof srv_mysql50_table_name_prefix;
2762
/* Encode using filename-safe characters. */
2764
*id = dst = mem_heap_alloc(heap, len);
2766
innobase_convert_from_table_id(cs, dst, str, len);
2772
/*************************************************************************
2773
Tries to scan a column name. */
2778
/* out: scanned to */
2779
const struct charset_info_st* cs, /* in: the character set of ptr */
2780
const char* ptr, /* in: scanned to */
2781
ibool* success,/* out: TRUE if success */
2782
dict_table_t* table, /* in: table in which the column is */
2783
const dict_col_t** column, /* out: pointer to column if success */
2784
mem_heap_t* heap, /* in: heap where to allocate */
2785
const char** name) /* out,own: the column name;
2786
NULL if no name was scannable */
2792
ptr = dict_scan_id(cs, ptr, heap, name, FALSE, TRUE);
2794
if (*name == NULL) {
2796
return(ptr); /* Syntax error */
2799
if (table == NULL) {
2803
for (i = 0; i < dict_table_get_n_cols(table); i++) {
2805
const char* col_name = dict_table_get_col_name(
2808
if (0 == innobase_strcasecmp(col_name, *name)) {
2812
*column = dict_table_get_nth_col(table, i);
2813
strcpy((char*) *name, col_name);
2823
/*************************************************************************
2824
Scans a table name from an SQL string. */
2827
dict_scan_table_name(
2828
/*=================*/
2829
/* out: scanned to */
2830
const struct charset_info_st* cs,/* in: the character set of ptr */
2831
const char* ptr, /* in: scanned to */
2832
dict_table_t** table, /* out: table object or NULL */
2833
const char* name, /* in: foreign key table name */
2834
ibool* success,/* out: TRUE if ok name found */
2835
mem_heap_t* heap, /* in: heap where to allocate the id */
2836
const char** ref_name)/* out,own: the table name;
2837
NULL if no name was scannable */
2839
const char* database_name = NULL;
2840
ulint database_name_len = 0;
2841
const char* table_name = NULL;
2842
ulint table_name_len;
2843
const char* scan_name;
2849
ptr = dict_scan_id(cs, ptr, heap, &scan_name, TRUE, FALSE);
2851
if (scan_name == NULL) {
2853
return(ptr); /* Syntax error */
2857
/* We scanned the database name; scan also the table name */
2861
database_name = scan_name;
2862
database_name_len = strlen(database_name);
2864
ptr = dict_scan_id(cs, ptr, heap, &table_name, TRUE, FALSE);
2866
if (table_name == NULL) {
2868
return(ptr); /* Syntax error */
2871
/* To be able to read table dumps made with InnoDB-4.0.17 or
2872
earlier, we must allow the dot separator between the database
2873
name and the table name also to appear within a quoted
2874
identifier! InnoDB used to print a constraint as:
2875
... REFERENCES `databasename.tablename` ...
2876
starting from 4.0.18 it is
2877
... REFERENCES `databasename`.`tablename` ... */
2880
for (s = scan_name; *s; s++) {
2882
database_name = scan_name;
2883
database_name_len = s - scan_name;
2885
break;/* to do: multiple dots? */
2889
table_name = scan_name;
2892
if (database_name == NULL) {
2893
/* Use the database name of the foreign key table */
2895
database_name = name;
2896
database_name_len = dict_get_db_name_len(name);
2899
table_name_len = strlen(table_name);
2901
/* Copy database_name, '/', table_name, '\0' */
2902
ref = mem_heap_alloc(heap, database_name_len + table_name_len + 2);
2903
memcpy(ref, database_name, database_name_len);
2904
ref[database_name_len] = '/';
2905
memcpy(ref + database_name_len + 1, table_name, table_name_len + 1);
2907
if (srv_lower_case_table_names) {
2908
#endif /* !__WIN__ */
2909
/* The table name is always put to lower case on Windows. */
2910
innobase_casedn_str(ref);
2913
#endif /* !__WIN__ */
2917
*table = dict_table_get_low(ref);
2922
/*************************************************************************
2923
Skips one id. The id is allowed to contain also '.'. */
2928
/* out: scanned to */
2929
const struct charset_info_st* cs,/* in: the character set of ptr */
2930
const char* ptr, /* in: scanned to */
2931
ibool* success)/* out: TRUE if success, FALSE if just spaces
2932
left in string or a syntax error */
2938
ptr = dict_scan_id(cs, ptr, NULL, &start, FALSE, TRUE);
2947
/*************************************************************************
2948
Removes MySQL comments from an SQL string. A comment is either
2949
(a) '#' to the end of the line,
2950
(b) '--<space>' to the end of the line, or
2951
(c) '<slash><asterisk>' till the next '<asterisk><slash>' (like the familiar
2952
C comment syntax). */
2955
dict_strip_comments(
2956
/*================*/
2957
/* out, own: SQL string stripped from
2958
comments; the caller must free this
2960
const char* sql_string) /* in: SQL string */
2965
/* unclosed quote character (0 if none) */
2968
str = mem_alloc(strlen(sql_string) + 1);
2975
if (*sptr == '\0') {
2978
ut_a(ptr <= str + strlen(sql_string));
2983
if (*sptr == quote) {
2984
/* Closing quote character: do not look for
2985
starting quote or comments. */
2988
/* Within quotes: do not look for
2989
starting quotes or comments. */
2990
} else if (*sptr == '"' || *sptr == '`') {
2991
/* Starting quote: remember the quote character. */
2993
} else if (*sptr == '#'
2994
|| (sptr[0] == '-' && sptr[1] == '-'
2995
&& sptr[2] == ' ')) {
2997
/* In Unix a newline is 0x0A while in Windows
2998
it is 0x0D followed by 0x0A */
3000
if (*sptr == (char)0x0A
3001
|| *sptr == (char)0x0D
3009
} else if (!quote && *sptr == '/' && *(sptr + 1) == '*') {
3011
if (*sptr == '*' && *(sptr + 1) == '/') {
3018
if (*sptr == '\0') {
3034
/*************************************************************************
3035
Finds the highest <number> for foreign key constraints of the table. Looks
3036
only at the >= 4.0.18-format id's, which are of the form
3037
databasename/tablename_ibfk_<number>. */
3040
dict_table_get_highest_foreign_id(
3041
/*==============================*/
3042
/* out: highest number, 0 if table has no new
3043
format foreign key constraints */
3044
dict_table_t* table) /* in: table in the dictionary memory cache */
3046
dict_foreign_t* foreign;
3048
ulint biggest_id = 0;
3054
len = ut_strlen(table->name);
3055
foreign = UT_LIST_GET_FIRST(table->foreign_list);
3058
if (ut_strlen(foreign->id) > ((sizeof dict_ibfk) - 1) + len
3059
&& 0 == ut_memcmp(foreign->id, table->name, len)
3060
&& 0 == ut_memcmp(foreign->id + len,
3061
dict_ibfk, (sizeof dict_ibfk) - 1)
3062
&& foreign->id[len + ((sizeof dict_ibfk) - 1)] != '0') {
3063
/* It is of the >= 4.0.18 format */
3065
id = strtoul(foreign->id + len
3066
+ ((sizeof dict_ibfk) - 1),
3068
if (*endp == '\0') {
3069
ut_a(id != biggest_id);
3071
if (id > biggest_id) {
3077
foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
3083
/*************************************************************************
3084
Reports a simple foreign key create clause syntax error. */
3087
dict_foreign_report_syntax_err(
3088
/*===========================*/
3089
const char* name, /* in: table name */
3090
const char* start_of_latest_foreign,
3091
/* in: start of the foreign key clause
3092
in the SQL string */
3093
const char* ptr) /* in: place of the syntax error */
3095
FILE* ef = dict_foreign_err_file;
3097
mutex_enter(&dict_foreign_err_mutex);
3098
dict_foreign_error_report_low(ef, name);
3099
fprintf(ef, "%s:\nSyntax error close to:\n%s\n",
3100
start_of_latest_foreign, ptr);
3101
mutex_exit(&dict_foreign_err_mutex);
3104
/*************************************************************************
3105
Scans a table create SQL string and adds to the data dictionary the foreign
3106
key constraints declared in the string. This function should be called after
3107
the indexes for a table have been created. Each foreign key constraint must
3108
be accompanied with indexes in both participating tables. The indexes are
3109
allowed to contain more fields than mentioned in the constraint. */
3112
dict_create_foreign_constraints_low(
3113
/*================================*/
3114
/* out: error code or DB_SUCCESS */
3115
trx_t* trx, /* in: transaction */
3116
mem_heap_t* heap, /* in: memory heap */
3117
const struct charset_info_st* cs,/* in: the character set of sql_string */
3118
const char* sql_string,
3119
/* in: CREATE TABLE or ALTER TABLE statement
3120
where foreign keys are declared like:
3121
FOREIGN KEY (a, b) REFERENCES table2(c, d),
3122
table2 can be written also with the database
3123
name before it: test.table2; the default
3124
database is the database of parameter name */
3125
const char* name, /* in: table full name in the normalized form
3126
database_name/table_name */
3128
/* in: if TRUE, fail with error code
3129
DB_CANNOT_ADD_CONSTRAINT if any foreign
3132
dict_table_t* table;
3133
dict_table_t* referenced_table;
3134
dict_table_t* table_to_alter;
3135
ulint highest_id_so_far = 0;
3136
dict_index_t* index;
3137
dict_foreign_t* foreign;
3138
const char* ptr = sql_string;
3139
const char* start_of_latest_foreign = sql_string;
3140
FILE* ef = dict_foreign_err_file;
3141
const char* constraint_name;
3151
const dict_col_t*columns[500];
3152
const char* column_names[500];
3153
const char* referenced_table_name;
3155
ut_ad(mutex_own(&(dict_sys->mutex)));
3157
table = dict_table_get_low(name);
3159
if (table == NULL) {
3160
mutex_enter(&dict_foreign_err_mutex);
3161
dict_foreign_error_report_low(ef, name);
3163
"Cannot find the table in the internal"
3164
" data dictionary of InnoDB.\n"
3165
"Create table statement:\n%s\n", sql_string);
3166
mutex_exit(&dict_foreign_err_mutex);
3171
/* First check if we are actually doing an ALTER TABLE, and in that
3172
case look for the table being altered */
3174
ptr = dict_accept(cs, ptr, "ALTER", &success);
3181
ptr = dict_accept(cs, ptr, "TABLE", &success);
3188
/* We are doing an ALTER TABLE: scan the table name we are altering */
3190
ptr = dict_scan_table_name(cs, ptr, &table_to_alter, name,
3191
&success, heap, &referenced_table_name);
3194
"InnoDB: Error: could not find"
3195
" the table being ALTERED in:\n%s\n",
3201
/* Starting from 4.0.18 and 4.1.2, we generate foreign key id's in the
3202
format databasename/tablename_ibfk_<number>, where <number> is local
3203
to the table; look for the highest <number> for table_to_alter, so
3204
that we can assign to new constraints higher numbers. */
3206
/* If we are altering a temporary table, the table name after ALTER
3207
TABLE does not correspond to the internal table name, and
3208
table_to_alter is NULL. TODO: should we fix this somehow? */
3210
if (table_to_alter == NULL) {
3211
highest_id_so_far = 0;
3213
highest_id_so_far = dict_table_get_highest_foreign_id(
3217
/* Scan for foreign key declarations in a loop */
3219
/* Scan either to "CONSTRAINT" or "FOREIGN", whichever is closer */
3221
ptr1 = dict_scan_to(ptr, "CONSTRAINT");
3222
ptr2 = dict_scan_to(ptr, "FOREIGN");
3224
constraint_name = NULL;
3227
/* The user may have specified a constraint name. Pick it so
3228
that we can store 'databasename/constraintname' as the id of
3229
of the constraint to system tables. */
3232
ptr = dict_accept(cs, ptr, "CONSTRAINT", &success);
3236
if (!my_isspace(cs, *ptr) && *ptr != '"' && *ptr != '`') {
3240
while (my_isspace(cs, *ptr)) {
3244
/* read constraint name unless got "CONSTRAINT FOREIGN" */
3246
ptr = dict_scan_id(cs, ptr, heap,
3247
&constraint_name, FALSE, FALSE);
3254
/* The proper way to reject foreign keys for temporary
3255
tables would be to split the lexing and syntactical
3256
analysis of foreign key clauses from the actual adding
3257
of them, so that ha_innodb.cc could first parse the SQL
3258
command, determine if there are any foreign keys, and
3259
if so, immediately reject the command if the table is a
3260
temporary one. For now, this kludge will work. */
3261
if (reject_fks && (UT_LIST_GET_LEN(table->foreign_list) > 0)) {
3263
return(DB_CANNOT_ADD_CONSTRAINT);
3266
/**********************************************************/
3267
/* The following call adds the foreign key constraints
3268
to the data dictionary system tables on disk */
3270
error = dict_create_add_foreigns_to_dictionary(
3271
highest_id_so_far, table, trx);
3275
start_of_latest_foreign = ptr;
3277
ptr = dict_accept(cs, ptr, "FOREIGN", &success);
3283
if (!my_isspace(cs, *ptr)) {
3287
ptr = dict_accept(cs, ptr, "KEY", &success);
3293
ptr = dict_accept(cs, ptr, "(", &success);
3296
/* MySQL allows also an index id before the '('; we
3298
ptr = dict_skip_word(cs, ptr, &success);
3301
dict_foreign_report_syntax_err(
3302
name, start_of_latest_foreign, ptr);
3304
return(DB_CANNOT_ADD_CONSTRAINT);
3307
ptr = dict_accept(cs, ptr, "(", &success);
3310
/* We do not flag a syntax error here because in an
3311
ALTER TABLE we may also have DROP FOREIGN KEY abc */
3319
/* Scan the columns in the first list */
3321
ut_a(i < (sizeof column_names) / sizeof *column_names);
3322
ptr = dict_scan_col(cs, ptr, &success, table, columns + i,
3323
heap, column_names + i);
3325
mutex_enter(&dict_foreign_err_mutex);
3326
dict_foreign_error_report_low(ef, name);
3327
fprintf(ef, "%s:\nCannot resolve column name close to:\n%s\n",
3328
start_of_latest_foreign, ptr);
3329
mutex_exit(&dict_foreign_err_mutex);
3331
return(DB_CANNOT_ADD_CONSTRAINT);
3336
ptr = dict_accept(cs, ptr, ",", &success);
3342
ptr = dict_accept(cs, ptr, ")", &success);
3345
dict_foreign_report_syntax_err(
3346
name, start_of_latest_foreign, ptr);
3347
return(DB_CANNOT_ADD_CONSTRAINT);
3350
/* Try to find an index which contains the columns
3351
as the first fields and in the right order */
3353
index = dict_foreign_find_index(table, column_names, i,
3357
mutex_enter(&dict_foreign_err_mutex);
3358
dict_foreign_error_report_low(ef, name);
3359
fputs("There is no index in table ", ef);
3360
ut_print_name(ef, NULL, TRUE, name);
3361
fprintf(ef, " where the columns appear\n"
3362
"as the first columns. Constraint:\n%s\n"
3363
"See http://dev.mysql.com/doc/refman/5.1/en/"
3364
"innodb-foreign-key-constraints.html\n"
3365
"for correct foreign key definition.\n",
3366
start_of_latest_foreign);
3367
mutex_exit(&dict_foreign_err_mutex);
3369
return(DB_CANNOT_ADD_CONSTRAINT);
3371
ptr = dict_accept(cs, ptr, "REFERENCES", &success);
3373
if (!success || !my_isspace(cs, *ptr)) {
3374
dict_foreign_report_syntax_err(
3375
name, start_of_latest_foreign, ptr);
3376
return(DB_CANNOT_ADD_CONSTRAINT);
3379
/* Let us create a constraint struct */
3381
foreign = dict_mem_foreign_create();
3383
if (constraint_name) {
3386
/* Catenate 'databasename/' to the constraint name specified
3387
by the user: we conceive the constraint as belonging to the
3388
same MySQL 'database' as the table itself. We store the name
3391
db_len = dict_get_db_name_len(table->name);
3393
foreign->id = mem_heap_alloc(
3394
foreign->heap, db_len + strlen(constraint_name) + 2);
3396
ut_memcpy(foreign->id, table->name, db_len);
3397
foreign->id[db_len] = '/';
3398
strcpy(foreign->id + db_len + 1, constraint_name);
3401
foreign->foreign_table = table;
3402
foreign->foreign_table_name = mem_heap_strdup(foreign->heap,
3404
foreign->foreign_index = index;
3405
foreign->n_fields = (unsigned int) i;
3406
foreign->foreign_col_names = mem_heap_alloc(foreign->heap,
3408
for (i = 0; i < foreign->n_fields; i++) {
3409
foreign->foreign_col_names[i] = mem_heap_strdup(
3411
dict_table_get_col_name(table,
3412
dict_col_get_no(columns[i])));
3415
ptr = dict_scan_table_name(cs, ptr, &referenced_table, name,
3416
&success, heap, &referenced_table_name);
3418
/* Note that referenced_table can be NULL if the user has suppressed
3419
checking of foreign key constraints! */
3421
if (!success || (!referenced_table && trx->check_foreigns)) {
3422
dict_foreign_free(foreign);
3424
mutex_enter(&dict_foreign_err_mutex);
3425
dict_foreign_error_report_low(ef, name);
3426
fprintf(ef, "%s:\nCannot resolve table name close to:\n"
3428
start_of_latest_foreign, ptr);
3429
mutex_exit(&dict_foreign_err_mutex);
3431
return(DB_CANNOT_ADD_CONSTRAINT);
3434
ptr = dict_accept(cs, ptr, "(", &success);
3437
dict_foreign_free(foreign);
3438
dict_foreign_report_syntax_err(name, start_of_latest_foreign,
3440
return(DB_CANNOT_ADD_CONSTRAINT);
3443
/* Scan the columns in the second list */
3447
ptr = dict_scan_col(cs, ptr, &success, referenced_table, columns + i,
3448
heap, column_names + i);
3452
dict_foreign_free(foreign);
3454
mutex_enter(&dict_foreign_err_mutex);
3455
dict_foreign_error_report_low(ef, name);
3456
fprintf(ef, "%s:\nCannot resolve column name close to:\n"
3458
start_of_latest_foreign, ptr);
3459
mutex_exit(&dict_foreign_err_mutex);
3461
return(DB_CANNOT_ADD_CONSTRAINT);
3464
ptr = dict_accept(cs, ptr, ",", &success);
3470
ptr = dict_accept(cs, ptr, ")", &success);
3472
if (!success || foreign->n_fields != i) {
3473
dict_foreign_free(foreign);
3475
dict_foreign_report_syntax_err(name, start_of_latest_foreign,
3477
return(DB_CANNOT_ADD_CONSTRAINT);
3484
/* Loop here as long as we can find ON ... conditions */
3486
ptr = dict_accept(cs, ptr, "ON", &success);
3490
goto try_find_index;
3493
ptr = dict_accept(cs, ptr, "DELETE", &success);
3496
ptr = dict_accept(cs, ptr, "UPDATE", &success);
3499
dict_foreign_free(foreign);
3501
dict_foreign_report_syntax_err(
3502
name, start_of_latest_foreign, ptr);
3503
return(DB_CANNOT_ADD_CONSTRAINT);
3506
is_on_delete = FALSE;
3509
is_on_delete = TRUE;
3513
ptr = dict_accept(cs, ptr, "RESTRICT", &success);
3516
goto scan_on_conditions;
3519
ptr = dict_accept(cs, ptr, "CASCADE", &success);
3523
foreign->type |= DICT_FOREIGN_ON_DELETE_CASCADE;
3525
foreign->type |= DICT_FOREIGN_ON_UPDATE_CASCADE;
3528
goto scan_on_conditions;
3531
ptr = dict_accept(cs, ptr, "NO", &success);
3534
ptr = dict_accept(cs, ptr, "ACTION", &success);
3537
dict_foreign_free(foreign);
3538
dict_foreign_report_syntax_err(
3539
name, start_of_latest_foreign, ptr);
3541
return(DB_CANNOT_ADD_CONSTRAINT);
3545
foreign->type |= DICT_FOREIGN_ON_DELETE_NO_ACTION;
3547
foreign->type |= DICT_FOREIGN_ON_UPDATE_NO_ACTION;
3550
goto scan_on_conditions;
3553
ptr = dict_accept(cs, ptr, "SET", &success);
3556
dict_foreign_free(foreign);
3557
dict_foreign_report_syntax_err(name, start_of_latest_foreign,
3559
return(DB_CANNOT_ADD_CONSTRAINT);
3562
ptr = dict_accept(cs, ptr, "NULL", &success);
3565
dict_foreign_free(foreign);
3566
dict_foreign_report_syntax_err(name, start_of_latest_foreign,
3568
return(DB_CANNOT_ADD_CONSTRAINT);
3571
for (j = 0; j < foreign->n_fields; j++) {
3572
if ((dict_index_get_nth_col(foreign->foreign_index, j)->prtype)
3575
/* It is not sensible to define SET NULL
3576
if the column is not allowed to be NULL! */
3578
dict_foreign_free(foreign);
3580
mutex_enter(&dict_foreign_err_mutex);
3581
dict_foreign_error_report_low(ef, name);
3583
"You have defined a SET NULL condition"
3584
" though some of the\n"
3585
"columns are defined as NOT NULL.\n",
3586
start_of_latest_foreign);
3587
mutex_exit(&dict_foreign_err_mutex);
3589
return(DB_CANNOT_ADD_CONSTRAINT);
3594
foreign->type |= DICT_FOREIGN_ON_DELETE_SET_NULL;
3596
foreign->type |= DICT_FOREIGN_ON_UPDATE_SET_NULL;
3599
goto scan_on_conditions;
3602
if (n_on_deletes > 1 || n_on_updates > 1) {
3603
/* It is an error to define more than 1 action */
3605
dict_foreign_free(foreign);
3607
mutex_enter(&dict_foreign_err_mutex);
3608
dict_foreign_error_report_low(ef, name);
3610
"You have twice an ON DELETE clause"
3611
" or twice an ON UPDATE clause.\n",
3612
start_of_latest_foreign);
3613
mutex_exit(&dict_foreign_err_mutex);
3615
return(DB_CANNOT_ADD_CONSTRAINT);
3618
/* Try to find an index which contains the columns as the first fields
3619
and in the right order, and the types are the same as in
3620
foreign->foreign_index */
3622
if (referenced_table) {
3623
index = dict_foreign_find_index(referenced_table,
3625
foreign->foreign_index,
3628
dict_foreign_free(foreign);
3629
mutex_enter(&dict_foreign_err_mutex);
3630
dict_foreign_error_report_low(ef, name);
3632
"Cannot find an index in the"
3633
" referenced table where the\n"
3634
"referenced columns appear as the"
3635
" first columns, or column types\n"
3636
"in the table and the referenced table"
3637
" do not match for constraint.\n"
3638
"Note that the internal storage type of"
3639
" ENUM and SET changed in\n"
3640
"tables created with >= InnoDB-4.1.12,"
3641
" and such columns in old tables\n"
3642
"cannot be referenced by such columns"
3644
"See http://dev.mysql.com/doc/refman/5.1/en/"
3645
"innodb-foreign-key-constraints.html\n"
3646
"for correct foreign key definition.\n",
3647
start_of_latest_foreign);
3648
mutex_exit(&dict_foreign_err_mutex);
3650
return(DB_CANNOT_ADD_CONSTRAINT);
3653
ut_a(trx->check_foreigns == FALSE);
3657
foreign->referenced_index = index;
3658
foreign->referenced_table = referenced_table;
3660
foreign->referenced_table_name
3661
= mem_heap_strdup(foreign->heap, referenced_table_name);
3663
foreign->referenced_col_names = mem_heap_alloc(foreign->heap,
3665
for (i = 0; i < foreign->n_fields; i++) {
3666
foreign->referenced_col_names[i]
3667
= mem_heap_strdup(foreign->heap, column_names[i]);
3670
/* We found an ok constraint definition: add to the lists */
3672
UT_LIST_ADD_LAST(foreign_list, table->foreign_list, foreign);
3674
if (referenced_table) {
3675
UT_LIST_ADD_LAST(referenced_list,
3676
referenced_table->referenced_list,
3683
/*************************************************************************
3684
Scans a table create SQL string and adds to the data dictionary the foreign
3685
key constraints declared in the string. This function should be called after
3686
the indexes for a table have been created. Each foreign key constraint must
3687
be accompanied with indexes in both participating tables. The indexes are
3688
allowed to contain more fields than mentioned in the constraint. */
3691
dict_create_foreign_constraints(
3692
/*============================*/
3693
/* out: error code or DB_SUCCESS */
3694
trx_t* trx, /* in: transaction */
3695
const char* sql_string, /* in: table create statement where
3696
foreign keys are declared like:
3697
FOREIGN KEY (a, b) REFERENCES
3698
table2(c, d), table2 can be written
3699
also with the database
3700
name before it: test.table2; the
3701
default database id the database of
3703
const char* name, /* in: table full name in the
3705
database_name/table_name */
3706
ibool reject_fks) /* in: if TRUE, fail with error
3707
code DB_CANNOT_ADD_CONSTRAINT if
3708
any foreign keys are found. */
3715
ut_a(trx->mysql_thd);
3717
str = dict_strip_comments(sql_string);
3718
heap = mem_heap_create(10000);
3720
err = dict_create_foreign_constraints_low(
3721
trx, heap, innobase_get_charset(trx->mysql_thd), str, name,
3724
mem_heap_free(heap);
3730
/**************************************************************************
3731
Parses the CONSTRAINT id's to be dropped in an ALTER TABLE statement. */
3734
dict_foreign_parse_drop_constraints(
3735
/*================================*/
3736
/* out: DB_SUCCESS or
3737
DB_CANNOT_DROP_CONSTRAINT if
3738
syntax error or the constraint
3739
id does not match */
3740
mem_heap_t* heap, /* in: heap from which we can
3742
trx_t* trx, /* in: transaction */
3743
dict_table_t* table, /* in: table */
3744
ulint* n, /* out: number of constraints
3746
const char*** constraints_to_drop) /* out: id's of the
3747
constraints to drop */
3749
dict_foreign_t* foreign;
3754
FILE* ef = dict_foreign_err_file;
3755
const struct charset_info_st* cs;
3758
ut_a(trx->mysql_thd);
3760
cs = innobase_get_charset(trx->mysql_thd);
3764
*constraints_to_drop = mem_heap_alloc(heap, 1000 * sizeof(char*));
3766
str = dict_strip_comments(*(trx->mysql_query_str));
3769
ut_ad(mutex_own(&(dict_sys->mutex)));
3771
ptr = dict_scan_to(ptr, "DROP");
3779
ptr = dict_accept(cs, ptr, "DROP", &success);
3781
if (!my_isspace(cs, *ptr)) {
3786
ptr = dict_accept(cs, ptr, "FOREIGN", &success);
3788
if (!success || !my_isspace(cs, *ptr)) {
3793
ptr = dict_accept(cs, ptr, "KEY", &success);
3800
ptr = dict_scan_id(cs, ptr, heap, &id, FALSE, TRUE);
3808
(*constraints_to_drop)[*n] = id;
3811
/* Look for the given constraint id */
3813
foreign = UT_LIST_GET_FIRST(table->foreign_list);
3815
while (foreign != NULL) {
3816
if (0 == strcmp(foreign->id, id)
3817
|| (strchr(foreign->id, '/')
3819
dict_remove_db_name(foreign->id)))) {
3824
foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
3827
if (foreign == NULL) {
3828
mutex_enter(&dict_foreign_err_mutex);
3830
ut_print_timestamp(ef);
3831
fputs(" Error in dropping of a foreign key constraint"
3833
ut_print_name(ef, NULL, TRUE, table->name);
3835
"in SQL command\n", ef);
3837
fputs("\nCannot find a constraint with the given id ", ef);
3838
ut_print_name(ef, NULL, FALSE, id);
3840
mutex_exit(&dict_foreign_err_mutex);
3844
return(DB_CANNOT_DROP_CONSTRAINT);
3850
mutex_enter(&dict_foreign_err_mutex);
3852
ut_print_timestamp(ef);
3853
fputs(" Syntax error in dropping of a"
3854
" foreign key constraint of table ", ef);
3855
ut_print_name(ef, NULL, TRUE, table->name);
3857
"close to:\n%s\n in SQL command\n%s\n", ptr, str);
3858
mutex_exit(&dict_foreign_err_mutex);
3862
return(DB_CANNOT_DROP_CONSTRAINT);
3864
#endif /* UNIV_HOTBACKUP */
3866
/*==================== END OF FOREIGN KEY PROCESSING ====================*/
3868
/**************************************************************************
3869
Returns an index object if it is found in the dictionary cache.
3870
Assumes that dict_sys->mutex is already being held. */
3873
dict_index_get_if_in_cache_low(
3874
/*===========================*/
3875
/* out: index, NULL if not found */
3876
dulint index_id) /* in: index id */
3878
ut_ad(mutex_own(&(dict_sys->mutex)));
3880
return(dict_index_find_on_id_low(index_id));
3883
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
3884
/**************************************************************************
3885
Returns an index object if it is found in the dictionary cache. */
3888
dict_index_get_if_in_cache(
3889
/*=======================*/
3890
/* out: index, NULL if not found */
3891
dulint index_id) /* in: index id */
3893
dict_index_t* index;
3895
if (dict_sys == NULL) {
3899
mutex_enter(&(dict_sys->mutex));
3901
index = dict_index_get_if_in_cache_low(index_id);
3903
mutex_exit(&(dict_sys->mutex));
3907
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
3910
/**************************************************************************
3911
Checks that a tuple has n_fields_cmp value in a sensible range, so that
3912
no comparison can occur with the page number field in a node pointer. */
3915
dict_index_check_search_tuple(
3916
/*==========================*/
3917
/* out: TRUE if ok */
3918
const dict_index_t* index, /* in: index tree */
3919
const dtuple_t* tuple) /* in: tuple used in a search */
3922
ut_a(dtuple_get_n_fields_cmp(tuple)
3923
<= dict_index_get_n_unique_in_tree(index));
3926
#endif /* UNIV_DEBUG */
3928
/**************************************************************************
3929
Builds a node pointer out of a physical record and a page number. */
3932
dict_index_build_node_ptr(
3933
/*======================*/
3934
/* out, own: node pointer */
3935
const dict_index_t* index, /* in: index */
3936
const rec_t* rec, /* in: record for which to build node
3938
ulint page_no,/* in: page number to put in node
3940
mem_heap_t* heap, /* in: memory heap where pointer
3942
ulint level) /* in: level of rec in tree:
3943
0 means leaf level */
3950
if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) {
3951
/* In a universal index tree, we take the whole record as
3952
the node pointer if the record is on the leaf level,
3953
on non-leaf levels we remove the last field, which
3954
contains the page number of the child page */
3956
ut_a(!dict_table_is_comp(index->table));
3957
n_unique = rec_get_n_fields_old(rec);
3964
n_unique = dict_index_get_n_unique_in_tree(index);
3967
tuple = dtuple_create(heap, n_unique + 1);
3969
/* When searching in the tree for the node pointer, we must not do
3970
comparison on the last field, the page number field, as on upper
3971
levels in the tree there may be identical node pointers with a
3972
different page number; therefore, we set the n_fields_cmp to one
3975
dtuple_set_n_fields_cmp(tuple, n_unique);
3977
dict_index_copy_types(tuple, index, n_unique);
3979
buf = mem_heap_alloc(heap, 4);
3981
mach_write_to_4(buf, page_no);
3983
field = dtuple_get_nth_field(tuple, n_unique);
3984
dfield_set_data(field, buf, 4);
3986
dtype_set(dfield_get_type(field), DATA_SYS_CHILD, DATA_NOT_NULL, 4);
3988
rec_copy_prefix_to_dtuple(tuple, rec, index, n_unique, heap);
3989
dtuple_set_info_bits(tuple, dtuple_get_info_bits(tuple)
3990
| REC_STATUS_NODE_PTR);
3992
ut_ad(dtuple_check_typed(tuple));
3997
/**************************************************************************
3998
Copies an initial segment of a physical record, long enough to specify an
3999
index entry uniquely. */
4002
dict_index_copy_rec_order_prefix(
4003
/*=============================*/
4004
/* out: pointer to the prefix record */
4005
const dict_index_t* index, /* in: index */
4006
const rec_t* rec, /* in: record for which to
4008
ulint* n_fields,/* out: number of fields copied */
4009
byte** buf, /* in/out: memory buffer for the
4010
copied prefix, or NULL */
4011
ulint* buf_size)/* in/out: buffer size */
4015
UNIV_PREFETCH_R(rec);
4017
if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) {
4018
ut_a(!dict_table_is_comp(index->table));
4019
n = rec_get_n_fields_old(rec);
4021
n = dict_index_get_n_unique_in_tree(index);
4025
return(rec_copy_prefix_to_buf(rec, index, n, buf, buf_size));
4028
/**************************************************************************
4029
Builds a typed data tuple out of a physical record. */
4032
dict_index_build_data_tuple(
4033
/*========================*/
4034
/* out, own: data tuple */
4035
dict_index_t* index, /* in: index tree */
4036
rec_t* rec, /* in: record for which to build data tuple */
4037
ulint n_fields,/* in: number of data fields */
4038
mem_heap_t* heap) /* in: memory heap where tuple created */
4042
ut_ad(dict_table_is_comp(index->table)
4043
|| n_fields <= rec_get_n_fields_old(rec));
4045
tuple = dtuple_create(heap, n_fields);
4047
dict_index_copy_types(tuple, index, n_fields);
4049
rec_copy_prefix_to_dtuple(tuple, rec, index, n_fields, heap);
4051
ut_ad(dtuple_check_typed(tuple));
4056
/*************************************************************************
4057
Calculates the minimum record length in an index. */
4060
dict_index_calc_min_rec_len(
4061
/*========================*/
4062
const dict_index_t* index) /* in: index */
4067
if (dict_table_is_comp(index->table)) {
4069
sum = REC_N_NEW_EXTRA_BYTES;
4070
for (i = 0; i < dict_index_get_n_fields(index); i++) {
4071
const dict_col_t* col
4072
= dict_index_get_nth_col(index, i);
4073
ulint size = dict_col_get_fixed_size(col);
4077
sum += size < 128 ? 1 : 2;
4079
if (!(col->prtype & DATA_NOT_NULL)) {
4084
/* round the NULL flags up to full bytes */
4085
sum += UT_BITS_IN_BYTES(nullable);
4090
for (i = 0; i < dict_index_get_n_fields(index); i++) {
4091
sum += dict_col_get_fixed_size(
4092
dict_index_get_nth_col(index, i));
4096
sum += 2 * dict_index_get_n_fields(index);
4098
sum += dict_index_get_n_fields(index);
4101
sum += REC_N_OLD_EXTRA_BYTES;
4106
/*************************************************************************
4107
Calculates new estimates for table and index statistics. The statistics
4108
are used in query optimization. */
4111
dict_update_statistics_low(
4112
/*=======================*/
4113
dict_table_t* table, /* in/out: table */
4114
ibool has_dict_mutex __attribute__((unused)))
4115
/* in: TRUE if the caller has the
4118
dict_index_t* index;
4120
ulint sum_of_index_sizes = 0;
4122
if (table->ibd_file_missing) {
4123
ut_print_timestamp(stderr);
4125
" InnoDB: cannot calculate statistics for table %s\n"
4126
"InnoDB: because the .ibd file is missing. For help,"
4127
" please refer to\n"
4128
"InnoDB: http://dev.mysql.com/doc/refman/5.1/en/"
4129
"innodb-troubleshooting.html\n",
4135
/* If we have set a high innodb_force_recovery level, do not calculate
4136
statistics, as a badly corrupted index can cause a crash in it. */
4138
if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
4143
/* Find out the sizes of the indexes and how many different values
4144
for the key they approximately have */
4146
index = dict_table_get_first_index(table);
4148
if (index == NULL) {
4149
/* Table definition is corrupt */
4155
size = btr_get_size(index, BTR_TOTAL_SIZE);
4157
index->stat_index_size = size;
4159
sum_of_index_sizes += size;
4161
size = btr_get_size(index, BTR_N_LEAF_PAGES);
4164
/* The root node of the tree is a leaf */
4168
index->stat_n_leaf_pages = size;
4170
btr_estimate_number_of_different_key_vals(index);
4172
index = dict_table_get_next_index(index);
4175
index = dict_table_get_first_index(table);
4177
table->stat_n_rows = index->stat_n_diff_key_vals[
4178
dict_index_get_n_unique(index)];
4180
table->stat_clustered_index_size = index->stat_index_size;
4182
table->stat_sum_of_other_index_sizes = sum_of_index_sizes
4183
- index->stat_index_size;
4185
table->stat_initialized = TRUE;
4187
table->stat_modified_counter = 0;
4190
/*************************************************************************
4191
Calculates new estimates for table and index statistics. The statistics
4192
are used in query optimization. */
4195
dict_update_statistics(
4196
/*===================*/
4197
dict_table_t* table) /* in/out: table */
4199
dict_update_statistics_low(table, FALSE);
4202
/**************************************************************************
4203
Prints info of a foreign key constraint. */
4206
dict_foreign_print_low(
4207
/*===================*/
4208
dict_foreign_t* foreign) /* in: foreign key constraint */
4212
ut_ad(mutex_own(&(dict_sys->mutex)));
4214
fprintf(stderr, " FOREIGN KEY CONSTRAINT %s: %s (",
4215
foreign->id, foreign->foreign_table_name);
4217
for (i = 0; i < foreign->n_fields; i++) {
4218
fprintf(stderr, " %s", foreign->foreign_col_names[i]);
4221
fprintf(stderr, " )\n"
4223
foreign->referenced_table_name);
4225
for (i = 0; i < foreign->n_fields; i++) {
4226
fprintf(stderr, " %s", foreign->referenced_col_names[i]);
4229
fputs(" )\n", stderr);
4232
/**************************************************************************
4233
Prints a table data. */
4238
dict_table_t* table) /* in: table */
4240
mutex_enter(&(dict_sys->mutex));
4241
dict_table_print_low(table);
4242
mutex_exit(&(dict_sys->mutex));
4245
/**************************************************************************
4246
Prints a table data when we know the table name. */
4249
dict_table_print_by_name(
4250
/*=====================*/
4253
dict_table_t* table;
4255
mutex_enter(&(dict_sys->mutex));
4257
table = dict_table_get_low(name);
4261
dict_table_print_low(table);
4262
mutex_exit(&(dict_sys->mutex));
4265
/**************************************************************************
4266
Prints a table data. */
4269
dict_table_print_low(
4270
/*=================*/
4271
dict_table_t* table) /* in: table */
4273
dict_index_t* index;
4274
dict_foreign_t* foreign;
4277
ut_ad(mutex_own(&(dict_sys->mutex)));
4279
dict_update_statistics_low(table, TRUE);
4282
"--------------------------------------\n"
4283
"TABLE: name %s, id %lu %lu, flags %lx, columns %lu,"
4284
" indexes %lu, appr.rows %lu\n"
4287
(ulong) ut_dulint_get_high(table->id),
4288
(ulong) ut_dulint_get_low(table->id),
4289
(ulong) table->flags,
4290
(ulong) table->n_cols,
4291
(ulong) UT_LIST_GET_LEN(table->indexes),
4292
(ulong) table->stat_n_rows);
4294
for (i = 0; i + 1 < (ulint) table->n_cols; i++) {
4295
dict_col_print_low(table, dict_table_get_nth_col(table, i));
4296
fputs("; ", stderr);
4301
index = UT_LIST_GET_FIRST(table->indexes);
4303
while (index != NULL) {
4304
dict_index_print_low(index);
4305
index = UT_LIST_GET_NEXT(indexes, index);
4308
foreign = UT_LIST_GET_FIRST(table->foreign_list);
4310
while (foreign != NULL) {
4311
dict_foreign_print_low(foreign);
4312
foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
4315
foreign = UT_LIST_GET_FIRST(table->referenced_list);
4317
while (foreign != NULL) {
4318
dict_foreign_print_low(foreign);
4319
foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
4323
/**************************************************************************
4324
Prints a column data. */
4329
const dict_table_t* table, /* in: table */
4330
const dict_col_t* col) /* in: column */
4334
ut_ad(mutex_own(&(dict_sys->mutex)));
4336
dict_col_copy_type(col, &type);
4337
fprintf(stderr, "%s: ", dict_table_get_col_name(table,
4338
dict_col_get_no(col)));
4343
/**************************************************************************
4344
Prints an index data. */
4347
dict_index_print_low(
4348
/*=================*/
4349
dict_index_t* index) /* in: index */
4353
const char* type_string;
4355
ut_ad(mutex_own(&(dict_sys->mutex)));
4357
if (index->n_user_defined_cols > 0) {
4358
n_vals = index->stat_n_diff_key_vals[
4359
index->n_user_defined_cols];
4361
n_vals = index->stat_n_diff_key_vals[1];
4364
if (dict_index_is_clust(index)) {
4365
type_string = "clustered index";
4366
} else if (dict_index_is_unique(index)) {
4367
type_string = "unique index";
4369
type_string = "secondary index";
4373
" INDEX: name %s, id %lu %lu, fields %lu/%lu,"
4374
" uniq %lu, type %lu\n"
4375
" root page %lu, appr.key vals %lu,"
4376
" leaf pages %lu, size pages %lu\n"
4379
(ulong) ut_dulint_get_high(index->id),
4380
(ulong) ut_dulint_get_low(index->id),
4381
(ulong) index->n_user_defined_cols,
4382
(ulong) index->n_fields,
4383
(ulong) index->n_uniq,
4384
(ulong) index->type,
4385
(ulong) index->page,
4387
(ulong) index->stat_n_leaf_pages,
4388
(ulong) index->stat_index_size);
4390
for (i = 0; i < index->n_fields; i++) {
4391
dict_field_print_low(dict_index_get_nth_field(index, i));
4396
#ifdef UNIV_BTR_PRINT
4397
btr_print_size(index);
4399
btr_print_index(index, 7);
4400
#endif /* UNIV_BTR_PRINT */
4403
/**************************************************************************
4404
Prints a field data. */
4407
dict_field_print_low(
4408
/*=================*/
4409
dict_field_t* field) /* in: field */
4411
ut_ad(mutex_own(&(dict_sys->mutex)));
4413
fprintf(stderr, " %s", field->name);
4415
if (field->prefix_len != 0) {
4416
fprintf(stderr, "(%lu)", (ulong) field->prefix_len);
4420
/**************************************************************************
4421
Outputs info on a foreign key of a table in a format suitable for
4425
dict_print_info_on_foreign_key_in_create_format(
4426
/*============================================*/
4427
FILE* file, /* in: file where to print */
4428
trx_t* trx, /* in: transaction */
4429
dict_foreign_t* foreign, /* in: foreign key constraint */
4430
ibool add_newline) /* in: whether to add a newline */
4432
const char* stripped_id;
4435
if (strchr(foreign->id, '/')) {
4436
/* Strip the preceding database name from the constraint id */
4437
stripped_id = foreign->id + 1
4438
+ dict_get_db_name_len(foreign->id);
4440
stripped_id = foreign->id;
4446
/* SHOW CREATE TABLE wants constraints each printed nicely
4447
on its own line, while error messages want no newlines
4452
fputs(" CONSTRAINT ", file);
4453
ut_print_name(file, trx, FALSE, stripped_id);
4454
fputs(" FOREIGN KEY (", file);
4457
ut_print_name(file, trx, FALSE, foreign->foreign_col_names[i]);
4458
if (++i < foreign->n_fields) {
4465
fputs(") REFERENCES ", file);
4467
if (dict_tables_have_same_db(foreign->foreign_table_name,
4468
foreign->referenced_table_name)) {
4469
/* Do not print the database name of the referenced table */
4470
ut_print_name(file, trx, TRUE,
4471
dict_remove_db_name(
4472
foreign->referenced_table_name));
4474
ut_print_name(file, trx, TRUE,
4475
foreign->referenced_table_name);
4482
ut_print_name(file, trx, FALSE,
4483
foreign->referenced_col_names[i]);
4484
if (++i < foreign->n_fields) {
4493
if (foreign->type & DICT_FOREIGN_ON_DELETE_CASCADE) {
4494
fputs(" ON DELETE CASCADE", file);
4497
if (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL) {
4498
fputs(" ON DELETE SET NULL", file);
4501
if (foreign->type & DICT_FOREIGN_ON_DELETE_NO_ACTION) {
4502
fputs(" ON DELETE NO ACTION", file);
4505
if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE) {
4506
fputs(" ON UPDATE CASCADE", file);
4509
if (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL) {
4510
fputs(" ON UPDATE SET NULL", file);
4513
if (foreign->type & DICT_FOREIGN_ON_UPDATE_NO_ACTION) {
4514
fputs(" ON UPDATE NO ACTION", file);
4518
/**************************************************************************
4519
Outputs info on foreign keys of a table. */
4522
dict_print_info_on_foreign_keys(
4523
/*============================*/
4524
ibool create_table_format, /* in: if TRUE then print in
4525
a format suitable to be inserted into
4526
a CREATE TABLE, otherwise in the format
4527
of SHOW TABLE STATUS */
4528
FILE* file, /* in: file where to print */
4529
trx_t* trx, /* in: transaction */
4530
dict_table_t* table) /* in: table */
4532
dict_foreign_t* foreign;
4534
mutex_enter(&(dict_sys->mutex));
4536
foreign = UT_LIST_GET_FIRST(table->foreign_list);
4538
if (foreign == NULL) {
4539
mutex_exit(&(dict_sys->mutex));
4544
while (foreign != NULL) {
4545
if (create_table_format) {
4546
dict_print_info_on_foreign_key_in_create_format(
4547
file, trx, foreign, TRUE);
4552
for (i = 0; i < foreign->n_fields; i++) {
4557
ut_print_name(file, trx, FALSE,
4558
foreign->foreign_col_names[i]);
4561
fputs(") REFER ", file);
4562
ut_print_name(file, trx, TRUE,
4563
foreign->referenced_table_name);
4566
for (i = 0; i < foreign->n_fields; i++) {
4572
foreign->referenced_col_names[i]);
4577
if (foreign->type == DICT_FOREIGN_ON_DELETE_CASCADE) {
4578
fputs(" ON DELETE CASCADE", file);
4581
if (foreign->type == DICT_FOREIGN_ON_DELETE_SET_NULL) {
4582
fputs(" ON DELETE SET NULL", file);
4585
if (foreign->type & DICT_FOREIGN_ON_DELETE_NO_ACTION) {
4586
fputs(" ON DELETE NO ACTION", file);
4589
if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE) {
4590
fputs(" ON UPDATE CASCADE", file);
4593
if (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL) {
4594
fputs(" ON UPDATE SET NULL", file);
4597
if (foreign->type & DICT_FOREIGN_ON_UPDATE_NO_ACTION) {
4598
fputs(" ON UPDATE NO ACTION", file);
4602
foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
4605
mutex_exit(&(dict_sys->mutex));
4608
/************************************************************************
4609
Displays the names of the index and the table. */
4612
dict_index_name_print(
4613
/*==================*/
4614
FILE* file, /* in: output stream */
4615
trx_t* trx, /* in: transaction */
4616
const dict_index_t* index) /* in: index to print */
4618
fputs("index ", file);
4619
ut_print_name(file, trx, FALSE, index->name);
4620
fputs(" of table ", file);
4621
ut_print_name(file, trx, TRUE, index->table_name);
4624
/**************************************************************************
4625
Get index by name */
4628
dict_table_get_index_on_name(
4629
/*=========================*/
4630
/* out: index, NULL if does not exist */
4631
dict_table_t* table, /* in: table */
4632
const char* name) /* in: name of the index to find */
4634
dict_index_t* index;
4636
index = dict_table_get_first_index(table);
4638
while (index != NULL) {
4639
if (ut_strcmp(index->name, name) == 0) {
4644
index = dict_table_get_next_index(index);
4651
/**************************************************************************
4652
Replace the index passed in with another equivalent index in the tables
4653
foreign key list. */
4656
dict_table_replace_index_in_foreign_list(
4657
/*=====================================*/
4658
dict_table_t* table, /* in/out: table */
4659
dict_index_t* index) /* in: index to be replaced */
4661
dict_foreign_t* foreign;
4663
for (foreign = UT_LIST_GET_FIRST(table->foreign_list);
4665
foreign = UT_LIST_GET_NEXT(foreign_list, foreign)) {
4667
if (foreign->foreign_index == index) {
4668
dict_index_t* new_index
4669
= dict_foreign_find_equiv_index(foreign);
4672
foreign->foreign_index = new_index;
4677
/**************************************************************************
4678
In case there is more than one index with the same name return the index
4679
with the min(id). */
4682
dict_table_get_index_on_name_and_min_id(
4683
/*=====================================*/
4684
/* out: index, NULL if does not exist */
4685
dict_table_t* table, /* in: table */
4686
const char* name) /* in: name of the index to find */
4688
dict_index_t* index;
4689
dict_index_t* min_index; /* Index with matching name and min(id) */
4692
index = dict_table_get_first_index(table);
4694
while (index != NULL) {
4695
if (ut_strcmp(index->name, name) == 0) {
4697
|| ut_dulint_cmp(index->id, min_index->id) < 0) {
4703
index = dict_table_get_next_index(index);
4711
/**************************************************************************
4712
Check for duplicate index entries in a table [using the index name] */
4715
dict_table_check_for_dup_indexes(
4716
/*=============================*/
4717
const dict_table_t* table) /* in: Check for dup indexes
4720
/* Check for duplicates, ignoring indexes that are marked
4723
const dict_index_t* index1;
4724
const dict_index_t* index2;
4726
/* The primary index _must_ exist */
4727
ut_a(UT_LIST_GET_LEN(table->indexes) > 0);
4729
index1 = UT_LIST_GET_FIRST(table->indexes);
4730
index2 = UT_LIST_GET_NEXT(indexes, index1);
4732
while (index1 && index2) {
4736
if (!index2->to_be_dropped) {
4737
ut_ad(ut_strcmp(index1->name, index2->name));
4740
index2 = UT_LIST_GET_NEXT(indexes, index2);
4743
index1 = UT_LIST_GET_NEXT(indexes, index1);
4744
index2 = UT_LIST_GET_NEXT(indexes, index1);
4747
#endif /* UNIV_DEBUG */