1
/*****************************************************************************
3
Copyright (C) 1996, 2010, Innobase Oy. All Rights Reserved.
5
This program is free software; you can redistribute it and/or modify it under
6
the terms of the GNU General Public License as published by the Free Software
7
Foundation; version 2 of the License.
9
This program is distributed in the hope that it will be useful, but WITHOUT
10
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
You should have received a copy of the GNU General Public License along with
14
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
15
St, Fifth Floor, Boston, MA 02110-1301 USA
17
*****************************************************************************/
19
/**************************************************//**
20
@file dict/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
const dict_table_t* table, /*!< in: table */
55
mem_heap_t* heap) /*!< in: memory heap from
56
which the memory for the built
59
dict_table_t* sys_tables;
67
sys_tables = dict_sys->sys_tables;
69
entry = dtuple_create(heap, 8 + DATA_N_SYS_COLS);
71
dict_table_copy_types(entry, sys_tables);
73
/* 0: NAME -----------------------------*/
74
dfield = dtuple_get_nth_field(entry, 0/*NAME*/);
76
dfield_set_data(dfield, table->name, ut_strlen(table->name));
77
/* 3: ID -------------------------------*/
78
dfield = dtuple_get_nth_field(entry, 1/*ID*/);
80
ptr = static_cast<unsigned char *>(mem_heap_alloc(heap, 8));
81
mach_write_to_8(ptr, table->id);
83
dfield_set_data(dfield, ptr, 8);
84
/* 4: N_COLS ---------------------------*/
85
dfield = dtuple_get_nth_field(entry, 2/*N_COLS*/);
87
#if DICT_TF_COMPACT != 1
91
ptr = static_cast<unsigned char *>(mem_heap_alloc(heap, 4));
92
mach_write_to_4(ptr, table->n_def
93
| ((table->flags & DICT_TF_COMPACT) << 31));
94
dfield_set_data(dfield, ptr, 4);
95
/* 5: TYPE -----------------------------*/
96
dfield = dtuple_get_nth_field(entry, 3/*TYPE*/);
98
ptr = static_cast<unsigned char *>(mem_heap_alloc(heap, 4));
99
if (table->flags & (~DICT_TF_COMPACT & ~(~0 << DICT_TF_BITS))) {
100
ut_a(table->flags & DICT_TF_COMPACT);
101
ut_a(dict_table_get_format(table) >= DICT_TF_FORMAT_ZIP);
102
ut_a((table->flags & DICT_TF_ZSSIZE_MASK)
103
<= (DICT_TF_ZSSIZE_MAX << DICT_TF_ZSSIZE_SHIFT));
104
ut_a(!(table->flags & (~0 << DICT_TF2_BITS)));
105
mach_write_to_4(ptr, table->flags & ~(~0 << DICT_TF_BITS));
107
mach_write_to_4(ptr, DICT_TABLE_ORDINARY);
110
dfield_set_data(dfield, ptr, 4);
111
/* 6: MIX_ID (obsolete) ---------------------------*/
112
dfield = dtuple_get_nth_field(entry, 4/*MIX_ID*/);
114
ptr = static_cast<unsigned char *>(mem_heap_zalloc(heap, 8));
116
dfield_set_data(dfield, ptr, 8);
117
/* 7: MIX_LEN (additional flags) --------------------------*/
119
dfield = dtuple_get_nth_field(entry, 5/*MIX_LEN*/);
121
ptr = static_cast<unsigned char *>(mem_heap_alloc(heap, 4));
122
mach_write_to_4(ptr, table->flags >> DICT_TF2_SHIFT);
124
dfield_set_data(dfield, ptr, 4);
125
/* 8: CLUSTER_NAME ---------------------*/
126
dfield = dtuple_get_nth_field(entry, 6/*CLUSTER_NAME*/);
127
dfield_set_null(dfield); /* not supported */
129
/* 9: SPACE ----------------------------*/
130
dfield = dtuple_get_nth_field(entry, 7/*SPACE*/);
132
ptr = static_cast<unsigned char *>(mem_heap_alloc(heap, 4));
133
mach_write_to_4(ptr, table->space);
135
dfield_set_data(dfield, ptr, 4);
136
/*----------------------------------*/
141
/*****************************************************************//**
142
Based on a table object, this function builds the entry to be inserted
143
in the SYS_COLUMNS system table.
144
@return the tuple which should be inserted */
147
dict_create_sys_columns_tuple(
148
/*==========================*/
149
const dict_table_t* table, /*!< in: table */
150
ulint i, /*!< in: column number */
151
mem_heap_t* heap) /*!< in: memory heap from
152
which the memory for the built
153
tuple is allocated */
155
dict_table_t* sys_columns;
157
const dict_col_t* column;
160
const char* col_name;
165
column = dict_table_get_nth_col(table, i);
167
sys_columns = dict_sys->sys_columns;
169
entry = dtuple_create(heap, 7 + DATA_N_SYS_COLS);
171
dict_table_copy_types(entry, sys_columns);
173
/* 0: TABLE_ID -----------------------*/
174
dfield = dtuple_get_nth_field(entry, 0/*TABLE_ID*/);
176
ptr = static_cast<unsigned char *>(mem_heap_alloc(heap, 8));
177
mach_write_to_8(ptr, table->id);
179
dfield_set_data(dfield, ptr, 8);
180
/* 1: POS ----------------------------*/
181
dfield = dtuple_get_nth_field(entry, 1/*POS*/);
183
ptr = static_cast<unsigned char *>(mem_heap_alloc(heap, 4));
184
mach_write_to_4(ptr, i);
186
dfield_set_data(dfield, ptr, 4);
187
/* 4: NAME ---------------------------*/
188
dfield = dtuple_get_nth_field(entry, 2/*NAME*/);
190
col_name = dict_table_get_col_name(table, i);
191
dfield_set_data(dfield, col_name, ut_strlen(col_name));
192
/* 5: MTYPE --------------------------*/
193
dfield = dtuple_get_nth_field(entry, 3/*MTYPE*/);
195
ptr = static_cast<unsigned char *>(mem_heap_alloc(heap, 4));
196
mach_write_to_4(ptr, column->mtype);
198
dfield_set_data(dfield, ptr, 4);
199
/* 6: PRTYPE -------------------------*/
200
dfield = dtuple_get_nth_field(entry, 4/*PRTYPE*/);
202
ptr = static_cast<unsigned char *>(mem_heap_alloc(heap, 4));
203
mach_write_to_4(ptr, column->prtype);
205
dfield_set_data(dfield, ptr, 4);
206
/* 7: LEN ----------------------------*/
207
dfield = dtuple_get_nth_field(entry, 5/*LEN*/);
209
ptr = static_cast<unsigned char *>(mem_heap_alloc(heap, 4));
210
mach_write_to_4(ptr, column->len);
212
dfield_set_data(dfield, ptr, 4);
213
/* 8: PREC ---------------------------*/
214
dfield = dtuple_get_nth_field(entry, 6/*PREC*/);
216
ptr = static_cast<unsigned char *>(mem_heap_alloc(heap, 4));
217
mach_write_to_4(ptr, 0/* unused */);
219
dfield_set_data(dfield, ptr, 4);
220
/*---------------------------------*/
225
/***************************************************************//**
226
Builds a table definition to insert.
227
@return DB_SUCCESS or error code */
230
dict_build_table_def_step(
231
/*======================*/
232
que_thr_t* thr, /*!< in: query thread */
233
tab_node_t* node) /*!< in: table create node */
239
const char* path_or_name;
243
ibool file_per_table;
245
ut_ad(mutex_own(&(dict_sys->mutex)));
249
/* Cache the global variable "srv_file_per_table" to
250
a local variable before using it. Please note
251
"srv_file_per_table" is not under dict_sys mutex
252
protection, and could be changed while executing
253
this function. So better to cache the current value
254
to a local variable, and all future reference to
255
"srv_file_per_table" should use this local variable. */
256
file_per_table = srv_file_per_table;
258
dict_hdr_get_new_id(&table->id, NULL, NULL);
260
thr_get_trx(thr)->table_id = table->id;
262
if (file_per_table) {
263
/* Get a new space id if srv_file_per_table is set */
264
dict_hdr_get_new_id(NULL, NULL, &space);
266
if (UNIV_UNLIKELY(space == ULINT_UNDEFINED)) {
270
/* We create a new single-table tablespace for the table.
271
We initially let it be 4 pages:
272
- page 0 is the fsp header and an extent descriptor page,
273
- page 1 is an ibuf bitmap page,
274
- page 2 is the first inode page,
275
- page 3 will contain the root of the clustered index of the
276
table we create here. */
278
if (table->dir_path_of_temp_table) {
279
/* We place tables created with CREATE TEMPORARY
280
TABLE in the tmp dir of mysqld server */
282
path_or_name = table->dir_path_of_temp_table;
285
path_or_name = table->name;
289
ut_ad(dict_table_get_format(table) <= DICT_TF_FORMAT_MAX);
290
ut_ad(!dict_table_zip_size(table)
291
|| dict_table_get_format(table) >= DICT_TF_FORMAT_ZIP);
293
flags = table->flags & ~(~0 << DICT_TF_BITS);
294
error = fil_create_new_single_table_tablespace(
295
space, path_or_name, is_path,
296
flags == DICT_TF_COMPACT ? 0 : flags,
297
FIL_IBD_FILE_INITIAL_SIZE);
298
table->space = (unsigned int) space;
300
if (error != DB_SUCCESS) {
307
fsp_header_init(table->space, FIL_IBD_FILE_INITIAL_SIZE, &mtr);
311
/* Create in the system tablespace: disallow new features */
312
table->flags &= (~0 << DICT_TF_BITS) | DICT_TF_COMPACT;
315
row = dict_create_sys_tables_tuple(table, node->heap);
317
ins_node_set_new_row(node->tab_def, row);
322
/***************************************************************//**
323
Builds a column definition to insert.
324
@return DB_SUCCESS */
327
dict_build_col_def_step(
328
/*====================*/
329
tab_node_t* node) /*!< in: table create node */
333
row = dict_create_sys_columns_tuple(node->table, node->col_no,
335
ins_node_set_new_row(node->col_def, row);
340
/*****************************************************************//**
341
Based on an index object, this function builds the entry to be inserted
342
in the SYS_INDEXES system table.
343
@return the tuple which should be inserted */
346
dict_create_sys_indexes_tuple(
347
/*==========================*/
348
const dict_index_t* index, /*!< in: index */
349
mem_heap_t* heap) /*!< in: memory heap from
350
which the memory for the built
351
tuple is allocated */
353
dict_table_t* sys_indexes;
359
ut_ad(mutex_own(&(dict_sys->mutex)));
363
sys_indexes = dict_sys->sys_indexes;
365
table = dict_table_get_low(index->table_name);
367
entry = dtuple_create(heap, 7 + DATA_N_SYS_COLS);
369
dict_table_copy_types(entry, sys_indexes);
371
/* 0: TABLE_ID -----------------------*/
372
dfield = dtuple_get_nth_field(entry, 0/*TABLE_ID*/);
374
ptr = static_cast<unsigned char *>(mem_heap_alloc(heap, 8));
375
mach_write_to_8(ptr, table->id);
377
dfield_set_data(dfield, ptr, 8);
378
/* 1: ID ----------------------------*/
379
dfield = dtuple_get_nth_field(entry, 1/*ID*/);
381
ptr = static_cast<unsigned char *>(mem_heap_alloc(heap, 8));
382
mach_write_to_8(ptr, index->id);
384
dfield_set_data(dfield, ptr, 8);
385
/* 4: NAME --------------------------*/
386
dfield = dtuple_get_nth_field(entry, 2/*NAME*/);
388
dfield_set_data(dfield, index->name, ut_strlen(index->name));
389
/* 5: N_FIELDS ----------------------*/
390
dfield = dtuple_get_nth_field(entry, 3/*N_FIELDS*/);
392
ptr = static_cast<unsigned char *>(mem_heap_alloc(heap, 4));
393
mach_write_to_4(ptr, index->n_fields);
395
dfield_set_data(dfield, ptr, 4);
396
/* 6: TYPE --------------------------*/
397
dfield = dtuple_get_nth_field(entry, 4/*TYPE*/);
399
ptr = static_cast<unsigned char *>(mem_heap_alloc(heap, 4));
400
mach_write_to_4(ptr, index->type);
402
dfield_set_data(dfield, ptr, 4);
403
/* 7: SPACE --------------------------*/
405
#if DICT_SYS_INDEXES_SPACE_NO_FIELD != 7
406
#error "DICT_SYS_INDEXES_SPACE_NO_FIELD != 7"
409
dfield = dtuple_get_nth_field(entry, 5/*SPACE*/);
411
ptr = static_cast<unsigned char *>(mem_heap_alloc(heap, 4));
412
mach_write_to_4(ptr, index->space);
414
dfield_set_data(dfield, ptr, 4);
415
/* 8: PAGE_NO --------------------------*/
417
#if DICT_SYS_INDEXES_PAGE_NO_FIELD != 8
418
#error "DICT_SYS_INDEXES_PAGE_NO_FIELD != 8"
421
dfield = dtuple_get_nth_field(entry, 6/*PAGE_NO*/);
423
ptr = static_cast<unsigned char *>(mem_heap_alloc(heap, 4));
424
mach_write_to_4(ptr, FIL_NULL);
426
dfield_set_data(dfield, ptr, 4);
427
/*--------------------------------*/
432
/*****************************************************************//**
433
Based on an index object, this function builds the entry to be inserted
434
in the SYS_FIELDS system table.
435
@return the tuple which should be inserted */
438
dict_create_sys_fields_tuple(
439
/*=========================*/
440
const dict_index_t* index, /*!< in: index */
441
ulint i, /*!< in: field number */
442
mem_heap_t* heap) /*!< in: memory heap from
443
which the memory for the built
444
tuple is allocated */
446
dict_table_t* sys_fields;
451
ibool index_contains_column_prefix_field = FALSE;
457
for (j = 0; j < index->n_fields; j++) {
458
if (dict_index_get_nth_field(index, j)->prefix_len > 0) {
459
index_contains_column_prefix_field = TRUE;
464
field = dict_index_get_nth_field(index, i);
466
sys_fields = dict_sys->sys_fields;
468
entry = dtuple_create(heap, 3 + DATA_N_SYS_COLS);
470
dict_table_copy_types(entry, sys_fields);
472
/* 0: INDEX_ID -----------------------*/
473
dfield = dtuple_get_nth_field(entry, 0/*INDEX_ID*/);
475
ptr = static_cast<unsigned char *>(mem_heap_alloc(heap, 8));
476
mach_write_to_8(ptr, index->id);
478
dfield_set_data(dfield, ptr, 8);
479
/* 1: POS + PREFIX LENGTH ----------------------------*/
481
dfield = dtuple_get_nth_field(entry, 1/*POS*/);
483
ptr = static_cast<unsigned char *>(mem_heap_alloc(heap, 4));
485
if (index_contains_column_prefix_field) {
486
/* If there are column prefix fields in the index, then
487
we store the number of the field to the 2 HIGH bytes
488
and the prefix length to the 2 low bytes, */
490
mach_write_to_4(ptr, (i << 16) + field->prefix_len);
492
/* Else we store the number of the field to the 2 LOW bytes.
493
This is to keep the storage format compatible with
494
InnoDB versions < 4.0.14. */
496
mach_write_to_4(ptr, i);
499
dfield_set_data(dfield, ptr, 4);
500
/* 4: COL_NAME -------------------------*/
501
dfield = dtuple_get_nth_field(entry, 2/*COL_NAME*/);
503
dfield_set_data(dfield, field->name,
504
ut_strlen(field->name));
505
/*---------------------------------*/
510
/*****************************************************************//**
511
Creates the tuple with which the index entry is searched for writing the index
512
tree root page number, if such a tree is created.
513
@return the tuple for search */
516
dict_create_search_tuple(
517
/*=====================*/
518
const dtuple_t* tuple, /*!< in: the tuple inserted in the SYS_INDEXES
520
mem_heap_t* heap) /*!< in: memory heap from which the memory for
521
the built tuple is allocated */
523
dtuple_t* search_tuple;
524
const dfield_t* field1;
527
ut_ad(tuple && heap);
529
search_tuple = dtuple_create(heap, 2);
531
field1 = dtuple_get_nth_field(tuple, 0);
532
field2 = dtuple_get_nth_field(search_tuple, 0);
534
dfield_copy(field2, field1);
536
field1 = dtuple_get_nth_field(tuple, 1);
537
field2 = dtuple_get_nth_field(search_tuple, 1);
539
dfield_copy(field2, field1);
541
ut_ad(dtuple_validate(search_tuple));
543
return(search_tuple);
546
/***************************************************************//**
547
Builds an index definition row to insert.
548
@return DB_SUCCESS or error code */
551
dict_build_index_def_step(
552
/*======================*/
553
que_thr_t* thr, /*!< in: query thread */
554
ind_node_t* node) /*!< in: index create node */
561
ut_ad(mutex_own(&(dict_sys->mutex)));
563
trx = thr_get_trx(thr);
567
table = dict_table_get_low(index->table_name);
570
return(DB_TABLE_NOT_FOUND);
573
trx->table_id = table->id;
577
ut_ad((UT_LIST_GET_LEN(table->indexes) > 0)
578
|| dict_index_is_clust(index));
580
dict_hdr_get_new_id(NULL, &index->id, NULL);
582
/* Inherit the space id from the table; we store all indexes of a
583
table in the same tablespace */
585
index->space = table->space;
586
node->page_no = FIL_NULL;
587
row = dict_create_sys_indexes_tuple(index, node->heap);
590
ins_node_set_new_row(node->ind_def, row);
592
/* Note that the index was created by this transaction. */
593
index->trx_id = trx->id;
598
/***************************************************************//**
599
Builds a field definition row to insert.
600
@return DB_SUCCESS */
603
dict_build_field_def_step(
604
/*======================*/
605
ind_node_t* node) /*!< in: index create node */
612
row = dict_create_sys_fields_tuple(index, node->field_no, node->heap);
614
ins_node_set_new_row(node->field_def, row);
619
/***************************************************************//**
620
Creates an index tree for the index if it is not a member of a cluster.
621
@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
624
dict_create_index_tree_step(
625
/*========================*/
626
ind_node_t* node) /*!< in: index create node */
629
dict_table_t* sys_indexes;
630
dtuple_t* search_tuple;
635
ut_ad(mutex_own(&(dict_sys->mutex)));
639
sys_indexes = dict_sys->sys_indexes;
641
/* Run a mini-transaction in which the index tree is allocated for
642
the index and its root address is written to the index entry in
647
search_tuple = dict_create_search_tuple(node->ind_row, node->heap);
649
btr_pcur_open(UT_LIST_GET_FIRST(sys_indexes->indexes),
650
search_tuple, PAGE_CUR_L, BTR_MODIFY_LEAF,
653
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
655
zip_size = dict_table_zip_size(index->table);
657
node->page_no = btr_create(index->type, index->space, zip_size,
658
index->id, index, &mtr);
659
/* printf("Created a new index tree in space %lu root page %lu\n",
660
index->space, index->page_no); */
662
page_rec_write_index_page_no(btr_pcur_get_rec(&pcur),
663
DICT_SYS_INDEXES_PAGE_NO_FIELD,
664
node->page_no, &mtr);
665
btr_pcur_close(&pcur);
668
if (node->page_no == FIL_NULL) {
670
return(DB_OUT_OF_FILE_SPACE);
676
/*******************************************************************//**
677
Drops the index tree associated with a row in SYS_INDEXES table. */
680
dict_drop_index_tree(
681
/*=================*/
682
rec_t* rec, /*!< in/out: record in the clustered index
683
of SYS_INDEXES table */
684
mtr_t* mtr) /*!< in: mtr having the latch on the record page */
692
ut_ad(mutex_own(&(dict_sys->mutex)));
693
ut_a(!dict_table_is_comp(dict_sys->sys_indexes));
694
ptr = rec_get_nth_field_old(rec, DICT_SYS_INDEXES_PAGE_NO_FIELD, &len);
698
root_page_no = mtr_read_ulint(ptr, MLOG_4BYTES, mtr);
700
if (root_page_no == FIL_NULL) {
701
/* The tree has already been freed */
706
ptr = rec_get_nth_field_old(rec,
707
DICT_SYS_INDEXES_SPACE_NO_FIELD, &len);
711
space = mtr_read_ulint(ptr, MLOG_4BYTES, mtr);
712
zip_size = fil_space_get_zip_size(space);
714
if (UNIV_UNLIKELY(zip_size == ULINT_UNDEFINED)) {
715
/* It is a single table tablespace and the .ibd file is
716
missing: do nothing */
721
/* We free all the pages but the root page first; this operation
722
may span several mini-transactions */
724
btr_free_but_not_root(space, zip_size, root_page_no);
726
/* Then we free the root page in the same mini-transaction where
727
we write FIL_NULL to the appropriate field in the SYS_INDEXES
728
record: this mini-transaction marks the B-tree totally freed */
730
/* printf("Dropping index tree in space %lu root page %lu\n", space,
732
btr_free_root(space, zip_size, root_page_no, mtr);
734
page_rec_write_index_page_no(rec,
735
DICT_SYS_INDEXES_PAGE_NO_FIELD,
739
/*******************************************************************//**
740
Truncates the index tree associated with a row in SYS_INDEXES table.
741
@return new root page number, or FIL_NULL on failure */
744
dict_truncate_index_tree(
745
/*=====================*/
746
dict_table_t* table, /*!< in: the table the index belongs to */
747
ulint space, /*!< in: 0=truncate,
748
nonzero=create the index tree in the
750
btr_pcur_t* pcur, /*!< in/out: persistent cursor pointing to
751
record in the clustered index of
752
SYS_INDEXES table. The cursor may be
753
repositioned in this call. */
754
mtr_t* mtr) /*!< in: mtr having the latch
755
on the record page. The mtr may be
756
committed and restarted in this call. */
768
ut_ad(mutex_own(&(dict_sys->mutex)));
769
ut_a(!dict_table_is_comp(dict_sys->sys_indexes));
770
rec = btr_pcur_get_rec(pcur);
771
ptr = rec_get_nth_field_old(rec, DICT_SYS_INDEXES_PAGE_NO_FIELD, &len);
775
root_page_no = mtr_read_ulint(ptr, MLOG_4BYTES, mtr);
777
if (drop && root_page_no == FIL_NULL) {
778
/* The tree has been freed. */
780
ut_print_timestamp(stderr);
781
fprintf(stderr, " InnoDB: Trying to TRUNCATE"
782
" a missing index of table %s!\n", table->name);
786
ptr = rec_get_nth_field_old(rec,
787
DICT_SYS_INDEXES_SPACE_NO_FIELD, &len);
792
space = mtr_read_ulint(ptr, MLOG_4BYTES, mtr);
795
zip_size = fil_space_get_zip_size(space);
797
if (UNIV_UNLIKELY(zip_size == ULINT_UNDEFINED)) {
798
/* It is a single table tablespace and the .ibd file is
799
missing: do nothing */
801
ut_print_timestamp(stderr);
802
fprintf(stderr, " InnoDB: Trying to TRUNCATE"
803
" a missing .ibd file of table %s!\n", table->name);
807
ptr = rec_get_nth_field_old(rec,
808
DICT_SYS_INDEXES_TYPE_FIELD, &len);
810
type = mach_read_from_4(ptr);
812
ptr = rec_get_nth_field_old(rec, 1, &len);
814
index_id = mach_read_from_8(ptr);
821
/* We free all the pages but the root page first; this operation
822
may span several mini-transactions */
824
btr_free_but_not_root(space, zip_size, root_page_no);
826
/* Then we free the root page in the same mini-transaction where
827
we create the b-tree and write its new root page number to the
828
appropriate field in the SYS_INDEXES record: this mini-transaction
829
marks the B-tree totally truncated */
831
btr_block_get(space, zip_size, root_page_no, RW_X_LATCH, mtr);
833
btr_free_root(space, zip_size, root_page_no, mtr);
835
/* We will temporarily write FIL_NULL to the PAGE_NO field
836
in SYS_INDEXES, so that the database will not get into an
837
inconsistent state in case it crashes between the mtr_commit()
838
below and the following mtr_commit() call. */
839
page_rec_write_index_page_no(rec, DICT_SYS_INDEXES_PAGE_NO_FIELD,
842
/* We will need to commit the mini-transaction in order to avoid
843
deadlocks in the btr_create() call, because otherwise we would
844
be freeing and allocating pages in the same mini-transaction. */
845
btr_pcur_store_position(pcur, mtr);
849
btr_pcur_restore_position(BTR_MODIFY_LEAF, pcur, mtr);
851
/* Find the index corresponding to this SYS_INDEXES record. */
852
for (index = UT_LIST_GET_FIRST(table->indexes);
854
index = UT_LIST_GET_NEXT(indexes, index)) {
855
if (index->id == index_id) {
856
root_page_no = btr_create(type, space, zip_size,
857
index_id, index, mtr);
858
index->page = (unsigned int) root_page_no;
859
return(root_page_no);
863
ut_print_timestamp(stderr);
865
" InnoDB: Index %llu of table %s is missing\n"
866
"InnoDB: from the data dictionary during TRUNCATE!\n",
873
/*********************************************************************//**
874
Creates a table create graph.
875
@return own: table create node */
878
tab_create_graph_create(
879
/*====================*/
880
dict_table_t* table, /*!< in: table to create, built as a memory data
882
mem_heap_t* heap) /*!< in: heap where created */
886
node = static_cast<tab_node_t *>(mem_heap_alloc(heap, sizeof(tab_node_t)));
888
node->common.type = QUE_NODE_CREATE_TABLE;
892
node->state = TABLE_BUILD_TABLE_DEF;
893
node->heap = mem_heap_create(256);
895
node->tab_def = ins_node_create(INS_DIRECT, dict_sys->sys_tables,
897
node->tab_def->common.parent = node;
899
node->col_def = ins_node_create(INS_DIRECT, dict_sys->sys_columns,
901
node->col_def->common.parent = node;
903
node->commit_node = commit_node_create(heap);
904
node->commit_node->common.parent = node;
909
/*********************************************************************//**
910
Creates an index create graph.
911
@return own: index create node */
914
ind_create_graph_create(
915
/*====================*/
916
dict_index_t* index, /*!< in: index to create, built as a memory data
918
mem_heap_t* heap) /*!< in: heap where created */
922
node = static_cast<ind_node_t *>(mem_heap_alloc(heap, sizeof(ind_node_t)));
924
node->common.type = QUE_NODE_CREATE_INDEX;
928
node->state = INDEX_BUILD_INDEX_DEF;
929
node->page_no = FIL_NULL;
930
node->heap = mem_heap_create(256);
932
node->ind_def = ins_node_create(INS_DIRECT,
933
dict_sys->sys_indexes, heap);
934
node->ind_def->common.parent = node;
936
node->field_def = ins_node_create(INS_DIRECT,
937
dict_sys->sys_fields, heap);
938
node->field_def->common.parent = node;
940
node->commit_node = commit_node_create(heap);
941
node->commit_node->common.parent = node;
946
/***********************************************************//**
947
Creates a table. This is a high-level function used in SQL execution graphs.
948
@return query thread to run next or NULL */
951
dict_create_table_step(
952
/*===================*/
953
que_thr_t* thr) /*!< in: query thread */
956
ulint err = DB_ERROR;
960
ut_ad(mutex_own(&(dict_sys->mutex)));
962
trx = thr_get_trx(thr);
964
node = static_cast<tab_node_t *>(thr->run_node);
966
ut_ad(que_node_get_type(node) == QUE_NODE_CREATE_TABLE);
968
if (thr->prev_node == que_node_get_parent(node)) {
969
node->state = TABLE_BUILD_TABLE_DEF;
972
if (node->state == TABLE_BUILD_TABLE_DEF) {
974
/* DO THE CHECKS OF THE CONSISTENCY CONSTRAINTS HERE */
976
err = dict_build_table_def_step(thr, node);
978
if (err != DB_SUCCESS) {
983
node->state = TABLE_BUILD_COL_DEF;
986
thr->run_node = node->tab_def;
991
if (node->state == TABLE_BUILD_COL_DEF) {
993
if (node->col_no < (node->table)->n_def) {
995
err = dict_build_col_def_step(node);
997
if (err != DB_SUCCESS) {
1004
thr->run_node = node->col_def;
1008
node->state = TABLE_COMMIT_WORK;
1012
if (node->state == TABLE_COMMIT_WORK) {
1014
/* Table was correctly defined: do NOT commit the transaction
1015
(CREATE TABLE does NOT do an implicit commit of the current
1018
node->state = TABLE_ADD_TO_CACHE;
1020
/* thr->run_node = node->commit_node;
1025
if (node->state == TABLE_ADD_TO_CACHE) {
1027
dict_table_add_to_cache(node->table, node->heap);
1033
trx->error_state = err;
1035
if (err == DB_SUCCESS) {
1036
/* Ok: do nothing */
1038
} else if (err == DB_LOCK_WAIT) {
1042
/* SQL error detected */
1047
thr->run_node = que_node_get_parent(node);
1052
/***********************************************************//**
1053
Creates an index. This is a high-level function used in SQL execution
1055
@return query thread to run next or NULL */
1058
dict_create_index_step(
1059
/*===================*/
1060
que_thr_t* thr) /*!< in: query thread */
1063
ulint err = DB_ERROR;
1067
ut_ad(mutex_own(&(dict_sys->mutex)));
1069
trx = thr_get_trx(thr);
1071
node = static_cast<ind_node_t *>(thr->run_node);
1073
ut_ad(que_node_get_type(node) == QUE_NODE_CREATE_INDEX);
1075
if (thr->prev_node == que_node_get_parent(node)) {
1076
node->state = INDEX_BUILD_INDEX_DEF;
1079
if (node->state == INDEX_BUILD_INDEX_DEF) {
1080
/* DO THE CHECKS OF THE CONSISTENCY CONSTRAINTS HERE */
1081
err = dict_build_index_def_step(thr, node);
1083
if (err != DB_SUCCESS) {
1088
node->state = INDEX_BUILD_FIELD_DEF;
1091
thr->run_node = node->ind_def;
1096
if (node->state == INDEX_BUILD_FIELD_DEF) {
1098
if (node->field_no < (node->index)->n_fields) {
1100
err = dict_build_field_def_step(node);
1102
if (err != DB_SUCCESS) {
1109
thr->run_node = node->field_def;
1113
node->state = INDEX_ADD_TO_CACHE;
1117
if (node->state == INDEX_ADD_TO_CACHE) {
1119
index_id_t index_id = node->index->id;
1121
err = dict_index_add_to_cache(
1122
node->table, node->index, FIL_NULL,
1124
|| dict_table_get_format(node->table)
1125
>= DICT_TF_FORMAT_ZIP);
1127
node->index = dict_index_get_if_in_cache_low(index_id);
1128
ut_a(!node->index == (err != DB_SUCCESS));
1130
if (err != DB_SUCCESS) {
1135
node->state = INDEX_CREATE_INDEX_TREE;
1138
if (node->state == INDEX_CREATE_INDEX_TREE) {
1140
err = dict_create_index_tree_step(node);
1142
if (err != DB_SUCCESS) {
1143
dict_index_remove_from_cache(node->table, node->index);
1149
node->index->page = node->page_no;
1150
node->state = INDEX_COMMIT_WORK;
1153
if (node->state == INDEX_COMMIT_WORK) {
1155
/* Index was correctly defined: do NOT commit the transaction
1156
(CREATE INDEX does NOT currently do an implicit commit of
1157
the current transaction) */
1159
node->state = INDEX_CREATE_INDEX_TREE;
1161
/* thr->run_node = node->commit_node;
1167
trx->error_state = err;
1169
if (err == DB_SUCCESS) {
1170
/* Ok: do nothing */
1172
} else if (err == DB_LOCK_WAIT) {
1176
/* SQL error detected */
1181
thr->run_node = que_node_get_parent(node);
1186
/****************************************************************//**
1187
Creates the foreign key constraints system tables inside InnoDB
1188
at database creation or database start if they are not found or are
1189
not of the right form.
1190
@return DB_SUCCESS or error code */
1193
dict_create_or_check_foreign_constraint_tables(void)
1194
/*================================================*/
1196
dict_table_t* table1;
1197
dict_table_t* table2;
1201
mutex_enter(&(dict_sys->mutex));
1203
table1 = dict_table_get_low("SYS_FOREIGN");
1204
table2 = dict_table_get_low("SYS_FOREIGN_COLS");
1206
if (table1 && table2
1207
&& UT_LIST_GET_LEN(table1->indexes) == 3
1208
&& UT_LIST_GET_LEN(table2->indexes) == 1) {
1210
/* Foreign constraint system tables have already been
1211
created, and they are ok */
1213
mutex_exit(&(dict_sys->mutex));
1218
mutex_exit(&(dict_sys->mutex));
1220
trx = trx_allocate_for_mysql();
1222
trx->op_info = "creating foreign key sys tables";
1224
row_mysql_lock_data_dictionary(trx);
1228
"InnoDB: dropping incompletely created"
1229
" SYS_FOREIGN table\n");
1230
row_drop_table_for_mysql("SYS_FOREIGN", trx, TRUE);
1235
"InnoDB: dropping incompletely created"
1236
" SYS_FOREIGN_COLS table\n");
1237
row_drop_table_for_mysql("SYS_FOREIGN_COLS", trx, TRUE);
1241
"InnoDB: Creating foreign key constraint system tables\n");
1243
/* NOTE: in dict_load_foreigns we use the fact that
1244
there are 2 secondary indexes on SYS_FOREIGN, and they
1245
are defined just like below */
1247
/* NOTE: when designing InnoDB's foreign key support in 2001, we made
1248
an error and made the table names and the foreign key id of type
1249
'CHAR' (internally, really a VARCHAR). We should have made the type
1250
VARBINARY, like in other InnoDB system tables, to get a clean
1253
pars_info_t *info = pars_info_create();
1254
error = que_eval_sql(info,
1255
"PROCEDURE CREATE_FOREIGN_SYS_TABLES_PROC () IS\n"
1258
"SYS_FOREIGN(ID CHAR, FOR_NAME CHAR,"
1259
" REF_NAME CHAR, N_COLS INT);\n"
1260
"CREATE UNIQUE CLUSTERED INDEX ID_IND"
1261
" ON SYS_FOREIGN (ID);\n"
1262
"CREATE INDEX FOR_IND"
1263
" ON SYS_FOREIGN (FOR_NAME);\n"
1264
"CREATE INDEX REF_IND"
1265
" ON SYS_FOREIGN (REF_NAME);\n"
1267
"SYS_FOREIGN_COLS(ID CHAR, POS INT,"
1268
" FOR_COL_NAME CHAR, REF_COL_NAME CHAR);\n"
1269
"CREATE UNIQUE CLUSTERED INDEX ID_IND"
1270
" ON SYS_FOREIGN_COLS (ID, POS);\n"
1274
if (error != DB_SUCCESS) {
1275
fprintf(stderr, "InnoDB: error %lu in creation\n",
1278
ut_a(error == DB_OUT_OF_FILE_SPACE
1279
|| error == DB_TOO_MANY_CONCURRENT_TRXS);
1282
"InnoDB: creation failed\n"
1283
"InnoDB: tablespace is full\n"
1284
"InnoDB: dropping incompletely created"
1285
" SYS_FOREIGN tables\n");
1287
row_drop_table_for_mysql("SYS_FOREIGN", trx, TRUE);
1288
row_drop_table_for_mysql("SYS_FOREIGN_COLS", trx, TRUE);
1290
error = DB_MUST_GET_MORE_FILE_SPACE;
1293
trx_commit_for_mysql(trx);
1295
row_mysql_unlock_data_dictionary(trx);
1297
trx_free_for_mysql(trx);
1299
if (error == DB_SUCCESS) {
1301
"InnoDB: Foreign key constraint system tables"
1308
/****************************************************************//**
1309
Evaluate the given foreign key SQL statement.
1310
@return error code or DB_SUCCESS */
1313
dict_foreign_eval_sql(
1314
/*==================*/
1315
pars_info_t* info, /*!< in: info struct, or NULL */
1316
const char* sql, /*!< in: SQL string to evaluate */
1317
dict_table_t* table, /*!< in: table */
1318
dict_foreign_t* foreign,/*!< in: foreign */
1319
trx_t* trx) /*!< in: transaction */
1322
FILE* ef = dict_foreign_err_file;
1324
error = que_eval_sql(info, sql, FALSE, trx);
1326
if (error == DB_DUPLICATE_KEY) {
1327
mutex_enter(&dict_foreign_err_mutex);
1329
ut_print_timestamp(ef);
1330
fputs(" Error in foreign key constraint creation for table ",
1332
ut_print_name(ef, trx, TRUE, table->name);
1333
fputs(".\nA foreign key constraint of name ", ef);
1334
ut_print_name(ef, trx, TRUE, foreign->id);
1335
fputs("\nalready exists."
1336
" (Note that internally InnoDB adds 'databasename'\n"
1337
"in front of the user-defined constraint name.)\n"
1338
"Note that InnoDB's FOREIGN KEY system tables store\n"
1339
"constraint names as case-insensitive, with the\n"
1340
"MySQL standard latin1_swedish_ci collation. If you\n"
1341
"create tables or databases whose names differ only in\n"
1342
"the character case, then collisions in constraint\n"
1343
"names can occur. Workaround: name your constraints\n"
1344
"explicitly with unique names.\n",
1347
mutex_exit(&dict_foreign_err_mutex);
1352
if (error != DB_SUCCESS) {
1354
"InnoDB: Foreign key constraint creation failed:\n"
1355
"InnoDB: internal error number %lu\n", (ulong) error);
1357
mutex_enter(&dict_foreign_err_mutex);
1358
ut_print_timestamp(ef);
1359
fputs(" Internal error in foreign key constraint creation"
1361
ut_print_name(ef, trx, TRUE, table->name);
1363
"See the MySQL .err log in the datadir"
1364
" for more information.\n", ef);
1365
mutex_exit(&dict_foreign_err_mutex);
1373
/********************************************************************//**
1374
Add a single foreign key field definition to the data dictionary tables in
1376
@return error code or DB_SUCCESS */
1379
dict_create_add_foreign_field_to_dictionary(
1380
/*========================================*/
1381
ulint field_nr, /*!< in: foreign field number */
1382
dict_table_t* table, /*!< in: table */
1383
dict_foreign_t* foreign, /*!< in: foreign */
1384
trx_t* trx) /*!< in: transaction */
1386
pars_info_t* info = pars_info_create();
1388
pars_info_add_str_literal(info, "id", foreign->id);
1390
pars_info_add_int4_literal(info, "pos", field_nr);
1392
pars_info_add_str_literal(info, "for_col_name",
1393
foreign->foreign_col_names[field_nr]);
1395
pars_info_add_str_literal(info, "ref_col_name",
1396
foreign->referenced_col_names[field_nr]);
1398
return(dict_foreign_eval_sql(
1400
"PROCEDURE P () IS\n"
1402
"INSERT INTO SYS_FOREIGN_COLS VALUES"
1403
"(:id, :pos, :for_col_name, :ref_col_name);\n"
1405
table, foreign, trx));
1408
/********************************************************************//**
1409
Add a single foreign key definition to the data dictionary tables in the
1410
database. We also generate names to constraints that were not named by the
1411
user. A generated constraint has a name of the format
1412
databasename/tablename_ibfk_<number>, where the numbers start from 1, and
1413
are given locally for this table, that is, the number is not global, as in
1414
the old format constraints < 4.0.18 it used to be.
1415
@return error code or DB_SUCCESS */
1418
dict_create_add_foreign_to_dictionary(
1419
/*==================================*/
1420
ulint* id_nr, /*!< in/out: number to use in id generation;
1421
incremented if used */
1422
dict_table_t* table, /*!< in: table */
1423
dict_foreign_t* foreign,/*!< in: foreign */
1424
trx_t* trx) /*!< in: transaction */
1429
pars_info_t* info = pars_info_create();
1431
if (foreign->id == NULL) {
1432
/* Generate a new constraint id */
1433
ulint namelen = strlen(table->name);
1434
char* id = static_cast<char *>(mem_heap_alloc(foreign->heap, namelen + 20));
1435
/* no overflow if number < 1e13 */
1436
sprintf(id, "%s_ibfk_%lu", table->name, (ulong) (*id_nr)++);
1440
pars_info_add_str_literal(info, "id", foreign->id);
1442
pars_info_add_str_literal(info, "for_name", table->name);
1444
pars_info_add_str_literal(info, "ref_name",
1445
foreign->referenced_table_name);
1447
pars_info_add_int4_literal(info, "n_cols",
1448
foreign->n_fields + (foreign->type << 24));
1450
error = dict_foreign_eval_sql(info,
1451
"PROCEDURE P () IS\n"
1453
"INSERT INTO SYS_FOREIGN VALUES"
1454
"(:id, :for_name, :ref_name, :n_cols);\n"
1456
, table, foreign, trx);
1458
if (error != DB_SUCCESS) {
1463
for (i = 0; i < foreign->n_fields; i++) {
1464
error = dict_create_add_foreign_field_to_dictionary(
1465
i, table, foreign, trx);
1467
if (error != DB_SUCCESS) {
1473
error = dict_foreign_eval_sql(NULL,
1474
"PROCEDURE P () IS\n"
1478
, table, foreign, trx);
1483
/********************************************************************//**
1484
Adds foreign key definitions to data dictionary tables in the database.
1485
@return error code or DB_SUCCESS */
1488
dict_create_add_foreigns_to_dictionary(
1489
/*===================================*/
1490
ulint start_id,/*!< in: if we are actually doing ALTER TABLE
1491
ADD CONSTRAINT, we want to generate constraint
1492
numbers which are bigger than in the table so
1493
far; we number the constraints from
1494
start_id + 1 up; start_id should be set to 0 if
1495
we are creating a new table, or if the table
1496
so far has no constraints for which the name
1497
was generated here */
1498
dict_table_t* table, /*!< in: table */
1499
trx_t* trx) /*!< in: transaction */
1501
dict_foreign_t* foreign;
1502
ulint number = start_id + 1;
1505
ut_ad(mutex_own(&(dict_sys->mutex)));
1507
if (NULL == dict_table_get_low("SYS_FOREIGN")) {
1509
"InnoDB: table SYS_FOREIGN not found"
1510
" in internal data dictionary\n");
1515
for (foreign = UT_LIST_GET_FIRST(table->foreign_list);
1517
foreign = UT_LIST_GET_NEXT(foreign_list, foreign)) {
1519
error = dict_create_add_foreign_to_dictionary(&number, table,
1522
if (error != DB_SUCCESS) {