1
/******************************************************
2
Database object creation
6
Created 1/8/1996 Heikki Tuuri
7
*******************************************************/
12
#include "dict0crea.ic"
17
#include "page0page.h"
18
#include "mach0data.h"
19
#include "dict0boot.h"
20
#include "dict0dict.h"
23
#include "row0mysql.h"
24
#include "pars0pars.h"
29
/*********************************************************************
30
Based on a table object, this function builds the entry to be inserted
31
in the SYS_TABLES system table. */
34
dict_create_sys_tables_tuple(
35
/*=========================*/
36
/* out: the tuple which should be inserted */
37
dict_table_t* table, /* in: table */
38
mem_heap_t* heap) /* in: memory heap from which the memory for
39
the built tuple is allocated */
41
dict_table_t* sys_tables;
48
sys_tables = dict_sys->sys_tables;
50
entry = dtuple_create(heap, 8 + DATA_N_SYS_COLS);
52
/* 0: NAME -----------------------------*/
53
dfield = dtuple_get_nth_field(entry, 0);
55
dfield_set_data(dfield, table->name, ut_strlen(table->name));
56
/* 3: ID -------------------------------*/
57
dfield = dtuple_get_nth_field(entry, 1);
59
ptr = mem_heap_alloc(heap, 8);
60
mach_write_to_8(ptr, table->id);
62
dfield_set_data(dfield, ptr, 8);
63
/* 4: N_COLS ---------------------------*/
64
dfield = dtuple_get_nth_field(entry, 2);
66
#if DICT_TF_COMPACT != 1
70
ptr = mem_heap_alloc(heap, 4);
71
mach_write_to_4(ptr, table->n_def
72
| ((table->flags & DICT_TF_COMPACT) << 31));
73
dfield_set_data(dfield, ptr, 4);
74
/* 5: TYPE -----------------------------*/
75
dfield = dtuple_get_nth_field(entry, 3);
77
ptr = mem_heap_alloc(heap, 4);
78
mach_write_to_4(ptr, DICT_TABLE_ORDINARY);
80
dfield_set_data(dfield, ptr, 4);
81
/* 6: MIX_ID (obsolete) ---------------------------*/
82
dfield = dtuple_get_nth_field(entry, 4);
84
ptr = mem_heap_alloc(heap, 8);
87
dfield_set_data(dfield, ptr, 8);
88
/* 7: MIX_LEN (obsolete) --------------------------*/
90
dfield = dtuple_get_nth_field(entry, 5);
92
ptr = mem_heap_alloc(heap, 4);
95
dfield_set_data(dfield, ptr, 4);
96
/* 8: CLUSTER_NAME ---------------------*/
97
dfield = dtuple_get_nth_field(entry, 6);
98
dfield_set_data(dfield, NULL, UNIV_SQL_NULL); /* not supported */
100
/* 9: SPACE ----------------------------*/
101
dfield = dtuple_get_nth_field(entry, 7);
103
ptr = mem_heap_alloc(heap, 4);
104
mach_write_to_4(ptr, table->space);
106
dfield_set_data(dfield, ptr, 4);
107
/*----------------------------------*/
109
dict_table_copy_types(entry, sys_tables);
114
/*********************************************************************
115
Based on a table object, this function builds the entry to be inserted
116
in the SYS_COLUMNS system table. */
119
dict_create_sys_columns_tuple(
120
/*==========================*/
121
/* out: the tuple which should be inserted */
122
dict_table_t* table, /* in: table */
123
ulint i, /* in: column number */
124
mem_heap_t* heap) /* in: memory heap from which the memory for
125
the built tuple is allocated */
127
dict_table_t* sys_columns;
129
const dict_col_t* column;
132
const char* col_name;
134
ut_ad(table && heap);
136
column = dict_table_get_nth_col(table, i);
138
sys_columns = dict_sys->sys_columns;
140
entry = dtuple_create(heap, 7 + DATA_N_SYS_COLS);
142
/* 0: TABLE_ID -----------------------*/
143
dfield = dtuple_get_nth_field(entry, 0);
145
ptr = mem_heap_alloc(heap, 8);
146
mach_write_to_8(ptr, table->id);
148
dfield_set_data(dfield, ptr, 8);
149
/* 1: POS ----------------------------*/
150
dfield = dtuple_get_nth_field(entry, 1);
152
ptr = mem_heap_alloc(heap, 4);
153
mach_write_to_4(ptr, i);
155
dfield_set_data(dfield, ptr, 4);
156
/* 4: NAME ---------------------------*/
157
dfield = dtuple_get_nth_field(entry, 2);
159
col_name = dict_table_get_col_name(table, i);
160
dfield_set_data(dfield, col_name, ut_strlen(col_name));
161
/* 5: MTYPE --------------------------*/
162
dfield = dtuple_get_nth_field(entry, 3);
164
ptr = mem_heap_alloc(heap, 4);
165
mach_write_to_4(ptr, column->mtype);
167
dfield_set_data(dfield, ptr, 4);
168
/* 6: PRTYPE -------------------------*/
169
dfield = dtuple_get_nth_field(entry, 4);
171
ptr = mem_heap_alloc(heap, 4);
172
mach_write_to_4(ptr, column->prtype);
174
dfield_set_data(dfield, ptr, 4);
175
/* 7: LEN ----------------------------*/
176
dfield = dtuple_get_nth_field(entry, 5);
178
ptr = mem_heap_alloc(heap, 4);
179
mach_write_to_4(ptr, column->len);
181
dfield_set_data(dfield, ptr, 4);
182
/* 8: PREC ---------------------------*/
183
dfield = dtuple_get_nth_field(entry, 6);
185
ptr = mem_heap_alloc(heap, 4);
186
mach_write_to_4(ptr, 0/* unused */);
188
dfield_set_data(dfield, ptr, 4);
189
/*---------------------------------*/
191
dict_table_copy_types(entry, sys_columns);
196
/*******************************************************************
197
Builds a table definition to insert. */
200
dict_build_table_def_step(
201
/*======================*/
202
/* out: DB_SUCCESS or error code */
203
que_thr_t* thr, /* in: query thread */
204
tab_node_t* node) /* in: table create node */
209
const char* path_or_name;
215
ut_ad(mutex_own(&(dict_sys->mutex)));
219
table->id = dict_hdr_get_new_id(DICT_HDR_TABLE_ID);
221
thr_get_trx(thr)->table_id = table->id;
224
for (i = 0; i < table->n_def; i++) {
225
row_len += dict_col_get_min_size(&table->cols[i]);
227
if (row_len > BTR_PAGE_MAX_REC_SIZE) {
228
return(DB_TOO_BIG_RECORD);
231
if (srv_file_per_table) {
232
/* We create a new single-table tablespace for the table.
233
We initially let it be 4 pages:
234
- page 0 is the fsp header and an extent descriptor page,
235
- page 1 is an ibuf bitmap page,
236
- page 2 is the first inode page,
237
- page 3 will contain the root of the clustered index of the
238
table we create here. */
240
ulint space = 0; /* reset to zero for the call below */
242
if (table->dir_path_of_temp_table) {
243
/* We place tables created with CREATE TEMPORARY
244
TABLE in the tmp dir of mysqld server */
246
path_or_name = table->dir_path_of_temp_table;
249
path_or_name = table->name;
253
error = fil_create_new_single_table_tablespace(
254
&space, path_or_name, is_path,
255
FIL_IBD_FILE_INITIAL_SIZE);
256
table->space = (unsigned int) space;
258
if (error != DB_SUCCESS) {
265
fsp_header_init(table->space, FIL_IBD_FILE_INITIAL_SIZE, &mtr);
270
row = dict_create_sys_tables_tuple(table, node->heap);
272
ins_node_set_new_row(node->tab_def, row);
277
/*******************************************************************
278
Builds a column definition to insert. */
281
dict_build_col_def_step(
282
/*====================*/
283
/* out: DB_SUCCESS */
284
tab_node_t* node) /* in: table create node */
288
row = dict_create_sys_columns_tuple(node->table, node->col_no,
290
ins_node_set_new_row(node->col_def, row);
295
/*********************************************************************
296
Based on an index object, this function builds the entry to be inserted
297
in the SYS_INDEXES system table. */
300
dict_create_sys_indexes_tuple(
301
/*==========================*/
302
/* out: the tuple which should be inserted */
303
dict_index_t* index, /* in: index */
304
mem_heap_t* heap) /* in: memory heap from which the memory for
305
the built tuple is allocated */
307
dict_table_t* sys_indexes;
313
ut_ad(mutex_own(&(dict_sys->mutex)));
314
ut_ad(index && heap);
316
sys_indexes = dict_sys->sys_indexes;
318
table = dict_table_get_low(index->table_name);
320
entry = dtuple_create(heap, 7 + DATA_N_SYS_COLS);
322
/* 0: TABLE_ID -----------------------*/
323
dfield = dtuple_get_nth_field(entry, 0);
325
ptr = mem_heap_alloc(heap, 8);
326
mach_write_to_8(ptr, table->id);
328
dfield_set_data(dfield, ptr, 8);
329
/* 1: ID ----------------------------*/
330
dfield = dtuple_get_nth_field(entry, 1);
332
ptr = mem_heap_alloc(heap, 8);
333
mach_write_to_8(ptr, index->id);
335
dfield_set_data(dfield, ptr, 8);
336
/* 4: NAME --------------------------*/
337
dfield = dtuple_get_nth_field(entry, 2);
339
dfield_set_data(dfield, index->name, ut_strlen(index->name));
340
/* 5: N_FIELDS ----------------------*/
341
dfield = dtuple_get_nth_field(entry, 3);
343
ptr = mem_heap_alloc(heap, 4);
344
mach_write_to_4(ptr, index->n_fields);
346
dfield_set_data(dfield, ptr, 4);
347
/* 6: TYPE --------------------------*/
348
dfield = dtuple_get_nth_field(entry, 4);
350
ptr = mem_heap_alloc(heap, 4);
351
mach_write_to_4(ptr, index->type);
353
dfield_set_data(dfield, ptr, 4);
354
/* 7: SPACE --------------------------*/
356
#if DICT_SYS_INDEXES_SPACE_NO_FIELD != 7
357
#error "DICT_SYS_INDEXES_SPACE_NO_FIELD != 7"
360
dfield = dtuple_get_nth_field(entry, 5);
362
ptr = mem_heap_alloc(heap, 4);
363
mach_write_to_4(ptr, index->space);
365
dfield_set_data(dfield, ptr, 4);
366
/* 8: PAGE_NO --------------------------*/
368
#if DICT_SYS_INDEXES_PAGE_NO_FIELD != 8
369
#error "DICT_SYS_INDEXES_PAGE_NO_FIELD != 8"
372
dfield = dtuple_get_nth_field(entry, 6);
374
ptr = mem_heap_alloc(heap, 4);
375
mach_write_to_4(ptr, FIL_NULL);
377
dfield_set_data(dfield, ptr, 4);
378
/*--------------------------------*/
380
dict_table_copy_types(entry, sys_indexes);
385
/*********************************************************************
386
Based on an index object, this function builds the entry to be inserted
387
in the SYS_FIELDS system table. */
390
dict_create_sys_fields_tuple(
391
/*=========================*/
392
/* out: the tuple which should be inserted */
393
dict_index_t* index, /* in: index */
394
ulint i, /* in: field number */
395
mem_heap_t* heap) /* in: memory heap from which the memory for
396
the built tuple is allocated */
398
dict_table_t* sys_fields;
403
ibool index_contains_column_prefix_field = FALSE;
406
ut_ad(index && heap);
408
for (j = 0; j < index->n_fields; j++) {
409
if (dict_index_get_nth_field(index, j)->prefix_len > 0) {
410
index_contains_column_prefix_field = TRUE;
414
field = dict_index_get_nth_field(index, i);
416
sys_fields = dict_sys->sys_fields;
418
entry = dtuple_create(heap, 3 + DATA_N_SYS_COLS);
420
/* 0: INDEX_ID -----------------------*/
421
dfield = dtuple_get_nth_field(entry, 0);
423
ptr = mem_heap_alloc(heap, 8);
424
mach_write_to_8(ptr, index->id);
426
dfield_set_data(dfield, ptr, 8);
427
/* 1: POS + PREFIX LENGTH ----------------------------*/
429
dfield = dtuple_get_nth_field(entry, 1);
431
ptr = mem_heap_alloc(heap, 4);
433
if (index_contains_column_prefix_field) {
434
/* If there are column prefix fields in the index, then
435
we store the number of the field to the 2 HIGH bytes
436
and the prefix length to the 2 low bytes, */
438
mach_write_to_4(ptr, (i << 16) + field->prefix_len);
440
/* Else we store the number of the field to the 2 LOW bytes.
441
This is to keep the storage format compatible with
442
InnoDB versions < 4.0.14. */
444
mach_write_to_4(ptr, i);
447
dfield_set_data(dfield, ptr, 4);
448
/* 4: COL_NAME -------------------------*/
449
dfield = dtuple_get_nth_field(entry, 2);
451
dfield_set_data(dfield, field->name,
452
ut_strlen(field->name));
453
/*---------------------------------*/
455
dict_table_copy_types(entry, sys_fields);
460
/*********************************************************************
461
Creates the tuple with which the index entry is searched for writing the index
462
tree root page number, if such a tree is created. */
465
dict_create_search_tuple(
466
/*=====================*/
467
/* out: the tuple for search */
468
dtuple_t* tuple, /* in: the tuple inserted in the SYS_INDEXES
470
mem_heap_t* heap) /* in: memory heap from which the memory for
471
the built tuple is allocated */
473
dtuple_t* search_tuple;
477
ut_ad(tuple && heap);
479
search_tuple = dtuple_create(heap, 2);
481
field1 = dtuple_get_nth_field(tuple, 0);
482
field2 = dtuple_get_nth_field(search_tuple, 0);
484
dfield_copy(field2, field1);
486
field1 = dtuple_get_nth_field(tuple, 1);
487
field2 = dtuple_get_nth_field(search_tuple, 1);
489
dfield_copy(field2, field1);
491
ut_ad(dtuple_validate(search_tuple));
493
return(search_tuple);
496
/*******************************************************************
497
Builds an index definition row to insert. */
500
dict_build_index_def_step(
501
/*======================*/
502
/* out: DB_SUCCESS or error code */
503
que_thr_t* thr, /* in: query thread */
504
ind_node_t* node) /* in: index create node */
511
ut_ad(mutex_own(&(dict_sys->mutex)));
513
trx = thr_get_trx(thr);
517
table = dict_table_get_low(index->table_name);
520
return(DB_TABLE_NOT_FOUND);
523
trx->table_id = table->id;
527
ut_ad((UT_LIST_GET_LEN(table->indexes) > 0)
528
|| (index->type & DICT_CLUSTERED));
530
index->id = dict_hdr_get_new_id(DICT_HDR_INDEX_ID);
532
/* Inherit the space id from the table; we store all indexes of a
533
table in the same tablespace */
535
index->space = table->space;
536
node->page_no = FIL_NULL;
537
row = dict_create_sys_indexes_tuple(index, node->heap);
540
ins_node_set_new_row(node->ind_def, row);
545
/*******************************************************************
546
Builds a field definition row to insert. */
549
dict_build_field_def_step(
550
/*======================*/
551
/* out: DB_SUCCESS */
552
ind_node_t* node) /* in: index create node */
559
row = dict_create_sys_fields_tuple(index, node->field_no, node->heap);
561
ins_node_set_new_row(node->field_def, row);
566
/*******************************************************************
567
Creates an index tree for the index if it is not a member of a cluster. */
570
dict_create_index_tree_step(
571
/*========================*/
572
/* out: DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
573
ind_node_t* node) /* in: index create node */
576
dict_table_t* sys_indexes;
578
dtuple_t* search_tuple;
582
ut_ad(mutex_own(&(dict_sys->mutex)));
587
sys_indexes = dict_sys->sys_indexes;
589
/* Run a mini-transaction in which the index tree is allocated for
590
the index and its root address is written to the index entry in
595
search_tuple = dict_create_search_tuple(node->ind_row, node->heap);
597
btr_pcur_open(UT_LIST_GET_FIRST(sys_indexes->indexes),
598
search_tuple, PAGE_CUR_L, BTR_MODIFY_LEAF,
601
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
603
node->page_no = btr_create(index->type, index->space, index->id,
604
dict_table_is_comp(table), &mtr);
605
/* printf("Created a new index tree in space %lu root page %lu\n",
606
index->space, index->page_no); */
608
page_rec_write_index_page_no(btr_pcur_get_rec(&pcur),
609
DICT_SYS_INDEXES_PAGE_NO_FIELD,
610
node->page_no, &mtr);
611
btr_pcur_close(&pcur);
614
if (node->page_no == FIL_NULL) {
616
return(DB_OUT_OF_FILE_SPACE);
622
/***********************************************************************
623
Drops the index tree associated with a row in SYS_INDEXES table. */
626
dict_drop_index_tree(
627
/*=================*/
628
rec_t* rec, /* in: record in the clustered index of SYS_INDEXES
630
mtr_t* mtr) /* in: mtr having the latch on the record page */
637
ut_ad(mutex_own(&(dict_sys->mutex)));
638
ut_a(!dict_table_is_comp(dict_sys->sys_indexes));
639
ptr = rec_get_nth_field_old(rec, DICT_SYS_INDEXES_PAGE_NO_FIELD, &len);
643
root_page_no = mtr_read_ulint(ptr, MLOG_4BYTES, mtr);
645
if (root_page_no == FIL_NULL) {
646
/* The tree has already been freed */
651
ptr = rec_get_nth_field_old(rec,
652
DICT_SYS_INDEXES_SPACE_NO_FIELD, &len);
656
space = mtr_read_ulint(ptr, MLOG_4BYTES, mtr);
658
if (!fil_tablespace_exists_in_mem(space)) {
659
/* It is a single table tablespace and the .ibd file is
660
missing: do nothing */
665
/* We free all the pages but the root page first; this operation
666
may span several mini-transactions */
668
btr_free_but_not_root(space, root_page_no);
670
/* Then we free the root page in the same mini-transaction where
671
we write FIL_NULL to the appropriate field in the SYS_INDEXES
672
record: this mini-transaction marks the B-tree totally freed */
674
/* printf("Dropping index tree in space %lu root page %lu\n", space,
676
btr_free_root(space, root_page_no, mtr);
678
page_rec_write_index_page_no(rec,
679
DICT_SYS_INDEXES_PAGE_NO_FIELD,
683
/***********************************************************************
684
Truncates the index tree associated with a row in SYS_INDEXES table. */
687
dict_truncate_index_tree(
688
/*=====================*/
689
/* out: new root page number, or
690
FIL_NULL on failure */
691
dict_table_t* table, /* in: the table the index belongs to */
692
btr_pcur_t* pcur, /* in/out: persistent cursor pointing to
693
record in the clustered index of
694
SYS_INDEXES table. The cursor may be
695
repositioned in this call. */
696
mtr_t* mtr) /* in: mtr having the latch
697
on the record page. The mtr may be
698
committed and restarted in this call. */
710
ut_ad(mutex_own(&(dict_sys->mutex)));
711
ut_a(!dict_table_is_comp(dict_sys->sys_indexes));
712
rec = btr_pcur_get_rec(pcur);
713
ptr = rec_get_nth_field_old(rec, DICT_SYS_INDEXES_PAGE_NO_FIELD, &len);
717
root_page_no = mtr_read_ulint(ptr, MLOG_4BYTES, mtr);
719
if (root_page_no == FIL_NULL) {
720
/* The tree has been freed. */
722
ut_print_timestamp(stderr);
723
fprintf(stderr, " InnoDB: Trying to TRUNCATE"
724
" a missing index of table %s!\n", table->name);
728
ptr = rec_get_nth_field_old(rec,
729
DICT_SYS_INDEXES_SPACE_NO_FIELD, &len);
733
space = mtr_read_ulint(ptr, MLOG_4BYTES, mtr);
735
if (!fil_tablespace_exists_in_mem(space)) {
736
/* It is a single table tablespace and the .ibd file is
737
missing: do nothing */
739
ut_print_timestamp(stderr);
740
fprintf(stderr, " InnoDB: Trying to TRUNCATE"
741
" a missing .ibd file of table %s!\n", table->name);
745
ptr = rec_get_nth_field_old(rec,
746
DICT_SYS_INDEXES_TYPE_FIELD, &len);
748
type = mach_read_from_4(ptr);
750
ptr = rec_get_nth_field_old(rec, 1, &len);
752
index_id = mach_read_from_8(ptr);
754
/* We free all the pages but the root page first; this operation
755
may span several mini-transactions */
757
btr_free_but_not_root(space, root_page_no);
759
/* Then we free the root page in the same mini-transaction where
760
we create the b-tree and write its new root page number to the
761
appropriate field in the SYS_INDEXES record: this mini-transaction
762
marks the B-tree totally truncated */
764
comp = page_is_comp(btr_page_get(space, root_page_no, RW_X_LATCH,
767
btr_free_root(space, root_page_no, mtr);
768
/* We will temporarily write FIL_NULL to the PAGE_NO field
769
in SYS_INDEXES, so that the database will not get into an
770
inconsistent state in case it crashes between the mtr_commit()
771
below and the following mtr_commit() call. */
772
page_rec_write_index_page_no(rec, DICT_SYS_INDEXES_PAGE_NO_FIELD,
775
/* We will need to commit the mini-transaction in order to avoid
776
deadlocks in the btr_create() call, because otherwise we would
777
be freeing and allocating pages in the same mini-transaction. */
778
btr_pcur_store_position(pcur, mtr);
782
btr_pcur_restore_position(BTR_MODIFY_LEAF, pcur, mtr);
784
/* Find the index corresponding to this SYS_INDEXES record. */
785
for (index = UT_LIST_GET_FIRST(table->indexes);
787
index = UT_LIST_GET_NEXT(indexes, index)) {
788
if (!ut_dulint_cmp(index->id, index_id)) {
793
root_page_no = btr_create(type, space, index_id, comp, mtr);
795
index->page = (unsigned int) root_page_no;
797
ut_print_timestamp(stderr);
799
" InnoDB: Index %lu %lu of table %s is missing\n"
800
"InnoDB: from the data dictionary during TRUNCATE!\n",
801
ut_dulint_get_high(index_id),
802
ut_dulint_get_low(index_id),
806
return(root_page_no);
809
/*************************************************************************
810
Creates a table create graph. */
813
tab_create_graph_create(
814
/*====================*/
815
/* out, own: table create node */
816
dict_table_t* table, /* in: table to create, built as a memory data
818
mem_heap_t* heap) /* in: heap where created */
822
node = mem_heap_alloc(heap, sizeof(tab_node_t));
824
node->common.type = QUE_NODE_CREATE_TABLE;
828
node->state = TABLE_BUILD_TABLE_DEF;
829
node->heap = mem_heap_create(256);
831
node->tab_def = ins_node_create(INS_DIRECT, dict_sys->sys_tables,
833
node->tab_def->common.parent = node;
835
node->col_def = ins_node_create(INS_DIRECT, dict_sys->sys_columns,
837
node->col_def->common.parent = node;
839
node->commit_node = commit_node_create(heap);
840
node->commit_node->common.parent = node;
845
/*************************************************************************
846
Creates an index create graph. */
849
ind_create_graph_create(
850
/*====================*/
851
/* out, own: index create node */
852
dict_index_t* index, /* in: index to create, built as a memory data
854
mem_heap_t* heap) /* in: heap where created */
858
node = mem_heap_alloc(heap, sizeof(ind_node_t));
860
node->common.type = QUE_NODE_CREATE_INDEX;
864
node->state = INDEX_BUILD_INDEX_DEF;
865
node->page_no = FIL_NULL;
866
node->heap = mem_heap_create(256);
868
node->ind_def = ins_node_create(INS_DIRECT,
869
dict_sys->sys_indexes, heap);
870
node->ind_def->common.parent = node;
872
node->field_def = ins_node_create(INS_DIRECT,
873
dict_sys->sys_fields, heap);
874
node->field_def->common.parent = node;
876
node->commit_node = commit_node_create(heap);
877
node->commit_node->common.parent = node;
882
/***************************************************************
883
Creates a table. This is a high-level function used in SQL execution graphs. */
886
dict_create_table_step(
887
/*===================*/
888
/* out: query thread to run next or NULL */
889
que_thr_t* thr) /* in: query thread */
892
ulint err = DB_ERROR;
896
ut_ad(mutex_own(&(dict_sys->mutex)));
898
trx = thr_get_trx(thr);
900
node = thr->run_node;
902
ut_ad(que_node_get_type(node) == QUE_NODE_CREATE_TABLE);
904
if (thr->prev_node == que_node_get_parent(node)) {
905
node->state = TABLE_BUILD_TABLE_DEF;
908
if (node->state == TABLE_BUILD_TABLE_DEF) {
910
/* DO THE CHECKS OF THE CONSISTENCY CONSTRAINTS HERE */
912
err = dict_build_table_def_step(thr, node);
914
if (err != DB_SUCCESS) {
919
node->state = TABLE_BUILD_COL_DEF;
922
thr->run_node = node->tab_def;
927
if (node->state == TABLE_BUILD_COL_DEF) {
929
if (node->col_no < (node->table)->n_def) {
931
err = dict_build_col_def_step(node);
933
if (err != DB_SUCCESS) {
940
thr->run_node = node->col_def;
944
node->state = TABLE_COMMIT_WORK;
948
if (node->state == TABLE_COMMIT_WORK) {
950
/* Table was correctly defined: do NOT commit the transaction
951
(CREATE TABLE does NOT do an implicit commit of the current
954
node->state = TABLE_ADD_TO_CACHE;
956
/* thr->run_node = node->commit_node;
961
if (node->state == TABLE_ADD_TO_CACHE) {
963
dict_table_add_to_cache(node->table, node->heap);
969
trx->error_state = err;
971
if (err == DB_SUCCESS) {
974
} else if (err == DB_LOCK_WAIT) {
978
/* SQL error detected */
983
thr->run_node = que_node_get_parent(node);
988
/***************************************************************
989
Creates an index. This is a high-level function used in SQL execution
993
dict_create_index_step(
994
/*===================*/
995
/* out: query thread to run next or NULL */
996
que_thr_t* thr) /* in: query thread */
999
ulint err = DB_ERROR;
1003
ut_ad(mutex_own(&(dict_sys->mutex)));
1005
trx = thr_get_trx(thr);
1007
node = thr->run_node;
1009
ut_ad(que_node_get_type(node) == QUE_NODE_CREATE_INDEX);
1011
if (thr->prev_node == que_node_get_parent(node)) {
1012
node->state = INDEX_BUILD_INDEX_DEF;
1015
if (node->state == INDEX_BUILD_INDEX_DEF) {
1016
/* DO THE CHECKS OF THE CONSISTENCY CONSTRAINTS HERE */
1017
err = dict_build_index_def_step(thr, node);
1019
if (err != DB_SUCCESS) {
1024
node->state = INDEX_BUILD_FIELD_DEF;
1027
thr->run_node = node->ind_def;
1032
if (node->state == INDEX_BUILD_FIELD_DEF) {
1034
if (node->field_no < (node->index)->n_fields) {
1036
err = dict_build_field_def_step(node);
1038
if (err != DB_SUCCESS) {
1045
thr->run_node = node->field_def;
1049
node->state = INDEX_CREATE_INDEX_TREE;
1053
if (node->state == INDEX_CREATE_INDEX_TREE) {
1055
err = dict_create_index_tree_step(node);
1057
if (err != DB_SUCCESS) {
1062
node->state = INDEX_COMMIT_WORK;
1065
if (node->state == INDEX_COMMIT_WORK) {
1067
/* Index was correctly defined: do NOT commit the transaction
1068
(CREATE INDEX does NOT currently do an implicit commit of
1069
the current transaction) */
1071
node->state = INDEX_ADD_TO_CACHE;
1073
/* thr->run_node = node->commit_node;
1078
if (node->state == INDEX_ADD_TO_CACHE) {
1080
dict_index_add_to_cache(node->table, node->index,
1087
trx->error_state = err;
1089
if (err == DB_SUCCESS) {
1090
/* Ok: do nothing */
1092
} else if (err == DB_LOCK_WAIT) {
1096
/* SQL error detected */
1101
thr->run_node = que_node_get_parent(node);
1106
/********************************************************************
1107
Creates the foreign key constraints system tables inside InnoDB
1108
at database creation or database start if they are not found or are
1109
not of the right form. */
1112
dict_create_or_check_foreign_constraint_tables(void)
1113
/*================================================*/
1114
/* out: DB_SUCCESS or error code */
1116
dict_table_t* table1;
1117
dict_table_t* table2;
1121
mutex_enter(&(dict_sys->mutex));
1123
table1 = dict_table_get_low("SYS_FOREIGN");
1124
table2 = dict_table_get_low("SYS_FOREIGN_COLS");
1126
if (table1 && table2
1127
&& UT_LIST_GET_LEN(table1->indexes) == 3
1128
&& UT_LIST_GET_LEN(table2->indexes) == 1) {
1130
/* Foreign constraint system tables have already been
1131
created, and they are ok */
1133
mutex_exit(&(dict_sys->mutex));
1138
mutex_exit(&(dict_sys->mutex));
1140
trx = trx_allocate_for_mysql();
1142
trx->op_info = "creating foreign key sys tables";
1144
row_mysql_lock_data_dictionary(trx);
1148
"InnoDB: dropping incompletely created"
1149
" SYS_FOREIGN table\n");
1150
row_drop_table_for_mysql("SYS_FOREIGN", trx, TRUE);
1155
"InnoDB: dropping incompletely created"
1156
" SYS_FOREIGN_COLS table\n");
1157
row_drop_table_for_mysql("SYS_FOREIGN_COLS", trx, TRUE);
1161
"InnoDB: Creating foreign key constraint system tables\n");
1163
/* NOTE: in dict_load_foreigns we use the fact that
1164
there are 2 secondary indexes on SYS_FOREIGN, and they
1165
are defined just like below */
1167
/* NOTE: when designing InnoDB's foreign key support in 2001, we made
1168
an error and made the table names and the foreign key id of type
1169
'CHAR' (internally, really a VARCHAR). We should have made the type
1170
VARBINARY, like in other InnoDB system tables, to get a clean
1173
error = que_eval_sql(NULL,
1174
"PROCEDURE CREATE_FOREIGN_SYS_TABLES_PROC () IS\n"
1177
"SYS_FOREIGN(ID CHAR, FOR_NAME CHAR,"
1178
" REF_NAME CHAR, N_COLS INT);\n"
1179
"CREATE UNIQUE CLUSTERED INDEX ID_IND"
1180
" ON SYS_FOREIGN (ID);\n"
1181
"CREATE INDEX FOR_IND"
1182
" ON SYS_FOREIGN (FOR_NAME);\n"
1183
"CREATE INDEX REF_IND"
1184
" ON SYS_FOREIGN (REF_NAME);\n"
1186
"SYS_FOREIGN_COLS(ID CHAR, POS INT,"
1187
" FOR_COL_NAME CHAR, REF_COL_NAME CHAR);\n"
1188
"CREATE UNIQUE CLUSTERED INDEX ID_IND"
1189
" ON SYS_FOREIGN_COLS (ID, POS);\n"
1194
if (error != DB_SUCCESS) {
1195
fprintf(stderr, "InnoDB: error %lu in creation\n",
1198
ut_a(error == DB_OUT_OF_FILE_SPACE
1199
|| error == DB_TOO_MANY_CONCURRENT_TRXS);
1202
"InnoDB: creation failed\n"
1203
"InnoDB: tablespace is full\n"
1204
"InnoDB: dropping incompletely created"
1205
" SYS_FOREIGN tables\n");
1207
row_drop_table_for_mysql("SYS_FOREIGN", trx, TRUE);
1208
row_drop_table_for_mysql("SYS_FOREIGN_COLS", trx, TRUE);
1210
error = DB_MUST_GET_MORE_FILE_SPACE;
1215
row_mysql_unlock_data_dictionary(trx);
1217
trx_free_for_mysql(trx);
1219
if (error == DB_SUCCESS) {
1221
"InnoDB: Foreign key constraint system tables"
1228
/********************************************************************
1229
Evaluate the given foreign key SQL statement. */
1232
dict_foreign_eval_sql(
1233
/*==================*/
1234
/* out: error code or DB_SUCCESS */
1235
pars_info_t* info, /* in: info struct, or NULL */
1236
const char* sql, /* in: SQL string to evaluate */
1237
dict_table_t* table, /* in: table */
1238
dict_foreign_t* foreign,/* in: foreign */
1239
trx_t* trx) /* in: transaction */
1242
FILE* ef = dict_foreign_err_file;
1244
error = que_eval_sql(info, sql, FALSE, trx);
1246
if (error == DB_DUPLICATE_KEY) {
1247
mutex_enter(&dict_foreign_err_mutex);
1249
ut_print_timestamp(ef);
1250
fputs(" Error in foreign key constraint creation for table ",
1252
ut_print_name(ef, trx, TRUE, table->name);
1253
fputs(".\nA foreign key constraint of name ", ef);
1254
ut_print_name(ef, trx, FALSE, foreign->id);
1255
fputs("\nalready exists."
1256
" (Note that internally InnoDB adds 'databasename/'\n"
1257
"in front of the user-defined constraint name).\n",
1259
fputs("Note that InnoDB's FOREIGN KEY system tables store\n"
1260
"constraint names as case-insensitive, with the\n"
1261
"MySQL standard latin1_swedish_ci collation. If you\n"
1262
"create tables or databases whose names differ only in\n"
1263
"the character case, then collisions in constraint\n"
1264
"names can occur. Workaround: name your constraints\n"
1265
"explicitly with unique names.\n",
1268
mutex_exit(&dict_foreign_err_mutex);
1273
if (error != DB_SUCCESS) {
1275
"InnoDB: Foreign key constraint creation failed:\n"
1276
"InnoDB: internal error number %lu\n", (ulong) error);
1278
mutex_enter(&dict_foreign_err_mutex);
1279
ut_print_timestamp(ef);
1280
fputs(" Internal error in foreign key constraint creation"
1282
ut_print_name(ef, trx, TRUE, table->name);
1284
"See the MySQL .err log in the datadir"
1285
" for more information.\n", ef);
1286
mutex_exit(&dict_foreign_err_mutex);
1294
/************************************************************************
1295
Add a single foreign key field definition to the data dictionary tables in
1299
dict_create_add_foreign_field_to_dictionary(
1300
/*========================================*/
1301
/* out: error code or DB_SUCCESS */
1302
ulint field_nr, /* in: foreign field number */
1303
dict_table_t* table, /* in: table */
1304
dict_foreign_t* foreign, /* in: foreign */
1305
trx_t* trx) /* in: transaction */
1307
pars_info_t* info = pars_info_create();
1309
pars_info_add_str_literal(info, "id", foreign->id);
1311
pars_info_add_int4_literal(info, "pos", field_nr);
1313
pars_info_add_str_literal(info, "for_col_name",
1314
foreign->foreign_col_names[field_nr]);
1316
pars_info_add_str_literal(info, "ref_col_name",
1317
foreign->referenced_col_names[field_nr]);
1319
return(dict_foreign_eval_sql(
1321
"PROCEDURE P () IS\n"
1323
"INSERT INTO SYS_FOREIGN_COLS VALUES"
1324
"(:id, :pos, :for_col_name, :ref_col_name);\n"
1326
table, foreign, trx));
1329
/************************************************************************
1330
Add a single foreign key definition to the data dictionary tables in the
1331
database. We also generate names to constraints that were not named by the
1332
user. A generated constraint has a name of the format
1333
databasename/tablename_ibfk_<number>, where the numbers start from 1, and
1334
are given locally for this table, that is, the number is not global, as in
1335
the old format constraints < 4.0.18 it used to be. */
1338
dict_create_add_foreign_to_dictionary(
1339
/*==================================*/
1340
/* out: error code or DB_SUCCESS */
1341
ulint* id_nr, /* in/out: number to use in id generation;
1342
incremented if used */
1343
dict_table_t* table, /* in: table */
1344
dict_foreign_t* foreign,/* in: foreign */
1345
trx_t* trx) /* in: transaction */
1350
pars_info_t* info = pars_info_create();
1352
if (foreign->id == NULL) {
1353
/* Generate a new constraint id */
1354
ulint namelen = strlen(table->name);
1355
char* id = mem_heap_alloc(foreign->heap, namelen + 20);
1356
/* no overflow if number < 1e13 */
1357
sprintf(id, "%s_ibfk_%lu", table->name, (ulong) (*id_nr)++);
1361
pars_info_add_str_literal(info, "id", foreign->id);
1363
pars_info_add_str_literal(info, "for_name", table->name);
1365
pars_info_add_str_literal(info, "ref_name",
1366
foreign->referenced_table_name);
1368
pars_info_add_int4_literal(info, "n_cols",
1369
foreign->n_fields + (foreign->type << 24));
1371
error = dict_foreign_eval_sql(info,
1372
"PROCEDURE P () IS\n"
1374
"INSERT INTO SYS_FOREIGN VALUES"
1375
"(:id, :for_name, :ref_name, :n_cols);\n"
1377
, table, foreign, trx);
1379
if (error != DB_SUCCESS) {
1384
for (i = 0; i < foreign->n_fields; i++) {
1385
error = dict_create_add_foreign_field_to_dictionary(
1386
i, table, foreign, trx);
1388
if (error != DB_SUCCESS) {
1394
error = dict_foreign_eval_sql(NULL,
1395
"PROCEDURE P () IS\n"
1399
, table, foreign, trx);
1404
/************************************************************************
1405
Adds foreign key definitions to data dictionary tables in the database. */
1408
dict_create_add_foreigns_to_dictionary(
1409
/*===================================*/
1410
/* out: error code or DB_SUCCESS */
1411
ulint start_id,/* in: if we are actually doing ALTER TABLE
1412
ADD CONSTRAINT, we want to generate constraint
1413
numbers which are bigger than in the table so
1414
far; we number the constraints from
1415
start_id + 1 up; start_id should be set to 0 if
1416
we are creating a new table, or if the table
1417
so far has no constraints for which the name
1418
was generated here */
1419
dict_table_t* table, /* in: table */
1420
trx_t* trx) /* in: transaction */
1422
dict_foreign_t* foreign;
1423
ulint number = start_id + 1;
1426
ut_ad(mutex_own(&(dict_sys->mutex)));
1428
if (NULL == dict_table_get_low("SYS_FOREIGN")) {
1430
"InnoDB: table SYS_FOREIGN not found"
1431
" in internal data dictionary\n");
1436
for (foreign = UT_LIST_GET_FIRST(table->foreign_list);
1438
foreign = UT_LIST_GET_NEXT(foreign_list, foreign)) {
1440
error = dict_create_add_foreign_to_dictionary(&number, table,
1443
if (error != DB_SUCCESS) {