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
@file dict/dict0crea.c
21
Database object creation
23
Created 1/8/1996 Heikki Tuuri
24
*******************************************************/
26
#include "dict0crea.h"
29
#include "dict0crea.ic"
34
#include "page0page.h"
35
#include "mach0data.h"
36
#include "dict0boot.h"
37
#include "dict0dict.h"
40
#include "row0mysql.h"
41
#include "pars0pars.h"
46
/*****************************************************************//**
47
Based on a table object, this function builds the entry to be inserted
48
in the SYS_TABLES system table.
49
@return the tuple which should be inserted */
52
dict_create_sys_tables_tuple(
53
/*=========================*/
54
dict_table_t* table, /*!< in: table */
55
mem_heap_t* heap) /*!< in: memory heap from which the memory for
56
the built tuple is allocated */
58
dict_table_t* sys_tables;
65
sys_tables = dict_sys->sys_tables;
67
entry = dtuple_create(heap, 8 + DATA_N_SYS_COLS);
69
dict_table_copy_types(entry, sys_tables);
71
/* 0: NAME -----------------------------*/
72
dfield = dtuple_get_nth_field(entry, 0);
74
dfield_set_data(dfield, table->name, ut_strlen(table->name));
75
/* 3: ID -------------------------------*/
76
dfield = dtuple_get_nth_field(entry, 1);
78
ptr = mem_heap_alloc(heap, 8);
79
mach_write_to_8(ptr, table->id);
81
dfield_set_data(dfield, ptr, 8);
82
/* 4: N_COLS ---------------------------*/
83
dfield = dtuple_get_nth_field(entry, 2);
85
#if DICT_TF_COMPACT != 1
89
ptr = mem_heap_alloc(heap, 4);
90
mach_write_to_4(ptr, table->n_def
91
| ((table->flags & DICT_TF_COMPACT) << 31));
92
dfield_set_data(dfield, ptr, 4);
93
/* 5: TYPE -----------------------------*/
94
dfield = dtuple_get_nth_field(entry, 3);
96
ptr = mem_heap_alloc(heap, 4);
97
if (table->flags & ~DICT_TF_COMPACT) {
98
ut_a(table->flags & DICT_TF_COMPACT);
99
ut_a(dict_table_get_format(table) >= DICT_TF_FORMAT_ZIP);
100
ut_a((table->flags & DICT_TF_ZSSIZE_MASK)
101
<= (DICT_TF_ZSSIZE_MAX << DICT_TF_ZSSIZE_SHIFT));
102
ut_a(!(table->flags & (~0 << DICT_TF_BITS)));
103
mach_write_to_4(ptr, table->flags);
105
mach_write_to_4(ptr, DICT_TABLE_ORDINARY);
108
dfield_set_data(dfield, ptr, 4);
109
/* 6: MIX_ID (obsolete) ---------------------------*/
110
dfield = dtuple_get_nth_field(entry, 4);
112
ptr = mem_heap_zalloc(heap, 8);
114
dfield_set_data(dfield, ptr, 8);
115
/* 7: MIX_LEN (obsolete) --------------------------*/
117
dfield = dtuple_get_nth_field(entry, 5);
119
ptr = mem_heap_zalloc(heap, 4);
121
dfield_set_data(dfield, ptr, 4);
122
/* 8: CLUSTER_NAME ---------------------*/
123
dfield = dtuple_get_nth_field(entry, 6);
124
dfield_set_null(dfield); /* not supported */
126
/* 9: SPACE ----------------------------*/
127
dfield = dtuple_get_nth_field(entry, 7);
129
ptr = mem_heap_alloc(heap, 4);
130
mach_write_to_4(ptr, table->space);
132
dfield_set_data(dfield, ptr, 4);
133
/*----------------------------------*/
138
/*****************************************************************//**
139
Based on a table object, this function builds the entry to be inserted
140
in the SYS_COLUMNS system table.
141
@return the tuple which should be inserted */
144
dict_create_sys_columns_tuple(
145
/*==========================*/
146
dict_table_t* table, /*!< in: table */
147
ulint i, /*!< in: column number */
148
mem_heap_t* heap) /*!< in: memory heap from which the memory for
149
the built tuple is allocated */
151
dict_table_t* sys_columns;
153
const dict_col_t* column;
156
const char* col_name;
158
ut_ad(table && heap);
160
column = dict_table_get_nth_col(table, i);
162
sys_columns = dict_sys->sys_columns;
164
entry = dtuple_create(heap, 7 + DATA_N_SYS_COLS);
166
dict_table_copy_types(entry, sys_columns);
168
/* 0: TABLE_ID -----------------------*/
169
dfield = dtuple_get_nth_field(entry, 0);
171
ptr = mem_heap_alloc(heap, 8);
172
mach_write_to_8(ptr, table->id);
174
dfield_set_data(dfield, ptr, 8);
175
/* 1: POS ----------------------------*/
176
dfield = dtuple_get_nth_field(entry, 1);
178
ptr = mem_heap_alloc(heap, 4);
179
mach_write_to_4(ptr, i);
181
dfield_set_data(dfield, ptr, 4);
182
/* 4: NAME ---------------------------*/
183
dfield = dtuple_get_nth_field(entry, 2);
185
col_name = dict_table_get_col_name(table, i);
186
dfield_set_data(dfield, col_name, ut_strlen(col_name));
187
/* 5: MTYPE --------------------------*/
188
dfield = dtuple_get_nth_field(entry, 3);
190
ptr = mem_heap_alloc(heap, 4);
191
mach_write_to_4(ptr, column->mtype);
193
dfield_set_data(dfield, ptr, 4);
194
/* 6: PRTYPE -------------------------*/
195
dfield = dtuple_get_nth_field(entry, 4);
197
ptr = mem_heap_alloc(heap, 4);
198
mach_write_to_4(ptr, column->prtype);
200
dfield_set_data(dfield, ptr, 4);
201
/* 7: LEN ----------------------------*/
202
dfield = dtuple_get_nth_field(entry, 5);
204
ptr = mem_heap_alloc(heap, 4);
205
mach_write_to_4(ptr, column->len);
207
dfield_set_data(dfield, ptr, 4);
208
/* 8: PREC ---------------------------*/
209
dfield = dtuple_get_nth_field(entry, 6);
211
ptr = mem_heap_alloc(heap, 4);
212
mach_write_to_4(ptr, 0/* unused */);
214
dfield_set_data(dfield, ptr, 4);
215
/*---------------------------------*/
220
/***************************************************************//**
221
Builds a table definition to insert.
222
@return DB_SUCCESS or error code */
225
dict_build_table_def_step(
226
/*======================*/
227
que_thr_t* thr, /*!< in: query thread */
228
tab_node_t* node) /*!< in: table create node */
233
const char* path_or_name;
237
ut_ad(mutex_own(&(dict_sys->mutex)));
241
table->id = dict_hdr_get_new_id(DICT_HDR_TABLE_ID);
243
thr_get_trx(thr)->table_id = table->id;
245
if (srv_file_per_table) {
246
/* We create a new single-table tablespace for the table.
247
We initially let it be 4 pages:
248
- page 0 is the fsp header and an extent descriptor page,
249
- page 1 is an ibuf bitmap page,
250
- page 2 is the first inode page,
251
- page 3 will contain the root of the clustered index of the
252
table we create here. */
254
ulint space = 0; /* reset to zero for the call below */
256
if (table->dir_path_of_temp_table) {
257
/* We place tables created with CREATE TEMPORARY
258
TABLE in the tmp dir of mysqld server */
260
path_or_name = table->dir_path_of_temp_table;
263
path_or_name = table->name;
267
ut_ad(dict_table_get_format(table) <= DICT_TF_FORMAT_MAX);
268
ut_ad(!dict_table_zip_size(table)
269
|| dict_table_get_format(table) >= DICT_TF_FORMAT_ZIP);
271
error = fil_create_new_single_table_tablespace(
272
&space, path_or_name, is_path,
273
table->flags == DICT_TF_COMPACT ? 0 : table->flags,
274
FIL_IBD_FILE_INITIAL_SIZE);
275
table->space = (unsigned int) space;
277
if (error != DB_SUCCESS) {
284
fsp_header_init(table->space, FIL_IBD_FILE_INITIAL_SIZE, &mtr);
288
/* Create in the system tablespace: disallow new features */
289
table->flags &= DICT_TF_COMPACT;
292
row = dict_create_sys_tables_tuple(table, node->heap);
294
ins_node_set_new_row(node->tab_def, row);
299
/***************************************************************//**
300
Builds a column definition to insert.
301
@return DB_SUCCESS */
304
dict_build_col_def_step(
305
/*====================*/
306
tab_node_t* node) /*!< in: table create node */
310
row = dict_create_sys_columns_tuple(node->table, node->col_no,
312
ins_node_set_new_row(node->col_def, row);
317
/*****************************************************************//**
318
Based on an index object, this function builds the entry to be inserted
319
in the SYS_INDEXES system table.
320
@return the tuple which should be inserted */
323
dict_create_sys_indexes_tuple(
324
/*==========================*/
325
dict_index_t* index, /*!< in: index */
326
mem_heap_t* heap) /*!< in: memory heap from which the memory for
327
the built tuple is allocated */
329
dict_table_t* sys_indexes;
335
ut_ad(mutex_own(&(dict_sys->mutex)));
336
ut_ad(index && heap);
338
sys_indexes = dict_sys->sys_indexes;
340
table = dict_table_get_low(index->table_name);
342
entry = dtuple_create(heap, 7 + DATA_N_SYS_COLS);
344
dict_table_copy_types(entry, sys_indexes);
346
/* 0: TABLE_ID -----------------------*/
347
dfield = dtuple_get_nth_field(entry, 0);
349
ptr = mem_heap_alloc(heap, 8);
350
mach_write_to_8(ptr, table->id);
352
dfield_set_data(dfield, ptr, 8);
353
/* 1: ID ----------------------------*/
354
dfield = dtuple_get_nth_field(entry, 1);
356
ptr = mem_heap_alloc(heap, 8);
357
mach_write_to_8(ptr, index->id);
359
dfield_set_data(dfield, ptr, 8);
360
/* 4: NAME --------------------------*/
361
dfield = dtuple_get_nth_field(entry, 2);
363
dfield_set_data(dfield, index->name, ut_strlen(index->name));
364
/* 5: N_FIELDS ----------------------*/
365
dfield = dtuple_get_nth_field(entry, 3);
367
ptr = mem_heap_alloc(heap, 4);
368
mach_write_to_4(ptr, index->n_fields);
370
dfield_set_data(dfield, ptr, 4);
371
/* 6: TYPE --------------------------*/
372
dfield = dtuple_get_nth_field(entry, 4);
374
ptr = mem_heap_alloc(heap, 4);
375
mach_write_to_4(ptr, index->type);
377
dfield_set_data(dfield, ptr, 4);
378
/* 7: SPACE --------------------------*/
380
#if DICT_SYS_INDEXES_SPACE_NO_FIELD != 7
381
#error "DICT_SYS_INDEXES_SPACE_NO_FIELD != 7"
384
dfield = dtuple_get_nth_field(entry, 5);
386
ptr = mem_heap_alloc(heap, 4);
387
mach_write_to_4(ptr, index->space);
389
dfield_set_data(dfield, ptr, 4);
390
/* 8: PAGE_NO --------------------------*/
392
#if DICT_SYS_INDEXES_PAGE_NO_FIELD != 8
393
#error "DICT_SYS_INDEXES_PAGE_NO_FIELD != 8"
396
dfield = dtuple_get_nth_field(entry, 6);
398
ptr = mem_heap_alloc(heap, 4);
399
mach_write_to_4(ptr, FIL_NULL);
401
dfield_set_data(dfield, ptr, 4);
402
/*--------------------------------*/
407
/*****************************************************************//**
408
Based on an index object, this function builds the entry to be inserted
409
in the SYS_FIELDS system table.
410
@return the tuple which should be inserted */
413
dict_create_sys_fields_tuple(
414
/*=========================*/
415
dict_index_t* index, /*!< in: index */
416
ulint i, /*!< in: field number */
417
mem_heap_t* heap) /*!< in: memory heap from which the memory for
418
the built tuple is allocated */
420
dict_table_t* sys_fields;
425
ibool index_contains_column_prefix_field = FALSE;
428
ut_ad(index && heap);
430
for (j = 0; j < index->n_fields; j++) {
431
if (dict_index_get_nth_field(index, j)->prefix_len > 0) {
432
index_contains_column_prefix_field = TRUE;
437
field = dict_index_get_nth_field(index, i);
439
sys_fields = dict_sys->sys_fields;
441
entry = dtuple_create(heap, 3 + DATA_N_SYS_COLS);
443
dict_table_copy_types(entry, sys_fields);
445
/* 0: INDEX_ID -----------------------*/
446
dfield = dtuple_get_nth_field(entry, 0);
448
ptr = mem_heap_alloc(heap, 8);
449
mach_write_to_8(ptr, index->id);
451
dfield_set_data(dfield, ptr, 8);
452
/* 1: POS + PREFIX LENGTH ----------------------------*/
454
dfield = dtuple_get_nth_field(entry, 1);
456
ptr = mem_heap_alloc(heap, 4);
458
if (index_contains_column_prefix_field) {
459
/* If there are column prefix fields in the index, then
460
we store the number of the field to the 2 HIGH bytes
461
and the prefix length to the 2 low bytes, */
463
mach_write_to_4(ptr, (i << 16) + field->prefix_len);
465
/* Else we store the number of the field to the 2 LOW bytes.
466
This is to keep the storage format compatible with
467
InnoDB versions < 4.0.14. */
469
mach_write_to_4(ptr, i);
472
dfield_set_data(dfield, ptr, 4);
473
/* 4: COL_NAME -------------------------*/
474
dfield = dtuple_get_nth_field(entry, 2);
476
dfield_set_data(dfield, field->name,
477
ut_strlen(field->name));
478
/*---------------------------------*/
483
/*****************************************************************//**
484
Creates the tuple with which the index entry is searched for writing the index
485
tree root page number, if such a tree is created.
486
@return the tuple for search */
489
dict_create_search_tuple(
490
/*=====================*/
491
const dtuple_t* tuple, /*!< in: the tuple inserted in the SYS_INDEXES
493
mem_heap_t* heap) /*!< in: memory heap from which the memory for
494
the built tuple is allocated */
496
dtuple_t* search_tuple;
497
const dfield_t* field1;
500
ut_ad(tuple && heap);
502
search_tuple = dtuple_create(heap, 2);
504
field1 = dtuple_get_nth_field(tuple, 0);
505
field2 = dtuple_get_nth_field(search_tuple, 0);
507
dfield_copy(field2, field1);
509
field1 = dtuple_get_nth_field(tuple, 1);
510
field2 = dtuple_get_nth_field(search_tuple, 1);
512
dfield_copy(field2, field1);
514
ut_ad(dtuple_validate(search_tuple));
516
return(search_tuple);
519
/***************************************************************//**
520
Builds an index definition row to insert.
521
@return DB_SUCCESS or error code */
524
dict_build_index_def_step(
525
/*======================*/
526
que_thr_t* thr, /*!< in: query thread */
527
ind_node_t* node) /*!< in: index create node */
534
ut_ad(mutex_own(&(dict_sys->mutex)));
536
trx = thr_get_trx(thr);
540
table = dict_table_get_low(index->table_name);
543
return(DB_TABLE_NOT_FOUND);
546
trx->table_id = table->id;
550
ut_ad((UT_LIST_GET_LEN(table->indexes) > 0)
551
|| dict_index_is_clust(index));
553
index->id = dict_hdr_get_new_id(DICT_HDR_INDEX_ID);
555
/* Inherit the space id from the table; we store all indexes of a
556
table in the same tablespace */
558
index->space = table->space;
559
node->page_no = FIL_NULL;
560
row = dict_create_sys_indexes_tuple(index, node->heap);
563
ins_node_set_new_row(node->ind_def, row);
565
/* Note that the index was created by this transaction. */
566
index->trx_id = (ib_uint64_t) ut_conv_dulint_to_longlong(trx->id);
571
/***************************************************************//**
572
Builds a field definition row to insert.
573
@return DB_SUCCESS */
576
dict_build_field_def_step(
577
/*======================*/
578
ind_node_t* node) /*!< in: index create node */
585
row = dict_create_sys_fields_tuple(index, node->field_no, node->heap);
587
ins_node_set_new_row(node->field_def, row);
592
/***************************************************************//**
593
Creates an index tree for the index if it is not a member of a cluster.
594
@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
597
dict_create_index_tree_step(
598
/*========================*/
599
ind_node_t* node) /*!< in: index create node */
602
dict_table_t* sys_indexes;
604
dtuple_t* search_tuple;
608
ut_ad(mutex_own(&(dict_sys->mutex)));
613
sys_indexes = dict_sys->sys_indexes;
615
/* Run a mini-transaction in which the index tree is allocated for
616
the index and its root address is written to the index entry in
621
search_tuple = dict_create_search_tuple(node->ind_row, node->heap);
623
btr_pcur_open(UT_LIST_GET_FIRST(sys_indexes->indexes),
624
search_tuple, PAGE_CUR_L, BTR_MODIFY_LEAF,
627
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
629
node->page_no = btr_create(index->type, index->space,
630
dict_table_zip_size(index->table),
631
index->id, index, &mtr);
632
/* printf("Created a new index tree in space %lu root page %lu\n",
633
index->space, index->page_no); */
635
page_rec_write_index_page_no(btr_pcur_get_rec(&pcur),
636
DICT_SYS_INDEXES_PAGE_NO_FIELD,
637
node->page_no, &mtr);
638
btr_pcur_close(&pcur);
641
if (node->page_no == FIL_NULL) {
643
return(DB_OUT_OF_FILE_SPACE);
649
/*******************************************************************//**
650
Drops the index tree associated with a row in SYS_INDEXES table. */
653
dict_drop_index_tree(
654
/*=================*/
655
rec_t* rec, /*!< in/out: record in the clustered index
656
of SYS_INDEXES table */
657
mtr_t* mtr) /*!< in: mtr having the latch on the record page */
665
ut_ad(mutex_own(&(dict_sys->mutex)));
666
ut_a(!dict_table_is_comp(dict_sys->sys_indexes));
667
ptr = rec_get_nth_field_old(rec, DICT_SYS_INDEXES_PAGE_NO_FIELD, &len);
671
root_page_no = mtr_read_ulint(ptr, MLOG_4BYTES, mtr);
673
if (root_page_no == FIL_NULL) {
674
/* The tree has already been freed */
679
ptr = rec_get_nth_field_old(rec,
680
DICT_SYS_INDEXES_SPACE_NO_FIELD, &len);
684
space = mtr_read_ulint(ptr, MLOG_4BYTES, mtr);
685
zip_size = fil_space_get_zip_size(space);
687
if (UNIV_UNLIKELY(zip_size == ULINT_UNDEFINED)) {
688
/* It is a single table tablespace and the .ibd file is
689
missing: do nothing */
694
/* We free all the pages but the root page first; this operation
695
may span several mini-transactions */
697
btr_free_but_not_root(space, zip_size, root_page_no);
699
/* Then we free the root page in the same mini-transaction where
700
we write FIL_NULL to the appropriate field in the SYS_INDEXES
701
record: this mini-transaction marks the B-tree totally freed */
703
/* printf("Dropping index tree in space %lu root page %lu\n", space,
705
btr_free_root(space, zip_size, root_page_no, mtr);
707
page_rec_write_index_page_no(rec,
708
DICT_SYS_INDEXES_PAGE_NO_FIELD,
712
/*******************************************************************//**
713
Truncates the index tree associated with a row in SYS_INDEXES table.
714
@return new root page number, or FIL_NULL on failure */
717
dict_truncate_index_tree(
718
/*=====================*/
719
dict_table_t* table, /*!< in: the table the index belongs to */
720
ulint space, /*!< in: 0=truncate,
721
nonzero=create the index tree in the
723
btr_pcur_t* pcur, /*!< in/out: persistent cursor pointing to
724
record in the clustered index of
725
SYS_INDEXES table. The cursor may be
726
repositioned in this call. */
727
mtr_t* mtr) /*!< in: mtr having the latch
728
on the record page. The mtr may be
729
committed and restarted in this call. */
741
ut_ad(mutex_own(&(dict_sys->mutex)));
742
ut_a(!dict_table_is_comp(dict_sys->sys_indexes));
743
rec = btr_pcur_get_rec(pcur);
744
ptr = rec_get_nth_field_old(rec, DICT_SYS_INDEXES_PAGE_NO_FIELD, &len);
748
root_page_no = mtr_read_ulint(ptr, MLOG_4BYTES, mtr);
750
if (drop && root_page_no == FIL_NULL) {
751
/* The tree has been freed. */
753
ut_print_timestamp(stderr);
754
fprintf(stderr, " InnoDB: Trying to TRUNCATE"
755
" a missing index of table %s!\n", table->name);
759
ptr = rec_get_nth_field_old(rec,
760
DICT_SYS_INDEXES_SPACE_NO_FIELD, &len);
765
space = mtr_read_ulint(ptr, MLOG_4BYTES, mtr);
768
zip_size = fil_space_get_zip_size(space);
770
if (UNIV_UNLIKELY(zip_size == ULINT_UNDEFINED)) {
771
/* It is a single table tablespace and the .ibd file is
772
missing: do nothing */
774
ut_print_timestamp(stderr);
775
fprintf(stderr, " InnoDB: Trying to TRUNCATE"
776
" a missing .ibd file of table %s!\n", table->name);
780
ptr = rec_get_nth_field_old(rec,
781
DICT_SYS_INDEXES_TYPE_FIELD, &len);
783
type = mach_read_from_4(ptr);
785
ptr = rec_get_nth_field_old(rec, 1, &len);
787
index_id = mach_read_from_8(ptr);
794
/* We free all the pages but the root page first; this operation
795
may span several mini-transactions */
797
btr_free_but_not_root(space, zip_size, root_page_no);
799
/* Then we free the root page in the same mini-transaction where
800
we create the b-tree and write its new root page number to the
801
appropriate field in the SYS_INDEXES record: this mini-transaction
802
marks the B-tree totally truncated */
804
btr_page_get(space, zip_size, root_page_no, RW_X_LATCH, mtr);
806
btr_free_root(space, zip_size, root_page_no, mtr);
808
/* We will temporarily write FIL_NULL to the PAGE_NO field
809
in SYS_INDEXES, so that the database will not get into an
810
inconsistent state in case it crashes between the mtr_commit()
811
below and the following mtr_commit() call. */
812
page_rec_write_index_page_no(rec, DICT_SYS_INDEXES_PAGE_NO_FIELD,
815
/* We will need to commit the mini-transaction in order to avoid
816
deadlocks in the btr_create() call, because otherwise we would
817
be freeing and allocating pages in the same mini-transaction. */
818
btr_pcur_store_position(pcur, mtr);
822
btr_pcur_restore_position(BTR_MODIFY_LEAF, pcur, mtr);
824
/* Find the index corresponding to this SYS_INDEXES record. */
825
for (index = UT_LIST_GET_FIRST(table->indexes);
827
index = UT_LIST_GET_NEXT(indexes, index)) {
828
if (!ut_dulint_cmp(index->id, index_id)) {
829
root_page_no = btr_create(type, space, zip_size,
830
index_id, index, mtr);
831
index->page = (unsigned int) root_page_no;
832
return(root_page_no);
836
ut_print_timestamp(stderr);
838
" InnoDB: Index %lu %lu of table %s is missing\n"
839
"InnoDB: from the data dictionary during TRUNCATE!\n",
840
ut_dulint_get_high(index_id),
841
ut_dulint_get_low(index_id),
847
/*********************************************************************//**
848
Creates a table create graph.
849
@return own: table create node */
852
tab_create_graph_create(
853
/*====================*/
854
dict_table_t* table, /*!< in: table to create, built as a memory data
856
mem_heap_t* heap) /*!< in: heap where created */
860
node = mem_heap_alloc(heap, sizeof(tab_node_t));
862
node->common.type = QUE_NODE_CREATE_TABLE;
866
node->state = TABLE_BUILD_TABLE_DEF;
867
node->heap = mem_heap_create(256);
869
node->tab_def = ins_node_create(INS_DIRECT, dict_sys->sys_tables,
871
node->tab_def->common.parent = node;
873
node->col_def = ins_node_create(INS_DIRECT, dict_sys->sys_columns,
875
node->col_def->common.parent = node;
877
node->commit_node = commit_node_create(heap);
878
node->commit_node->common.parent = node;
883
/*********************************************************************//**
884
Creates an index create graph.
885
@return own: index create node */
888
ind_create_graph_create(
889
/*====================*/
890
dict_index_t* index, /*!< in: index to create, built as a memory data
892
mem_heap_t* heap) /*!< in: heap where created */
896
node = mem_heap_alloc(heap, sizeof(ind_node_t));
898
node->common.type = QUE_NODE_CREATE_INDEX;
902
node->state = INDEX_BUILD_INDEX_DEF;
903
node->page_no = FIL_NULL;
904
node->heap = mem_heap_create(256);
906
node->ind_def = ins_node_create(INS_DIRECT,
907
dict_sys->sys_indexes, heap);
908
node->ind_def->common.parent = node;
910
node->field_def = ins_node_create(INS_DIRECT,
911
dict_sys->sys_fields, heap);
912
node->field_def->common.parent = node;
914
node->commit_node = commit_node_create(heap);
915
node->commit_node->common.parent = node;
920
/***********************************************************//**
921
Creates a table. This is a high-level function used in SQL execution graphs.
922
@return query thread to run next or NULL */
925
dict_create_table_step(
926
/*===================*/
927
que_thr_t* thr) /*!< in: query thread */
930
ulint err = DB_ERROR;
934
ut_ad(mutex_own(&(dict_sys->mutex)));
936
trx = thr_get_trx(thr);
938
node = thr->run_node;
940
ut_ad(que_node_get_type(node) == QUE_NODE_CREATE_TABLE);
942
if (thr->prev_node == que_node_get_parent(node)) {
943
node->state = TABLE_BUILD_TABLE_DEF;
946
if (node->state == TABLE_BUILD_TABLE_DEF) {
948
/* DO THE CHECKS OF THE CONSISTENCY CONSTRAINTS HERE */
950
err = dict_build_table_def_step(thr, node);
952
if (err != DB_SUCCESS) {
957
node->state = TABLE_BUILD_COL_DEF;
960
thr->run_node = node->tab_def;
965
if (node->state == TABLE_BUILD_COL_DEF) {
967
if (node->col_no < (node->table)->n_def) {
969
err = dict_build_col_def_step(node);
971
if (err != DB_SUCCESS) {
978
thr->run_node = node->col_def;
982
node->state = TABLE_COMMIT_WORK;
986
if (node->state == TABLE_COMMIT_WORK) {
988
/* Table was correctly defined: do NOT commit the transaction
989
(CREATE TABLE does NOT do an implicit commit of the current
992
node->state = TABLE_ADD_TO_CACHE;
994
/* thr->run_node = node->commit_node;
999
if (node->state == TABLE_ADD_TO_CACHE) {
1001
dict_table_add_to_cache(node->table, node->heap);
1007
trx->error_state = err;
1009
if (err == DB_SUCCESS) {
1010
/* Ok: do nothing */
1012
} else if (err == DB_LOCK_WAIT) {
1016
/* SQL error detected */
1021
thr->run_node = que_node_get_parent(node);
1026
/***********************************************************//**
1027
Creates an index. This is a high-level function used in SQL execution
1029
@return query thread to run next or NULL */
1032
dict_create_index_step(
1033
/*===================*/
1034
que_thr_t* thr) /*!< in: query thread */
1037
ulint err = DB_ERROR;
1041
ut_ad(mutex_own(&(dict_sys->mutex)));
1043
trx = thr_get_trx(thr);
1045
node = thr->run_node;
1047
ut_ad(que_node_get_type(node) == QUE_NODE_CREATE_INDEX);
1049
if (thr->prev_node == que_node_get_parent(node)) {
1050
node->state = INDEX_BUILD_INDEX_DEF;
1053
if (node->state == INDEX_BUILD_INDEX_DEF) {
1054
/* DO THE CHECKS OF THE CONSISTENCY CONSTRAINTS HERE */
1055
err = dict_build_index_def_step(thr, node);
1057
if (err != DB_SUCCESS) {
1062
node->state = INDEX_BUILD_FIELD_DEF;
1065
thr->run_node = node->ind_def;
1070
if (node->state == INDEX_BUILD_FIELD_DEF) {
1072
if (node->field_no < (node->index)->n_fields) {
1074
err = dict_build_field_def_step(node);
1076
if (err != DB_SUCCESS) {
1083
thr->run_node = node->field_def;
1087
node->state = INDEX_ADD_TO_CACHE;
1091
if (node->state == INDEX_ADD_TO_CACHE) {
1093
dulint index_id = node->index->id;
1095
err = dict_index_add_to_cache(node->table, node->index,
1098
node->index = dict_index_get_if_in_cache_low(index_id);
1099
ut_a(!node->index == (err != DB_SUCCESS));
1101
if (err != DB_SUCCESS) {
1106
node->state = INDEX_CREATE_INDEX_TREE;
1109
if (node->state == INDEX_CREATE_INDEX_TREE) {
1111
err = dict_create_index_tree_step(node);
1113
if (err != DB_SUCCESS) {
1114
dict_index_remove_from_cache(node->table, node->index);
1120
node->index->page = node->page_no;
1121
node->state = INDEX_COMMIT_WORK;
1124
if (node->state == INDEX_COMMIT_WORK) {
1126
/* Index was correctly defined: do NOT commit the transaction
1127
(CREATE INDEX does NOT currently do an implicit commit of
1128
the current transaction) */
1130
node->state = INDEX_CREATE_INDEX_TREE;
1132
/* thr->run_node = node->commit_node;
1138
trx->error_state = err;
1140
if (err == DB_SUCCESS) {
1141
/* Ok: do nothing */
1143
} else if (err == DB_LOCK_WAIT) {
1147
/* SQL error detected */
1152
thr->run_node = que_node_get_parent(node);
1157
/****************************************************************//**
1158
Creates the foreign key constraints system tables inside InnoDB
1159
at database creation or database start if they are not found or are
1160
not of the right form.
1161
@return DB_SUCCESS or error code */
1164
dict_create_or_check_foreign_constraint_tables(void)
1165
/*================================================*/
1167
dict_table_t* table1;
1168
dict_table_t* table2;
1172
mutex_enter(&(dict_sys->mutex));
1174
table1 = dict_table_get_low("SYS_FOREIGN");
1175
table2 = dict_table_get_low("SYS_FOREIGN_COLS");
1177
if (table1 && table2
1178
&& UT_LIST_GET_LEN(table1->indexes) == 3
1179
&& UT_LIST_GET_LEN(table2->indexes) == 1) {
1181
/* Foreign constraint system tables have already been
1182
created, and they are ok */
1184
mutex_exit(&(dict_sys->mutex));
1189
mutex_exit(&(dict_sys->mutex));
1191
trx = trx_allocate_for_mysql();
1193
trx->op_info = "creating foreign key sys tables";
1195
row_mysql_lock_data_dictionary(trx);
1199
"InnoDB: dropping incompletely created"
1200
" SYS_FOREIGN table\n");
1201
row_drop_table_for_mysql("SYS_FOREIGN", trx, TRUE);
1206
"InnoDB: dropping incompletely created"
1207
" SYS_FOREIGN_COLS table\n");
1208
row_drop_table_for_mysql("SYS_FOREIGN_COLS", trx, TRUE);
1212
"InnoDB: Creating foreign key constraint system tables\n");
1214
/* NOTE: in dict_load_foreigns we use the fact that
1215
there are 2 secondary indexes on SYS_FOREIGN, and they
1216
are defined just like below */
1218
/* NOTE: when designing InnoDB's foreign key support in 2001, we made
1219
an error and made the table names and the foreign key id of type
1220
'CHAR' (internally, really a VARCHAR). We should have made the type
1221
VARBINARY, like in other InnoDB system tables, to get a clean
1224
pars_info_t *info = pars_info_create();
1225
error = que_eval_sql(info,
1226
"PROCEDURE CREATE_FOREIGN_SYS_TABLES_PROC () IS\n"
1229
"SYS_FOREIGN(ID CHAR, FOR_NAME CHAR,"
1230
" REF_NAME CHAR, N_COLS INT);\n"
1231
"CREATE UNIQUE CLUSTERED INDEX ID_IND"
1232
" ON SYS_FOREIGN (ID);\n"
1233
"CREATE INDEX FOR_IND"
1234
" ON SYS_FOREIGN (FOR_NAME);\n"
1235
"CREATE INDEX REF_IND"
1236
" ON SYS_FOREIGN (REF_NAME);\n"
1238
"SYS_FOREIGN_COLS(ID CHAR, POS INT,"
1239
" FOR_COL_NAME CHAR, REF_COL_NAME CHAR);\n"
1240
"CREATE UNIQUE CLUSTERED INDEX ID_IND"
1241
" ON SYS_FOREIGN_COLS (ID, POS);\n"
1245
if (error != DB_SUCCESS) {
1246
fprintf(stderr, "InnoDB: error %lu in creation\n",
1249
ut_a(error == DB_OUT_OF_FILE_SPACE
1250
|| error == DB_TOO_MANY_CONCURRENT_TRXS);
1253
"InnoDB: creation failed\n"
1254
"InnoDB: tablespace is full\n"
1255
"InnoDB: dropping incompletely created"
1256
" SYS_FOREIGN tables\n");
1258
row_drop_table_for_mysql("SYS_FOREIGN", trx, TRUE);
1259
row_drop_table_for_mysql("SYS_FOREIGN_COLS", trx, TRUE);
1261
error = DB_MUST_GET_MORE_FILE_SPACE;
1264
trx_commit_for_mysql(trx);
1266
row_mysql_unlock_data_dictionary(trx);
1268
trx_free_for_mysql(trx);
1270
if (error == DB_SUCCESS) {
1272
"InnoDB: Foreign key constraint system tables"
1279
/****************************************************************//**
1280
Evaluate the given foreign key SQL statement.
1281
@return error code or DB_SUCCESS */
1284
dict_foreign_eval_sql(
1285
/*==================*/
1286
pars_info_t* info, /*!< in: info struct, or NULL */
1287
const char* sql, /*!< in: SQL string to evaluate */
1288
dict_table_t* table, /*!< in: table */
1289
dict_foreign_t* foreign,/*!< in: foreign */
1290
trx_t* trx) /*!< in: transaction */
1293
FILE* ef = dict_foreign_err_file;
1295
error = que_eval_sql(info, sql, FALSE, trx);
1297
if (error == DB_DUPLICATE_KEY) {
1298
mutex_enter(&dict_foreign_err_mutex);
1300
ut_print_timestamp(ef);
1301
fputs(" Error in foreign key constraint creation for table ",
1303
ut_print_name(ef, trx, TRUE, table->name);
1304
fputs(".\nA foreign key constraint of name ", ef);
1305
ut_print_name(ef, trx, TRUE, foreign->id);
1306
fputs("\nalready exists."
1307
" (Note that internally InnoDB adds 'databasename'\n"
1308
"in front of the user-defined constraint name.)\n"
1309
"Note that InnoDB's FOREIGN KEY system tables store\n"
1310
"constraint names as case-insensitive, with the\n"
1311
"MySQL standard latin1_swedish_ci collation. If you\n"
1312
"create tables or databases whose names differ only in\n"
1313
"the character case, then collisions in constraint\n"
1314
"names can occur. Workaround: name your constraints\n"
1315
"explicitly with unique names.\n",
1318
mutex_exit(&dict_foreign_err_mutex);
1323
if (error != DB_SUCCESS) {
1325
"InnoDB: Foreign key constraint creation failed:\n"
1326
"InnoDB: internal error number %lu\n", (ulong) error);
1328
mutex_enter(&dict_foreign_err_mutex);
1329
ut_print_timestamp(ef);
1330
fputs(" Internal error in foreign key constraint creation"
1332
ut_print_name(ef, trx, TRUE, table->name);
1334
"See the MySQL .err log in the datadir"
1335
" for more information.\n", ef);
1336
mutex_exit(&dict_foreign_err_mutex);
1344
/********************************************************************//**
1345
Add a single foreign key field definition to the data dictionary tables in
1347
@return error code or DB_SUCCESS */
1350
dict_create_add_foreign_field_to_dictionary(
1351
/*========================================*/
1352
ulint field_nr, /*!< in: foreign field number */
1353
dict_table_t* table, /*!< in: table */
1354
dict_foreign_t* foreign, /*!< in: foreign */
1355
trx_t* trx) /*!< in: transaction */
1357
pars_info_t* info = pars_info_create();
1359
pars_info_add_str_literal(info, "id", foreign->id);
1361
pars_info_add_int4_literal(info, "pos", field_nr);
1363
pars_info_add_str_literal(info, "for_col_name",
1364
foreign->foreign_col_names[field_nr]);
1366
pars_info_add_str_literal(info, "ref_col_name",
1367
foreign->referenced_col_names[field_nr]);
1369
return(dict_foreign_eval_sql(
1371
"PROCEDURE P () IS\n"
1373
"INSERT INTO SYS_FOREIGN_COLS VALUES"
1374
"(:id, :pos, :for_col_name, :ref_col_name);\n"
1376
table, foreign, trx));
1379
/********************************************************************//**
1380
Add a single foreign key definition to the data dictionary tables in the
1381
database. We also generate names to constraints that were not named by the
1382
user. A generated constraint has a name of the format
1383
databasename/tablename_ibfk_<number>, where the numbers start from 1, and
1384
are given locally for this table, that is, the number is not global, as in
1385
the old format constraints < 4.0.18 it used to be.
1386
@return error code or DB_SUCCESS */
1389
dict_create_add_foreign_to_dictionary(
1390
/*==================================*/
1391
ulint* id_nr, /*!< in/out: number to use in id generation;
1392
incremented if used */
1393
dict_table_t* table, /*!< in: table */
1394
dict_foreign_t* foreign,/*!< in: foreign */
1395
trx_t* trx) /*!< in: transaction */
1400
pars_info_t* info = pars_info_create();
1402
if (foreign->id == NULL) {
1403
/* Generate a new constraint id */
1404
ulint namelen = strlen(table->name);
1405
char* id = mem_heap_alloc(foreign->heap, namelen + 20);
1406
/* no overflow if number < 1e13 */
1407
sprintf(id, "%s_ibfk_%lu", table->name, (ulong) (*id_nr)++);
1411
pars_info_add_str_literal(info, "id", foreign->id);
1413
pars_info_add_str_literal(info, "for_name", table->name);
1415
pars_info_add_str_literal(info, "ref_name",
1416
foreign->referenced_table_name);
1418
pars_info_add_int4_literal(info, "n_cols",
1419
foreign->n_fields + (foreign->type << 24));
1421
error = dict_foreign_eval_sql(info,
1422
"PROCEDURE P () IS\n"
1424
"INSERT INTO SYS_FOREIGN VALUES"
1425
"(:id, :for_name, :ref_name, :n_cols);\n"
1427
, table, foreign, trx);
1429
if (error != DB_SUCCESS) {
1434
for (i = 0; i < foreign->n_fields; i++) {
1435
error = dict_create_add_foreign_field_to_dictionary(
1436
i, table, foreign, trx);
1438
if (error != DB_SUCCESS) {
1444
error = dict_foreign_eval_sql(NULL,
1445
"PROCEDURE P () IS\n"
1449
, table, foreign, trx);
1454
/********************************************************************//**
1455
Adds foreign key definitions to data dictionary tables in the database.
1456
@return error code or DB_SUCCESS */
1459
dict_create_add_foreigns_to_dictionary(
1460
/*===================================*/
1461
ulint start_id,/*!< in: if we are actually doing ALTER TABLE
1462
ADD CONSTRAINT, we want to generate constraint
1463
numbers which are bigger than in the table so
1464
far; we number the constraints from
1465
start_id + 1 up; start_id should be set to 0 if
1466
we are creating a new table, or if the table
1467
so far has no constraints for which the name
1468
was generated here */
1469
dict_table_t* table, /*!< in: table */
1470
trx_t* trx) /*!< in: transaction */
1472
dict_foreign_t* foreign;
1473
ulint number = start_id + 1;
1476
ut_ad(mutex_own(&(dict_sys->mutex)));
1478
if (NULL == dict_table_get_low("SYS_FOREIGN")) {
1480
"InnoDB: table SYS_FOREIGN not found"
1481
" in internal data dictionary\n");
1486
for (foreign = UT_LIST_GET_FIRST(table->foreign_list);
1488
foreign = UT_LIST_GET_NEXT(foreign_list, foreign)) {
1490
error = dict_create_add_foreign_to_dictionary(&number, table,
1493
if (error != DB_SUCCESS) {